func convertProfiles(filenames ...string) error { var ps gocovutil.Packages for i := range filenames { converter := converter{ packages: make(map[string]*gocov.Package), } profiles, err := cover.ParseProfiles(filenames[i]) if err != nil { return err } for _, p := range profiles { if err := converter.convertProfile(p); err != nil { return err } } for _, pkg := range converter.packages { ps.AddPackage(pkg) } } bytes, err := marshalJson(ps) if err != nil { return err } fmt.Println(string(bytes)) return nil }
func instrumentAndTest() (rc int) { testFlags.Parse(os.Args[2:]) packagePaths, gotestArgs, err := packagesAndTestargs() if err != nil { errorf("failed to process package list: %s\n", err) return 1 } tempDir, err := ioutil.TempDir("", "gocov") if err != nil { errorf("failed to create temporary GOROOT: %s\n", err) return 1 } if *testWorkFlag { fmt.Fprintf(os.Stderr, "WORK=%s\n", tempDir) } else { defer func() { err := os.RemoveAll(tempDir) if err != nil { fmt.Fprintf(os.Stderr, "warning: failed to delete temporary GOROOT (%s)\n", tempDir) } }() } goroot := runtime.GOROOT() for _, name := range [...]string{"src", "pkg"} { dir := filepath.Join(goroot, name) err = symlinkHierarchy(dir, filepath.Join(tempDir, name)) if err != nil { errorf("failed to create $GOROOT/%s: %s\n", name, err) return 1 } } // Copy gocov into the temporary GOROOT, since otherwise it'll // be eclipsed by the instrumented packages root. Use the default // build context here since gocov doesn't use custom build tags. if p, err := build.Import(gocovPackagePath, "", build.FindOnly); err == nil { err = symlinkHierarchy(p.Dir, filepath.Join(tempDir, "src", "pkg", gocovPackagePath)) if err != nil { errorf("failed to symlink gocov: %s\n", err) return 1 } } else { errorf("failed to locate gocov: %s\n", err) return 1 } var excluded []string if len(*testExcludeFlag) > 0 { excluded = strings.Split(*testExcludeFlag, ",") sort.Strings(excluded) } cwd, err := os.Getwd() if err != nil { errorf("failed to determine current working directory: %s\n", err) } context := build.Default if *testTagsFlag != "" { context.BuildTags = strings.Fields(*testTagsFlag) } in := &instrumenter{ goroot: tempDir, context: context, instrumented: make(map[string]*gocov.Package), excluded: excluded, processed: make(map[string]bool), workingdir: cwd, } instrumentedPackagePaths := make([]string, len(packagePaths)) for i, packagePath := range packagePaths { var absPackagePath string absPackagePath, err = in.abspkgpath(packagePath) if err != nil { errorf("failed to resolve package path(%s): %s\n", packagePath, err) return 1 } packagePath = absPackagePath err = in.instrumentPackage(packagePath, true) if err != nil { errorf("failed to instrument package(%s): %s\n", packagePath, err) return 1 } instrumentedPackagePaths[i] = instrumentedPackagePath(packagePath) } ninstrumented := 0 for _, pkg := range in.instrumented { if pkg != nil { ninstrumented++ } } if ninstrumented == 0 { errorf("error: no packages were instrumented\n") return 1 } // Run "go test". const gocovOutPrefix = "gocov.out" env := os.Environ() env = putenv(env, "GOCOVOUT", filepath.Join(tempDir, gocovOutPrefix)) env = putenv(env, "GOROOT", tempDir) args := []string{"test"} if verbose { args = append(args, "-v") } if verboseX { args = append(args, "-x") } if *testTagsFlag != "" { args = append(args, "-tags", *testTagsFlag) } if *testRunFlag != "" { args = append(args, "-run", *testRunFlag) } if *testTimeoutFlag != "" { args = append(args, "-timeout", *testTimeoutFlag) } args = append(args, "-parallel", fmt.Sprint(*testParallelFlag)) args = append(args, instrumentedPackagePaths...) args = append(args, gotestArgs...) // First run with "-i" to avoid the warning // about out-of-date packages. testiargs := append([]string{args[0], "-i"}, args[1:]...) cmd := exec.Command("go", testiargs...) cmd.Env = env cmd.Stdout = os.Stderr cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { errorf("go test -i failed: %s\n", err) return 1 } else { // Now run "go test" normally. cmd = exec.Command("go", args...) cmd.Env = env cmd.Stdout = os.Stderr cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { errorf("go test failed: %s\n", err) return 1 } } tempDirFile, err := os.Open(tempDir) if err != nil { errorf("failed to open output directory: %s\n", err) return 1 } defer tempDirFile.Close() names, err := tempDirFile.Readdirnames(-1) if err != nil { errorf("failed to list output directory: %s\n", err) return 1 } var allpackages gocovutil.Packages for _, name := range names { if !strings.HasPrefix(name, gocovOutPrefix) { continue } outfilePath := filepath.Join(tempDir, name) packages, err := parser.ParseTrace(outfilePath) if err != nil { errorf("failed to parse gocov output: %s\n", err) return 1 } for _, p := range packages { allpackages.AddPackage(p) } } data, err := marshalJson(allpackages) if err != nil { errorf("failed to format as JSON: %s\n", err) return 1 } else { fmt.Println(string(data)) } return }