8 "github.com/vapor/testutil"
11 func TestNumericOps(t *testing.T) {
12 type testStruct struct {
14 startVM *virtualMachine
16 wantVM *virtualMachine
18 cases := []testStruct{{
20 startVM: &virtualMachine{
22 dataStack: [][]byte{{2}},
24 wantVM: &virtualMachine{
26 dataStack: [][]byte{{3}},
30 startVM: &virtualMachine{
32 dataStack: [][]byte{{2}},
34 wantVM: &virtualMachine{
36 dataStack: [][]byte{{1}},
40 startVM: &virtualMachine{
42 dataStack: [][]byte{{2}},
44 wantVM: &virtualMachine{
46 dataStack: [][]byte{{4}},
50 startVM: &virtualMachine{
52 dataStack: [][]byte{{2}},
54 wantVM: &virtualMachine{
56 dataStack: [][]byte{{1}},
60 startVM: &virtualMachine{
62 dataStack: [][]byte{Int64Bytes(-2)},
64 wantVM: &virtualMachine{
66 dataStack: [][]byte{Int64Bytes(-1)},
70 startVM: &virtualMachine{
72 dataStack: [][]byte{Int64Bytes(-1)},
74 wantVM: &virtualMachine{
76 dataStack: [][]byte{Int64Bytes(-1)},
80 startVM: &virtualMachine{
82 dataStack: [][]byte{{2}},
84 wantVM: &virtualMachine{
87 dataStack: [][]byte{Int64Bytes(-2)},
91 startVM: &virtualMachine{
93 dataStack: [][]byte{{2}},
95 wantVM: &virtualMachine{
97 dataStack: [][]byte{{2}},
101 startVM: &virtualMachine{
103 dataStack: [][]byte{Int64Bytes(-2)},
105 wantVM: &virtualMachine{
108 dataStack: [][]byte{{2}},
112 startVM: &virtualMachine{
114 dataStack: [][]byte{{2}},
116 wantVM: &virtualMachine{
119 dataStack: [][]byte{{}},
123 startVM: &virtualMachine{
125 dataStack: [][]byte{{2}},
127 wantVM: &virtualMachine{
129 dataStack: [][]byte{{1}},
133 startVM: &virtualMachine{
135 dataStack: [][]byte{{2}, {1}},
137 wantVM: &virtualMachine{
140 dataStack: [][]byte{{3}},
144 startVM: &virtualMachine{
146 dataStack: [][]byte{{2}, {1}},
148 wantVM: &virtualMachine{
151 dataStack: [][]byte{{1}},
155 startVM: &virtualMachine{
157 dataStack: [][]byte{{2}, {1}},
159 wantVM: &virtualMachine{
162 dataStack: [][]byte{{2}},
166 startVM: &virtualMachine{
168 dataStack: [][]byte{{2}, {1}},
170 wantVM: &virtualMachine{
173 dataStack: [][]byte{{2}},
177 startVM: &virtualMachine{
179 dataStack: [][]byte{Int64Bytes(-2), {1}},
181 wantVM: &virtualMachine{
184 dataStack: [][]byte{Int64Bytes(-2)},
188 startVM: &virtualMachine{
190 dataStack: [][]byte{Int64Bytes(-2), Int64Bytes(-1)},
192 wantVM: &virtualMachine{
195 dataStack: [][]byte{{2}},
199 startVM: &virtualMachine{
201 dataStack: [][]byte{Int64Bytes(-3), Int64Bytes(2)},
203 wantVM: &virtualMachine{
206 dataStack: [][]byte{Int64Bytes(-1)},
210 startVM: &virtualMachine{
212 dataStack: [][]byte{{2}, {}},
217 startVM: &virtualMachine{
219 dataStack: [][]byte{{2}, {1}},
221 wantVM: &virtualMachine{
224 dataStack: [][]byte{{}},
228 startVM: &virtualMachine{
230 dataStack: [][]byte{Int64Bytes(-12), {10}},
232 wantVM: &virtualMachine{
235 dataStack: [][]byte{{8}},
239 startVM: &virtualMachine{
241 dataStack: [][]byte{{2}, {0}},
246 startVM: &virtualMachine{
248 dataStack: [][]byte{{2}, {1}},
250 wantVM: &virtualMachine{
253 dataStack: [][]byte{{4}},
257 startVM: &virtualMachine{
259 dataStack: [][]byte{Int64Bytes(-2), {1}},
261 wantVM: &virtualMachine{
264 dataStack: [][]byte{Int64Bytes(-4)},
268 startVM: &virtualMachine{
270 dataStack: [][]byte{{2}, {1}},
272 wantVM: &virtualMachine{
275 dataStack: [][]byte{{1}},
279 startVM: &virtualMachine{
281 dataStack: [][]byte{Int64Bytes(-2), {1}},
283 wantVM: &virtualMachine{
286 dataStack: [][]byte{Int64Bytes(-1)},
290 startVM: &virtualMachine{
292 dataStack: [][]byte{{2}, {1}},
294 wantVM: &virtualMachine{
297 dataStack: [][]byte{{1}},
301 startVM: &virtualMachine{
303 dataStack: [][]byte{{2}, {1}},
305 wantVM: &virtualMachine{
308 dataStack: [][]byte{{1}},
312 startVM: &virtualMachine{
314 dataStack: [][]byte{{2}, {1}},
316 wantVM: &virtualMachine{
319 dataStack: [][]byte{{}},
322 op: OP_NUMEQUALVERIFY,
323 startVM: &virtualMachine{
325 dataStack: [][]byte{{2}, {2}},
327 wantVM: &virtualMachine{
330 dataStack: [][]byte{},
333 op: OP_NUMEQUALVERIFY,
334 startVM: &virtualMachine{
336 dataStack: [][]byte{{1}, {2}},
338 wantErr: ErrVerifyFailed,
341 startVM: &virtualMachine{
343 dataStack: [][]byte{{2}, {1}},
345 wantVM: &virtualMachine{
348 dataStack: [][]byte{{1}},
352 startVM: &virtualMachine{
354 dataStack: [][]byte{{2}, {1}},
356 wantVM: &virtualMachine{
359 dataStack: [][]byte{{}},
362 op: OP_LESSTHANOREQUAL,
363 startVM: &virtualMachine{
365 dataStack: [][]byte{{2}, {1}},
367 wantVM: &virtualMachine{
370 dataStack: [][]byte{{}},
374 startVM: &virtualMachine{
376 dataStack: [][]byte{{2}, {1}},
378 wantVM: &virtualMachine{
381 dataStack: [][]byte{{1}},
384 op: OP_GREATERTHANOREQUAL,
385 startVM: &virtualMachine{
387 dataStack: [][]byte{{2}, {1}},
389 wantVM: &virtualMachine{
392 dataStack: [][]byte{{1}},
396 startVM: &virtualMachine{
398 dataStack: [][]byte{{2}, {1}},
400 wantVM: &virtualMachine{
403 dataStack: [][]byte{{1}},
407 startVM: &virtualMachine{
409 dataStack: [][]byte{{1}, {2}},
411 wantVM: &virtualMachine{
414 dataStack: [][]byte{{1}},
418 startVM: &virtualMachine{
420 dataStack: [][]byte{{2}, {1}},
422 wantVM: &virtualMachine{
425 dataStack: [][]byte{{2}},
429 startVM: &virtualMachine{
431 dataStack: [][]byte{{1}, {2}},
433 wantVM: &virtualMachine{
436 dataStack: [][]byte{{2}},
440 startVM: &virtualMachine{
442 dataStack: [][]byte{{1}, {1}, {2}},
444 wantVM: &virtualMachine{
447 dataStack: [][]byte{{1}},
452 OP_1ADD, OP_1SUB, OP_2MUL, OP_2DIV, OP_NEGATE, OP_ABS, OP_NOT, OP_0NOTEQUAL,
453 OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_LSHIFT, OP_RSHIFT, OP_BOOLAND,
454 OP_BOOLOR, OP_NUMEQUAL, OP_NUMEQUALVERIFY, OP_NUMNOTEQUAL, OP_LESSTHAN,
455 OP_LESSTHANOREQUAL, OP_GREATERTHAN, OP_GREATERTHANOREQUAL, OP_MIN, OP_MAX, OP_WITHIN,
458 for _, op := range numops {
459 cases = append(cases, testStruct{
461 startVM: &virtualMachine{
463 dataStack: [][]byte{{2}, {2}, {2}},
465 wantErr: ErrRunLimitExceeded,
469 for i, c := range cases {
470 err := ops[c.op].fn(c.startVM)
472 if err != c.wantErr {
473 t.Errorf("case %d, op %s: got err = %v want %v", i, ops[c.op].name, err, c.wantErr)
476 if c.wantErr != nil {
480 if !testutil.DeepEqual(c.startVM, c.wantVM) {
481 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)
486 func TestRangeErrs(t *testing.T) {
492 {fmt.Sprintf("%d 1ADD", int64(math.MinInt64)), false},
493 {fmt.Sprintf("%d 1ADD", int64(math.MaxInt64)-1), false},
494 {fmt.Sprintf("%d 1ADD", int64(math.MaxInt64)), true},
496 {fmt.Sprintf("%d 1SUB", int64(math.MaxInt64)), false},
497 {fmt.Sprintf("%d 1SUB", int64(math.MinInt64)+1), false},
498 {fmt.Sprintf("%d 1SUB", int64(math.MinInt64)), true},
500 {fmt.Sprintf("%d 2MUL", int64(math.MaxInt64)/2-1), false},
501 {fmt.Sprintf("%d 2MUL", int64(math.MaxInt64)/2+1), true},
502 {fmt.Sprintf("%d 2MUL", int64(math.MinInt64)/2+1), false},
503 {fmt.Sprintf("%d 2MUL", int64(math.MinInt64)/2-1), true},
505 {"-1 NEGATE", false},
506 {fmt.Sprintf("%d NEGATE", int64(math.MaxInt64)), false},
507 {fmt.Sprintf("%d NEGATE", int64(math.MinInt64)), true},
510 {fmt.Sprintf("%d ABS", int64(math.MaxInt64)), false},
511 {fmt.Sprintf("%d ABS", int64(math.MinInt64)), true},
513 {fmt.Sprintf("%d %d ADD", int64(math.MinInt64), int64(math.MaxInt64)), false},
514 {fmt.Sprintf("%d %d ADD", int64(math.MaxInt64)/2-1, int64(math.MaxInt64)/2-2), false},
515 {fmt.Sprintf("%d %d ADD", int64(math.MaxInt64)/2+1, int64(math.MaxInt64)/2+2), true},
516 {fmt.Sprintf("%d %d ADD", int64(math.MinInt64)/2+1, int64(math.MinInt64)/2+2), false},
517 {fmt.Sprintf("%d %d ADD", int64(math.MinInt64)/2-1, int64(math.MinInt64)/2-2), true},
519 {fmt.Sprintf("1 %d SUB", int64(math.MaxInt64)), false},
520 {fmt.Sprintf("-1 %d SUB", int64(math.MinInt64)), false},
521 {fmt.Sprintf("1 %d SUB", int64(math.MinInt64)), true},
522 {fmt.Sprintf("-1 %d SUB", int64(math.MaxInt64)), false},
523 {fmt.Sprintf("-2 %d SUB", int64(math.MaxInt64)), true},
524 {"1 2 LSHIFT", false},
525 {"-1 2 LSHIFT", false},
526 {"-1 63 LSHIFT", false},
527 {"-1 64 LSHIFT", true},
528 {"0 64 LSHIFT", false},
529 {"1 62 LSHIFT", false},
530 {"1 63 LSHIFT", true},
531 {fmt.Sprintf("%d 0 LSHIFT", int64(math.MaxInt64)), false},
532 {fmt.Sprintf("%d 1 LSHIFT", int64(math.MaxInt64)), true},
533 {fmt.Sprintf("%d 1 LSHIFT", int64(math.MaxInt64)/2), false},
534 {fmt.Sprintf("%d 2 LSHIFT", int64(math.MaxInt64)/2), true},
535 {fmt.Sprintf("%d 0 LSHIFT", int64(math.MinInt64)), false},
536 {fmt.Sprintf("%d 1 LSHIFT", int64(math.MinInt64)), true},
537 {fmt.Sprintf("%d 1 LSHIFT", int64(math.MinInt64)/2), false},
538 {fmt.Sprintf("%d 2 LSHIFT", int64(math.MinInt64)/2), true},
541 for i, c := range cases {
542 prog, _ := Assemble(c.prog)
543 vm := &virtualMachine{
550 if c.expectRangeErr {
551 t.Errorf("case %d (%s): expected range error, got none", i, c.prog)
554 if !c.expectRangeErr {
555 t.Errorf("case %d (%s): got unexpected range error", i, c.prog)
558 if c.expectRangeErr {
559 t.Errorf("case %d (%s): expected range error, got %s", i, c.prog, err)
561 t.Errorf("case %d (%s): got unexpected error %s", i, c.prog, err)