diff options
author | Russ Cox <rsc@golang.org> | 2009-10-14 18:10:43 -0700 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2009-10-14 18:10:43 -0700 |
commit | 8f49b30671161bc5425c4f2f56cee96ad11befeb (patch) | |
tree | a545d9b275fbbc2346c40d8ea51b2c741ba9faa2 /src/pkg/exp/eval/eval_test.go | |
parent | 9615b0b1cfb8bbfc2b963b471bf9ac2afb7c8662 (diff) | |
download | golang-8f49b30671161bc5425c4f2f56cee96ad11befeb.tar.gz |
move austin/eval and austin/ogle to exp/eval and exp/ogle
R=r
OCL=35736
CL=35746
Diffstat (limited to 'src/pkg/exp/eval/eval_test.go')
-rw-r--r-- | src/pkg/exp/eval/eval_test.go | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/pkg/exp/eval/eval_test.go b/src/pkg/exp/eval/eval_test.go new file mode 100644 index 000000000..192a2e782 --- /dev/null +++ b/src/pkg/exp/eval/eval_test.go @@ -0,0 +1,270 @@ +// Copyright 2009 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. + +package eval + +import ( + "bignum"; + "flag"; + "fmt"; + "log"; + "os"; + "reflect"; + "testing"; +) + +// Print each statement or expression before parsing it +var noisy = false +func init() { + flag.BoolVar(&noisy, "noisy", false, "chatter during eval tests"); +} + +/* + * Generic statement/expression test framework + */ + +type test []job + +type job struct { + code string; + cerr string; + rterr string; + val Value; + noval bool; +} + +func runTests(t *testing.T, baseName string, tests []test) { + for i, test := range tests { + name := fmt.Sprintf("%s[%d]", baseName, i); + test.run(t, name); + } +} + +func (a test) run(t *testing.T, name string) { + w := newTestWorld(); + for _, j := range a { + src := j.code; + if noisy { + println("code:", src); + } + + code, err := w.Compile(src); + if err != nil { + if j.cerr == "" { + t.Errorf("%s: Compile %s: %v", name, src, err); + break; + } + if !match(t, err, j.cerr) { + t.Errorf("%s: Compile %s = error %s; want %v", name, src, err, j.cerr); + break; + } + continue; + } + if j.cerr != "" { + t.Errorf("%s: Compile %s succeeded; want %s", name, src, j.cerr); + break; + } + + val, err := code.Run(); + if err != nil { + if j.rterr == "" { + t.Errorf("%s: Run %s: %v", name, src, err); + break; + } + if !match(t, err, j.rterr) { + t.Errorf("%s: Run %s = error %s; want %v", name, src, err, j.rterr); + break; + } + continue; + } + if j.rterr != "" { + t.Errorf("%s: Run %s succeeded; want %s", name, src, j.rterr); + break; + } + + if !j.noval && !reflect.DeepEqual(val, j.val) { + t.Errorf("%s: Run %s = %T(%v) want %T(%v)", name, src, val, val, j.val, j.val); + } + } +} + +func match(t *testing.T, err os.Error, pat string) bool { + ok, errstr := testing.MatchString(pat, err.String()); + if errstr != "" { + t.Fatalf("compile regexp %s: %v", pat, errstr); + } + return ok; +} + + +/* + * Test constructors + */ + +// Expression compile error +func CErr(expr string, cerr string) test { + return test([]job{job{code: expr, cerr: cerr}}) +} + +// Expression runtime error +func RErr(expr string, rterr string) test { + return test([]job{job{code: expr, rterr: rterr}}) +} + +// Expression value +func Val(expr string, val interface{}) test { + return test([]job{job{code: expr, val: toValue(val)}}) +} + +// Statement runs without error +func Run(stmts string) test { + return test([]job{job{code: stmts, noval: true}}) +} + +// Two statements without error. +// TODO(rsc): Should be possible with Run but the parser +// won't let us do both top-level and non-top-level statements. +func Run2(stmt1, stmt2 string) test { + return test([]job{job{code: stmt1, noval: true}, job{code: stmt2, noval: true}}) +} + +// Statement runs and test one expression's value +func Val1(stmts string, expr1 string, val1 interface{}) test { + return test([]job{ + job{code: stmts, noval: true}, + job{code: expr1, val: toValue(val1)} + }) +} + +// Statement runs and test two expressions' values +func Val2(stmts string, expr1 string, val1 interface{}, expr2 string, val2 interface{}) test { + return test([]job{ + job{code: stmts, noval: true}, + job{code: expr1, val: toValue(val1)}, + job{code: expr2, val: toValue(val2)} + }) +} + +/* + * Value constructors + */ + +type vstruct []interface{} + +type varray []interface{} + +type vslice struct { + arr varray; + len, cap int; +} + +func toValue(val interface{}) Value { + switch val := val.(type) { + case bool: + r := boolV(val); + return &r; + case uint8: + r := uint8V(val); + return &r; + case uint: + r := uintV(val); + return &r; + case int: + r := intV(val); + return &r; + case *bignum.Integer: + return &idealIntV{val}; + case float: + r := floatV(val); + return &r; + case *bignum.Rational: + return &idealFloatV{val}; + case string: + r := stringV(val); + return &r; + case vstruct: + elems := make([]Value, len(val)); + for i, e := range val { + elems[i] = toValue(e); + } + r := structV(elems); + return &r; + case varray: + elems := make([]Value, len(val)); + for i, e := range val { + elems[i] = toValue(e); + } + r := arrayV(elems); + return &r; + case vslice: + return &sliceV{Slice{toValue(val.arr).(ArrayValue), int64(val.len), int64(val.cap)}}; + case Func: + return &funcV{val}; + } + log.Crashf("toValue(%T) not implemented", val); + panic(); +} + +/* + * Default test scope + */ + +type testFunc struct {}; + +func (*testFunc) NewFrame() *Frame { + return &Frame{nil, &[2]Value {}}; +} + +func (*testFunc) Call(t *Thread) { + n := t.f.Vars[0].(IntValue).Get(t); + + res := n + 1; + + t.f.Vars[1].(IntValue).Set(t, res); +} + +type oneTwoFunc struct {}; + +func (*oneTwoFunc) NewFrame() *Frame { + return &Frame{nil, &[2]Value {}}; +} + +func (*oneTwoFunc) Call(t *Thread) { + t.f.Vars[0].(IntValue).Set(t, 1); + t.f.Vars[1].(IntValue).Set(t, 2); +} + +type voidFunc struct {}; + +func (*voidFunc) NewFrame() *Frame { + return &Frame{nil, []Value {}}; +} + +func (*voidFunc) Call(t *Thread) { +} + +func newTestWorld() *World { + w := NewWorld(); + + def := func(name string, t Type, val interface{}) { + w.DefineVar(name, t, toValue(val)); + }; + + w.DefineConst("c", IdealIntType, toValue(bignum.Int(1))); + def("i", IntType, 1); + def("i2", IntType, 2); + def("u", UintType, uint(1)); + def("f", FloatType, 1.0); + def("s", StringType, "abc"); + def("t", NewStructType([]StructField {StructField{"a", IntType, false}}), vstruct{1}); + def("ai", NewArrayType(2, IntType), varray{1, 2}); + def("aai", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{1,2}, varray{3,4}}); + def("aai2", NewArrayType(2, NewArrayType(2, IntType)), varray{varray{5,6}, varray{7,8}}); + def("fn", NewFuncType([]Type{IntType}, false, []Type {IntType}), &testFunc{}); + def("oneTwo", NewFuncType([]Type{}, false, []Type {IntType, IntType}), &oneTwoFunc{}); + def("void", NewFuncType([]Type{}, false, []Type {}), &voidFunc{}); + def("sli", NewSliceType(IntType), vslice{varray{1, 2, 3}, 2, 3}); + + return w; +} |