github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/vm/ops_test.go (about)

     1  package vm
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/bytom/bytom/errors"
     9  	"github.com/bytom/bytom/math/checked"
    10  	"github.com/bytom/bytom/testutil"
    11  )
    12  
    13  func TestParseOp(t *testing.T) {
    14  	cases := []struct {
    15  		prog    []byte
    16  		pc      uint32
    17  		want    Instruction
    18  		wantErr error
    19  	}{{
    20  		prog: []byte{byte(OP_ADD)},
    21  		want: Instruction{Op: OP_ADD, Len: 1},
    22  	}, {
    23  		prog: []byte{byte(OP_16)},
    24  		want: Instruction{Op: OP_16, Data: []byte{16}, Len: 1},
    25  	}, {
    26  		prog: []byte{byte(OP_DATA_5), 1, 1, 1, 1, 1},
    27  		want: Instruction{Op: OP_DATA_5, Data: []byte{1, 1, 1, 1, 1}, Len: 6},
    28  	}, {
    29  		prog: []byte{byte(OP_DATA_5), 1, 1, 1, 1, 1, 255},
    30  		want: Instruction{Op: OP_DATA_5, Data: []byte{1, 1, 1, 1, 1}, Len: 6},
    31  	}, {
    32  		prog: []byte{byte(OP_PUSHDATA1), 1, 1},
    33  		want: Instruction{Op: OP_PUSHDATA1, Data: []byte{1}, Len: 3},
    34  	}, {
    35  		prog: []byte{byte(OP_PUSHDATA1), 1, 1, 255},
    36  		want: Instruction{Op: OP_PUSHDATA1, Data: []byte{1}, Len: 3},
    37  	}, {
    38  		prog: []byte{byte(OP_PUSHDATA2), 1, 0, 1},
    39  		want: Instruction{Op: OP_PUSHDATA2, Data: []byte{1}, Len: 4},
    40  	}, {
    41  		prog: []byte{byte(OP_PUSHDATA2), 1, 0, 1, 255},
    42  		want: Instruction{Op: OP_PUSHDATA2, Data: []byte{1}, Len: 4},
    43  	}, {
    44  		prog: []byte{byte(OP_PUSHDATA4), 1, 0, 0, 0, 1},
    45  		want: Instruction{Op: OP_PUSHDATA4, Data: []byte{1}, Len: 6},
    46  	}, {
    47  		prog: []byte{byte(OP_PUSHDATA4), 1, 0, 0, 0, 1, 255},
    48  		want: Instruction{Op: OP_PUSHDATA4, Data: []byte{1}, Len: 6},
    49  	}, {
    50  		prog:    []byte{},
    51  		wantErr: ErrShortProgram,
    52  	}, {
    53  		prog:    []byte{byte(OP_0)},
    54  		pc:      1,
    55  		wantErr: ErrShortProgram,
    56  	}, {
    57  		prog:    []byte{byte(OP_DATA_1)},
    58  		wantErr: ErrShortProgram,
    59  	}, {
    60  		prog:    []byte{byte(OP_PUSHDATA1)},
    61  		wantErr: ErrShortProgram,
    62  	}, {
    63  		prog:    []byte{byte(OP_PUSHDATA1), 1},
    64  		wantErr: ErrShortProgram,
    65  	}, {
    66  		prog:    []byte{byte(OP_PUSHDATA2)},
    67  		wantErr: ErrShortProgram,
    68  	}, {
    69  		prog:    []byte{byte(OP_PUSHDATA2), 1, 0},
    70  		wantErr: ErrShortProgram,
    71  	}, {
    72  		prog:    []byte{byte(OP_PUSHDATA4)},
    73  		wantErr: ErrShortProgram,
    74  	}, {
    75  		prog:    []byte{byte(OP_PUSHDATA4), 1, 0, 0, 0},
    76  		wantErr: ErrShortProgram,
    77  	}, {
    78  		pc:      71,
    79  		prog:    []byte{0x6d, 0x6b, 0xaa, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0, 0x0, 0x4e, 0xff, 0xff, 0xff, 0xff, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30},
    80  		wantErr: checked.ErrOverflow,
    81  	}}
    82  
    83  	for _, c := range cases {
    84  		t.Run(fmt.Sprintf("%d: %x", c.pc, c.prog), func(t *testing.T) {
    85  			got, gotErr := ParseOp(c.prog, c.pc)
    86  
    87  			if errors.Root(gotErr) != c.wantErr {
    88  				t.Errorf("ParseOp(%x, %d) error = %v want %v", c.prog, c.pc, gotErr, c.wantErr)
    89  			}
    90  
    91  			if c.wantErr != nil {
    92  				return
    93  			}
    94  
    95  			if !testutil.DeepEqual(got, c.want) {
    96  				t.Errorf("ParseOp(%x, %d) = %+v want %+v", c.prog, c.pc, got, c.want)
    97  			}
    98  		})
    99  	}
   100  }
   101  
   102  func TestParseProgram(t *testing.T) {
   103  	cases := []struct {
   104  		prog    []byte
   105  		want    []Instruction
   106  		wantErr error
   107  	}{
   108  		{
   109  			prog: []byte{byte(OP_2), byte(OP_3), byte(OP_ADD), byte(OP_5), byte(OP_NUMEQUAL)},
   110  			want: []Instruction{
   111  				{Op: OP_2, Data: []byte{0x02}, Len: 1},
   112  				{Op: OP_3, Data: []byte{0x03}, Len: 1},
   113  				{Op: OP_ADD, Len: 1},
   114  				{Op: OP_5, Data: []byte{0x05}, Len: 1},
   115  				{Op: OP_NUMEQUAL, Len: 1},
   116  			},
   117  		},
   118  		{
   119  			prog: []byte{255},
   120  			want: []Instruction{
   121  				{Op: 255, Len: 1},
   122  			},
   123  		},
   124  	}
   125  
   126  	for _, c := range cases {
   127  		got, gotErr := ParseProgram(c.prog)
   128  
   129  		if errors.Root(gotErr) != c.wantErr {
   130  			t.Errorf("ParseProgram(%x) error = %v want %v", c.prog, gotErr, c.wantErr)
   131  		}
   132  
   133  		if c.wantErr != nil {
   134  			continue
   135  		}
   136  
   137  		if !testutil.DeepEqual(got, c.want) {
   138  			t.Errorf("ParseProgram(%x) = %+v want %+v", c.prog, got, c.want)
   139  		}
   140  	}
   141  }
   142  
   143  func TestIsPushData(t *testing.T) {
   144  	cases := []struct {
   145  		want    Instruction
   146  		wantErr error
   147  	}{
   148  		{
   149  			want: Instruction{Op: OP_16, Data: []byte{16}, Len: 1},
   150  		},
   151  		{
   152  			want: Instruction{Op: OP_DATA_32, Data: []byte{16}, Len: 1},
   153  		},
   154  		{
   155  			want: Instruction{Op: OP_FALSE, Data: []byte{}, Len: 1},
   156  		},
   157  		{
   158  			want: Instruction{Op: OP_TRUE, Data: []byte{1}, Len: 1},
   159  		},
   160  		{
   161  			want:    Instruction{Op: OP_JUMP, Data: []byte{0x00000000}, Len: 1},
   162  			wantErr: ErrShortProgram,
   163  		},
   164  		{
   165  			want:    Instruction{Op: OP_ADD, Data: []byte{0x12, 0x56}, Len: 2},
   166  			wantErr: ErrShortProgram,
   167  		},
   168  	}
   169  
   170  	for _, c := range cases {
   171  		if c.want.IsPushdata() {
   172  			t.Logf("check success")
   173  		} else if c.wantErr != nil {
   174  			t.Logf("check err success")
   175  		} else {
   176  			t.Errorf("check false: %v -- %v", reflect.ValueOf(ops[OP_1].fn), reflect.ValueOf(ops[c.want.Op].fn))
   177  		}
   178  	}
   179  }