diff --git a/ph7_test.go b/ph7_test.go index 3383dcf..48ca19d 100644 --- a/ph7_test.go +++ b/ph7_test.go @@ -31,6 +31,33 @@ func mustSucceedF(t *testing.T, f func() error) { } } +func setupVM(t *testing.T, script string) (vm *ph7.VM, close func()) { + t.Helper() + engine, err := ph7.NewEngine() + mustSucceed(t, err) + + vm, err = engine.Compile([]byte(script), true) + if err != nil { + mustSucceed(t, engine.Close()) + mustSucceed(t, err) + } + + return vm, func() { + mustSucceed(t, vm.Close()) + mustSucceed(t, engine.Close()) + } +} + +func expectOutput(t *testing.T, vm *ph7.VM, expected string) { + t.Helper() + mustSucceed(t, vm.Exec()) + output, err := vm.ExtractOutput() + mustSucceed(t, err) + if output != expected { + t.Fatalf("expected %q, got %q", expected, output) + } +} + func TestCore(t *testing.T) { engine, err := ph7.NewEngine() mustSucceed(t, err) @@ -72,27 +99,21 @@ func TestCompileError(t *testing.T) { } func TestOutputWriter(t *testing.T) { - const source = `` + }` var expected bytes.Buffer for i := 0; i <= 1000; i++ { _, err := fmt.Fprint(&expected, i) mustSucceed(t, err) } - engine, err := ph7.NewEngine() - mustSucceed(t, err) - defer mustSucceedF(t, engine.Close) - - vm, err := engine.Compile([]byte(source), false) - mustSucceed(t, err) - defer vm.Close() + vm, close := setupVM(t, source) + defer close() var actual bytes.Buffer - err = vm.SetOutputWriter(&actual) + err := vm.SetOutputWriter(&actual) mustSucceed(t, err) mustSucceed(t, vm.Exec()) @@ -104,3 +125,63 @@ func TestOutputWriter(t *testing.T) { // TODO Test failing writer, including vm.OutputWriteError // TODO Test setting writer twice + +type CtxFunc func(*ph7.Context) error + +func (r CtxFunc) Call(ctx *ph7.Context, _ []*ph7.Value) ph7.ResultCode { + err := r(ctx) + if err != nil { + return r(ctx).(ph7.Error).Code + } + return ph7.ResultCodeOK +} + +func testResultCode(t *testing.T, expectedOutput string, f CtxFunc) { + t.Helper() + const script = "echo doStuff();" + vm, close := setupVM(t, script) + defer close() + + mustSucceed(t, vm.CreateFunction("doStuff", f)) + expectOutput(t, vm, expectedOutput) +} + +func TestContextResultInt(t *testing.T) { + testResultCode(t, "42", func(ctx *ph7.Context) error { + return ctx.ResultInt(42) + }) +} + +func TestContextResultInt64(t *testing.T) { + testResultCode(t, "1234", func(ctx *ph7.Context) error { + return ctx.ResultInt64(1234) + }) +} + +func TestContextResultBool(t *testing.T) { + testResultCode(t, "TRUE", func(ctx *ph7.Context) error { + return ctx.ResultBool(true) + }) + testResultCode(t, "", func(ctx *ph7.Context) error { + return ctx.ResultBool(false) + }) +} + +func TestContextResultDouble(t *testing.T) { + testResultCode(t, "1.23", func(ctx *ph7.Context) error { + return ctx.ResultDouble(1.23) + }) +} + +func TestContextResultNull(t *testing.T) { + testResultCode(t, "", (*ph7.Context).ResultNull) +} + +func TestContextResultString(t *testing.T) { + testResultCode(t, "hello", func(ctx *ph7.Context) error { + return ctx.ResultString("hello") + }) +} + +// TODO TestContextResultValue +// TODO TestContextResultResource