diff options
author | Meng-Ying Yang <garfield@dexon.org> | 2019-02-23 10:52:14 +0800 |
---|---|---|
committer | Jhih-Ming Huang <jm.huang@cobinhood.com> | 2019-05-06 10:44:04 +0800 |
commit | 3fef4167b90d8340f53f89cfc12f270fab865aac (patch) | |
tree | a96f9d62cb25692a4ffc95bf8548d91e2754163e | |
parent | 8115f8c82f95e6581361fcd7e2d838406517ea4f (diff) | |
download | dexon-3fef4167b90d8340f53f89cfc12f270fab865aac.tar.gz dexon-3fef4167b90d8340f53f89cfc12f270fab865aac.tar.zst dexon-3fef4167b90d8340f53f89cfc12f270fab865aac.zip |
core: vm: sqlvm: add op testcases with template
We reduce code of funtion call and nested struct initialization by
generating testcases with go template system.
Run `go run cmd/gen-op-test/main.go` first before testing instructions,
and commit generated code for fully testing on CI.
-rw-r--r-- | core/vm/sqlvm/cmd/gen-op-test/main.go | 21 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/instructions_op_test.go | 3110 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/instructions_test.go | 61 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/instructions_tmpl.go | 82 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/instructions_tmpl_data.go | 2934 | ||||
-rw-r--r-- | core/vm/sqlvm/runtime/runtime.go | 8 |
6 files changed, 6207 insertions, 9 deletions
diff --git a/core/vm/sqlvm/cmd/gen-op-test/main.go b/core/vm/sqlvm/cmd/gen-op-test/main.go new file mode 100644 index 000000000..60387dddf --- /dev/null +++ b/core/vm/sqlvm/cmd/gen-op-test/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "flag" + + "github.com/dexon-foundation/dexon/core/vm/sqlvm/runtime" +) + +func main() { + var output string + flag.StringVar( + &output, "o", "./runtime/instructions_op_test.go", + "the output path of generated testcases", + ) + flag.Parse() + + err := runtime.RenderOpTest(output) + if err != nil { + panic(err) + } +} diff --git a/core/vm/sqlvm/runtime/instructions_op_test.go b/core/vm/sqlvm/runtime/instructions_op_test.go new file mode 100644 index 000000000..f18fb0181 --- /dev/null +++ b/core/vm/sqlvm/runtime/instructions_op_test.go @@ -0,0 +1,3110 @@ +// Code generated - DO NOT EDIT. + +package runtime + +import ( + "github.com/dexon-foundation/decimal" + + "github.com/dexon-foundation/dexon/core/vm/sqlvm/ast" + "github.com/dexon-foundation/dexon/core/vm/sqlvm/errors" +) + +func (s *instructionSuite) TestOpAdd() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: ADD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-2)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(3)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(4)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(20)}}, + {&Raw{Value: decimal.NewFromFloat(-20)}, &Raw{Value: decimal.NewFromFloat(13)}}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: ADD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(11)}, &Raw{Value: decimal.NewFromFloat(8)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-9)}, &Raw{Value: decimal.NewFromFloat(-12)}, &Raw{Value: decimal.NewFromFloat(-20)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + nil, + }, + { + "Immediate 2", + Instruction{ + Op: ADD, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(11)}, &Raw{Value: decimal.NewFromFloat(8)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-9)}, &Raw{Value: decimal.NewFromFloat(-12)}, &Raw{Value: decimal.NewFromFloat(-20)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + nil, + }, + { + "Overflow - Immediate", + Instruction{ + Op: ADD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(127)}}, + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeOverflow, + }, + { + "Overflow None Immediate", + Instruction{ + Op: ADD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(126)}}, + {&Raw{Value: decimal.NewFromFloat(126)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeOverflow, + }, + { + "Underflow - Immediate", + Instruction{ + Op: ADD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-128)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeUnderflow, + }, + { + "Underflow None Immediate", + Instruction{ + Op: ADD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-127)}}, + {&Raw{Value: decimal.NewFromFloat(-127)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeUnderflow, + }, + } + + s.run(testcases, opAdd) +} + +func (s *instructionSuite) TestOpSub() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: SUB, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-2)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(3)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-4)}}, + {&Raw{Value: decimal.NewFromFloat(20)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-20)}, &Raw{Value: decimal.NewFromFloat(7)}}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: SUB, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(9)}, &Raw{Value: decimal.NewFromFloat(12)}, &Raw{Value: decimal.NewFromFloat(20)}}, + {&Raw{Value: decimal.NewFromFloat(-11)}, &Raw{Value: decimal.NewFromFloat(-8)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(4)}, &Raw{Value: decimal.NewFromFloat(10)}}, + }, + ), + nil, + }, + { + "Immediate 2", + Instruction{ + Op: SUB, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-9)}, &Raw{Value: decimal.NewFromFloat(-12)}, &Raw{Value: decimal.NewFromFloat(-20)}}, + {&Raw{Value: decimal.NewFromFloat(11)}, &Raw{Value: decimal.NewFromFloat(8)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-4)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + nil, + }, + { + "Overflow - Immediate", + Instruction{ + Op: SUB, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(127)}}, + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeOverflow, + }, + { + "Overflow None Immediate", + Instruction{ + Op: SUB, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(126)}}, + {&Raw{Value: decimal.NewFromFloat(126)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeOverflow, + }, + { + "Underflow - Immediate", + Instruction{ + Op: SUB, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-128)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeUnderflow, + }, + { + "Underflow None Immediate", + Instruction{ + Op: SUB, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-127)}}, + {&Raw{Value: decimal.NewFromFloat(-127)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeUnderflow, + }, + } + + s.run(testcases, opSub) +} + +func (s *instructionSuite) TestOpMul() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: MUL, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(4)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-4)}, &Raw{Value: decimal.NewFromFloat(-100)}}, + {&Raw{Value: decimal.NewFromFloat(100)}, &Raw{Value: decimal.NewFromFloat(100)}}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: MUL, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-20)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(20)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + nil, + }, + { + "Immediate - 2", + Instruction{ + Op: MUL, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-20)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(20)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + nil, + }, + { + "Overflow - Immediate", + Instruction{ + Op: MUL, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(127)}}, + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeOverflow, + }, + { + "Overflow None Immediate", + Instruction{ + Op: MUL, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(126)}}, + {&Raw{Value: decimal.NewFromFloat(126)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeOverflow, + }, + { + "Underflow - Immediate", + Instruction{ + Op: MUL, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-128)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeUnderflow, + }, + { + "Underflow None Immediate", + Instruction{ + Op: MUL, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-127)}}, + {&Raw{Value: decimal.NewFromFloat(-127)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeUnderflow, + }, + } + + s.run(testcases, opMul) +} + +func (s *instructionSuite) TestOpDiv() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: DIV, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: DIV, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(13)}, &Raw{Value: decimal.NewFromFloat(13)}}, + {&Raw{Value: decimal.NewFromFloat(-13)}, &Raw{Value: decimal.NewFromFloat(-13)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}, + {&Raw{Value: decimal.NewFromFloat(-5)}, &Raw{Value: decimal.NewFromFloat(5)}}, + {&Raw{Value: decimal.NewFromFloat(6)}, &Raw{Value: decimal.NewFromFloat(-6)}}, + {&Raw{Value: decimal.NewFromFloat(-6)}, &Raw{Value: decimal.NewFromFloat(6)}}, + }, + ), + nil, + }, + { + "Immediate 2", + Instruction{ + Op: DIV, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(50)}, &Raw{Value: decimal.NewFromFloat(-50)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(9)}, &Raw{Value: decimal.NewFromFloat(9)}}, + {&Raw{Value: decimal.NewFromFloat(-9)}, &Raw{Value: decimal.NewFromFloat(-9)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}, + {&Raw{Value: decimal.NewFromFloat(-5)}, &Raw{Value: decimal.NewFromFloat(5)}}, + {&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}, + {&Raw{Value: decimal.NewFromFloat(-5)}, &Raw{Value: decimal.NewFromFloat(5)}}, + }, + ), + nil, + }, + { + "DivideByZero Immediate", + Instruction{ + Op: DIV, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeDividedByZero, + }, + { + "DivideByZero None Immediate", + Instruction{ + Op: DIV, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeDividedByZero, + }, + { + "Overflow - Immediate", + Instruction{ + Op: DIV, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(-128)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeOverflow, + }, + { + "Overflow None Immediate", + Instruction{ + Op: DIV, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-128)}}, + {&Raw{Value: decimal.NewFromFloat(-128)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(-2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeOverflow, + }, + } + + s.run(testcases, opDiv) +} + +func (s *instructionSuite) TestOpMod() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: MOD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(3)}, &Raw{Value: decimal.NewFromFloat(3)}}, + {&Raw{Value: decimal.NewFromFloat(-3)}, &Raw{Value: decimal.NewFromFloat(-3)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}, + {&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: MOD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(13)}, &Raw{Value: decimal.NewFromFloat(13)}}, + {&Raw{Value: decimal.NewFromFloat(-13)}, &Raw{Value: decimal.NewFromFloat(-13)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(3)}, &Raw{Value: decimal.NewFromFloat(-3)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + nil, + }, + { + "Immediate - 2", + Instruction{ + Op: MOD, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(31)}, &Raw{Value: decimal.NewFromFloat(-31)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}, + {&Raw{Value: decimal.NewFromFloat(13)}, &Raw{Value: decimal.NewFromFloat(13)}}, + {&Raw{Value: decimal.NewFromFloat(-13)}, &Raw{Value: decimal.NewFromFloat(-13)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}, + {&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}, + }, + ), + nil, + }, + { + "ModideByZero Immediate", + Instruction{ + Op: MOD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeDividedByZero, + }, + { + "ModideByZero None Immediate", + Instruction{ + Op: MOD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(10)}}, + {&Raw{Value: decimal.NewFromFloat(10)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeDividedByZero, + }, + } + + s.run(testcases, opMod) +} + +func (s *instructionSuite) TestOpLt() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: LT, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawTrue, rawTrue}, + {rawFalse, rawFalse, rawTrue}, + {rawFalse, rawFalse, rawFalse}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: LT, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawFalse, rawTrue}, + }, + ), + nil, + }, + { + "Immediate - 2", + Instruction{ + Op: LT, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawTrue, rawFalse}, + }, + ), + nil, + }, + } + + s.run(testcases, opLt) +} + +func (s *instructionSuite) TestOpGt() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: GT, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawFalse, rawFalse}, + {rawTrue, rawFalse, rawFalse}, + {rawTrue, rawTrue, rawFalse}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: GT, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawTrue, rawFalse}, + }, + ), + nil, + }, + { + "Immediate - 2", + Instruction{ + Op: GT, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawFalse, rawTrue}, + }, + ), + nil, + }, + } + + s.run(testcases, opGt) +} + +func (s *instructionSuite) TestOpEq() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: EQ, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue, rawTrue}, + {rawTrue, rawFalse, rawFalse}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: EQ, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue, rawTrue}, + {rawTrue, rawFalse, rawFalse}, + }, + ), + nil, + }, + } + + s.run(testcases, opEq) +} + +func (s *instructionSuite) TestOpAnd() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: AND, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + {rawFalse, rawFalse}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawFalse}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: AND, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + nil, + }, + { + "Immediate - 2", + Instruction{ + Op: AND, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + nil, + }, + { + "Invalid Data Type", + Instruction{ + Op: AND, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeInvalidDataType, + }, + } + + s.run(testcases, opAnd) +} + +func (s *instructionSuite) TestOpOr() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: OR, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + {rawFalse, rawFalse}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + {rawFalse, rawTrue}, + }, + ), + nil, + }, + { + "Immediate", + Instruction{ + Op: OR, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + {rawTrue, rawTrue}, + }, + ), + nil, + }, + { + "Immediate - 2", + Instruction{ + Op: OR, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + {rawTrue, rawTrue}, + }, + ), + nil, + }, + { + "Invalid Data Type", + Instruction{ + Op: OR, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeInvalidDataType, + }, + } + + s.run(testcases, opOr) +} + +func (s *instructionSuite) TestOpNot() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: NOT, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawTrue}, + {rawTrue, rawFalse}, + }, + ), + nil, + }, + { + "Errors Invalid Data Type", + Instruction{ + Op: NOT, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeInvalidDataType, + }, + } + + s.run(testcases, opNot) +} + +func (s *instructionSuite) TestOpUnion() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: UNION, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + {rawFalse, rawFalse}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawFalse}, + {rawFalse, rawTrue}, + {rawTrue, rawFalse}, + {rawTrue, rawTrue}, + }, + ), + nil, + }, + } + + s.run(testcases, opUnion) +} + +func (s *instructionSuite) TestOpIntxn() { + testcases := []opTestcase{ + { + "None Immediate", + Instruction{ + Op: INTXN, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + {rawTrue, rawTrue}, + {rawFalse, rawFalse}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + {rawFalse, rawFalse}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawFalse, rawFalse}, + {rawTrue, rawTrue}, + }, + ), + nil, + }, + } + + s.run(testcases, opIntxn) +} + +func (s *instructionSuite) TestOpLike() { + testcases := []opTestcase{ + { + "Like %\\%b% escape \\", + Instruction{ + Op: LIKE, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("a%bcdefg")}, &Raw{Bytes: []byte("gfedcba")}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("%\\%b%")}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("\\")}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + }, + ), + nil, + }, + { + "Like t1 escape t2", + Instruction{ + Op: LIKE, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("a%bcdefg")}}, + {&Raw{Bytes: []byte("gfedcba")}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("%\\%b%")}}, + {&Raw{Bytes: []byte("_fed%")}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("\\")}}, + {&Raw{Bytes: []byte("")}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue}, + {rawTrue}, + }, + ), + nil, + }, + { + "Like with valid and invalid UTF8", + Instruction{ + Op: LIKE, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte{226, 40, 161, 228, 189, 160, 229, 165, 189}}, &Raw{Bytes: []byte("gfedcba")}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte{37, 228, 189, 160, 37}}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + }, + ), + nil, + }, + } + + s.run(testcases, opLike) +} + +func (s *instructionSuite) TestOpZip() { + testcases := []opTestcase{ + { + "Zip two array", + Instruction{ + Op: ZIP, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}}, + {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + {&Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + }, + ), + nil, + }, + { + "Zip immediate", + Instruction{ + Op: ZIP, + Input: []*Operand{ + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(7, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + {&Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + }, + ), + nil, + }, + } + + s.run(testcases, opZip) +} + +func (s *instructionSuite) TestOpField() { + testcases := []opTestcase{ + { + "Retrieve 2nd,3rd column", + Instruction{ + Op: FIELD, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + nil, + }, + } + + s.run(testcases, opField) +} + +func (s *instructionSuite) TestOpPrune() { + testcases := []opTestcase{ + { + "Prune 2nd,4th,5th column", + Instruction{ + Op: PRUNE, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse, rawTrue}, + {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue, rawFalse}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(3)}, &Raw{Value: decimal.NewFromFloat(4)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Value: decimal.NewFromFloat(1)}}, + {&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + nil, + }, + } + + s.run(testcases, opPrune) +} + +func (s *instructionSuite) TestOpFilter() { + testcases := []opTestcase{ + { + "Filter first 2 rows", + Instruction{ + Op: FILTER, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + {rawTrue, rawTrue}, + {rawFalse, rawFalse}, + }, + ), + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue}, + {rawTrue}, + {rawFalse}, + {rawFalse}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + {rawFalse, rawTrue}, + }, + ), + nil, + }, + } + + s.run(testcases, opFilter) +} + +func (s *instructionSuite) TestOpCast() { + testcases := []opTestcase{ + { + "None Immediate - int", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 1), ast.ComposeDataType(4, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(127)}, &Raw{Value: decimal.NewFromFloat(127)}}, + {&Raw{Value: decimal.NewFromFloat(-128)}, &Raw{Value: decimal.NewFromFloat(-128)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 2), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 0), ast.ComposeDataType(4, 2), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(127)}, &Raw{Value: decimal.NewFromFloat(127)}}, + {&Raw{Value: decimal.NewFromFloat(-128)}, &Raw{Value: decimal.NewFromFloat(-128)}}, + }, + ), + nil, + }, + { + "None Immediate - int2", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 1), ast.ComposeDataType(4, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(-32768)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(5, 1), ast.ComposeDataType(5, 1), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(5, 1), ast.ComposeDataType(5, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(32768)}}, + }, + ), + nil, + }, + { + "None Immediate - int3", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 1), ast.ComposeDataType(4, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(-32768)}}, + {&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawTrue}, + {rawFalse, rawFalse}, + }, + ), + nil, + }, + { + "None Immediate - int4", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 1), ast.ComposeDataType(4, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(-32768)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(6, 1), ast.ComposeDataType(3, 0), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(6, 1), ast.ComposeDataType(3, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte{0x7f, 0xff}}, &Raw{Bytes: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0x80, 0x00}}}, + }, + ), + nil, + }, + { + "None Immediate - uint", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(5, 1), ast.ComposeDataType(5, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(128)}, &Raw{Value: decimal.NewFromFloat(128)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(5, 0), ast.ComposeDataType(5, 2), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(5, 0), ast.ComposeDataType(5, 2), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(128)}, &Raw{Value: decimal.NewFromFloat(128)}}, + }, + ), + nil, + }, + { + "None Immediate - uint2", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(5, 1), ast.ComposeDataType(5, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(32768)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 1), ast.ComposeDataType(6, 1), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 1), ast.ComposeDataType(6, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Bytes: []byte{0x80, 0x00}}}, + }, + ), + nil, + }, + { + "None Immediate - uint3", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(5, 1), ast.ComposeDataType(5, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue, rawFalse}, + }, + ), + nil, + }, + { + "None Immediate - uint4", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(5, 1), ast.ComposeDataType(5, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(6, 1), ast.ComposeDataType(6, 1), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(6, 1), ast.ComposeDataType(6, 1), + }, + []Tuple{ + {&Raw{Bytes: []byte{0x7f, 0xff}}, &Raw{Bytes: []byte{0x00, 0x00}}}, + }, + ), + nil, + }, + { + "None Immediate - uint5", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(5, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(3, 1), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(3, 1), + }, + []Tuple{ + {&Raw{Bytes: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x7f, 0xff}}}, + }, + ), + nil, + }, + { + "None Immediate - bytes", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(6, 1), ast.ComposeDataType(6, 1), + }, + []Tuple{ + {&Raw{Bytes: []byte{0xff, 0xff}}, &Raw{Bytes: []byte{0xff, 0xff}}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(6, 0), ast.ComposeDataType(6, 2), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(6, 0), ast.ComposeDataType(6, 2), + }, + []Tuple{ + {&Raw{Bytes: []byte{0xff}}, &Raw{Bytes: []byte{0xff, 0xff, 0x00}}}, + }, + ), + nil, + }, + { + "None Immediate - bytes2", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(6, 1), ast.ComposeDataType(6, 1), + }, + []Tuple{ + {&Raw{Bytes: []byte{0x7f, 0xff}}, &Raw{Bytes: []byte{0x80, 0x00}}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(4, 1), ast.ComposeDataType(5, 1), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 1), ast.ComposeDataType(5, 1), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(32768)}}, + }, + ), + nil, + }, + { + "None Immediate - bytes3", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(6, 1), + }, + []Tuple{ + {&Raw{Bytes: []byte{0x7f, 0xff}}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(7, 1), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 1), + }, + []Tuple{ + {&Raw{Bytes: []byte{0x7f, 0xff}}}, + }, + ), + nil, + }, + { + "Same type", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(2, 0), + }, + []Tuple{ + {rawTrue}, + }, + ), + nil, + }, + { + "Error Invalid Type", + Instruction{ + Op: CAST, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(4, 2), + }, + []Tuple{ + {&Raw{Value: decimal.NewFromFloat(-32768)}}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(7, 0), + }, + []Tuple{}, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{}, + []Tuple{}, + ), + errors.ErrorCodeInvalidCastType, + }, + } + + s.run(testcases, opCast) +} + +func (s *instructionSuite) TestOpSort() { + testcases := []opTestcase{ + { + "Multi-column sorting", + Instruction{ + Op: SORT, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawTrue}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + {&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {rawFalse, &Raw{Value: decimal.NewFromFloat(1)}}, + {rawTrue, &Raw{Value: decimal.NewFromFloat(2)}}, + {rawFalse, &Raw{Value: decimal.NewFromFloat(0)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawTrue}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse}, + {&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + }, + ), + nil, + }, + { + "Multi-column sorting - 2", + Instruction{ + Op: SORT, + Input: []*Operand{ + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawTrue}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + {&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + }, + ), + makeOperand( + true, + []ast.DataType{ + ast.ComposeDataType(2, 0), ast.ComposeDataType(4, 0), + }, + []Tuple{ + {rawTrue, &Raw{Value: decimal.NewFromFloat(0)}}, + {rawTrue, &Raw{Value: decimal.NewFromFloat(1)}}, + {rawFalse, &Raw{Value: decimal.NewFromFloat(2)}}, + }, + ), + }, + Output: 0, + }, + makeOperand( + false, + []ast.DataType{ + ast.ComposeDataType(7, 0), ast.ComposeDataType(4, 0), ast.ComposeDataType(2, 0), + }, + []Tuple{ + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawTrue}, + {&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}, + {&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + {&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}, + {&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}, + }, + ), + nil, + }, + } + + s.run(testcases, opSort) +} diff --git a/core/vm/sqlvm/runtime/instructions_test.go b/core/vm/sqlvm/runtime/instructions_test.go index 7c6bb2c5b..b679c366f 100644 --- a/core/vm/sqlvm/runtime/instructions_test.go +++ b/core/vm/sqlvm/runtime/instructions_test.go @@ -191,7 +191,7 @@ type decodeTestCase struct { type opLoadTestCase struct { title string - outputIdx int + outputIdx uint expectedOutput *Operand expectedErr error ids []uint64 @@ -410,3 +410,62 @@ func (s *opLoadSuite) TestOpLoad() { func TestOpLoad(t *testing.T) { suite.Run(t, new(opLoadSuite)) } + +func TestInstructions(t *testing.T) { + suite.Run(t, new(instructionSuite)) +} + +func makeOperand(im bool, meta []ast.DataType, pTuple []Tuple) (op *Operand) { + op = &Operand{IsImmediate: im, Meta: meta, Data: pTuple} + return +} + +func loadRegister(input, registers []*Operand) { + for i, operand := range input { + if operand != nil && !operand.IsImmediate { + input[i] = registers[operand.RegisterIndex] + } + } +} + +type opTestcase struct { + Name string + In Instruction + Output *Operand + Err error +} + +type instructionSuite struct { + suite.Suite +} + +func (s *instructionSuite) run(testcases []opTestcase, opfunc OpFunction) { + for idx, c := range testcases { + registers := make([]*Operand, len(c.In.Input)) + + for i, j := 0, 0; i < len(c.In.Input); i++ { + if !c.In.Input[i].IsImmediate { + registers[j] = c.In.Input[i] + j++ + } + } + err := opfunc( + &common.Context{Opt: common.Option{SafeMath: true}}, + c.In.Input, registers, c.In.Output) + s.Require().Equal( + c.Err, err, + "idx: %v, op: %v, case: %v\nerror not equal: %v != %v", + idx, c.In.Op, c.Name, c.Err, err, + ) + if c.Err != nil { + continue + } + + result := registers[0] + s.Require().True( + c.Output.Equal(result), + "idx: %v, op: %v, case: %v\noutput not equal.\nExpect: %v\nResult: %v\n", + idx, c.In.Op, c.Name, c.Output, result, + ) + } +} diff --git a/core/vm/sqlvm/runtime/instructions_tmpl.go b/core/vm/sqlvm/runtime/instructions_tmpl.go new file mode 100644 index 000000000..22c6bef88 --- /dev/null +++ b/core/vm/sqlvm/runtime/instructions_tmpl.go @@ -0,0 +1,82 @@ +package runtime + +import "github.com/dexon-foundation/dexon/core/vm/sqlvm/ast" + +type tmplData struct { + BinOpCollections []tmplTestCollection +} + +type tmplTestCollection struct { + TestName string + Cases []tmplTestCase + OpFunc string +} + +type tmplTestCase struct { + Name string + OpCode string + Inputs []tmplOp + Output tmplOp + Error string +} + +type tmplOp struct { + Im bool + Metas []tmplOpMeta + Data []string +} + +type tmplOpMeta struct { + Major ast.DataTypeMajor + Minor ast.DataTypeMinor +} + +const binOpTmplStr = ` +// Code generated - DO NOT EDIT. + +package runtime + +import ( + "github.com/dexon-foundation/decimal" + + "github.com/dexon-foundation/dexon/core/vm/sqlvm/ast" + "github.com/dexon-foundation/dexon/core/vm/sqlvm/errors" +) + +{{range .BinOpCollections}} +func (s *instructionSuite) Test{{.TestName}}() { + testcases := []opTestcase{ {{range .Cases}} + { + "{{.Name}}", + Instruction{ + Op: {{.OpCode}}, + Input: []*Operand{ {{range .Inputs}} + makeOperand( + {{.Im}}, + []ast.DataType{ + {{range .Metas}}ast.ComposeDataType({{.Major}}, {{.Minor}}),{{end}} + }, + []Tuple{ {{range .Data}} + {{.}},{{end}} + }, + ),{{end}} + }, + Output: 0, + }, + makeOperand( + {{.Output.Im}}, + []ast.DataType{ + {{range .Output.Metas}}ast.ComposeDataType({{.Major}}, {{.Minor}}),{{end}} + }, + []Tuple{ {{range .Output.Data}} + {{.}},{{end}} + }, + ), + {{.Error}}, + },{{end}} + } + + s.run(testcases, {{.OpFunc}}) +} +{{end}} +` diff --git a/core/vm/sqlvm/runtime/instructions_tmpl_data.go b/core/vm/sqlvm/runtime/instructions_tmpl_data.go new file mode 100644 index 000000000..345d200ec --- /dev/null +++ b/core/vm/sqlvm/runtime/instructions_tmpl_data.go @@ -0,0 +1,2934 @@ +package runtime + +import ( + "bytes" + "go/format" + "os" + "text/template" + + "github.com/dexon-foundation/dexon/core/vm/sqlvm/ast" +) + +// RenderOpTest render op test to test file. +func RenderOpTest(output string) (err error) { + binOpT, err := template.New("binOp").Parse(binOpTmplStr) + if err != nil { + return + } + + b := new(bytes.Buffer) + + err = binOpT.Execute(b, testData) + if err != nil { + return + } + + src, err := format.Source(b.Bytes()) + if err != nil { + return + } + + f, err := os.Create(output) + if err != nil { + return + } + defer f.Close() + + _, err = f.Write(src) + return +} + +var testData = tmplData{ + BinOpCollections: []tmplTestCollection{ + { + TestName: "OpAdd", OpFunc: "opAdd", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "ADD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-2)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(3)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(4)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(20)}}", + "{&Raw{Value: decimal.NewFromFloat(-20)}, &Raw{Value: decimal.NewFromFloat(13)}}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "ADD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(11)}, &Raw{Value: decimal.NewFromFloat(8)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-9)}, &Raw{Value: decimal.NewFromFloat(-12)}, &Raw{Value: decimal.NewFromFloat(-20)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + }, + { + Name: "Immediate 2", + Error: "nil", OpCode: "ADD", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(11)}, &Raw{Value: decimal.NewFromFloat(8)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-9)}, &Raw{Value: decimal.NewFromFloat(-12)}, &Raw{Value: decimal.NewFromFloat(-20)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + }, + { + Name: "Overflow - Immediate", + Error: "errors.ErrorCodeOverflow", OpCode: "ADD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(127)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Overflow None Immediate", + Error: "errors.ErrorCodeOverflow", OpCode: "ADD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(126)}}", + "{&Raw{Value: decimal.NewFromFloat(126)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Underflow - Immediate", + Error: "errors.ErrorCodeUnderflow", OpCode: "ADD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-128)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Underflow None Immediate", + Error: "errors.ErrorCodeUnderflow", OpCode: "ADD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-127)}}", + "{&Raw{Value: decimal.NewFromFloat(-127)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + }, + }, + // -- end of ADD + { + TestName: "OpSub", OpFunc: "opSub", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "SUB", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-2)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(3)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-4)}}", + "{&Raw{Value: decimal.NewFromFloat(20)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-20)}, &Raw{Value: decimal.NewFromFloat(7)}}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "SUB", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(9)}, &Raw{Value: decimal.NewFromFloat(12)}, &Raw{Value: decimal.NewFromFloat(20)}}", + "{&Raw{Value: decimal.NewFromFloat(-11)}, &Raw{Value: decimal.NewFromFloat(-8)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(4)}, &Raw{Value: decimal.NewFromFloat(10)}}", + }, + }, + }, + { + Name: "Immediate 2", + Error: "nil", OpCode: "SUB", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-9)}, &Raw{Value: decimal.NewFromFloat(-12)}, &Raw{Value: decimal.NewFromFloat(-20)}}", + "{&Raw{Value: decimal.NewFromFloat(11)}, &Raw{Value: decimal.NewFromFloat(8)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-4)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + }, + { + Name: "Overflow - Immediate", + Error: "errors.ErrorCodeOverflow", OpCode: "SUB", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(127)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Overflow None Immediate", + Error: "errors.ErrorCodeOverflow", OpCode: "SUB", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(126)}}", + "{&Raw{Value: decimal.NewFromFloat(126)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Underflow - Immediate", + Error: "errors.ErrorCodeUnderflow", OpCode: "SUB", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-128)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Underflow None Immediate", + Error: "errors.ErrorCodeUnderflow", OpCode: "SUB", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-127)}}", + "{&Raw{Value: decimal.NewFromFloat(-127)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + }, + }, + // -- end of SUB + { + TestName: "OpMul", OpFunc: "opMul", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "MUL", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(4)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-4)}, &Raw{Value: decimal.NewFromFloat(-100)}}", + "{&Raw{Value: decimal.NewFromFloat(100)}, &Raw{Value: decimal.NewFromFloat(100)}}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "MUL", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-20)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(20)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + { + Name: "Immediate - 2", + Error: "nil", OpCode: "MUL", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-20)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(20)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + { + Name: "Overflow - Immediate", + Error: "errors.ErrorCodeOverflow", OpCode: "MUL", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(127)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Overflow None Immediate", + Error: "errors.ErrorCodeOverflow", OpCode: "MUL", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(126)}}", + "{&Raw{Value: decimal.NewFromFloat(126)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Underflow - Immediate", + Error: "errors.ErrorCodeUnderflow", OpCode: "MUL", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-128)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Underflow None Immediate", + Error: "errors.ErrorCodeUnderflow", OpCode: "MUL", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-127)}}", + "{&Raw{Value: decimal.NewFromFloat(-127)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + }, + }, + // -- end of MUL + { + TestName: "OpDiv", OpFunc: "opDiv", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "DIV", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-2)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "DIV", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(13)}, &Raw{Value: decimal.NewFromFloat(13)}}", + "{&Raw{Value: decimal.NewFromFloat(-13)}, &Raw{Value: decimal.NewFromFloat(-13)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}", + "{&Raw{Value: decimal.NewFromFloat(-5)}, &Raw{Value: decimal.NewFromFloat(5)}}", + "{&Raw{Value: decimal.NewFromFloat(6)}, &Raw{Value: decimal.NewFromFloat(-6)}}", + "{&Raw{Value: decimal.NewFromFloat(-6)}, &Raw{Value: decimal.NewFromFloat(6)}}", + }, + }, + }, + { + Name: "Immediate 2", + Error: "nil", OpCode: "DIV", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(50)}, &Raw{Value: decimal.NewFromFloat(-50)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(9)}, &Raw{Value: decimal.NewFromFloat(9)}}", + "{&Raw{Value: decimal.NewFromFloat(-9)}, &Raw{Value: decimal.NewFromFloat(-9)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}", + "{&Raw{Value: decimal.NewFromFloat(-5)}, &Raw{Value: decimal.NewFromFloat(5)}}", + "{&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}", + "{&Raw{Value: decimal.NewFromFloat(-5)}, &Raw{Value: decimal.NewFromFloat(5)}}", + }, + }, + }, + { + Name: "DivideByZero Immediate", + Error: "errors.ErrorCodeDividedByZero", OpCode: "DIV", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "DivideByZero None Immediate", + Error: "errors.ErrorCodeDividedByZero", OpCode: "DIV", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Overflow - Immediate", + Error: "errors.ErrorCodeOverflow", OpCode: "DIV", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(-128)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "Overflow None Immediate", + Error: "errors.ErrorCodeOverflow", OpCode: "DIV", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-128)}}", + "{&Raw{Value: decimal.NewFromFloat(-128)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(-2)}}", + }, + }, + }, + Output: tmplOp{}, + }, + }, + }, + // -- end of DIV + { + TestName: "OpMod", OpFunc: "opMod", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "MOD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(3)}, &Raw{Value: decimal.NewFromFloat(3)}}", + "{&Raw{Value: decimal.NewFromFloat(-3)}, &Raw{Value: decimal.NewFromFloat(-3)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}", + "{&Raw{Value: decimal.NewFromFloat(2)}, &Raw{Value: decimal.NewFromFloat(-2)}}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "MOD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(13)}, &Raw{Value: decimal.NewFromFloat(13)}}", + "{&Raw{Value: decimal.NewFromFloat(-13)}, &Raw{Value: decimal.NewFromFloat(-13)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(3)}, &Raw{Value: decimal.NewFromFloat(-3)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + }, + { + Name: "Immediate - 2", + Error: "nil", OpCode: "MOD", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(31)}, &Raw{Value: decimal.NewFromFloat(-31)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}, &Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(-10)}, &Raw{Value: decimal.NewFromFloat(-10)}}", + "{&Raw{Value: decimal.NewFromFloat(13)}, &Raw{Value: decimal.NewFromFloat(13)}}", + "{&Raw{Value: decimal.NewFromFloat(-13)}, &Raw{Value: decimal.NewFromFloat(-13)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}", + "{&Raw{Value: decimal.NewFromFloat(5)}, &Raw{Value: decimal.NewFromFloat(-5)}}", + }, + }, + }, + { + Name: "ModideByZero Immediate", + Error: "errors.ErrorCodeDividedByZero", OpCode: "MOD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{}, + }, + { + Name: "ModideByZero None Immediate", + Error: "errors.ErrorCodeDividedByZero", OpCode: "MOD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(10)}}", + "{&Raw{Value: decimal.NewFromFloat(10)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{}, + }, + }, + }, + // -- end of MOD + { + TestName: "OpLt", OpFunc: "opLt", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "LT", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawTrue, rawTrue}", + "{rawFalse, rawFalse, rawTrue}", + "{rawFalse, rawFalse, rawFalse}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "LT", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawFalse, rawTrue}", + }, + }, + }, + { + Name: "Immediate - 2", + Error: "nil", OpCode: "LT", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawTrue, rawFalse}", + }, + }, + }, + }, + }, + // -- end of LT + { + TestName: "OpGt", OpFunc: "opGt", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "GT", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawFalse, rawFalse}", + "{rawTrue, rawFalse, rawFalse}", + "{rawTrue, rawTrue, rawFalse}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "GT", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawTrue, rawFalse}", + }, + }, + }, + { + Name: "Immediate - 2", + Error: "nil", OpCode: "GT", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawFalse, rawTrue}", + }, + }, + }, + }, + }, + // -- end of GT + { + TestName: "OpEq", OpFunc: "opEq", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "EQ", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue, rawTrue}", + "{rawTrue, rawFalse, rawFalse}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "EQ", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(-1)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue, rawTrue}", + "{rawTrue, rawFalse, rawFalse}", + }, + }, + }, + }, + }, + // -- end of EQ + { + TestName: "OpAnd", OpFunc: "opAnd", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "AND", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + "{rawFalse, rawFalse}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawFalse}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "AND", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + }, + { + Name: "Immediate - 2", + Error: "nil", OpCode: "AND", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + }, + { + Name: "Invalid Data Type", + Error: "errors.ErrorCodeInvalidDataType", OpCode: "AND", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + }, + Output: tmplOp{}, + }, + }, + }, + // -- end of AND + { + TestName: "OpOr", OpFunc: "opOr", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "OR", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + "{rawFalse, rawFalse}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + "{rawFalse, rawTrue}", + }, + }, + }, + { + Name: "Immediate", + Error: "nil", OpCode: "OR", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + "{rawTrue, rawTrue}", + }, + }, + }, + { + Name: "Immediate - 2", + Error: "nil", OpCode: "OR", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + "{rawTrue, rawTrue}", + }, + }, + }, + { + Name: "Invalid Data Type", + Error: "errors.ErrorCodeInvalidDataType", OpCode: "OR", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + }, + Output: tmplOp{}, + }, + }, + }, + // -- end of OR + { + TestName: "OpNot", OpFunc: "opNot", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "NOT", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawTrue}", + "{rawTrue, rawFalse}", + }, + }, + }, + { + Name: "Errors Invalid Data Type", + Error: "errors.ErrorCodeInvalidDataType", OpCode: "NOT", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}}", + }, + }, + }, + Output: tmplOp{}, + }, + }, + }, + // -- end of NOT + { + TestName: "OpUnion", OpFunc: "opUnion", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "UNION", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + "{rawFalse, rawFalse}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawFalse}", + "{rawFalse, rawTrue}", + "{rawTrue, rawFalse}", + "{rawTrue, rawTrue}", + }, + }, + }, + }, + }, + // -- end of UNION + { + TestName: "OpIntxn", OpFunc: "opIntxn", + Cases: []tmplTestCase{ + { + Name: "None Immediate", + Error: "nil", OpCode: "INTXN", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + "{rawTrue, rawTrue}", + "{rawFalse, rawFalse}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", + "{rawFalse, rawFalse}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawFalse, rawFalse}", + "{rawTrue, rawTrue}", + }, + }, + }, + }, + }, + // -- end of INTXN + { + TestName: "OpLike", OpFunc: "opLike", + Cases: []tmplTestCase{ + { + Name: `Like %\\%b% escape \\`, // \\ is raw string escape for \ + Error: "nil", OpCode: "LIKE", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("a%bcdefg")}, &Raw{Bytes: []byte("gfedcba")}}`, + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{`{&Raw{Bytes: []byte("%\\%b%")}}`}, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{`{&Raw{Bytes: []byte("\\")}}`}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + }, + }, + }, + { + Name: `Like t1 escape t2`, + Error: "nil", OpCode: "LIKE", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("a%bcdefg")}}`, + `{&Raw{Bytes: []byte("gfedcba")}}`, + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("%\\%b%")}}`, + `{&Raw{Bytes: []byte("_fed%")}}`, + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("\\")}}`, + `{&Raw{Bytes: []byte("")}}`, + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue}", + "{rawTrue}", + }, + }, + }, + { + Name: `Like with valid and invalid UTF8`, + Error: "nil", OpCode: "LIKE", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte{226, 40, 161, 228, 189, 160, 229, 165, 189}}, &Raw{Bytes: []byte("gfedcba")}}`, + // "\xe2(\xa1你好" + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte{37, 228, 189, 160, 37}}}`, + // "%你%" + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + }, + }, + }, + }, + }, + // -- end of LIKE + { + TestName: "OpZip", OpFunc: "opZip", + Cases: []tmplTestCase{ + { + Name: "Zip two array", + Error: "nil", OpCode: "ZIP", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}}`, + `{&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}}`, + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, rawTrue}", + "{&Raw{Value: decimal.NewFromFloat(2)}, rawFalse}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}`, + `{&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}`, + }, + }, + }, + { + Name: "Zip immediate", + Error: "nil", OpCode: "ZIP", + Inputs: []tmplOp{ + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}}`, + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, rawTrue}", + "{&Raw{Value: decimal.NewFromFloat(2)}, rawFalse}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}`, + `{&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}`, + }, + }, + }, + }, + }, + // -- end of ZIP + { + TestName: "OpField", OpFunc: "opField", + Cases: []tmplTestCase{ + { + Name: "Retrieve 2nd,3rd column", + Error: "nil", OpCode: "FIELD", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}`, + `{&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}`, + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(2)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}}`, + `{&Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}}`, + }, + }, + }, + }, + }, + // -- end of FIELD + { + TestName: "OpPrune", OpFunc: "opPrune", + Cases: []tmplTestCase{ + { + Name: "Prune 2nd,4th,5th column", + Error: "nil", OpCode: "PRUNE", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Bytes: []byte("gfedcba-1")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse, rawTrue}`, + `{&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Bytes: []byte("gfedcba-2")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue, rawFalse}`, + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(1)}, &Raw{Value: decimal.NewFromFloat(3)}, &Raw{Value: decimal.NewFromFloat(4)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("abcdefg-1")}, &Raw{Value: decimal.NewFromFloat(1)}}`, + `{&Raw{Bytes: []byte("abcdefg-2")}, &Raw{Value: decimal.NewFromFloat(2)}}`, + }, + }, + }, + }, + }, + // -- end of PRUNE + { + TestName: "OpFilter", OpFunc: "opFilter", + Cases: []tmplTestCase{ + { + Name: "Filter first 2 rows", + Error: "nil", OpCode: "FILTER", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + "{rawTrue, rawTrue}", + "{rawFalse, rawFalse}", + }, + }, + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue}", + "{rawTrue}", + "{rawFalse}", + "{rawFalse}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + "{rawFalse, rawTrue}", + }, + }, + }, + }, + }, + // -- end of FILTER + { + TestName: "OpCast", OpFunc: "opCast", + Cases: []tmplTestCase{ + { + Name: "None Immediate - int", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 1}, // int16 -> int8 + {Major: ast.DataTypeMajorInt, Minor: 1}, // int16 -> int24 + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(127)}, &Raw{Value: decimal.NewFromFloat(127)}}", + "{&Raw{Value: decimal.NewFromFloat(-128)}, &Raw{Value: decimal.NewFromFloat(-128)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 2}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 2}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(127)}, &Raw{Value: decimal.NewFromFloat(127)}}", + "{&Raw{Value: decimal.NewFromFloat(-128)}, &Raw{Value: decimal.NewFromFloat(-128)}}", + }, + }, + }, + { + Name: "None Immediate - int2", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 1}, // int16 -> uint16 + {Major: ast.DataTypeMajorInt, Minor: 1}, // int16 -> uint16 + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(-32768)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 1}, + {Major: ast.DataTypeMajorUint, Minor: 1}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 1}, + {Major: ast.DataTypeMajorUint, Minor: 1}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(32768)}}", + }, + }, + }, + { + Name: "None Immediate - int3", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 1}, // int16 -> bool + {Major: ast.DataTypeMajorInt, Minor: 1}, // int16 -> bool + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(-32768)}}", + "{&Raw{Value: decimal.NewFromFloat(0)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawTrue}", "{rawFalse, rawFalse}", + }, + }, + }, + { + Name: "None Immediate - int4", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 1}, // int16 -> bytes16 + {Major: ast.DataTypeMajorInt, Minor: 1}, // int16 -> address + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(-32768)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, + {Major: ast.DataTypeMajorAddress, Minor: 0}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, + {Major: ast.DataTypeMajorAddress, Minor: 0}, + }, + Data: []string{ + "{&Raw{Bytes: []byte{0x7f, 0xff}}, &Raw{Bytes: []byte{255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0x80,0x00}}}", + }, + }, + }, + { + Name: "None Immediate - uint", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> uint8 + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> uint24 + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(128)}, &Raw{Value: decimal.NewFromFloat(128)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 0}, + {Major: ast.DataTypeMajorUint, Minor: 2}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 0}, + {Major: ast.DataTypeMajorUint, Minor: 2}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(128)}, &Raw{Value: decimal.NewFromFloat(128)}}", + }, + }, + }, + { + Name: "None Immediate - uint2", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> int16 + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> byte16 + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(32768)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 1}, + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 1}, + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Bytes: []byte{0x80,0x00}}}", + }, + }, + }, + { + Name: "None Immediate - uint3", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> bool + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> bool + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue, rawFalse}", + }, + }, + }, + { + Name: "None Immediate - uint4", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> bytes + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> bytes + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, + }, + Data: []string{ + "{&Raw{Bytes: []byte{0x7f, 0xff}}, &Raw{Bytes: []byte{0x00, 0x00}}}", + }, + }, + }, + { + Name: "None Immediate - uint5", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorUint, Minor: 1}, // uint16 -> address + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorAddress, Minor: 1}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorAddress, Minor: 1}, + }, + Data: []string{ + "{&Raw{Bytes: []byte{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x7f,0xff}}}", + }, + }, + }, + { + Name: "None Immediate - bytes", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, // byte16 -> byte8 + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, // byte16 -> byte24 + }, + Data: []string{ + "{&Raw{Bytes: []byte{0xff, 0xff}}, &Raw{Bytes: []byte{0xff, 0xff}}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 0}, + {Major: ast.DataTypeMajorFixedBytes, Minor: 2}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 0}, + {Major: ast.DataTypeMajorFixedBytes, Minor: 2}, + }, + Data: []string{ + "{&Raw{Bytes: []byte{0xff}}, &Raw{Bytes: []byte{0xff, 0xff, 0x00}}}", + }, + }, + }, + { + Name: "None Immediate - bytes2", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, // byte16 -> int16 + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, // byte16 -> uint16 + }, + Data: []string{ + "{&Raw{Bytes: []byte{0x7f, 0xff}}, &Raw{Bytes: []byte{0x80, 0x00}}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 1}, + {Major: ast.DataTypeMajorUint, Minor: 1}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 1}, + {Major: ast.DataTypeMajorUint, Minor: 1}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(32767)}, &Raw{Value: decimal.NewFromFloat(32768)}}", + }, + }, + }, + { + Name: "None Immediate - bytes3", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorFixedBytes, Minor: 1}, // byte16 -> dyn + }, + Data: []string{ + "{&Raw{Bytes: []byte{0x7f, 0xff}}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 1}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 1}, + }, + Data: []string{ + "{&Raw{Bytes: []byte{0x7f, 0xff}}}", + }, + }, + }, + { + Name: "Same type", + Error: "nil", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + "{rawTrue}", + }, + }, + }, + { + Name: "Error Invalid Type", + Error: "errors.ErrorCodeInvalidCastType", OpCode: "CAST", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorInt, Minor: 2}, + }, + Data: []string{ + "{&Raw{Value: decimal.NewFromFloat(-32768)}}", + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + }, + Data: []string{}, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{}, + Data: []string{}, + }, + }, + }, + }, + // -- end of CAST + { + TestName: "OpSort", OpFunc: "opSort", + Cases: []tmplTestCase{ + { + Name: "Multi-column sorting", + Error: "nil", OpCode: "SORT", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawTrue}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}`, + `{&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{rawFalse, &Raw{Value: decimal.NewFromFloat(1)}}", + "{rawTrue, &Raw{Value: decimal.NewFromFloat(2)}}", + "{rawFalse, &Raw{Value: decimal.NewFromFloat(0)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawTrue}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse}`, + `{&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}`, + }, + }, + }, + { + Name: "Multi-column sorting - 2", + Error: "nil", OpCode: "SORT", + Inputs: []tmplOp{ + { + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawTrue}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}`, + `{&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + }, + }, + { + Im: true, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorBool, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + }, + Data: []string{ + "{rawTrue, &Raw{Value: decimal.NewFromFloat(0)}}", + "{rawTrue, &Raw{Value: decimal.NewFromFloat(1)}}", + "{rawFalse, &Raw{Value: decimal.NewFromFloat(2)}}", + }, + }, + }, + Output: tmplOp{ + Im: false, + Metas: []tmplOpMeta{ + {Major: ast.DataTypeMajorDynamicBytes, Minor: 0}, + {Major: ast.DataTypeMajorInt, Minor: 0}, + {Major: ast.DataTypeMajorBool, Minor: 0}, + }, + Data: []string{ + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(1)}, rawFalse}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawTrue}`, + `{&Raw{Bytes: []byte("a")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawTrue}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(2)}, rawFalse}`, + `{&Raw{Bytes: []byte("b")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + `{&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(1)}, rawTrue}`, + `{&Raw{Bytes: []byte("c")}, &Raw{Value: decimal.NewFromFloat(3)}, rawFalse}`, + }, + }, + }, + }, + }, + // -- end of SORT + }, +} diff --git a/core/vm/sqlvm/runtime/runtime.go b/core/vm/sqlvm/runtime/runtime.go index e6a3a0006..5cae111c9 100644 --- a/core/vm/sqlvm/runtime/runtime.go +++ b/core/vm/sqlvm/runtime/runtime.go @@ -29,11 +29,3 @@ func Run(stateDB vm.StateDB, ins []Instruction, registers []*Operand) (ret []byt // TODO: ret = ABIEncode(ins[len(ins)-1].Output) return } - -func loadRegister(input, registers []*Operand) { - for i, operand := range input { - if operand != nil && !operand.IsImmediate { - input[i] = registers[operand.RegisterIndex] - } - } -} |