mirror of
				https://github.com/golang/go.git
				synced 2025-10-31 16:50:58 +00:00 
			
		
		
		
	 b8efc006f2
			
		
	
	
		b8efc006f2
		
	
	
	
	
		
			
			Change-Id: Iab669b2a9dd0510c0e54f9ec1cbe2b83b991bceb Reviewed-on: https://go-review.googlesource.com/14283 Reviewed-by: Minux Ma <minux@golang.org>
		
			
				
	
	
		
			230 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			230 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright 2015 The Go Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| // run runs the docs tests found in this directory.
 | |
| package main
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"flag"
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 	"os"
 | |
| 	"os/exec"
 | |
| 	"path/filepath"
 | |
| 	"regexp"
 | |
| 	"runtime"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| const usage = `go run run.go [tests]
 | |
| 
 | |
| run.go runs the docs tests in this directory.
 | |
| If no tests are provided, it runs all tests.
 | |
| Tests may be specified without their .go suffix.
 | |
| `
 | |
| 
 | |
| func main() {
 | |
| 	flag.Usage = func() {
 | |
| 		fmt.Fprintf(os.Stderr, usage)
 | |
| 		flag.PrintDefaults()
 | |
| 		os.Exit(2)
 | |
| 	}
 | |
| 
 | |
| 	flag.Parse()
 | |
| 	if flag.NArg() == 0 {
 | |
| 		// run all tests
 | |
| 		fixcgo()
 | |
| 	} else {
 | |
| 		// run specified tests
 | |
| 		onlyTest(flag.Args()...)
 | |
| 	}
 | |
| 
 | |
| 	tmpdir, err := ioutil.TempDir("", "go-progs")
 | |
| 	if err != nil {
 | |
| 		fmt.Fprintln(os.Stderr, err)
 | |
| 		os.Exit(1)
 | |
| 	}
 | |
| 
 | |
| 	// ratec limits the number of tests running concurrently.
 | |
| 	// None of the tests are intensive, so don't bother
 | |
| 	// trying to manually adjust for slow builders.
 | |
| 	ratec := make(chan bool, runtime.NumCPU())
 | |
| 	errc := make(chan error, len(tests))
 | |
| 
 | |
| 	for _, tt := range tests {
 | |
| 		tt := tt
 | |
| 		ratec <- true
 | |
| 		go func() {
 | |
| 			errc <- test(tmpdir, tt.file, tt.want)
 | |
| 			<-ratec
 | |
| 		}()
 | |
| 	}
 | |
| 
 | |
| 	var rc int
 | |
| 	for range tests {
 | |
| 		if err := <-errc; err != nil {
 | |
| 			fmt.Fprintln(os.Stderr, err)
 | |
| 			rc = 1
 | |
| 		}
 | |
| 	}
 | |
| 	os.Remove(tmpdir)
 | |
| 	os.Exit(rc)
 | |
| }
 | |
| 
 | |
| // test builds the test in the given file.
 | |
| // If want is non-empty, test also runs the test
 | |
| // and checks that the output matches the regexp want.
 | |
| func test(tmpdir, file, want string) error {
 | |
| 	// Build the program.
 | |
| 	prog := filepath.Join(tmpdir, file)
 | |
| 	cmd := exec.Command("go", "build", "-o", prog, file+".go")
 | |
| 	out, err := cmd.CombinedOutput()
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("go build %s.go failed: %v\nOutput:\n%s", file, err, out)
 | |
| 	}
 | |
| 	defer os.Remove(prog)
 | |
| 
 | |
| 	// Only run the test if we have output to check.
 | |
| 	if want == "" {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	cmd = exec.Command(prog)
 | |
| 	out, err = cmd.CombinedOutput()
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("%s failed: %v\nOutput:\n%s", file, err, out)
 | |
| 	}
 | |
| 
 | |
| 	// Canonicalize output.
 | |
| 	out = bytes.TrimRight(out, "\n")
 | |
| 	out = bytes.Replace(out, []byte{'\n'}, []byte{' '}, -1)
 | |
| 
 | |
| 	// Check the result.
 | |
| 	match, err := regexp.Match(want, out)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to parse regexp %q: %v", want, err)
 | |
| 	}
 | |
| 	if !match {
 | |
| 		return fmt.Errorf("%s.go:\n%q\ndoes not match %s", file, out, want)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| type testcase struct {
 | |
| 	file string
 | |
| 	want string
 | |
| }
 | |
| 
 | |
| var tests = []testcase{
 | |
| 	// defer_panic_recover
 | |
| 	{"defer", `^0 3210 2$`},
 | |
| 	{"defer2", `^Calling g. Printing in g 0 Printing in g 1 Printing in g 2 Printing in g 3 Panicking! Defer in g 3 Defer in g 2 Defer in g 1 Defer in g 0 Recovered in f 4 Returned normally from f.$`},
 | |
| 
 | |
| 	// effective_go
 | |
| 	{"eff_bytesize", `^1.00YB 9.09TB$`},
 | |
| 	{"eff_qr", ""},
 | |
| 	{"eff_sequence", `^\[-1 2 6 16 44\]$`},
 | |
| 	{"eff_unused2", ""},
 | |
| 
 | |
| 	// error_handling
 | |
| 	{"error", ""},
 | |
| 	{"error2", ""},
 | |
| 	{"error3", ""},
 | |
| 	{"error4", ""},
 | |
| 
 | |
| 	// law_of_reflection
 | |
| 	{"interface", ""},
 | |
| 	{"interface2", `^type: float64$`},
 | |
| 
 | |
| 	// c_go_cgo
 | |
| 	{"cgo1", ""},
 | |
| 	{"cgo2", ""},
 | |
| 	{"cgo3", ""},
 | |
| 	{"cgo4", ""},
 | |
| 
 | |
| 	// timeout
 | |
| 	{"timeout1", ""},
 | |
| 	{"timeout2", ""},
 | |
| 
 | |
| 	// gobs
 | |
| 	{"gobs1", ""},
 | |
| 	{"gobs2", ""},
 | |
| 
 | |
| 	// json
 | |
| 	{"json1", `^$`},
 | |
| 	{"json2", `the reciprocal of i is`},
 | |
| 	{"json3", `Age is int 6`},
 | |
| 	{"json4", `^$`},
 | |
| 	{"json5", ""},
 | |
| 
 | |
| 	// image_package
 | |
| 	{"image_package1", `^X is 2 Y is 1$`},
 | |
| 	{"image_package2", `^3 4 false$`},
 | |
| 	{"image_package3", `^3 4 true$`},
 | |
| 	{"image_package4", `^image.Point{X:2, Y:1}$`},
 | |
| 	{"image_package5", `^{255 0 0 255}$`},
 | |
| 	{"image_package6", `^8 4 true$`},
 | |
| 
 | |
| 	// other
 | |
| 	{"go1", `^Christmas is a holiday: true .*go1.go already exists$`},
 | |
| 	{"slices", ""},
 | |
| }
 | |
| 
 | |
| func onlyTest(files ...string) {
 | |
| 	var new []testcase
 | |
| NextFile:
 | |
| 	for _, file := range files {
 | |
| 		file = strings.TrimSuffix(file, ".go")
 | |
| 		for _, tt := range tests {
 | |
| 			if tt.file == file {
 | |
| 				new = append(new, tt)
 | |
| 				continue NextFile
 | |
| 			}
 | |
| 		}
 | |
| 		fmt.Fprintf(os.Stderr, "test %s.go not found\n", file)
 | |
| 		os.Exit(1)
 | |
| 	}
 | |
| 	tests = new
 | |
| }
 | |
| 
 | |
| func skipTest(file string) {
 | |
| 	for i, tt := range tests {
 | |
| 		if tt.file == file {
 | |
| 			copy(tests[i:], tests[i+1:])
 | |
| 			tests = tests[:len(tests)-1]
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| 	panic("delete(" + file + "): not found")
 | |
| }
 | |
| 
 | |
| func fixcgo() {
 | |
| 	if os.Getenv("CGO_ENABLED") != "1" {
 | |
| 		skipTest("cgo1")
 | |
| 		skipTest("cgo2")
 | |
| 		skipTest("cgo3")
 | |
| 		skipTest("cgo4")
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	switch runtime.GOOS {
 | |
| 	case "freebsd":
 | |
| 		// cgo1 and cgo2 don't run on freebsd, srandom has a different signature
 | |
| 		skipTest("cgo1")
 | |
| 		skipTest("cgo2")
 | |
| 	case "netbsd":
 | |
| 		// cgo1 and cgo2 don't run on netbsd, srandom has a different signature
 | |
| 		skipTest("cgo1")
 | |
| 		skipTest("cgo2")
 | |
| 		// cgo3 and cgo4 don't run on netbsd, since cgo cannot handle stdout correctly, see issue #10715.
 | |
| 		skipTest("cgo3")
 | |
| 		skipTest("cgo4")
 | |
| 	case "openbsd", "solaris":
 | |
| 		// cgo3 and cgo4 don't run on openbsd and solaris, since cgo cannot handle stdout correctly, see issue #10715.
 | |
| 		skipTest("cgo3")
 | |
| 		skipTest("cgo4")
 | |
| 	}
 | |
| }
 |