diff --git a/_test/a12.go b/_test/a12.go index 09341473..371dd1b1 100644 --- a/_test/a12.go +++ b/_test/a12.go @@ -6,3 +6,6 @@ func main() { var buf [12]int fmt.Println(buf[0]) } + +// Output: +// 0 diff --git a/_test/a15.go b/_test/a15.go index c4a5bc75..248d454a 100644 --- a/_test/a15.go +++ b/_test/a15.go @@ -8,3 +8,6 @@ func main() { var buf [size]int fmt.Println(buf[:]) } + +// Output: +// [0 0 0 0 0 0 0 0 0 0 0 0] diff --git a/_test/a8.go b/_test/a8.go index cfd3f9c4..fa666960 100644 --- a/_test/a8.go +++ b/_test/a8.go @@ -9,3 +9,6 @@ func main() { //a[1] = 2 fmt.Println(a) } + +// Output: +// [0 0] diff --git a/_test/bltn.go b/_test/bltn.go index ecc9e1b8..a1a978fc 100644 --- a/_test/bltn.go +++ b/_test/bltn.go @@ -1,6 +1,8 @@ package main func main() { - f := println - f("Hello") + println("Hello") } + +// Output: +// Hello diff --git a/_test/bltn0.go b/_test/bltn0.go new file mode 100644 index 00000000..ecc9e1b8 --- /dev/null +++ b/_test/bltn0.go @@ -0,0 +1,6 @@ +package main + +func main() { + f := println + f("Hello") +} diff --git a/_test/bool0.go b/_test/bool0.go index 82cfe2c1..83d996bd 100644 --- a/_test/bool0.go +++ b/_test/bool0.go @@ -5,3 +5,6 @@ import "fmt" func main() { fmt.Println(true) } + +// Output: +// true diff --git a/_test/io1.go b/_test/io1.go index 457843d1..53892c7c 100644 --- a/_test/io1.go +++ b/_test/io1.go @@ -7,8 +7,9 @@ import ( func main() { var buf [4]byte - //fmt.Println(buf) s := base64.RawStdEncoding.EncodeToString(buf[:]) - //fmt.Println(base64.RawStdEncoding) fmt.Println(s) } + +// Output: +// AAAAAA diff --git a/_test/method5.go b/_test/method5.go index 326ee0f0..9863c296 100644 --- a/_test/method5.go +++ b/_test/method5.go @@ -35,3 +35,10 @@ func main() { Bar{}.Call() Baz{}.Call() } + +// Output: +// Foo Called +// Foo Showed +// Foo Called +// Foo Showed +// Baz Called diff --git a/_test/op0.go b/_test/op0.go index 8f2d96ec..860f525a 100644 --- a/_test/op0.go +++ b/_test/op0.go @@ -9,3 +9,6 @@ func main() { c = a * b fmt.Printf("c: %v %T", c, c) } + +// Output: +// c: 4096 uint16 diff --git a/_test/op2.go b/_test/op2.go new file mode 100644 index 00000000..2b6b7966 --- /dev/null +++ b/_test/op2.go @@ -0,0 +1,37 @@ +package main + +import "fmt" + +func main() { + a := 64 + a += 64 + fmt.Printf("a: %v %T", a, a) + fmt.Println() + + b := 64 + b -= 64 + fmt.Printf("b: %v %T", b, b) + fmt.Println() + + c := 64 + c *= 64 + fmt.Printf("c: %v %T", c, c) + fmt.Println() + + d := 64 + d /= 64 + fmt.Printf("d: %v %T", d, d) + fmt.Println() + + e := 64 + e %= 64 + fmt.Printf("e: %v %T", e, e) + fmt.Println() +} + +// Output: +// a: 128 int +// b: 0 int +// c: 4096 int +// d: 1 int +// e: 0 int diff --git a/_test/time1.go b/_test/time1.go index caf5a038..9749d472 100644 --- a/_test/time1.go +++ b/_test/time1.go @@ -6,7 +6,10 @@ import ( ) func main() { - t := time.Now() + t := time.Date(2009, time.November, 10, 23, 4, 5, 0, time.UTC) m := t.Minute() fmt.Println(t, m) } + +// Output: +// 2009-11-10 23:04:05 +0000 UTC 4 diff --git a/_test/time2.go b/_test/time2.go index 939f5910..03ea3a2b 100644 --- a/_test/time2.go +++ b/_test/time2.go @@ -6,7 +6,10 @@ import ( ) func main() { - t := time.Now() + t := time.Date(2009, time.November, 10, 23, 4, 5, 0, time.UTC) h, m, s := t.Clock() fmt.Println(h, m, s) } + +// Output: +// 23 4 5 diff --git a/_test/time3.go b/_test/time3.go index 6082c264..1740ccc9 100644 --- a/_test/time3.go +++ b/_test/time3.go @@ -5,7 +5,8 @@ import ( "time" ) +// FIXME related to named returns func main() { - t := time.Now() + t := time.Date(2009, time.November, 10, 23, 4, 5, 0, time.UTC) fmt.Println(t.Clock()) } diff --git a/interp/interp_consistent_test.go b/interp/interp_consistent_test.go index 82c35a64..6984a3b6 100644 --- a/interp/interp_consistent_test.go +++ b/interp/interp_consistent_test.go @@ -1,7 +1,6 @@ package interp_test import ( - "fmt" "io/ioutil" "os" "os/exec" @@ -26,9 +25,8 @@ func TestInterpConsistency(t *testing.T) { file.Name() == "export0.go" || // non-main package file.Name() == "io0.go" || // use random number file.Name() == "op1.go" || // expect error + file.Name() == "bltn0.go" || // expect error file.Name() == "time0.go" || // display time (similar to random number) - file.Name() == "time1.go" || // display time (similar to random number) - file.Name() == "time2.go" || // display time (similar to random number) file.Name() == "cli1.go" || // FIXME global vars file.Name() == "interface0.go" || // TODO not implemented yet @@ -36,7 +34,7 @@ func TestInterpConsistency(t *testing.T) { file.Name() == "chan6.go" || // FIXME related to channel #7 file.Name() == "select1.go" || // FIXME related to channel #7 file.Name() == "ret1.go" || // TODO not implemented yet #22 - file.Name() == "time3.go" || // FIXME only hour is printed, and other returned values minute and second are skipped. + file.Name() == "time3.go" || // FIXME related to named returns file.Name() == "type5.go" || // used to illustrate a limitation with no workaround, related to the fact that the reflect package does not allow the creation of named types file.Name() == "type6.go" || // used to illustrate a limitation with no workaround, related to the fact that the reflect package does not allow the creation of named types @@ -52,10 +50,6 @@ func TestInterpConsistency(t *testing.T) { continue } - if !strings.HasPrefix(file.Name(), "for") { - continue - } - file := file t.Run(file.Name(), func(t *testing.T) { filePath := filepath.Join(baseDir, file.Name()) @@ -81,9 +75,8 @@ func TestInterpConsistency(t *testing.T) { t.Fatal(err) } - // read and restore stdout - err = w.Close() - if err != nil { + // read stdout + if err = w.Close(); err != nil { t.Fatal(err) } outInterp, err := ioutil.ReadAll(r) @@ -91,7 +84,7 @@ func TestInterpConsistency(t *testing.T) { t.Fatal(err) } - // Restore Stdout + // restore Stdout os.Stdout = backupStdout cmd := exec.Command("go", "run", filePath) @@ -101,11 +94,67 @@ func TestInterpConsistency(t *testing.T) { t.Fatal(err) } - fmt.Println(string(outInterp)) - if string(outInterp) != string(outRun) { t.Errorf("\nGot: %q,\n want: %q", string(outInterp), string(outRun)) } }) } } + +func TestInterpErrorConsistency(t *testing.T) { + testCases := []struct { + fileName string + expectedInterp string + expectedExec string + }{ + { + fileName: "op1.go", + expectedInterp: "5:7: invalid float truncate", + expectedExec: "5:4: constant 1.3 truncated to integer", + }, + { + fileName: "bltn0.go", + expectedInterp: "4:7: use of builtin println not in function call", + }, + } + + for _, test := range testCases { + t.Run(test.fileName, func(t *testing.T) { + if len(test.expectedInterp) == 0 && len(test.expectedExec) == 0 { + t.Fatal("at least expectedInterp must be define") + } + + filePath := filepath.Join("..", "_test", test.fileName) + + src, err := ioutil.ReadFile(filePath) + if err != nil { + t.Fatal(err) + } + + i := interp.New(interp.Opt{Entry: "main"}) + i.Use(stdlib.Value, stdlib.Type) + + _, errEval := i.Eval(string(src)) + if errEval == nil { + t.Fatal("An error is expected but got none.") + } + + if errEval.Error() != test.expectedInterp { + t.Errorf("got %q, want: %q", errEval.Error(), test.expectedInterp) + } + + cmd := exec.Command("go", "run", filePath) + outRun, errExec := cmd.CombinedOutput() + if errExec == nil { + t.Log(string(outRun)) + t.Fatal("An error is expected but got none.") + } + + if len(test.expectedExec) == 0 && !strings.Contains(string(outRun), test.expectedInterp) { + t.Errorf("got %q, want: %q", string(outRun), test.expectedInterp) + } else if !strings.Contains(string(outRun), test.expectedExec) { + t.Errorf("got %q, want: %q", string(outRun), test.expectedExec) + } + }) + } +} diff --git a/interp/interp_test.go b/interp/interp_test.go index dd6d8b4c..157e18f7 100644 --- a/interp/interp_test.go +++ b/interp/interp_test.go @@ -101,7 +101,8 @@ import "fmt" func main() { var buf [12]int fmt.Println(buf[0]) -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -109,6 +110,8 @@ func main() { panic(err) } + // Output: + // 0 } func Example_a13() { @@ -174,7 +177,8 @@ const size = 12 func main() { var buf [size]int fmt.Println(buf[:]) -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -182,6 +186,8 @@ func main() { panic(err) } + // Output: + // [0 0 0 0 0 0 0 0 0 0 0 0] } func Example_a16() { @@ -442,7 +448,8 @@ func main() { //a[0] = 1 //a[1] = 2 fmt.Println(a) -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -450,6 +457,8 @@ func main() { panic(err) } + // Output: + // [0 0] } func Example_a9() { @@ -626,6 +635,25 @@ func Example_bltn() { src := ` package main +func main() { + println("Hello") +} +` + i := interp.New(interp.Opt{Entry: "main"}) + i.Use(stdlib.Value, stdlib.Type) + _, err := i.Eval(src) + if err != nil { + panic(err) + } + + // Output: + // Hello +} + +func Example_bltn0() { + src := ` +package main + func main() { f := println f("Hello") @@ -668,7 +696,8 @@ import "fmt" func main() { fmt.Println(true) -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -676,6 +705,8 @@ func main() { panic(err) } + // Output: + // true } func Example_bool1() { @@ -2358,11 +2389,10 @@ import ( func main() { var buf [4]byte - //fmt.Println(buf) s := base64.RawStdEncoding.EncodeToString(buf[:]) - //fmt.Println(base64.RawStdEncoding) fmt.Println(s) -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -2370,6 +2400,8 @@ func main() { panic(err) } + // Output: + // AAAAAA } func Example_iota() { @@ -3189,7 +3221,8 @@ func main() { Foo{}.Call() Bar{}.Call() Baz{}.Call() -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -3197,6 +3230,12 @@ func main() { panic(err) } + // Output: + // Foo Called + // Foo Showed + // Foo Called + // Foo Showed + // Baz Called } func Example_method6() { @@ -3355,7 +3394,8 @@ func main() { b = 64 c = a * b fmt.Printf("c: %v %T", c, c) -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -3363,6 +3403,8 @@ func main() { panic(err) } + // Output: + // c: 4096 uint16 } func Example_op1() { @@ -3383,6 +3425,54 @@ func main() { } +func Example_op2() { + src := ` +package main + +import "fmt" + +func main() { + a := 64 + a += 64 + fmt.Printf("a: %v %T", a, a) + fmt.Println() + + b := 64 + b -= 64 + fmt.Printf("b: %v %T", b, b) + fmt.Println() + + c := 64 + c *= 64 + fmt.Printf("c: %v %T", c, c) + fmt.Println() + + d := 64 + d /= 64 + fmt.Printf("d: %v %T", d, d) + fmt.Println() + + e := 64 + e %= 64 + fmt.Printf("e: %v %T", e, e) + fmt.Println() +} +` + i := interp.New(interp.Opt{Entry: "main"}) + i.Use(stdlib.Value, stdlib.Type) + _, err := i.Eval(src) + if err != nil { + panic(err) + } + + // Output: + // a: 128 int + // b: 0 int + // c: 4096 int + // d: 1 int + // e: 0 int +} + func Example_ptr0() { src := ` package main @@ -5165,10 +5255,11 @@ import ( ) func main() { - t := time.Now() + t := time.Date(2009, time.November, 10, 23, 4, 5, 0, time.UTC) m := t.Minute() fmt.Println(t, m) -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -5176,6 +5267,8 @@ func main() { panic(err) } + // Output: + // 2009-11-10 23:04:05 +0000 UTC 4 } func Example_time2() { @@ -5188,10 +5281,11 @@ import ( ) func main() { - t := time.Now() + t := time.Date(2009, time.November, 10, 23, 4, 5, 0, time.UTC) h, m, s := t.Clock() fmt.Println(h, m, s) -}` +} +` i := interp.New(interp.Opt{Entry: "main"}) i.Use(stdlib.Value, stdlib.Type) _, err := i.Eval(src) @@ -5199,6 +5293,8 @@ func main() { panic(err) } + // Output: + // 23 4 5 } func Example_time3() { @@ -5210,8 +5306,9 @@ import ( "time" ) +// FIXME related to named returns func main() { - t := time.Now() + t := time.Date(2009, time.November, 10, 23, 4, 5, 0, time.UTC) fmt.Println(t.Clock()) }` i := interp.New(interp.Opt{Entry: "main"})