示例#1
0
func instrumentAndTest() (rc int) {
	testFlags.Parse(os.Args[2:])
	packageName := "."
	if testFlags.NArg() > 0 {
		packageName = testFlags.Arg(0)
	}

	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", "bin", "lib", "include"} {
		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.
	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)
	}

	in := &instrumenter{
		gopath:       tempDir,
		instrumented: make(map[string]*gocov.Package),
		excluded:     excluded,
		processed:    make(map[string]struct{}),
		workingdir:   cwd}
	err, packageName = in.abspkgpath(packageName)
	if err != nil {
		errorf("failed to resolve package path(%s): %s\n", packageName, err)
		return 1
	}
	err = in.instrumentPackage(packageName, true)
	if err != nil {
		errorf("failed to instrument package(%s): %s\n", packageName, err)
		return 1
	}

	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".
	// TODO pass through test flags.
	outfilePath := filepath.Join(tempDir, "gocov.out")
	env := os.Environ()
	env = putenv(env, "GOCOVOUT", outfilePath)
	env = putenv(env, "GOROOT", tempDir)

	args := []string{"test"}
	if verbose {
		args = append(args, "-v")
	}
	if *testRunFlag != "" {
		args = append(args, "-run", *testRunFlag)
	}
	instrumentedPackageName := instrumentedPackagePath(packageName)
	args = append(args, instrumentedPackageName)
	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)
		rc = 1
	}

	packages, err := parser.ParseTrace(outfilePath)
	if err != nil {
		errorf("failed to parse gocov output: %s\n", err)
		rc = 1
	} else {
		data, err := marshalJson(packages)
		if err != nil {
			errorf("failed to format as JSON: %s\n", err)
			rc = 1
		} else {
			fmt.Println(string(data))
		}
	}
	return
}
示例#2
0
文件: main.go 项目: pjvds/gocov
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
}
示例#3
0
文件: main.go 项目: davecheney/gocov
func instrumentAndTest() (rc int) {
	testFlags.Parse(os.Args[2:])
	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)
			}
		}()
	}

	for _, name := range [...]string{"src", "pkg", "bin", "lib", "include"} {
		dir := filepath.Join(runtime.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.
	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)
	}

	in := &instrumenter{
		gopath:       tempDir,
		instrumented: make(map[string]*gocov.Package),
		excluded:     excluded,
		processed:    make(map[string]struct{}),
		workingdir:   cwd,
	}

	for _, packageName := range importPaths(testFlags.Args()) {
		err, packageName = in.abspkgpath(packageName)
		if err != nil {
			errorf("failed to resolve package path(%s): %s\n", packageName, err)
			return 1
		}
		if err := in.instrumentPackage(packageName, true); err != nil {
			warnf("warning: failed to instrument package(%s): %s\n", packageName, err)
		}
	}

	if in.ninstrumented() == 0 {
		errorf("error: no packages were instrumented\n")
		return 1
	}

	// Run "go test".
	// TODO pass through test flags.
	outfile, err := ioutil.TempFile(tempDir, "gocov")
	if err != nil {
		errorf("could not create GOCOVOUT: %v", err)
		rc = 1
		return
	}
	outfile.Close()
	outfilePath := outfile.Name()
	env := os.Environ()
	env = putenv(env, "GOCOVOUT", outfilePath)
	env = putenv(env, "GOROOT", tempDir)

	args := []string{"test", "-p", "1"} // disable parallel testing
	if verbose {
		args = append(args, "-v")
	}
	if *testRunFlag != "" {
		args = append(args, "-run", *testRunFlag)
	}
	args = append(args, testFlags.Args()...)
	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)
		rc = 1
	}

	packages, err := parser.ParseTrace(outfilePath)
	if err != nil {
		errorf("failed to parse gocov output: %s\n", err)
		rc = 1
		return
	}

	e := json.NewEncoder(os.Stdout)
	if err := e.Encode(struct{ Packages []*gocov.Package }{packages}); err != nil {
		errorf("failed to format as JSON: %s\n", err)
		rc = 1
	}
	return
}