gitlab.com/ethan.reesor/vscode-notebooks/yaegi@v0.0.0-20220417214422-5c573557938e/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  	"strings"
    11  	"testing"
    12  
    13  	"gitlab.com/ethan.reesor/vscode-notebooks/yaegi/interp"
    14  	"gitlab.com/ethan.reesor/vscode-notebooks/yaegi/stdlib"
    15  	"gitlab.com/ethan.reesor/vscode-notebooks/yaegi/stdlib/unsafe"
    16  )
    17  
    18  func TestFile(t *testing.T) {
    19  	filePath := "../_test/str.go"
    20  	runCheck(t, filePath)
    21  
    22  	defer func() {
    23  		_ = os.Setenv("YAEGI_SPECIAL_STDIO", "0")
    24  	}()
    25  	_ = os.Setenv("YAEGI_SPECIAL_STDIO", "1")
    26  
    27  	baseDir := filepath.Join("..", "_test")
    28  	files, err := os.ReadDir(baseDir)
    29  	if err != nil {
    30  		t.Fatal(err)
    31  	}
    32  	for _, file := range files {
    33  		if filepath.Ext(file.Name()) != ".go" {
    34  			continue
    35  		}
    36  		file := file
    37  		t.Run(file.Name(), func(t *testing.T) {
    38  			runCheck(t, filepath.Join(baseDir, file.Name()))
    39  		})
    40  	}
    41  }
    42  
    43  func runCheck(t *testing.T, p string) {
    44  	t.Helper()
    45  
    46  	wanted, goPath, errWanted := wantedFromComment(p)
    47  	if wanted == "" {
    48  		t.Skip(p, "has no comment 'Output:' or 'Error:'")
    49  	}
    50  	wanted = strings.TrimSpace(wanted)
    51  
    52  	if goPath == "" {
    53  		goPath = build.Default.GOPATH
    54  	}
    55  	var stdout, stderr bytes.Buffer
    56  	i := interp.New(interp.Options{GoPath: goPath, Stdout: &stdout, Stderr: &stderr})
    57  	if err := i.Use(interp.Symbols); err != nil {
    58  		t.Fatal(err)
    59  	}
    60  	if err := i.Use(stdlib.Symbols); err != nil {
    61  		t.Fatal(err)
    62  	}
    63  	if err := i.Use(unsafe.Symbols); err != nil {
    64  		t.Fatal(err)
    65  	}
    66  
    67  	_, err := i.EvalPath(p)
    68  	if errWanted {
    69  		if err == nil {
    70  			t.Fatalf("got nil error, want: %q", wanted)
    71  		}
    72  		if res := strings.TrimSpace(err.Error()); !strings.Contains(res, wanted) {
    73  			t.Errorf("got %q, want: %q", res, wanted)
    74  		}
    75  		return
    76  	}
    77  
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  
    82  	if res := 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  }