-// +build ignore
-
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import (
"cmd/asm/internal/lex"
+ "strings"
"testing"
"text/scanner"
)
{"3<<(2+4)", 3 << (2 + 4), true},
// Junk at EOF.
{"3 x", 3, false},
+ // Big number
+ {"4611686018427387904", 4611686018427387904, true},
}
func TestExpr(t *testing.T) {
}
}
}
+
+type badExprTest struct {
+ input string
+ error string // Empty means no error.
+}
+
+var badExprTests = []badExprTest{
+ {"0/0", "division by zero"},
+ {"3/0", "division by zero"},
+ {"(1<<63)/0", "divide of value with high bit set"},
+ {"3%0", "modulo by zero"},
+ {"(1<<63)%0", "modulo of value with high bit set"},
+ {"3<<-4", "negative left shift count"},
+ {"3<<(1<<63)", "negative left shift count"},
+ {"3>>-4", "negative right shift count"},
+ {"3>>(1<<63)", "negative right shift count"},
+ {"(1<<63)>>2", "right shift of value with high bit set"},
+ {"(1<<62)>>2", ""},
+ {`'\x80'`, "illegal UTF-8 encoding for character constant"},
+ {"(23*4", "missing closing paren"},
+ {")23*4", "unexpected ) evaluating expression"},
+ {"18446744073709551616", "value out of range"},
+}
+
+func TestBadExpr(t *testing.T) {
+ panicOnError = true
+ defer func() {
+ panicOnError = false
+ }()
+ for i, test := range badExprTests {
+ err := runBadTest(i, test, t)
+ if err == nil {
+ if test.error != "" {
+ t.Errorf("#%d: %q: expected error %q; got none", i, test.input, test.error)
+ }
+ continue
+ }
+ if !strings.Contains(err.Error(), test.error) {
+ t.Errorf("#%d: expected error %q; got %q", i, test.error, err)
+ continue
+ }
+ }
+}
+
+func runBadTest(i int, test badExprTest, t *testing.T) (err error) {
+ p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
+ p.start(lex.Tokenize(test.input))
+ defer func() {
+ e := recover()
+ var ok bool
+ if err, ok = e.(error); e != nil && !ok {
+ t.Fatal(e)
+ }
+ }()
+ p.expr()
+ return nil
+}
}
}
+// panicOnError is enable when testing to abort execution on the first error
+// and turn it into a recoverable panic.
+var panicOnError bool
+
func (p *Parser) errorf(format string, args ...interface{}) {
+ if panicOnError {
+ panic(fmt.Errorf(format, args...))
+ }
if p.histLineNum == p.errorLine {
// Only one error per line.
return
if int64(value) < 0 {
p.errorf("divide of value with high bit set")
}
- value /= p.factor()
+ divisor := p.factor()
+ if divisor == 0 {
+ p.errorf("division by zero")
+ } else {
+ value /= divisor
+ }
case '%':
p.next()
- value %= p.factor()
+ divisor := p.factor()
+ if int64(value) < 0 {
+ p.errorf("modulo of value with high bit set")
+ }
+ if divisor == 0 {
+ p.errorf("modulo by zero")
+ } else {
+ value %= divisor
+ }
case lex.LSH:
p.next()
shift := p.factor()