--- /dev/null
+package vm
+
+import (
+ "testing"
+
+ "github.com/bytom/testutil"
+)
+
+func TestSpliceOps(t *testing.T) {
+ type testStruct struct {
+ op Op
+ startVM *virtualMachine
+ wantErr error
+ wantVM *virtualMachine
+ }
+ cases := []testStruct{{
+ op: OP_CAT,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("hello"), []byte("world")},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49986,
+ deferredCost: -18,
+ dataStack: [][]byte{[]byte("helloworld")},
+ },
+ }, {
+ op: OP_CAT,
+ startVM: &virtualMachine{
+ runLimit: 4,
+ dataStack: [][]byte{[]byte("hello"), []byte("world")},
+ },
+ wantErr: ErrRunLimitExceeded,
+ }, {
+ op: OP_SUBSTR,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), {3}, {5}},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49991,
+ deferredCost: -28,
+ dataStack: [][]byte{[]byte("lowor")},
+ },
+ }, {
+ op: OP_SUBSTR,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), {3}, Int64Bytes(-1)},
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_SUBSTR,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), Int64Bytes(-1), {5}},
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_SUBSTR,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), {6}, {5}},
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_SUBSTR,
+ startVM: &virtualMachine{
+ runLimit: 4,
+ dataStack: [][]byte{[]byte("helloworld"), {3}, {5}},
+ },
+ wantErr: ErrRunLimitExceeded,
+ }, {
+ op: OP_LEFT,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), {5}},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49991,
+ deferredCost: -19,
+ dataStack: [][]byte{[]byte("hello")},
+ },
+ }, {
+ op: OP_LEFT,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), Int64Bytes(-1)},
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_LEFT,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), {11}},
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_LEFT,
+ startVM: &virtualMachine{
+ runLimit: 4,
+ dataStack: [][]byte{[]byte("helloworld"), {5}},
+ },
+ wantErr: ErrRunLimitExceeded,
+ }, {
+ op: OP_RIGHT,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), {5}},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49991,
+ deferredCost: -19,
+ dataStack: [][]byte{[]byte("world")},
+ },
+ }, {
+ op: OP_RIGHT,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), Int64Bytes(-1)},
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_RIGHT,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld"), {11}},
+ },
+ wantErr: ErrBadValue,
+ }, {
+ op: OP_RIGHT,
+ startVM: &virtualMachine{
+ runLimit: 4,
+ dataStack: [][]byte{[]byte("helloworld"), {5}},
+ },
+ wantErr: ErrRunLimitExceeded,
+ }, {
+ op: OP_SIZE,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{[]byte("helloworld")},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49999,
+ deferredCost: 9,
+ dataStack: [][]byte{[]byte("helloworld"), {10}},
+ },
+ }, {
+ op: OP_CATPUSHDATA,
+ startVM: &virtualMachine{
+ runLimit: 50000,
+ dataStack: [][]byte{{0xff}, {0xab, 0xcd}},
+ },
+ wantVM: &virtualMachine{
+ runLimit: 49993,
+ deferredCost: -10,
+ dataStack: [][]byte{{0xff, 0x02, 0xab, 0xcd}},
+ },
+ }, {
+ op: OP_CATPUSHDATA,
+ startVM: &virtualMachine{
+ runLimit: 4,
+ dataStack: [][]byte{{0xff}, {0xab, 0xcd}},
+ },
+ wantErr: ErrRunLimitExceeded,
+ }}
+
+ spliceops := []Op{OP_CAT, OP_SUBSTR, OP_LEFT, OP_RIGHT, OP_CATPUSHDATA, OP_SIZE}
+ for _, op := range spliceops {
+ cases = append(cases, testStruct{
+ op: op,
+ startVM: &virtualMachine{runLimit: 0},
+ 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)
+ }
+ }
+}