OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / bytom / protocol / vm / numeric_test.go
diff --git a/vendor/github.com/bytom/protocol/vm/numeric_test.go b/vendor/github.com/bytom/protocol/vm/numeric_test.go
new file mode 100644 (file)
index 0000000..0c7ac48
--- /dev/null
@@ -0,0 +1,565 @@
+package vm
+
+import (
+       "fmt"
+       "math"
+       "testing"
+
+       "github.com/bytom/testutil"
+)
+
+func TestNumericOps(t *testing.T) {
+       type testStruct struct {
+               op      Op
+               startVM *virtualMachine
+               wantErr error
+               wantVM  *virtualMachine
+       }
+       cases := []testStruct{{
+               op: OP_1ADD,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:  49998,
+                       dataStack: [][]byte{{3}},
+               },
+       }, {
+               op: OP_1SUB,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:  49998,
+                       dataStack: [][]byte{{1}},
+               },
+       }, {
+               op: OP_2MUL,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:  49998,
+                       dataStack: [][]byte{{4}},
+               },
+       }, {
+               op: OP_2DIV,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:  49998,
+                       dataStack: [][]byte{{1}},
+               },
+       }, {
+               op: OP_2DIV,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-2)},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:  49998,
+                       dataStack: [][]byte{Int64Bytes(-1)},
+               },
+       }, {
+               op: OP_2DIV,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-1)},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:  49998,
+                       dataStack: [][]byte{Int64Bytes(-1)},
+               },
+       }, {
+               op: OP_NEGATE,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: 7,
+                       dataStack:    [][]byte{Int64Bytes(-2)},
+               },
+       }, {
+               op: OP_ABS,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:  49998,
+                       dataStack: [][]byte{{2}},
+               },
+       }, {
+               op: OP_ABS,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-2)},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -7,
+                       dataStack:    [][]byte{{2}},
+               },
+       }, {
+               op: OP_NOT,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -1,
+                       dataStack:    [][]byte{{}},
+               },
+       }, {
+               op: OP_0NOTEQUAL,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:  49998,
+                       dataStack: [][]byte{{1}},
+               },
+       }, {
+               op: OP_ADD,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{3}},
+               },
+       }, {
+               op: OP_SUB,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_MUL,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{2}},
+               },
+       }, {
+               op: OP_DIV,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{2}},
+               },
+       }, {
+               op: OP_DIV,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-2), {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{Int64Bytes(-2)},
+               },
+       }, {
+               op: OP_DIV,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-2), Int64Bytes(-1)},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -23,
+                       dataStack:    [][]byte{{2}},
+               },
+       }, {
+               op: OP_DIV,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-3), Int64Bytes(2)},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{Int64Bytes(-1)},
+               },
+       }, {
+               op: OP_DIV,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {}},
+               },
+               wantErr: ErrDivZero,
+       }, {
+               op: OP_MOD,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -10,
+                       dataStack:    [][]byte{{}},
+               },
+       }, {
+               op: OP_MOD,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-12), {10}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -16,
+                       dataStack:    [][]byte{{8}},
+               },
+       }, {
+               op: OP_MOD,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {0}},
+               },
+               wantErr: ErrDivZero,
+       }, {
+               op: OP_LSHIFT,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{4}},
+               },
+       }, {
+               op: OP_LSHIFT,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-2), {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{Int64Bytes(-4)},
+               },
+       }, {
+               op: OP_RSHIFT,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_RSHIFT,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{Int64Bytes(-2), {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49992,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{Int64Bytes(-1)},
+               },
+       }, {
+               op: OP_BOOLAND,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_BOOLOR,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_NUMEQUAL,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -10,
+                       dataStack:    [][]byte{{}},
+               },
+       }, {
+               op: OP_NUMEQUALVERIFY,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -18,
+                       dataStack:    [][]byte{},
+               },
+       }, {
+               op: OP_NUMEQUALVERIFY,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{1}, {2}},
+               },
+               wantErr: ErrVerifyFailed,
+       }, {
+               op: OP_NUMNOTEQUAL,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_LESSTHAN,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -10,
+                       dataStack:    [][]byte{{}},
+               },
+       }, {
+               op: OP_LESSTHANOREQUAL,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -10,
+                       dataStack:    [][]byte{{}},
+               },
+       }, {
+               op: OP_GREATERTHAN,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_GREATERTHANOREQUAL,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_MIN,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_MIN,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{1}, {2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{1}},
+               },
+       }, {
+               op: OP_MAX,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{2}, {1}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{2}},
+               },
+       }, {
+               op: OP_MAX,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{1}, {2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49998,
+                       deferredCost: -9,
+                       dataStack:    [][]byte{{2}},
+               },
+       }, {
+               op: OP_WITHIN,
+               startVM: &virtualMachine{
+                       runLimit:  50000,
+                       dataStack: [][]byte{{1}, {1}, {2}},
+               },
+               wantVM: &virtualMachine{
+                       runLimit:     49996,
+                       deferredCost: -18,
+                       dataStack:    [][]byte{{1}},
+               },
+       }}
+
+       numops := []Op{
+               OP_1ADD, OP_1SUB, OP_2MUL, OP_2DIV, OP_NEGATE, OP_ABS, OP_NOT, OP_0NOTEQUAL,
+               OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_LSHIFT, OP_RSHIFT, OP_BOOLAND,
+               OP_BOOLOR, OP_NUMEQUAL, OP_NUMEQUALVERIFY, OP_NUMNOTEQUAL, OP_LESSTHAN,
+               OP_LESSTHANOREQUAL, OP_GREATERTHAN, OP_GREATERTHANOREQUAL, OP_MIN, OP_MAX, OP_WITHIN,
+       }
+
+       for _, op := range numops {
+               cases = append(cases, testStruct{
+                       op: op,
+                       startVM: &virtualMachine{
+                               runLimit:  0,
+                               dataStack: [][]byte{{2}, {2}, {2}},
+                       },
+                       wantErr: ErrRunLimitExceeded,
+               })
+       }
+
+       for i, c := range cases {
+               err := ops[c.op].fn(c.startVM)
+
+               if err != c.wantErr {
+                       t.Errorf("case %d, op %s: got err = %v want %v", i, ops[c.op].name, err, c.wantErr)
+                       continue
+               }
+               if c.wantErr != nil {
+                       continue
+               }
+
+               if !testutil.DeepEqual(c.startVM, c.wantVM) {
+                       t.Errorf("case %d, op %s: unexpected vm result\n\tgot:  %+v\n\twant: %+v\n", i, ops[c.op].name, c.startVM, c.wantVM)
+               }
+       }
+}
+
+func TestRangeErrs(t *testing.T) {
+       cases := []struct {
+               prog           string
+               expectRangeErr bool
+       }{
+               {"0 1ADD", false},
+               {fmt.Sprintf("%d 1ADD", int64(math.MinInt64)), false},
+               {fmt.Sprintf("%d 1ADD", int64(math.MaxInt64)-1), false},
+               {fmt.Sprintf("%d 1ADD", int64(math.MaxInt64)), true},
+               {"0 1SUB", false},
+               {fmt.Sprintf("%d 1SUB", int64(math.MaxInt64)), false},
+               {fmt.Sprintf("%d 1SUB", int64(math.MinInt64)+1), false},
+               {fmt.Sprintf("%d 1SUB", int64(math.MinInt64)), true},
+               {"1 2MUL", false},
+               {fmt.Sprintf("%d 2MUL", int64(math.MaxInt64)/2-1), false},
+               {fmt.Sprintf("%d 2MUL", int64(math.MaxInt64)/2+1), true},
+               {fmt.Sprintf("%d 2MUL", int64(math.MinInt64)/2+1), false},
+               {fmt.Sprintf("%d 2MUL", int64(math.MinInt64)/2-1), true},
+               {"1 NEGATE", false},
+               {"-1 NEGATE", false},
+               {fmt.Sprintf("%d NEGATE", int64(math.MaxInt64)), false},
+               {fmt.Sprintf("%d NEGATE", int64(math.MinInt64)), true},
+               {"1 ABS", false},
+               {"-1 ABS", false},
+               {fmt.Sprintf("%d ABS", int64(math.MaxInt64)), false},
+               {fmt.Sprintf("%d ABS", int64(math.MinInt64)), true},
+               {"2 3 ADD", false},
+               {fmt.Sprintf("%d %d ADD", int64(math.MinInt64), int64(math.MaxInt64)), false},
+               {fmt.Sprintf("%d %d ADD", int64(math.MaxInt64)/2-1, int64(math.MaxInt64)/2-2), false},
+               {fmt.Sprintf("%d %d ADD", int64(math.MaxInt64)/2+1, int64(math.MaxInt64)/2+2), true},
+               {fmt.Sprintf("%d %d ADD", int64(math.MinInt64)/2+1, int64(math.MinInt64)/2+2), false},
+               {fmt.Sprintf("%d %d ADD", int64(math.MinInt64)/2-1, int64(math.MinInt64)/2-2), true},
+               {"2 3 SUB", false},
+               {fmt.Sprintf("1 %d SUB", int64(math.MaxInt64)), false},
+               {fmt.Sprintf("-1 %d SUB", int64(math.MinInt64)), false},
+               {fmt.Sprintf("1 %d SUB", int64(math.MinInt64)), true},
+               {fmt.Sprintf("-1 %d SUB", int64(math.MaxInt64)), false},
+               {fmt.Sprintf("-2 %d SUB", int64(math.MaxInt64)), true},
+               {"1 2 LSHIFT", false},
+               {"-1 2 LSHIFT", false},
+               {"-1 63 LSHIFT", false},
+               {"-1 64 LSHIFT", true},
+               {"0 64 LSHIFT", false},
+               {"1 62 LSHIFT", false},
+               {"1 63 LSHIFT", true},
+               {fmt.Sprintf("%d 0 LSHIFT", int64(math.MaxInt64)), false},
+               {fmt.Sprintf("%d 1 LSHIFT", int64(math.MaxInt64)), true},
+               {fmt.Sprintf("%d 1 LSHIFT", int64(math.MaxInt64)/2), false},
+               {fmt.Sprintf("%d 2 LSHIFT", int64(math.MaxInt64)/2), true},
+               {fmt.Sprintf("%d 0 LSHIFT", int64(math.MinInt64)), false},
+               {fmt.Sprintf("%d 1 LSHIFT", int64(math.MinInt64)), true},
+               {fmt.Sprintf("%d 1 LSHIFT", int64(math.MinInt64)/2), false},
+               {fmt.Sprintf("%d 2 LSHIFT", int64(math.MinInt64)/2), true},
+       }
+
+       for i, c := range cases {
+               prog, _ := Assemble(c.prog)
+               vm := &virtualMachine{
+                       program:  prog,
+                       runLimit: 50000,
+               }
+               err := vm.run()
+               switch err {
+               case nil:
+                       if c.expectRangeErr {
+                               t.Errorf("case %d (%s): expected range error, got none", i, c.prog)
+                       }
+               case ErrRange:
+                       if !c.expectRangeErr {
+                               t.Errorf("case %d (%s): got unexpected range error", i, c.prog)
+                       }
+               default:
+                       if c.expectRangeErr {
+                               t.Errorf("case %d (%s): expected range error, got %s", i, c.prog, err)
+                       } else {
+                               t.Errorf("case %d (%s): got unexpected error %s", i, c.prog, err)
+                       }
+               }
+       }
+}