diff options
Diffstat (limited to 'src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/gopherjs/gopherjs/tool.go')
-rw-r--r-- | src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/gopherjs/gopherjs/tool.go | 963 |
1 files changed, 0 insertions, 963 deletions
diff --git a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/gopherjs/gopherjs/tool.go b/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/gopherjs/gopherjs/tool.go deleted file mode 100644 index 4c580a1395b..00000000000 --- a/src/mongo/gotools/src/github.com/mongodb/mongo-tools/vendor/github.com/gopherjs/gopherjs/tool.go +++ /dev/null @@ -1,963 +0,0 @@ -package main - -import ( - "bytes" - "errors" - "fmt" - "go/ast" - "go/build" - "go/doc" - "go/parser" - "go/scanner" - "go/token" - "go/types" - "io" - "io/ioutil" - "net" - "net/http" - "os" - "os/exec" - "path" - "path/filepath" - "runtime" - "sort" - "strconv" - "strings" - "syscall" - "text/template" - "time" - "unicode" - "unicode/utf8" - - gbuild "github.com/gopherjs/gopherjs/build" - "github.com/gopherjs/gopherjs/compiler" - "github.com/gopherjs/gopherjs/internal/sysutil" - "github.com/kisielk/gotool" - "github.com/neelance/sourcemap" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/crypto/ssh/terminal" - "golang.org/x/tools/go/buildutil" -) - -var currentDirectory string - -func init() { - var err error - currentDirectory, err = os.Getwd() - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - currentDirectory, err = filepath.EvalSymlinks(currentDirectory) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - gopaths := filepath.SplitList(build.Default.GOPATH) - if len(gopaths) == 0 { - fmt.Fprintf(os.Stderr, "$GOPATH not set. For more details see: go help gopath\n") - os.Exit(1) - } -} - -func main() { - var ( - options = &gbuild.Options{CreateMapFile: true} - pkgObj string - tags string - ) - - flagVerbose := pflag.NewFlagSet("", 0) - flagVerbose.BoolVarP(&options.Verbose, "verbose", "v", false, "print the names of packages as they are compiled") - flagQuiet := pflag.NewFlagSet("", 0) - flagQuiet.BoolVarP(&options.Quiet, "quiet", "q", false, "suppress non-fatal warnings") - - compilerFlags := pflag.NewFlagSet("", 0) - compilerFlags.BoolVarP(&options.Minify, "minify", "m", false, "minify generated code") - compilerFlags.BoolVar(&options.Color, "color", terminal.IsTerminal(int(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb", "colored output") - compilerFlags.StringVar(&tags, "tags", "", "a list of build tags to consider satisfied during the build") - compilerFlags.BoolVar(&options.MapToLocalDisk, "localmap", false, "use local paths for sourcemap") - - flagWatch := pflag.NewFlagSet("", 0) - flagWatch.BoolVarP(&options.Watch, "watch", "w", false, "watch for changes to the source files") - - cmdBuild := &cobra.Command{ - Use: "build [packages]", - Short: "compile packages and dependencies", - } - cmdBuild.Flags().StringVarP(&pkgObj, "output", "o", "", "output file") - cmdBuild.Flags().AddFlagSet(flagVerbose) - cmdBuild.Flags().AddFlagSet(flagQuiet) - cmdBuild.Flags().AddFlagSet(compilerFlags) - cmdBuild.Flags().AddFlagSet(flagWatch) - cmdBuild.Run = func(cmd *cobra.Command, args []string) { - options.BuildTags = strings.Fields(tags) - for { - s := gbuild.NewSession(options) - - err := func() error { - // Handle "gopherjs build [files]" ad-hoc package mode. - if len(args) > 0 && (strings.HasSuffix(args[0], ".go") || strings.HasSuffix(args[0], ".inc.js")) { - for _, arg := range args { - if !strings.HasSuffix(arg, ".go") && !strings.HasSuffix(arg, ".inc.js") { - return fmt.Errorf("named files must be .go or .inc.js files") - } - } - if pkgObj == "" { - basename := filepath.Base(args[0]) - pkgObj = basename[:len(basename)-3] + ".js" - } - names := make([]string, len(args)) - for i, name := range args { - name = filepath.ToSlash(name) - names[i] = name - if s.Watcher != nil { - s.Watcher.Add(name) - } - } - err := s.BuildFiles(args, pkgObj, currentDirectory) - return err - } - - // Expand import path patterns. - patternContext := gbuild.NewBuildContext("", options.BuildTags) - pkgs := (&gotool.Context{BuildContext: *patternContext}).ImportPaths(args) - - for _, pkgPath := range pkgs { - if s.Watcher != nil { - pkg, err := gbuild.NewBuildContext(s.InstallSuffix(), options.BuildTags).Import(pkgPath, "", build.FindOnly) - if err != nil { - return err - } - s.Watcher.Add(pkg.Dir) - } - pkg, err := gbuild.Import(pkgPath, 0, s.InstallSuffix(), options.BuildTags) - if err != nil { - return err - } - archive, err := s.BuildPackage(pkg) - if err != nil { - return err - } - if len(pkgs) == 1 { // Only consider writing output if single package specified. - if pkgObj == "" { - pkgObj = filepath.Base(pkg.Dir) + ".js" - } - if pkg.IsCommand() && !pkg.UpToDate { - if err := s.WriteCommandPackage(archive, pkgObj); err != nil { - return err - } - } - } - } - return nil - }() - exitCode := handleError(err, options, nil) - - if s.Watcher == nil { - os.Exit(exitCode) - } - s.WaitForChange() - } - } - - cmdInstall := &cobra.Command{ - Use: "install [packages]", - Short: "compile and install packages and dependencies", - } - cmdInstall.Flags().AddFlagSet(flagVerbose) - cmdInstall.Flags().AddFlagSet(flagQuiet) - cmdInstall.Flags().AddFlagSet(compilerFlags) - cmdInstall.Flags().AddFlagSet(flagWatch) - cmdInstall.Run = func(cmd *cobra.Command, args []string) { - options.BuildTags = strings.Fields(tags) - for { - s := gbuild.NewSession(options) - - err := func() error { - // Expand import path patterns. - patternContext := gbuild.NewBuildContext("", options.BuildTags) - pkgs := (&gotool.Context{BuildContext: *patternContext}).ImportPaths(args) - - if cmd.Name() == "get" { - goGet := exec.Command("go", append([]string{"get", "-d", "-tags=js"}, pkgs...)...) - goGet.Stdout = os.Stdout - goGet.Stderr = os.Stderr - if err := goGet.Run(); err != nil { - return err - } - } - for _, pkgPath := range pkgs { - pkg, err := gbuild.Import(pkgPath, 0, s.InstallSuffix(), options.BuildTags) - if s.Watcher != nil && pkg != nil { // add watch even on error - s.Watcher.Add(pkg.Dir) - } - if err != nil { - return err - } - - archive, err := s.BuildPackage(pkg) - if err != nil { - return err - } - - if pkg.IsCommand() && !pkg.UpToDate { - if err := s.WriteCommandPackage(archive, pkg.PkgObj); err != nil { - return err - } - } - } - return nil - }() - exitCode := handleError(err, options, nil) - - if s.Watcher == nil { - os.Exit(exitCode) - } - s.WaitForChange() - } - } - - cmdDoc := &cobra.Command{ - Use: "doc [arguments]", - Short: "display documentation for the requested, package, method or symbol", - } - cmdDoc.Run = func(cmd *cobra.Command, args []string) { - goDoc := exec.Command("go", append([]string{"doc"}, args...)...) - goDoc.Stdout = os.Stdout - goDoc.Stderr = os.Stderr - goDoc.Env = append(os.Environ(), "GOARCH=js") - err := goDoc.Run() - exitCode := handleError(err, options, nil) - os.Exit(exitCode) - } - - cmdGet := &cobra.Command{ - Use: "get [packages]", - Short: "download and install packages and dependencies", - } - cmdGet.Flags().AddFlagSet(flagVerbose) - cmdGet.Flags().AddFlagSet(flagQuiet) - cmdGet.Flags().AddFlagSet(compilerFlags) - cmdGet.Run = cmdInstall.Run - - cmdRun := &cobra.Command{ - Use: "run [gofiles...] [arguments...]", - Short: "compile and run Go program", - } - cmdRun.Flags().AddFlagSet(flagVerbose) - cmdRun.Flags().AddFlagSet(flagQuiet) - cmdRun.Flags().AddFlagSet(compilerFlags) - cmdRun.Run = func(cmd *cobra.Command, args []string) { - err := func() error { - lastSourceArg := 0 - for { - if lastSourceArg == len(args) || !(strings.HasSuffix(args[lastSourceArg], ".go") || strings.HasSuffix(args[lastSourceArg], ".inc.js")) { - break - } - lastSourceArg++ - } - if lastSourceArg == 0 { - return fmt.Errorf("gopherjs run: no go files listed") - } - - tempfile, err := ioutil.TempFile(currentDirectory, filepath.Base(args[0])+".") - if err != nil && strings.HasPrefix(currentDirectory, runtime.GOROOT()) { - tempfile, err = ioutil.TempFile("", filepath.Base(args[0])+".") - } - if err != nil { - return err - } - defer func() { - tempfile.Close() - os.Remove(tempfile.Name()) - os.Remove(tempfile.Name() + ".map") - }() - s := gbuild.NewSession(options) - if err := s.BuildFiles(args[:lastSourceArg], tempfile.Name(), currentDirectory); err != nil { - return err - } - if err := runNode(tempfile.Name(), args[lastSourceArg:], "", options.Quiet); err != nil { - return err - } - return nil - }() - exitCode := handleError(err, options, nil) - - os.Exit(exitCode) - } - - cmdTest := &cobra.Command{ - Use: "test [packages]", - Short: "test packages", - } - bench := cmdTest.Flags().String("bench", "", "Run benchmarks matching the regular expression. By default, no benchmarks run. To run all benchmarks, use '--bench=.'.") - benchtime := cmdTest.Flags().String("benchtime", "", "Run enough iterations of each benchmark to take t, specified as a time.Duration (for example, -benchtime 1h30s). The default is 1 second (1s).") - count := cmdTest.Flags().String("count", "", "Run each test and benchmark n times (default 1). Examples are always run once.") - run := cmdTest.Flags().String("run", "", "Run only those tests and examples matching the regular expression.") - short := cmdTest.Flags().Bool("short", false, "Tell long-running tests to shorten their run time.") - verbose := cmdTest.Flags().BoolP("verbose", "v", false, "Log all tests as they are run. Also print all text from Log and Logf calls even if the test succeeds.") - compileOnly := cmdTest.Flags().BoolP("compileonly", "c", false, "Compile the test binary to pkg.test.js but do not run it (where pkg is the last element of the package's import path). The file name can be changed with the -o flag.") - outputFilename := cmdTest.Flags().StringP("output", "o", "", "Compile the test binary to the named file. The test still runs (unless -c is specified).") - cmdTest.Flags().AddFlagSet(compilerFlags) - cmdTest.Run = func(cmd *cobra.Command, args []string) { - options.BuildTags = strings.Fields(tags) - err := func() error { - // Expand import path patterns. - patternContext := gbuild.NewBuildContext("", options.BuildTags) - args = (&gotool.Context{BuildContext: *patternContext}).ImportPaths(args) - - if *compileOnly && len(args) > 1 { - return errors.New("cannot use -c flag with multiple packages") - } - if *outputFilename != "" && len(args) > 1 { - return errors.New("cannot use -o flag with multiple packages") - } - - pkgs := make([]*gbuild.PackageData, len(args)) - for i, pkgPath := range args { - var err error - pkgs[i], err = gbuild.Import(pkgPath, 0, "", options.BuildTags) - if err != nil { - return err - } - } - - var exitErr error - for _, pkg := range pkgs { - if len(pkg.TestGoFiles) == 0 && len(pkg.XTestGoFiles) == 0 { - fmt.Printf("? \t%s\t[no test files]\n", pkg.ImportPath) - continue - } - s := gbuild.NewSession(options) - - tests := &testFuncs{BuildContext: s.BuildContext(), Package: pkg.Package} - collectTests := func(testPkg *gbuild.PackageData, testPkgName string, needVar *bool) error { - if testPkgName == "_test" { - for _, file := range pkg.TestGoFiles { - if err := tests.load(pkg.Package.Dir, file, testPkgName, &tests.ImportTest, &tests.NeedTest); err != nil { - return err - } - } - } else { - for _, file := range pkg.XTestGoFiles { - if err := tests.load(pkg.Package.Dir, file, "_xtest", &tests.ImportXtest, &tests.NeedXtest); err != nil { - return err - } - } - } - _, err := s.BuildPackage(testPkg) - return err - } - - if err := collectTests(&gbuild.PackageData{ - Package: &build.Package{ - ImportPath: pkg.ImportPath, - Dir: pkg.Dir, - GoFiles: append(pkg.GoFiles, pkg.TestGoFiles...), - Imports: append(pkg.Imports, pkg.TestImports...), - }, - IsTest: true, - JSFiles: pkg.JSFiles, - }, "_test", &tests.NeedTest); err != nil { - return err - } - - if err := collectTests(&gbuild.PackageData{ - Package: &build.Package{ - ImportPath: pkg.ImportPath + "_test", - Dir: pkg.Dir, - GoFiles: pkg.XTestGoFiles, - Imports: pkg.XTestImports, - }, - IsTest: true, - }, "_xtest", &tests.NeedXtest); err != nil { - return err - } - - buf := new(bytes.Buffer) - if err := testmainTmpl.Execute(buf, tests); err != nil { - return err - } - - fset := token.NewFileSet() - mainFile, err := parser.ParseFile(fset, "_testmain.go", buf, 0) - if err != nil { - return err - } - - importContext := &compiler.ImportContext{ - Packages: s.Types, - Import: func(path string) (*compiler.Archive, error) { - if path == pkg.ImportPath || path == pkg.ImportPath+"_test" { - return s.Archives[path], nil - } - return s.BuildImportPath(path) - }, - } - mainPkgArchive, err := compiler.Compile("main", []*ast.File{mainFile}, fset, importContext, options.Minify) - if err != nil { - return err - } - - if *compileOnly && *outputFilename == "" { - *outputFilename = pkg.Package.Name + "_test.js" - } - - var outfile *os.File - if *outputFilename != "" { - outfile, err = os.Create(*outputFilename) - if err != nil { - return err - } - } else { - outfile, err = ioutil.TempFile(currentDirectory, "test.") - if err != nil { - return err - } - } - defer func() { - outfile.Close() - if *outputFilename == "" { - os.Remove(outfile.Name()) - os.Remove(outfile.Name() + ".map") - } - }() - - if err := s.WriteCommandPackage(mainPkgArchive, outfile.Name()); err != nil { - return err - } - - if *compileOnly { - continue - } - - var args []string - if *bench != "" { - args = append(args, "-test.bench", *bench) - } - if *benchtime != "" { - args = append(args, "-test.benchtime", *benchtime) - } - if *count != "" { - args = append(args, "-test.count", *count) - } - if *run != "" { - args = append(args, "-test.run", *run) - } - if *short { - args = append(args, "-test.short") - } - if *verbose { - args = append(args, "-test.v") - } - status := "ok " - start := time.Now() - if err := runNode(outfile.Name(), args, runTestDir(pkg), options.Quiet); err != nil { - if _, ok := err.(*exec.ExitError); !ok { - return err - } - exitErr = err - status = "FAIL" - } - fmt.Printf("%s\t%s\t%.3fs\n", status, pkg.ImportPath, time.Since(start).Seconds()) - } - return exitErr - }() - exitCode := handleError(err, options, nil) - - os.Exit(exitCode) - } - - cmdServe := &cobra.Command{ - Use: "serve [root]", - Short: "compile on-the-fly and serve", - } - cmdServe.Flags().AddFlagSet(flagVerbose) - cmdServe.Flags().AddFlagSet(flagQuiet) - cmdServe.Flags().AddFlagSet(compilerFlags) - var addr string - cmdServe.Flags().StringVarP(&addr, "http", "", ":8080", "HTTP bind address to serve") - cmdServe.Run = func(cmd *cobra.Command, args []string) { - options.BuildTags = strings.Fields(tags) - dirs := append(filepath.SplitList(build.Default.GOPATH), build.Default.GOROOT) - var root string - - if len(args) > 1 { - cmdServe.HelpFunc()(cmd, args) - os.Exit(1) - } - - if len(args) == 1 { - root = args[0] - } - - sourceFiles := http.FileServer(serveCommandFileSystem{ - serveRoot: root, - options: options, - dirs: dirs, - sourceMaps: make(map[string][]byte), - }) - - ln, err := net.Listen("tcp", addr) - if err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - if tcpAddr := ln.Addr().(*net.TCPAddr); tcpAddr.IP.Equal(net.IPv4zero) || tcpAddr.IP.Equal(net.IPv6zero) { // Any available addresses. - fmt.Printf("serving at http://localhost:%d and on port %d of any available addresses\n", tcpAddr.Port, tcpAddr.Port) - } else { // Specific address. - fmt.Printf("serving at http://%s\n", tcpAddr) - } - fmt.Fprintln(os.Stderr, http.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}, sourceFiles)) - } - - cmdVersion := &cobra.Command{ - Use: "version", - Short: "print GopherJS compiler version", - } - cmdVersion.Run = func(cmd *cobra.Command, args []string) { - if len(args) > 0 { - cmdServe.HelpFunc()(cmd, args) - os.Exit(1) - } - - fmt.Printf("GopherJS %s\n", compiler.Version) - } - - rootCmd := &cobra.Command{ - Use: "gopherjs", - Long: "GopherJS is a tool for compiling Go source code to JavaScript.", - } - rootCmd.AddCommand(cmdBuild, cmdGet, cmdInstall, cmdRun, cmdTest, cmdServe, cmdVersion, cmdDoc) - err := rootCmd.Execute() - if err != nil { - os.Exit(2) - } -} - -// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted -// connections. It's used by ListenAndServe and ListenAndServeTLS so -// dead TCP connections (e.g. closing laptop mid-download) eventually -// go away. -type tcpKeepAliveListener struct { - *net.TCPListener -} - -func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { - tc, err := ln.AcceptTCP() - if err != nil { - return - } - tc.SetKeepAlive(true) - tc.SetKeepAlivePeriod(3 * time.Minute) - return tc, nil -} - -type serveCommandFileSystem struct { - serveRoot string - options *gbuild.Options - dirs []string - sourceMaps map[string][]byte -} - -func (fs serveCommandFileSystem) Open(requestName string) (http.File, error) { - name := path.Join(fs.serveRoot, requestName[1:]) // requestName[0] == '/' - - dir, file := path.Split(name) - base := path.Base(dir) // base is parent folder name, which becomes the output file name. - - isPkg := file == base+".js" - isMap := file == base+".js.map" - isIndex := file == "index.html" - - if isPkg || isMap || isIndex { - // If we're going to be serving our special files, make sure there's a Go command in this folder. - s := gbuild.NewSession(fs.options) - pkg, err := gbuild.Import(path.Dir(name), 0, s.InstallSuffix(), fs.options.BuildTags) - if err != nil || pkg.Name != "main" { - isPkg = false - isMap = false - isIndex = false - } - - switch { - case isPkg: - buf := new(bytes.Buffer) - browserErrors := new(bytes.Buffer) - err := func() error { - archive, err := s.BuildPackage(pkg) - if err != nil { - return err - } - - sourceMapFilter := &compiler.SourceMapFilter{Writer: buf} - m := &sourcemap.Map{File: base + ".js"} - sourceMapFilter.MappingCallback = gbuild.NewMappingCallback(m, fs.options.GOROOT, fs.options.GOPATH, fs.options.MapToLocalDisk) - - deps, err := compiler.ImportDependencies(archive, s.BuildImportPath) - if err != nil { - return err - } - if err := compiler.WriteProgramCode(deps, sourceMapFilter); err != nil { - return err - } - - mapBuf := new(bytes.Buffer) - m.WriteTo(mapBuf) - buf.WriteString("//# sourceMappingURL=" + base + ".js.map\n") - fs.sourceMaps[name+".map"] = mapBuf.Bytes() - - return nil - }() - handleError(err, fs.options, browserErrors) - if err != nil { - buf = browserErrors - } - return newFakeFile(base+".js", buf.Bytes()), nil - - case isMap: - if content, ok := fs.sourceMaps[name]; ok { - return newFakeFile(base+".js.map", content), nil - } - } - } - - for _, d := range fs.dirs { - dir := http.Dir(filepath.Join(d, "src")) - - f, err := dir.Open(name) - if err == nil { - return f, nil - } - - // source maps are served outside of serveRoot - f, err = dir.Open(requestName) - if err == nil { - return f, nil - } - } - - if isIndex { - // If there was no index.html file in any dirs, supply our own. - return newFakeFile("index.html", []byte(`<html><head><meta charset="utf-8"><script src="`+base+`.js"></script></head><body></body></html>`)), nil - } - - return nil, os.ErrNotExist -} - -type fakeFile struct { - name string - size int - io.ReadSeeker -} - -func newFakeFile(name string, content []byte) *fakeFile { - return &fakeFile{name: name, size: len(content), ReadSeeker: bytes.NewReader(content)} -} - -func (f *fakeFile) Close() error { - return nil -} - -func (f *fakeFile) Readdir(count int) ([]os.FileInfo, error) { - return nil, os.ErrInvalid -} - -func (f *fakeFile) Stat() (os.FileInfo, error) { - return f, nil -} - -func (f *fakeFile) Name() string { - return f.name -} - -func (f *fakeFile) Size() int64 { - return int64(f.size) -} - -func (f *fakeFile) Mode() os.FileMode { - return 0 -} - -func (f *fakeFile) ModTime() time.Time { - return time.Time{} -} - -func (f *fakeFile) IsDir() bool { - return false -} - -func (f *fakeFile) Sys() interface{} { - return nil -} - -// handleError handles err and returns an appropriate exit code. -// If browserErrors is non-nil, errors are written for presentation in browser. -func handleError(err error, options *gbuild.Options, browserErrors *bytes.Buffer) int { - switch err := err.(type) { - case nil: - return 0 - case compiler.ErrorList: - for _, entry := range err { - printError(entry, options, browserErrors) - } - return 1 - case *exec.ExitError: - return err.Sys().(syscall.WaitStatus).ExitStatus() - default: - printError(err, options, browserErrors) - return 1 - } -} - -// printError prints err to Stderr with options. If browserErrors is non-nil, errors are also written for presentation in browser. -func printError(err error, options *gbuild.Options, browserErrors *bytes.Buffer) { - e := sprintError(err) - options.PrintError("%s\n", e) - if browserErrors != nil { - fmt.Fprintln(browserErrors, `console.error("`+template.JSEscapeString(e)+`");`) - } -} - -// sprintError returns an annotated error string without trailing newline. -func sprintError(err error) string { - makeRel := func(name string) string { - if relname, err := filepath.Rel(currentDirectory, name); err == nil { - return relname - } - return name - } - - switch e := err.(type) { - case *scanner.Error: - return fmt.Sprintf("%s:%d:%d: %s", makeRel(e.Pos.Filename), e.Pos.Line, e.Pos.Column, e.Msg) - case types.Error: - pos := e.Fset.Position(e.Pos) - return fmt.Sprintf("%s:%d:%d: %s", makeRel(pos.Filename), pos.Line, pos.Column, e.Msg) - default: - return fmt.Sprintf("%s", e) - } -} - -// runNode runs script with args using Node.js in directory dir. -// If dir is empty string, current directory is used. -func runNode(script string, args []string, dir string, quiet bool) error { - var allArgs []string - if b, _ := strconv.ParseBool(os.Getenv("SOURCE_MAP_SUPPORT")); os.Getenv("SOURCE_MAP_SUPPORT") == "" || b { - allArgs = []string{"--require", "source-map-support/register"} - if err := exec.Command("node", "--require", "source-map-support/register", "--eval", "").Run(); err != nil { - if !quiet { - fmt.Fprintln(os.Stderr, "gopherjs: Source maps disabled. Install source-map-support module for nice stack traces. See https://github.com/gopherjs/gopherjs#gopherjs-run-gopherjs-test.") - } - allArgs = []string{} - } - } - - if runtime.GOOS != "windows" { - // We've seen issues with stack space limits causing - // recursion-heavy standard library tests to fail (e.g., see - // https://github.com/gopherjs/gopherjs/pull/669#issuecomment-319319483). - // - // There are two separate limits in non-Windows environments: - // - // - OS process limit - // - Node.js (V8) limit - // - // GopherJS fetches the current OS process limit, and sets the - // Node.js limit to the same value. So both limits are kept in sync - // and can be controlled by setting OS process limit. E.g.: - // - // ulimit -s 10000 && gopherjs test - // - cur, err := sysutil.RlimitStack() - if err != nil { - return fmt.Errorf("failed to get stack size limit: %v", err) - } - allArgs = append(allArgs, fmt.Sprintf("--stack_size=%v", cur/1000)) // Convert from bytes to KB. - } - - allArgs = append(allArgs, script) - allArgs = append(allArgs, args...) - - node := exec.Command("node", allArgs...) - node.Dir = dir - node.Stdin = os.Stdin - node.Stdout = os.Stdout - node.Stderr = os.Stderr - err := node.Run() - if _, ok := err.(*exec.ExitError); err != nil && !ok { - err = fmt.Errorf("could not run Node.js: %s", err.Error()) - } - return err -} - -// runTestDir returns the directory for Node.js to use when running tests for package p. -// Empty string means current directory. -func runTestDir(p *gbuild.PackageData) string { - if p.IsVirtual { - // The package is virtual and doesn't have a physical directory. Use current directory. - return "" - } - // Run tests in the package directory. - return p.Dir -} - -type testFuncs struct { - BuildContext *build.Context - Tests []testFunc - Benchmarks []testFunc - Examples []testFunc - TestMain *testFunc - Package *build.Package - ImportTest bool - NeedTest bool - ImportXtest bool - NeedXtest bool -} - -type testFunc struct { - Package string // imported package name (_test or _xtest) - Name string // function name - Output string // output, for examples - Unordered bool // output is allowed to be unordered. -} - -var testFileSet = token.NewFileSet() - -func (t *testFuncs) load(dir, file, pkg string, doImport, seen *bool) error { - f, err := buildutil.ParseFile(testFileSet, t.BuildContext, nil, dir, file, parser.ParseComments) - if err != nil { - return err - } - for _, d := range f.Decls { - n, ok := d.(*ast.FuncDecl) - if !ok { - continue - } - if n.Recv != nil { - continue - } - name := n.Name.String() - switch { - case isTestMain(n): - if t.TestMain != nil { - return errors.New("multiple definitions of TestMain") - } - t.TestMain = &testFunc{pkg, name, "", false} - *doImport, *seen = true, true - case isTest(name, "Test"): - t.Tests = append(t.Tests, testFunc{pkg, name, "", false}) - *doImport, *seen = true, true - case isTest(name, "Benchmark"): - t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false}) - *doImport, *seen = true, true - } - } - ex := doc.Examples(f) - sort.Sort(byOrder(ex)) - for _, e := range ex { - *doImport = true // import test file whether executed or not - if e.Output == "" && !e.EmptyOutput { - // Don't run examples with no output. - continue - } - t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, e.Unordered}) - *seen = true - } - - return nil -} - -type byOrder []*doc.Example - -func (x byOrder) Len() int { return len(x) } -func (x byOrder) Swap(i, j int) { x[i], x[j] = x[j], x[i] } -func (x byOrder) Less(i, j int) bool { return x[i].Order < x[j].Order } - -// isTestMain tells whether fn is a TestMain(m *testing.M) function. -func isTestMain(fn *ast.FuncDecl) bool { - if fn.Name.String() != "TestMain" || - fn.Type.Results != nil && len(fn.Type.Results.List) > 0 || - fn.Type.Params == nil || - len(fn.Type.Params.List) != 1 || - len(fn.Type.Params.List[0].Names) > 1 { - return false - } - ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr) - if !ok { - return false - } - // We can't easily check that the type is *testing.M - // because we don't know how testing has been imported, - // but at least check that it's *M or *something.M. - if name, ok := ptr.X.(*ast.Ident); ok && name.Name == "M" { - return true - } - if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == "M" { - return true - } - return false -} - -// isTest tells whether name looks like a test (or benchmark, according to prefix). -// It is a Test (say) if there is a character after Test that is not a lower-case letter. -// We don't want TesticularCancer. -func isTest(name, prefix string) bool { - if !strings.HasPrefix(name, prefix) { - return false - } - if len(name) == len(prefix) { // "Test" is ok - return true - } - rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) - return !unicode.IsLower(rune) -} - -var testmainTmpl = template.Must(template.New("main").Parse(` -package main - -import ( -{{if not .TestMain}} - "os" -{{end}} - "testing" - "testing/internal/testdeps" - -{{if .ImportTest}} - {{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}} -{{end}} -{{if .ImportXtest}} - {{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}} -{{end}} -) - -var tests = []testing.InternalTest{ -{{range .Tests}} - {"{{.Name}}", {{.Package}}.{{.Name}}}, -{{end}} -} - -var benchmarks = []testing.InternalBenchmark{ -{{range .Benchmarks}} - {"{{.Name}}", {{.Package}}.{{.Name}}}, -{{end}} -} - -var examples = []testing.InternalExample{ -{{range .Examples}} - {"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}, {{.Unordered}}}, -{{end}} -} - -func main() { - m := testing.MainStart(testdeps.TestDeps{}, tests, benchmarks, examples) -{{with .TestMain}} - {{.Package}}.{{.Name}}(m) -{{else}} - os.Exit(m.Run()) -{{end}} -} - -`)) |