github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/protocol/vm/control_test.go (about)

     1  package vm
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/bytom/bytom/testutil"
     7  )
     8  
     9  func TestControlOps(t *testing.T) {
    10  	type testStruct struct {
    11  		op      Op
    12  		startVM *virtualMachine
    13  		wantErr error
    14  		wantVM  *virtualMachine
    15  	}
    16  	cases := []testStruct{{
    17  		op: OP_JUMP,
    18  		startVM: &virtualMachine{
    19  			runLimit: 50000,
    20  			pc:       0,
    21  			nextPC:   1,
    22  			data:     []byte{0x05, 0x00, 0x00, 0x00},
    23  		},
    24  		wantErr: nil,
    25  		wantVM: &virtualMachine{
    26  			runLimit: 49999,
    27  			pc:       0,
    28  			nextPC:   5,
    29  			data:     []byte{0x05, 0x00, 0x00, 0x00},
    30  		},
    31  	}, {
    32  		op: OP_JUMP,
    33  		startVM: &virtualMachine{
    34  			runLimit: 50000,
    35  			pc:       0,
    36  			nextPC:   1,
    37  			data:     []byte{0xff, 0xff, 0xff, 0xff},
    38  		},
    39  		wantErr: nil,
    40  		wantVM: &virtualMachine{
    41  			runLimit: 49999,
    42  			pc:       0,
    43  			nextPC:   4294967295,
    44  			data:     []byte{0xff, 0xff, 0xff, 0xff},
    45  		},
    46  	}, {
    47  		op: OP_JUMPIF,
    48  		startVM: &virtualMachine{
    49  			runLimit:     50000,
    50  			pc:           0,
    51  			nextPC:       1,
    52  			deferredCost: 0,
    53  			dataStack:    [][]byte{{1}},
    54  			data:         []byte{0x05, 0x00, 0x00, 0x00},
    55  		},
    56  		wantErr: nil,
    57  		wantVM: &virtualMachine{
    58  			runLimit:     49999,
    59  			pc:           0,
    60  			nextPC:       5,
    61  			deferredCost: -9,
    62  			dataStack:    [][]byte{},
    63  			data:         []byte{0x05, 0x00, 0x00, 0x00},
    64  		},
    65  	}, {
    66  		op: OP_JUMPIF,
    67  		startVM: &virtualMachine{
    68  			runLimit:     50000,
    69  			pc:           0,
    70  			nextPC:       1,
    71  			deferredCost: 0,
    72  			dataStack:    [][]byte{{}},
    73  			data:         []byte{0x05, 0x00, 0x00, 0x00},
    74  		},
    75  		wantErr: nil,
    76  		wantVM: &virtualMachine{
    77  			runLimit:     49999,
    78  			pc:           0,
    79  			nextPC:       1,
    80  			deferredCost: -8,
    81  			dataStack:    [][]byte{},
    82  			data:         []byte{0x05, 0x00, 0x00, 0x00},
    83  		},
    84  	}, {
    85  		op: OP_VERIFY,
    86  		startVM: &virtualMachine{
    87  			pc:           0,
    88  			runLimit:     50000,
    89  			deferredCost: 0,
    90  			dataStack:    [][]byte{{1}},
    91  		},
    92  		wantErr: nil,
    93  		wantVM: &virtualMachine{
    94  			runLimit:     49999,
    95  			deferredCost: -9,
    96  			dataStack:    [][]byte{},
    97  		},
    98  	}, {
    99  		op: OP_VERIFY,
   100  		startVM: &virtualMachine{
   101  			runLimit:     50000,
   102  			deferredCost: 0,
   103  			dataStack:    [][]byte{{1, 1}},
   104  		},
   105  		wantErr: nil,
   106  		wantVM: &virtualMachine{
   107  			runLimit:     49999,
   108  			deferredCost: -10,
   109  			dataStack:    [][]byte{},
   110  		},
   111  	}, {
   112  		op: OP_VERIFY,
   113  		startVM: &virtualMachine{
   114  			runLimit:     50000,
   115  			deferredCost: 0,
   116  			dataStack:    [][]byte{{}},
   117  		},
   118  		wantErr: ErrVerifyFailed,
   119  	}, {
   120  		startVM: &virtualMachine{runLimit: 50000},
   121  		op:      OP_FAIL,
   122  		wantErr: ErrReturn,
   123  	}, {
   124  		op: OP_CHECKPREDICATE,
   125  		startVM: &virtualMachine{
   126  			runLimit:  50000,
   127  			dataStack: [][]byte{{}, {byte(OP_TRUE)}, {}},
   128  		},
   129  		wantVM: &virtualMachine{
   130  			runLimit:     0,
   131  			deferredCost: -49951,
   132  			dataStack:    [][]byte{{1}},
   133  		},
   134  	}, {
   135  		op: OP_CHECKPREDICATE,
   136  		startVM: &virtualMachine{
   137  			runLimit:  50000,
   138  			dataStack: [][]byte{{}, {}, {}},
   139  		},
   140  		wantVM: &virtualMachine{
   141  			runLimit:     0,
   142  			deferredCost: -49952,
   143  			dataStack:    [][]byte{{}},
   144  		},
   145  	}, {
   146  		op: OP_CHECKPREDICATE,
   147  		startVM: &virtualMachine{
   148  			runLimit:  50000,
   149  			dataStack: [][]byte{{}, {byte(OP_FAIL)}, {}},
   150  		},
   151  		wantVM: &virtualMachine{
   152  			runLimit:     0,
   153  			deferredCost: -49952,
   154  			dataStack:    [][]byte{{}},
   155  		},
   156  	}, {
   157  		op: OP_CHECKPREDICATE,
   158  		startVM: &virtualMachine{
   159  			runLimit:  50000,
   160  			dataStack: [][]byte{{}, {}, Int64Bytes(-1)},
   161  		},
   162  		wantErr: ErrBadValue,
   163  	}, {
   164  		op: OP_CHECKPREDICATE,
   165  		startVM: &virtualMachine{
   166  			runLimit:  50000,
   167  			dataStack: [][]byte{{}, {}, Int64Bytes(50000)},
   168  		},
   169  		wantErr: ErrRunLimitExceeded,
   170  	}, {
   171  		op: OP_CHECKPREDICATE,
   172  		startVM: &virtualMachine{
   173  			runLimit:  50000,
   174  			dataStack: [][]byte{{0x05}, {0x07}, {0x02}, {byte(OP_ADD), byte(OP_12), byte(OP_NUMEQUAL)}, {}},
   175  		},
   176  		wantVM: &virtualMachine{
   177  			deferredCost: -49968,
   178  			dataStack:    [][]byte{{0x01}},
   179  		},
   180  	}, {
   181  		// stack underflow in child vm should produce false result in parent vm
   182  		op: OP_CHECKPREDICATE,
   183  		startVM: &virtualMachine{
   184  			runLimit:  50000,
   185  			dataStack: [][]byte{{0x05}, {0x07}, {0x01}, {byte(OP_ADD), byte(OP_DATA_12), byte(OP_NUMEQUAL)}, {}},
   186  		},
   187  		wantVM: &virtualMachine{
   188  			deferredCost: -49954,
   189  			dataStack:    [][]byte{{0x05}, {}},
   190  		},
   191  	}}
   192  
   193  	limitChecks := []Op{
   194  		OP_CHECKPREDICATE, OP_VERIFY, OP_FAIL,
   195  	}
   196  
   197  	for _, op := range limitChecks {
   198  		cases = append(cases, testStruct{
   199  			op:      op,
   200  			startVM: &virtualMachine{runLimit: 0},
   201  			wantErr: ErrRunLimitExceeded,
   202  		})
   203  	}
   204  
   205  	for i, c := range cases {
   206  		err := ops[c.op].fn(c.startVM)
   207  
   208  		if err != c.wantErr {
   209  			t.Errorf("case %d, op %s: got err = %v want %v", i, c.op.String(), err, c.wantErr)
   210  			continue
   211  		}
   212  		if c.wantErr != nil {
   213  			continue
   214  		}
   215  
   216  		if !testutil.DeepEqual(c.startVM, c.wantVM) {
   217  			t.Errorf("case %d, op %s: unexpected vm result\n\tgot:  %+v\n\twant: %+v\n", i, c.op.String(), c.startVM, c.wantVM)
   218  		}
   219  	}
   220  }