package main import ( "bytes" "go/build" "io/ioutil" "os" "os/exec" "path/filepath" "runtime" "strings" "syscall" "testing" "lab.nexedi.com/kirr/go123/exc" ) func xglob(t *testing.T, pattern string) []string { t.Helper() matchv, err := filepath.Glob(pattern) if err != nil { t.Fatal(err) } return matchv } type TreePrepareMode int const ( TreePrepareGolden TreePrepareMode = iota // prepare golden tree - how `gotrace gen` result should look like TreePrepareWork // prepare work tree - inital state for `gotrace gen` to run ) // prepareTestTree copies files from src to dst recursively processing *.ok and *.rm depending on mode // dst should not initially exist func prepareTestTree(src, dst string, mode TreePrepareMode) error { err := os.MkdirAll(dst, 0777) if err != nil { return err } return filepath.Walk(src, func(srcpath string, info os.FileInfo, err error) error { dstpath := dst + "/" + strings.TrimPrefix(srcpath, src) if info.IsDir() { err := os.Mkdir(dstpath, 0777) if err != nil { return err } return prepareTestTree(srcpath, dstpath, mode) } var isOk, isRm bool if strings.HasSuffix(srcpath, ".ok") { isOk = true dstpath = strings.TrimSuffix(dstpath, ".ok") } if strings.HasSuffix(srcpath, ".rm") { isRm = true dstpath = strings.TrimSuffix(dstpath, ".rm") } data, err := ioutil.ReadFile(srcpath) if err != nil { return err } switch mode { case TreePrepareGolden: // ok files are written as is // no removed files if isRm { return nil } case TreePrepareWork: // no ok files initially if isOk { return nil } // files to remove - prepopulate with magic if isRm { data = []byte(magic) } } err = ioutil.WriteFile(dstpath, data, info.Mode()) if err != nil { return err } return nil }) } func xprepareTree(src, dst string, mode TreePrepareMode) { err := prepareTestTree(src, dst, mode) exc.Raiseif(err) } // diffR compares two directories recursively func diffR(patha, pathb string) (diff string, err error) { out := &bytes.Buffer{} cmd := exec.Command("diff", "-urN", patha, pathb) cmd.Stdout = out err = cmd.Run() if e, ok := err.(*exec.ExitError); ok && e.Sys().(syscall.WaitStatus).ExitStatus() == 1 { err = nil // diff signals with 1 just a difference - problem exit code is 2 } return out.String(), err } func TestGoTraceGen(t *testing.T) { tmp, err := ioutil.TempDir("", "t-gotrace") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmp) good := tmp + "/good" work := tmp + "/work" xprepareTree("testdata", good, TreePrepareGolden) xprepareTree("testdata", work, TreePrepareWork) // test build context with GOPATH set to work tree var tBuildCtx = &build.Context{ GOARCH: "amd64", GOOS: "linux", GOROOT: runtime.GOROOT(), GOPATH: work, Compiler: runtime.Compiler, } // XXX autodetect (go list ?) testv := []string{"a/pkg1", "b/pkg2"} for _, tpkg := range testv { err = tracegen(tpkg, tBuildCtx) if err != nil { t.Errorf("%v: %v", tpkg, err) } diff, err := diffR(good+"/"+tpkg, work+"/"+tpkg) if err != nil { t.Fatalf("%v: %v", tpkg, err) } if diff != "" { t.Errorf("%v: gold & work differ:\n%s", tpkg, diff) } } }