// NewAgoraClosure loads a full agora context with the module passed in, then // returns a closure that calls the 'Run' method on the closure and returns the // result func NewAgoraClosure(modPath string) func() string { ctx := runtime.NewCtx(new(HTTPResolver), new(compiler.Compiler)) f, _ := os.Open(modPath) defer f.Close() ctx.Compiler.Compile(modPath, f) ctx.RegisterNativeModule(new(stdlib.FmtMod)) ctx.RegisterNativeModule(new(stdlib.FilepathMod)) ctx.RegisterNativeModule(new(stdlib.ConvMod)) ctx.RegisterNativeModule(new(stdlib.StringsMod)) ctx.RegisterNativeModule(new(stdlib.MathMod)) ctx.RegisterNativeModule(new(stdlib.OsMod)) ctx.RegisterNativeModule(new(stdlib.TimeMod)) mod, err := ctx.Load(modPath) if err != nil { fmt.Println("Couldn't load module", err.Error()) os.Exit(1) } return func() string { val, err := mod.Run() if err != nil { fmt.Println("Error executing module", err.Error()) os.Exit(1) } return val.String() } }
func TestMin(t *testing.T) { ctx := runtime.NewCtx(nil, nil) mm := new(MathMod) mm.SetCtx(ctx) cases := []struct { src []runtime.Val exp runtime.Val }{ 0: { src: []runtime.Val{runtime.Number(3), runtime.Number(0), runtime.Number(-12.74), runtime.Number(1)}, exp: runtime.Number(-12.74), }, 1: { src: []runtime.Val{runtime.String("24"), runtime.Bool(true), runtime.Number(12.74)}, exp: runtime.Number(1), }, 2: { src: []runtime.Val{runtime.Number(0), runtime.String("0")}, exp: runtime.Number(0), }, } for i, c := range cases { ret := mm.math_Min(c.src...) if ret != c.exp { t.Errorf("[%d] - expected %f, got %f", i, c.exp.Float(), ret.Float()) } } }
func TestStringsSplit(t *testing.T) { ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) ret := sm.strings_Split(runtime.String("aa:bb::dd"), runtime.String(":")) ob := ret.(runtime.Object) exp := []string{"aa", "bb", "", "dd"} if l := ob.Len().Int(); l != int64(len(exp)) { t.Errorf("expected split length of %d, got %d", len(exp), l) } for i, v := range exp { got := ob.Get(runtime.Number(i)) if got.String() != v { t.Errorf("expected split index %d to be %s, got %s", i, v, got) } } ret = sm.strings_Split(runtime.String("aa:bb::dd:ee:"), runtime.String(":"), runtime.Number(2)) ob = ret.(runtime.Object) exp = []string{"aa", "bb::dd:ee:"} if l := ob.Len().Int(); l != int64(len(exp)) { t.Errorf("expected split length of %d, got %d", len(exp), l) } for i, v := range exp { got := ob.Get(runtime.Number(i)) if got.String() != v { t.Errorf("expected split index %d to be %s, got %s", i, v, got) } } }
func TestOsFields(t *testing.T) { ctx := runtime.NewCtx(nil, nil) om := new(OsMod) om.SetCtx(ctx) ob, err := om.Run() if err != nil { panic(err) } { ob := ob.(runtime.Object) ret := ob.Get(runtime.String("PathSeparator")) exp := string(os.PathSeparator) if ret.String() != exp { t.Errorf("expected path separator %s, got %s", exp, ret.String()) } ret = ob.Get(runtime.String("PathListSeparator")) exp = string(os.PathListSeparator) if ret.String() != exp { t.Errorf("expected path list separator %s, got %s", exp, ret.String()) } ret = ob.Get(runtime.String("DevNull")) exp = os.DevNull if ret.String() != exp { t.Errorf("expected dev/null %s, got %s", exp, ret) } ret = ob.Get(runtime.String("TempDir")) exp = os.TempDir() if ret.String() != exp { t.Errorf("expected temp dir %s, got %s", exp, ret) } } }
func TestOsOpen(t *testing.T) { ctx := runtime.NewCtx(nil, nil) om := new(OsMod) om.SetCtx(ctx) fn := "./testdata/readfile.txt" f := om.os_Open(runtime.String(fn)) fl := f.(*file) ret := fl.Get(runtime.String("Name")) if ret.String() != fn { t.Errorf("expected Name to be '%s', got '%s'", fn, ret) } exp := "ok" ret = fl.readLine() if ret.String() != exp { t.Errorf("expected read line 1 to be '%s', got '%s'", exp, ret) } exp = "" ret = fl.readLine() if ret.String() != exp { t.Errorf("expected read line 2 to be '%s', got '%s'", exp, ret) } ret = fl.readLine() if ret != runtime.Nil { t.Errorf("expected read line 3 to be nil, got '%v'", ret) } ret = fl.closeFile() if ret != runtime.Nil { t.Errorf("expected close file to be nil, got '%v'", ret) } }
func TestTimeConv(t *testing.T) { ctx := runtime.NewCtx(nil, nil) tm := new(TimeMod) tm.SetCtx(ctx) nw := time.Now().UTC() n := tm.time_Date(runtime.Number(nw.Year()), runtime.Number(nw.Month()), runtime.Number(nw.Day()), runtime.Number(nw.Hour()), runtime.Number(nw.Minute()), runtime.Number(nw.Second()), runtime.Number(nw.Nanosecond())) ob := n.(runtime.Object) cnv := ob.Get(runtime.String("__string")) f := cnv.(runtime.Func) ret := f.Call(nil) exp := nw.Format(time.RFC3339) if ret.String() != exp { t.Errorf("expected string to return '%s', got '%s'", exp, ret) } cnv = ob.Get(runtime.String("__int")) f = cnv.(runtime.Func) ret = f.Call(nil) { exp := nw.Unix() if ret.Int() != int64(exp) { t.Errorf("expected int to return %d, got %d", exp, ret.Int()) } } }
func TestTimeNow(t *testing.T) { ctx := runtime.NewCtx(nil, nil) tm := new(TimeMod) tm.SetCtx(ctx) exp := time.Now() ret := tm.time_Now() ob := ret.(runtime.Object) if yr := ob.Get(runtime.String("Year")); yr.Int() != int64(exp.Year()) { t.Errorf("expected year %d, got %d", exp.Year(), yr.Int()) } if mt := ob.Get(runtime.String("Month")); mt.Int() != int64(exp.Month()) { t.Errorf("expected month %d, got %d", exp.Month(), mt.Int()) } if dy := ob.Get(runtime.String("Day")); dy.Int() != int64(exp.Day()) { t.Errorf("expected day %d, got %d", exp.Day(), dy.Int()) } if hr := ob.Get(runtime.String("Hour")); hr.Int() != int64(exp.Hour()) { t.Errorf("expected hour %d, got %d", exp.Hour(), hr.Int()) } if mn := ob.Get(runtime.String("Minute")); mn.Int() != int64(exp.Minute()) { t.Errorf("expected minute %d, got %d", exp.Minute(), mn.Int()) } if sc := ob.Get(runtime.String("Second")); sc.Int() != int64(exp.Second()) { t.Errorf("expected second %d, got %d", exp.Second(), sc.Int()) } if ns := ob.Get(runtime.String("Nanosecond")); ns.Int() < int64(exp.Nanosecond()) { t.Errorf("expected nanosecond %d, got %d", exp.Nanosecond(), ns.Int()) } }
func TestStringsTrim(t *testing.T) { cases := []struct { args []runtime.Val exp string }{ 0: { args: []runtime.Val{ runtime.String(" "), }, exp: "", }, 1: { args: []runtime.Val{ runtime.String("\n \t hi \r"), }, exp: "hi", }, 2: { args: []runtime.Val{ runtime.String("xoxolovexox"), runtime.String("xo"), }, exp: "love", }, } ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) for i, c := range cases { ret := sm.strings_Trim(c.args...) if ret.String() != c.exp { t.Errorf("[%d] - expected %s, got %s", i, c.exp, ret) } } }
func TestFilepathBaseDirExt(t *testing.T) { ctx := runtime.NewCtx(nil, nil) fm := new(FilepathMod) fm.SetCtx(ctx) p, e := filepath.Abs("./testdata/readfile.txt") if e != nil { panic(e) } // Base exp := filepath.Base(p) ret := fm.filepath_Base(runtime.String(p)) if ret.String() != exp { t.Errorf("expected base '%s', got '%s'", exp, ret.String()) } // Dir exp = filepath.Dir(p) ret = fm.filepath_Dir(runtime.String(p)) if ret.String() != exp { t.Errorf("expected dir '%s', got '%s'", exp, ret.String()) } // Ext exp = filepath.Ext(p) ret = fm.filepath_Ext(runtime.String(p)) if ret.String() != exp { t.Errorf("expected extension '%s', got '%s'", exp, ret.String()) } }
func TestStringsToUpper(t *testing.T) { ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) ret := sm.strings_ToUpper(runtime.String("this"), runtime.String("Is"), runtime.String("A"), runtime.String("... strInG")) exp := "THISISA... STRING" if ret.String() != exp { t.Errorf("expected %s, got %s", exp, ret) } }
func TestTimeSleep(t *testing.T) { ctx := runtime.NewCtx(nil, nil) tm := new(TimeMod) tm.SetCtx(ctx) n := time.Now() tm.time_Sleep(runtime.Number(100)) if diff := time.Now().Sub(n); diff < 100*time.Millisecond { t.Errorf("expected at least 100ms, got %f", diff.Seconds()*1000) } }
func TestStringsConcat(t *testing.T) { ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) ret := sm.strings_Concat(runtime.String("hello"), runtime.Number(12), runtime.Bool(true), runtime.String("end")) exp := "hello12trueend" if ret.String() != exp { t.Errorf("expected %s, got %s", exp, ret) } }
func TestFmtScanint(t *testing.T) { ctx := runtime.NewCtx(nil, nil) buf := bytes.NewBuffer([]byte("12\n")) ctx.Stdin = buf fm := new(FmtMod) fm.SetCtx(ctx) ret := fm.fmt_Scanint() if ret.Int() != 12 { t.Errorf("expected 12, got %d", ret.Int()) } }
func TestOsExec(t *testing.T) { ctx := runtime.NewCtx(nil, nil) om := new(OsMod) om.SetCtx(ctx) exp := "hello" ret := om.os_Exec(runtime.String("echo"), runtime.String(exp)) // Shell adds a \n after output if ret.String() != exp+"\n" { t.Errorf("expected '%s', got '%s'", exp, ret) } }
func TestMathNaN(t *testing.T) { // This is just an interface to Go's function, so just a quick simple test ctx := runtime.NewCtx(nil, nil) mm := new(MathMod) mm.SetCtx(ctx) ret := mm.math_NaN() exp := math.NaN() if math.IsNaN(ret.Float()) != math.IsNaN(exp) { t.Errorf("expected NaN, got %f", ret.Float()) } }
func TestMathIsNaN(t *testing.T) { // This is just an interface to Go's function, so just a quick simple test ctx := runtime.NewCtx(nil, nil) mm := new(MathMod) mm.SetCtx(ctx) val := 0.12 ret := mm.math_IsNaN(runtime.Number(val)) exp := math.IsNaN(val) if ret.Bool() != exp { t.Errorf("expected %v, got %v", exp, ret.Bool()) } }
func TestMathTanh(t *testing.T) { // This is just an interface to Go's function, so just a quick simple test ctx := runtime.NewCtx(nil, nil) mm := new(MathMod) mm.SetCtx(ctx) val := 1.12 ret := mm.math_Tanh(runtime.Number(val)) exp := math.Tanh(val) if ret.Float() != exp { t.Errorf("expected %f, got %f", exp, ret.Float()) } }
func TestStringsHasSuffix(t *testing.T) { ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) ret := sm.strings_HasSuffix(runtime.String("suffix, you say"), runtime.String("ay"), runtime.Nil, runtime.Number(3), runtime.String("wh")) if !ret.Bool() { t.Errorf("expected true, got false") } ret = sm.strings_HasSuffix(runtime.String("suffix, you say"), runtime.String("no"), runtime.Nil, runtime.Number(3), runtime.String("hw")) if ret.Bool() { t.Errorf("expected false, got true") } }
func TestStringsContains(t *testing.T) { ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) ret := sm.strings_Contains(runtime.String("contains something"), runtime.String("what"), runtime.Nil, runtime.Number(3), runtime.String("some")) if !ret.Bool() { t.Errorf("expected true, got false") } ret = sm.strings_Contains(runtime.String("contains something"), runtime.String("no"), runtime.Nil, runtime.Number(3), runtime.String("hw")) if ret.Bool() { t.Errorf("expected false, got true") } }
func TestOsGetwd(t *testing.T) { ctx := runtime.NewCtx(nil, nil) om := new(OsMod) om.SetCtx(ctx) exp, e := os.Getwd() if e != nil { panic(e) } ret := om.os_Getwd() if ret.String() != exp { t.Errorf("expected '%s', got '%s'", exp, ret.String()) } }
func TestFmtScanln(t *testing.T) { ctx := runtime.NewCtx(nil, nil) buf := bytes.NewBuffer([]byte(`This is two lines `)) ctx.Stdin = buf fm := new(FmtMod) fm.SetCtx(ctx) ret := fm.fmt_Scanln() if ret.String() != "This is" { t.Errorf("expected line 1 to be 'This is', got '%s'", ret) } }
func TestPi(t *testing.T) { ctx := runtime.NewCtx(nil, nil) mm := new(MathMod) mm.SetCtx(ctx) ob, err := mm.Run() if err != nil { panic(err) } ret := ob.(runtime.Object).Get(runtime.String("Pi")) exp := math.Pi if ret.Float() != exp { t.Errorf("expected %f, got %f", exp, ret.Float()) } }
func TestOsGetenv(t *testing.T) { ctx := runtime.NewCtx(nil, nil) om := new(OsMod) om.SetCtx(ctx) exp := "ok" e := os.Setenv("TEST", exp) if e != nil { panic(e) } ret := om.os_Getenv(runtime.String("TEST")) if ret.String() != exp { t.Errorf("expected '%s', got '%s'", exp, ret.String()) } }
func TestOsReadFile(t *testing.T) { ctx := runtime.NewCtx(nil, nil) om := new(OsMod) om.SetCtx(ctx) b, e := ioutil.ReadFile("./testdata/readfile.txt") if e != nil { panic(e) } exp := string(b) ret := om.os_ReadFile(runtime.String("./testdata/readfile.txt")) if ret.String() != exp { t.Errorf("expected '%s', got '%s'", exp, ret.String()) } }
func TestStringsSlice(t *testing.T) { ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) ret := sm.strings_Slice(runtime.String("agora"), runtime.Number(2)) exp := "ora" if ret.String() != exp { t.Errorf("expected %s, got %s", exp, ret) } ret = sm.strings_Slice(runtime.String("agora"), runtime.Number(2), runtime.Number(4)) exp = "or" if ret.String() != exp { t.Errorf("expected %s, got %s", exp, ret) } }
func TestFilepathJoin(t *testing.T) { ctx := runtime.NewCtx(nil, nil) fm := new(FilepathMod) fm.SetCtx(ctx) parts := []string{"./testdata", "..", "../../compiler", "test"} exp := filepath.Join(parts...) vals := make([]runtime.Val, len(parts)) for i, s := range parts { vals[i] = runtime.String(s) } ret := fm.filepath_Join(vals...) if ret.String() != exp { t.Errorf("expected '%s', got '%s'", exp, ret.String()) } }
func TestStringsLastIndex(t *testing.T) { ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) ret := sm.strings_LastIndex(runtime.String("agoragore"), runtime.String("arg"), runtime.Nil, runtime.Number(3), runtime.String("go")) exp := 5 if ret.Int() != int64(exp) { t.Errorf("expected %d, got %d", exp, ret.Int()) } ret = sm.strings_Index(runtime.String("agoragore"), runtime.Number(6), runtime.String("arg"), runtime.Nil, runtime.Number(3), runtime.String("go")) exp = -1 if ret.Int() != int64(exp) { t.Errorf("expected %d, got %d", exp, ret.Int()) } }
func TestStringsReplace(t *testing.T) { cases := []struct { args []runtime.Val exp string }{ 0: { args: []runtime.Val{ runtime.String("this is the source"), runtime.String("th"), }, exp: "is is e source", }, 1: { args: []runtime.Val{ runtime.String("this is the source"), runtime.String("th"), runtime.Number(1), }, exp: "is is the source", }, 2: { args: []runtime.Val{ runtime.String("this is the source"), runtime.String("t"), runtime.String("T"), }, exp: "This is The source", }, 3: { args: []runtime.Val{ runtime.String("this is the source"), runtime.String("t"), runtime.String("T"), runtime.Number(1), }, exp: "This is the source", }, } ctx := runtime.NewCtx(nil, nil) sm := new(StringsMod) sm.SetCtx(ctx) for i, c := range cases { ret := sm.strings_Replace(c.args...) if ret.String() != c.exp { t.Errorf("[%d] - expected %s, got %s", i, c.exp, ret) } } }
func (r *run) Execute(args []string) error { if len(args) < 1 { return fmt.Errorf("expected an input file") } var c runtime.Compiler if r.FromAsm { c = new(compiler.Asm) } else { c = new(compiler.Compiler) } ctx := runtime.NewCtx(new(runtime.FileResolver), c) if !r.NoStdlib { // Register the standard lib's Fmt package ctx.RegisterNativeModule(new(stdlib.FmtMod)) ctx.RegisterNativeModule(new(stdlib.FilepathMod)) ctx.RegisterNativeModule(new(stdlib.StringsMod)) ctx.RegisterNativeModule(new(stdlib.MathMod)) ctx.RegisterNativeModule(new(stdlib.OsMod)) ctx.RegisterNativeModule(new(stdlib.TimeMod)) } ctx.Debug = r.Debug m, err := ctx.Load(args[0]) if err != nil { return err } // Prepare extra parameters to send to module vals := make([]runtime.Val, len(args)-1) for i, s := range args[1:] { vals[i] = runtime.String(s) } // Open output stream outf := os.Stdout if r.Output != "" { outf, err = os.Open(r.Output) if err != nil { return err } defer outf.Close() ctx.Stdout = outf } res, err := m.Run(vals...) if err == nil && !r.NoResult { fmt.Fprintf(outf, "\n= %s (%T)\n", res, res) } return err }
func TestOsMkRemRenReadDir(t *testing.T) { ctx := runtime.NewCtx(nil, nil) om := new(OsMod) om.SetCtx(ctx) // First create directories d1, d2 := "./testdata/d1", "./testdata/d2/d3" om.os_Mkdir(runtime.String(d1), runtime.String(d2)) // Check that they exist if _, e := os.Stat(d1); os.IsNotExist(e) { t.Errorf("expected d1 to be created, got %s", e) } else if e != nil { panic(e) } if _, e := os.Stat(d2); os.IsNotExist(e) { t.Errorf("expected d2 to be created, got %s", e) } else if e != nil { panic(e) } // Create a file fn := filepath.Join(d2, "test.txt") om.os_WriteFile(runtime.String(fn), runtime.String("hi")) // Read the dir ret := om.os_ReadDir(runtime.String(d2)) ob := ret.(runtime.Object) if ob.Len().Int() != 1 { t.Errorf("expected read dir to return 1 file, got %d", ob.Len().Int()) } v := ob.Get(runtime.Number(0)) ob = v.(runtime.Object) if s := ob.Get(runtime.String("Name")); s.String() != "test.txt" { t.Errorf("expected read file to be 'test.txt', got %s", s) } // Remove the first dir om.os_Remove(runtime.String(d1)) if _, e := os.Stat(d1); !os.IsNotExist(e) { t.Errorf("expected d1 to be deleted, got %s", e) } // Remove all for the second dir and file d2 = filepath.Join(d2, "..") om.os_RemoveAll(runtime.String(d2)) if _, e := os.Stat(d2); !os.IsNotExist(e) { t.Errorf("expected d2 to be deleted, got %s", e) } }