gopl.io/ch7/eval/eval_test.go

114 lines
2.4 KiB
Go

// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
package eval
import (
"fmt"
"math"
"testing"
)
//!+Eval
func TestEval(t *testing.T) {
tests := []struct {
expr string
env Env
want string
}{
{"sqrt(A / pi)", Env{"A": 87616, "pi": math.Pi}, "167"},
{"pow(x, 3) + pow(y, 3)", Env{"x": 12, "y": 1}, "1729"},
{"pow(x, 3) + pow(y, 3)", Env{"x": 9, "y": 10}, "1729"},
{"5 / 9 * (F - 32)", Env{"F": -40}, "-40"},
{"5 / 9 * (F - 32)", Env{"F": 32}, "0"},
{"5 / 9 * (F - 32)", Env{"F": 212}, "100"},
//!-Eval
// additional tests that don't appear in the book
{"-1 + -x", Env{"x": 1}, "-2"},
{"-1 - x", Env{"x": 1}, "-2"},
//!+Eval
}
var prevExpr string
for _, test := range tests {
// Print expr only when it changes.
if test.expr != prevExpr {
fmt.Printf("\n%s\n", test.expr)
prevExpr = test.expr
}
expr, err := Parse(test.expr)
if err != nil {
t.Error(err) // parse error
continue
}
got := fmt.Sprintf("%.6g", expr.Eval(test.env))
fmt.Printf("\t%v => %s\n", test.env, got)
if got != test.want {
t.Errorf("%s.Eval() in %s = %q, want %q\n",
test.expr, test.env, got, test.want)
}
}
}
//!-Eval
/*
//!+output
sqrt(A / pi)
map[A:87616 pi:3.141592653589793] => 167
pow(x, 3) + pow(y, 3)
map[x:12 y:1] => 1729
map[x:9 y:10] => 1729
5 / 9 * (F - 32)
map[F:-40] => -40
map[F:32] => 0
map[F:212] => 100
//!-output
// Additional outputs that don't appear in the book.
-1 - x
map[x:1] => -2
-1 + -x
map[x:1] => -2
*/
func TestErrors(t *testing.T) {
for _, test := range []struct{ expr, wantErr string }{
{"x % 2", "unexpected '%'"},
{"math.Pi", "unexpected '.'"},
{"!true", "unexpected '!'"},
{`"hello"`, "unexpected '\"'"},
{"log(10)", `unknown function "log"`},
{"sqrt(1, 2)", "call to sqrt has 2 args, want 1"},
} {
expr, err := Parse(test.expr)
if err == nil {
vars := make(map[Var]bool)
err = expr.Check(vars)
if err == nil {
t.Errorf("unexpected success: %s", test.expr)
continue
}
}
fmt.Printf("%-20s%v\n", test.expr, err) // (for book)
if err.Error() != test.wantErr {
t.Errorf("got error %s, want %s", err, test.wantErr)
}
}
}
/*
//!+errors
x % 2 unexpected '%'
math.Pi unexpected '.'
!true unexpected '!'
"hello" unexpected '"'
log(10) unknown function "log"
sqrt(1, 2) call to sqrt has 2 args, want 1
//!-errors
*/