mirror of
https://github.com/golang/go
synced 2024-11-26 23:41:37 -07:00
03876af91c
Currently, cgo supports only macros which can be reduced to constants or variables. The CL addresses remaining parts, macros which can be represented as niladic functions. The basic idea is simple: 1. make a thin wrapper function per macros. 2. replace macro expansions with function calls. Fixes #10715 Fixes #18720 Change-Id: I150b4fb48e9dc4cc34466ef6417c04ac93d4bc1a Reviewed-on: https://go-review.googlesource.com/43970 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
224 lines
4.6 KiB
Go
224 lines
4.6 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")
|
|
}
|
|
}
|