]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/asm: add tests for erroneous expressions
authorRob Pike <r@golang.org>
Fri, 26 Jun 2015 03:39:09 +0000 (13:39 +1000)
committerRob Pike <r@golang.org>
Fri, 26 Jun 2015 23:33:39 +0000 (23:33 +0000)
Also add a couple more errors, such as modulo with a zero divisor.

Change-Id: If24c95477f7ae86cf4aef5b3460e9ec249ea5ae2
Reviewed-on: https://go-review.googlesource.com/11535
Reviewed-by: Russ Cox <rsc@golang.org>
src/cmd/asm/internal/asm/expr_test.go
src/cmd/asm/internal/asm/parse.go

index 8543bab49d9fe881f78dd0c39202d550a5d935b0..eafbc5fee715910a73b7f2f9d7148c959736bdfe 100644 (file)
@@ -1,5 +1,3 @@
-// +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.
@@ -8,6 +6,7 @@ package asm
 
 import (
        "cmd/asm/internal/lex"
+       "strings"
        "testing"
        "text/scanner"
 )
@@ -53,6 +52,8 @@ var exprTests = []exprTest{
        {"3<<(2+4)", 3 << (2 + 4), true},
        // Junk at EOF.
        {"3 x", 3, false},
+       // Big number
+       {"4611686018427387904", 4611686018427387904, true},
 }
 
 func TestExpr(t *testing.T) {
@@ -71,3 +72,60 @@ 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
+}
index 2533256f88210983b3f723f565cb97f9441c5ec8..1028c9208e64c1284d0f9cd33d3e0568a44db428 100644 (file)
@@ -54,7 +54,14 @@ func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
        }
 }
 
+// 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
@@ -800,10 +807,23 @@ func (p *Parser) term() uint64 {
                        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()