Home | History | Annotate | Download | only in asm
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package asm
      6 
      7 import (
      8 	"cmd/asm/internal/lex"
      9 	"strings"
     10 	"testing"
     11 	"text/scanner"
     12 )
     13 
     14 type exprTest struct {
     15 	input  string
     16 	output int64
     17 	atEOF  bool
     18 }
     19 
     20 var exprTests = []exprTest{
     21 	// Simple
     22 	{"0", 0, true},
     23 	{"3", 3, true},
     24 	{"070", 8 * 7, true},
     25 	{"0x0f", 15, true},
     26 	{"0xFF", 255, true},
     27 	{"9223372036854775807", 9223372036854775807, true}, // max int64
     28 	// Unary
     29 	{"-0", 0, true},
     30 	{"~0", -1, true},
     31 	{"~0*0", 0, true},
     32 	{"+3", 3, true},
     33 	{"-3", -3, true},
     34 	{"-9223372036854775808", -9223372036854775808, true}, // min int64
     35 	// Binary
     36 	{"3+4", 3 + 4, true},
     37 	{"3-4", 3 - 4, true},
     38 	{"2|5", 2 | 5, true},
     39 	{"3^4", 3 ^ 4, true},
     40 	{"3*4", 3 * 4, true},
     41 	{"14/4", 14 / 4, true},
     42 	{"3<<4", 3 << 4, true},
     43 	{"48>>3", 48 >> 3, true},
     44 	{"3&9", 3 & 9, true},
     45 	// General
     46 	{"3*2+3", 3*2 + 3, true},
     47 	{"3+2*3", 3 + 2*3, true},
     48 	{"3*(2+3)", 3 * (2 + 3), true},
     49 	{"3*-(2+3)", 3 * -(2 + 3), true},
     50 	{"3<<2+4", 3<<2 + 4, true},
     51 	{"3<<2+4", 3<<2 + 4, true},
     52 	{"3<<(2+4)", 3 << (2 + 4), true},
     53 	// Junk at EOF.
     54 	{"3 x", 3, false},
     55 	// Big number
     56 	{"4611686018427387904", 4611686018427387904, true},
     57 }
     58 
     59 func TestExpr(t *testing.T) {
     60 	p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
     61 	for i, test := range exprTests {
     62 		p.start(lex.Tokenize(test.input))
     63 		result := int64(p.expr())
     64 		if result != test.output {
     65 			t.Errorf("%d: %q evaluated to %d; expected %d", i, test.input, result, test.output)
     66 		}
     67 		tok := p.next()
     68 		if test.atEOF && tok.ScanToken != scanner.EOF {
     69 			t.Errorf("%d: %q: at EOF got %s", i, test.input, tok)
     70 		} else if !test.atEOF && tok.ScanToken == scanner.EOF {
     71 			t.Errorf("%d: %q: expected not EOF but at EOF", i, test.input)
     72 		}
     73 	}
     74 }
     75 
     76 type badExprTest struct {
     77 	input string
     78 	error string // Empty means no error.
     79 }
     80 
     81 var badExprTests = []badExprTest{
     82 	{"0/0", "division by zero"},
     83 	{"3/0", "division by zero"},
     84 	{"(1<<63)/0", "divide of value with high bit set"},
     85 	{"3%0", "modulo by zero"},
     86 	{"(1<<63)%0", "modulo of value with high bit set"},
     87 	{"3<<-4", "negative left shift count"},
     88 	{"3<<(1<<63)", "negative left shift count"},
     89 	{"3>>-4", "negative right shift count"},
     90 	{"3>>(1<<63)", "negative right shift count"},
     91 	{"(1<<63)>>2", "right shift of value with high bit set"},
     92 	{"(1<<62)>>2", ""},
     93 	{`'\x80'`, "illegal UTF-8 encoding for character constant"},
     94 	{"(23*4", "missing closing paren"},
     95 	{")23*4", "unexpected ) evaluating expression"},
     96 	{"18446744073709551616", "value out of range"},
     97 }
     98 
     99 func TestBadExpr(t *testing.T) {
    100 	panicOnError = true
    101 	defer func() {
    102 		panicOnError = false
    103 	}()
    104 	for i, test := range badExprTests {
    105 		err := runBadTest(i, test, t)
    106 		if err == nil {
    107 			if test.error != "" {
    108 				t.Errorf("#%d: %q: expected error %q; got none", i, test.input, test.error)
    109 			}
    110 			continue
    111 		}
    112 		if !strings.Contains(err.Error(), test.error) {
    113 			t.Errorf("#%d: expected error %q; got %q", i, test.error, err)
    114 			continue
    115 		}
    116 	}
    117 }
    118 
    119 func runBadTest(i int, test badExprTest, t *testing.T) (err error) {
    120 	p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
    121 	p.start(lex.Tokenize(test.input))
    122 	defer func() {
    123 		e := recover()
    124 		var ok bool
    125 		if err, ok = e.(error); e != nil && !ok {
    126 			t.Fatal(e)
    127 		}
    128 	}()
    129 	p.expr()
    130 	return nil
    131 }
    132