github.com/traefik/yaegi@v0.15.1/interp/interp_file_test.go (about) 1 package interp_test 2 3 import ( 4 "bytes" 5 "go/build" 6 "go/parser" 7 "go/token" 8 "os" 9 "path/filepath" 10 "regexp" 11 "strings" 12 "testing" 13 14 "github.com/traefik/yaegi/interp" 15 "github.com/traefik/yaegi/stdlib" 16 "github.com/traefik/yaegi/stdlib/unsafe" 17 ) 18 19 func TestFile(t *testing.T) { 20 filePath := "../_test/str.go" 21 runCheck(t, filePath) 22 23 t.Setenv("YAEGI_SPECIAL_STDIO", "1") 24 25 baseDir := filepath.Join("..", "_test") 26 files, err := os.ReadDir(baseDir) 27 if err != nil { 28 t.Fatal(err) 29 } 30 for _, file := range files { 31 if filepath.Ext(file.Name()) != ".go" { 32 continue 33 } 34 file := file 35 t.Run(file.Name(), func(t *testing.T) { 36 runCheck(t, filepath.Join(baseDir, file.Name())) 37 }) 38 } 39 } 40 41 func runCheck(t *testing.T, p string) { 42 t.Helper() 43 44 wanted, goPath, errWanted := wantedFromComment(p) 45 if wanted == "" { 46 t.Skip(p, "has no comment 'Output:' or 'Error:'") 47 } 48 wanted = strings.TrimSpace(wanted) 49 50 if goPath == "" { 51 goPath = build.Default.GOPATH 52 } 53 var stdout, stderr bytes.Buffer 54 i := interp.New(interp.Options{GoPath: goPath, Stdout: &stdout, Stderr: &stderr}) 55 if err := i.Use(interp.Symbols); err != nil { 56 t.Fatal(err) 57 } 58 if err := i.Use(stdlib.Symbols); err != nil { 59 t.Fatal(err) 60 } 61 if err := i.Use(unsafe.Symbols); err != nil { 62 t.Fatal(err) 63 } 64 65 _, err := i.EvalPath(p) 66 if errWanted { 67 if err == nil { 68 t.Fatalf("got nil error, want: %q", wanted) 69 } 70 if res := strings.TrimSpace(err.Error()); !strings.Contains(res, wanted) { 71 t.Errorf("got %q, want: %q", res, wanted) 72 } 73 return 74 } 75 76 if err != nil { 77 t.Fatal(err) 78 } 79 80 // Remove path in output, to have results independent of location. 81 re := regexp.MustCompile(p + ":") 82 if res := re.ReplaceAllString(strings.TrimSpace(stdout.String()), ""); res != wanted { 83 t.Errorf("\ngot: %q,\nwant: %q", res, wanted) 84 } 85 } 86 87 func wantedFromComment(p string) (res string, goPath string, err bool) { 88 fset := token.NewFileSet() 89 f, _ := parser.ParseFile(fset, p, nil, parser.ParseComments) 90 if len(f.Comments) == 0 { 91 return 92 } 93 text := f.Comments[len(f.Comments)-1].Text() 94 if strings.HasPrefix(text, "GOPATH:") { 95 parts := strings.SplitN(text, "\n", 2) 96 text = parts[1] 97 wd, err := os.Getwd() 98 if err != nil { 99 panic(err) 100 } 101 goPath = filepath.Join(wd, "../_test", strings.TrimPrefix(parts[0], "GOPATH:")) 102 } 103 if strings.HasPrefix(text, "Output:\n") { 104 return strings.TrimPrefix(text, "Output:\n"), goPath, false 105 } 106 if strings.HasPrefix(text, "Error:\n") { 107 return strings.TrimPrefix(text, "Error:\n"), goPath, true 108 } 109 return 110 }