diff --git a/misc/cgo/errors/errors_test.go b/misc/cgo/errors/errors_test.go index f727158c48..e6bac0fff4 100644 --- a/misc/cgo/errors/errors_test.go +++ b/misc/cgo/errors/errors_test.go @@ -63,7 +63,7 @@ func expect(t *testing.T, file string, errors []*regexp.Regexp) { defer os.RemoveAll(dir) dst := filepath.Join(dir, strings.TrimSuffix(file, ".go")) - cmd := exec.Command("go", "build", "-gcflags=-L", "-o="+dst, path(file)) // TODO(gri) no need for -gcflags=-L if go tool is adjusted + cmd := exec.Command("go", "build", "-gcflags=-L -e", "-o="+dst, path(file)) // TODO(gri) no need for -gcflags=-L if go tool is adjusted out, err := cmd.CombinedOutput() if err == nil { t.Errorf("expected cgo to fail but it succeeded") @@ -107,21 +107,10 @@ func TestReportsTypeErrors(t *testing.T) { for _, file := range []string{ "err1.go", "err2.go", - "err3.go", - "issue7757.go", - "issue8442.go", "issue11097a.go", "issue11097b.go", - "issue13129.go", - "issue13423.go", - "issue13467.go", - "issue13635.go", - "issue13830.go", - "issue16116.go", - "issue16591.go", "issue18452.go", "issue18889.go", - "issue26745.go", "issue28721.go", } { check(t, file) diff --git a/misc/cgo/errors/ptr_test.go b/misc/cgo/errors/ptr_test.go index 629f4c9226..ba4f4ade64 100644 --- a/misc/cgo/errors/ptr_test.go +++ b/misc/cgo/errors/ptr_test.go @@ -7,21 +7,25 @@ package errorstest import ( - "bufio" "bytes" + "flag" "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "strings" + "sync/atomic" "testing" ) +var tmp = flag.String("tmp", "", "use `dir` for temporary files and do not clean up") + // ptrTest is the tests without the boilerplate. type ptrTest struct { name string // for reporting c string // the cgo comment + c1 string // cgo comment forced into non-export cgo file imports []string // a list of imports support string // supporting functions body string // the body of the main function @@ -39,253 +43,248 @@ var ptrTests = []ptrTest{ { // Passing a pointer to a struct that contains a Go pointer. name: "ptr1", - c: `typedef struct s { int *p; } s; void f(s *ps) {}`, - body: `C.f(&C.s{new(C.int)})`, + c: `typedef struct s1 { int *p; } s1; void f1(s1 *ps) {}`, + body: `C.f1(&C.s1{new(C.int)})`, fail: true, }, { // Passing a pointer to a struct that contains a Go pointer. name: "ptr2", - c: `typedef struct s { int *p; } s; void f(s *ps) {}`, - body: `p := &C.s{new(C.int)}; C.f(p)`, + c: `typedef struct s2 { int *p; } s2; void f2(s2 *ps) {}`, + body: `p := &C.s2{new(C.int)}; C.f2(p)`, fail: true, }, { // Passing a pointer to an int field of a Go struct // that (irrelevantly) contains a Go pointer. name: "ok1", - c: `struct s { int i; int *p; }; void f(int *p) {}`, - body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.i)`, + c: `struct s3 { int i; int *p; }; void f3(int *p) {}`, + body: `p := &C.struct_s3{i: 0, p: new(C.int)}; C.f3(&p.i)`, fail: false, }, { // Passing a pointer to a pointer field of a Go struct. - name: "ptr-field", - c: `struct s { int i; int *p; }; void f(int **p) {}`, - body: `p := &C.struct_s{i: 0, p: new(C.int)}; C.f(&p.p)`, + name: "ptrfield", + c: `struct s4 { int i; int *p; }; void f4(int **p) {}`, + body: `p := &C.struct_s4{i: 0, p: new(C.int)}; C.f4(&p.p)`, fail: true, }, { // Passing a pointer to a pointer field of a Go // struct, where the field does not contain a Go // pointer, but another field (irrelevantly) does. - name: "ptr-field-ok", - c: `struct s { int *p1; int *p2; }; void f(int **p) {}`, - body: `p := &C.struct_s{p1: nil, p2: new(C.int)}; C.f(&p.p1)`, + name: "ptrfieldok", + c: `struct s5 { int *p1; int *p2; }; void f5(int **p) {}`, + body: `p := &C.struct_s5{p1: nil, p2: new(C.int)}; C.f5(&p.p1)`, fail: false, }, { // Passing the address of a slice with no Go pointers. - name: "slice-ok-1", - c: `void f(void **p) {}`, + name: "sliceok1", + c: `void f6(void **p) {}`, imports: []string{"unsafe"}, - body: `s := []unsafe.Pointer{nil}; C.f(&s[0])`, + body: `s := []unsafe.Pointer{nil}; C.f6(&s[0])`, fail: false, }, { // Passing the address of a slice with a Go pointer. - name: "slice-ptr-1", - c: `void f(void **p) {}`, + name: "sliceptr1", + c: `void f7(void **p) {}`, imports: []string{"unsafe"}, - body: `i := 0; s := []unsafe.Pointer{unsafe.Pointer(&i)}; C.f(&s[0])`, + body: `i := 0; s := []unsafe.Pointer{unsafe.Pointer(&i)}; C.f7(&s[0])`, fail: true, }, { // Passing the address of a slice with a Go pointer, // where we are passing the address of an element that // is not a Go pointer. - name: "slice-ptr-2", - c: `void f(void **p) {}`, + name: "sliceptr2", + c: `void f8(void **p) {}`, imports: []string{"unsafe"}, - body: `i := 0; s := []unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f(&s[0])`, + body: `i := 0; s := []unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f8(&s[0])`, fail: true, }, { // Passing the address of a slice that is an element // in a struct only looks at the slice. - name: "slice-ok-2", - c: `void f(void **p) {}`, + name: "sliceok2", + c: `void f9(void **p) {}`, imports: []string{"unsafe"}, - support: `type S struct { p *int; s []unsafe.Pointer }`, - body: `i := 0; p := &S{p:&i, s:[]unsafe.Pointer{nil}}; C.f(&p.s[0])`, + support: `type S9 struct { p *int; s []unsafe.Pointer }`, + body: `i := 0; p := &S9{p:&i, s:[]unsafe.Pointer{nil}}; C.f9(&p.s[0])`, fail: false, }, { // Passing the address of a slice of an array that is // an element in a struct, with a type conversion. - name: "slice-ok-3", - c: `void f(void* p) {}`, + name: "sliceok3", + c: `void f10(void* p) {}`, imports: []string{"unsafe"}, - support: `type S struct { p *int; a [4]byte }`, - body: `i := 0; p := &S{p:&i}; s := p.a[:]; C.f(unsafe.Pointer(&s[0]))`, + support: `type S10 struct { p *int; a [4]byte }`, + body: `i := 0; p := &S10{p:&i}; s := p.a[:]; C.f10(unsafe.Pointer(&s[0]))`, fail: false, }, { // Passing the address of a slice of an array that is // an element in a struct, with a type conversion. - name: "slice-ok-4", - c: `typedef void* PV; void f(PV p) {}`, + name: "sliceok4", + c: `typedef void* PV11; void f11(PV11 p) {}`, imports: []string{"unsafe"}, - support: `type S struct { p *int; a [4]byte }`, - body: `i := 0; p := &S{p:&i}; C.f(C.PV(unsafe.Pointer(&p.a[0])))`, + support: `type S11 struct { p *int; a [4]byte }`, + body: `i := 0; p := &S11{p:&i}; C.f11(C.PV11(unsafe.Pointer(&p.a[0])))`, fail: false, }, { // Passing the address of a static variable with no // pointers doesn't matter. name: "varok", - c: `void f(char** parg) {}`, - support: `var hello = [...]C.char{'h', 'e', 'l', 'l', 'o'}`, - body: `parg := [1]*C.char{&hello[0]}; C.f(&parg[0])`, + c: `void f12(char** parg) {}`, + support: `var hello12 = [...]C.char{'h', 'e', 'l', 'l', 'o'}`, + body: `parg := [1]*C.char{&hello12[0]}; C.f12(&parg[0])`, fail: false, }, { // Passing the address of a static variable with // pointers does matter. - name: "var", - c: `void f(char*** parg) {}`, - support: `var hello = [...]*C.char{new(C.char)}`, - body: `parg := [1]**C.char{&hello[0]}; C.f(&parg[0])`, + name: "var1", + c: `void f13(char*** parg) {}`, + support: `var hello13 = [...]*C.char{new(C.char)}`, + body: `parg := [1]**C.char{&hello13[0]}; C.f13(&parg[0])`, fail: true, }, { // Storing a Go pointer into C memory should fail. name: "barrier", c: `#include - char **f1() { return malloc(sizeof(char*)); } - void f2(char **p) {}`, - body: `p := C.f1(); *p = new(C.char); C.f2(p)`, + char **f14a() { return malloc(sizeof(char*)); } + void f14b(char **p) {}`, + body: `p := C.f14a(); *p = new(C.char); C.f14b(p)`, fail: true, expensive: true, }, { // Storing a Go pointer into C memory by assigning a // large value should fail. - name: "barrier-struct", + name: "barrierstruct", c: `#include - struct s { char *a[10]; }; - struct s *f1() { return malloc(sizeof(struct s)); } - void f2(struct s *p) {}`, - body: `p := C.f1(); p.a = [10]*C.char{new(C.char)}; C.f2(p)`, + struct s15 { char *a[10]; }; + struct s15 *f15() { return malloc(sizeof(struct s15)); } + void f15b(struct s15 *p) {}`, + body: `p := C.f15(); p.a = [10]*C.char{new(C.char)}; C.f15b(p)`, fail: true, expensive: true, }, { // Storing a Go pointer into C memory using a slice // copy should fail. - name: "barrier-slice", + name: "barrierslice", c: `#include - struct s { char *a[10]; }; - struct s *f1() { return malloc(sizeof(struct s)); } - void f2(struct s *p) {}`, - body: `p := C.f1(); copy(p.a[:], []*C.char{new(C.char)}); C.f2(p)`, + struct s16 { char *a[10]; }; + struct s16 *f16() { return malloc(sizeof(struct s16)); } + void f16b(struct s16 *p) {}`, + body: `p := C.f16(); copy(p.a[:], []*C.char{new(C.char)}); C.f16b(p)`, fail: true, expensive: true, }, { // A very large value uses a GC program, which is a // different code path. - name: "barrier-gcprog-array", + name: "barriergcprogarray", c: `#include - struct s { char *a[32769]; }; - struct s *f1() { return malloc(sizeof(struct s)); } - void f2(struct s *p) {}`, - body: `p := C.f1(); p.a = [32769]*C.char{new(C.char)}; C.f2(p)`, + struct s17 { char *a[32769]; }; + struct s17 *f17() { return malloc(sizeof(struct s17)); } + void f17b(struct s17 *p) {}`, + body: `p := C.f17(); p.a = [32769]*C.char{new(C.char)}; C.f17b(p)`, fail: true, expensive: true, }, { // Similar case, with a source on the heap. - name: "barrier-gcprog-array-heap", + name: "barriergcprogarrayheap", c: `#include - struct s { char *a[32769]; }; - struct s *f1() { return malloc(sizeof(struct s)); } - void f2(struct s *p) {} - void f3(void *p) {}`, + struct s18 { char *a[32769]; }; + struct s18 *f18() { return malloc(sizeof(struct s18)); } + void f18b(struct s18 *p) {} + void f18c(void *p) {}`, imports: []string{"unsafe"}, - body: `p := C.f1(); n := &[32769]*C.char{new(C.char)}; p.a = *n; C.f2(p); n[0] = nil; C.f3(unsafe.Pointer(n))`, + body: `p := C.f18(); n := &[32769]*C.char{new(C.char)}; p.a = *n; C.f18b(p); n[0] = nil; C.f18c(unsafe.Pointer(n))`, fail: true, expensive: true, }, { // A GC program with a struct. - name: "barrier-gcprog-struct", + name: "barriergcprogstruct", c: `#include - struct s { char *a[32769]; }; - struct s2 { struct s f; }; - struct s2 *f1() { return malloc(sizeof(struct s2)); } - void f2(struct s2 *p) {}`, - body: `p := C.f1(); p.f = C.struct_s{[32769]*C.char{new(C.char)}}; C.f2(p)`, + struct s19a { char *a[32769]; }; + struct s19b { struct s19a f; }; + struct s19b *f19() { return malloc(sizeof(struct s19b)); } + void f19b(struct s19b *p) {}`, + body: `p := C.f19(); p.f = C.struct_s19a{[32769]*C.char{new(C.char)}}; C.f19b(p)`, fail: true, expensive: true, }, { // Similar case, with a source on the heap. - name: "barrier-gcprog-struct-heap", + name: "barriergcprogstructheap", c: `#include - struct s { char *a[32769]; }; - struct s2 { struct s f; }; - struct s2 *f1() { return malloc(sizeof(struct s2)); } - void f2(struct s2 *p) {} - void f3(void *p) {}`, + struct s20a { char *a[32769]; }; + struct s20b { struct s20a f; }; + struct s20b *f20() { return malloc(sizeof(struct s20b)); } + void f20b(struct s20b *p) {} + void f20c(void *p) {}`, imports: []string{"unsafe"}, - body: `p := C.f1(); n := &C.struct_s{[32769]*C.char{new(C.char)}}; p.f = *n; C.f2(p); n.a[0] = nil; C.f3(unsafe.Pointer(n))`, + body: `p := C.f20(); n := &C.struct_s20a{[32769]*C.char{new(C.char)}}; p.f = *n; C.f20b(p); n.a[0] = nil; C.f20c(unsafe.Pointer(n))`, fail: true, expensive: true, }, { // Exported functions may not return Go pointers. name: "export1", - c: `extern unsigned char *GoFn();`, - support: `//export GoFn - func GoFn() *byte { return new(byte) }`, - body: `C.GoFn()`, + c: `extern unsigned char *GoFn21();`, + support: `//export GoFn21 + func GoFn21() *byte { return new(byte) }`, + body: `C.GoFn21()`, fail: true, }, { // Returning a C pointer is fine. name: "exportok", c: `#include - extern unsigned char *GoFn();`, - support: `//export GoFn - func GoFn() *byte { return (*byte)(C.malloc(1)) }`, - body: `C.GoFn()`, + extern unsigned char *GoFn22();`, + support: `//export GoFn22 + func GoFn22() *byte { return (*byte)(C.malloc(1)) }`, + body: `C.GoFn22()`, }, { // Passing a Go string is fine. - name: "pass-string", + name: "passstring", c: `#include - typedef struct { const char *p; ptrdiff_t n; } gostring; - gostring f(gostring s) { return s; }`, + typedef struct { const char *p; ptrdiff_t n; } gostring23; + gostring23 f23(gostring23 s) { return s; }`, imports: []string{"unsafe"}, - body: `s := "a"; r := C.f(*(*C.gostring)(unsafe.Pointer(&s))); if *(*string)(unsafe.Pointer(&r)) != s { panic(r) }`, + body: `s := "a"; r := C.f23(*(*C.gostring23)(unsafe.Pointer(&s))); if *(*string)(unsafe.Pointer(&r)) != s { panic(r) }`, }, { // Passing a slice of Go strings fails. - name: "pass-string-slice", - c: `void f(void *p) {}`, + name: "passstringslice", + c: `void f24(void *p) {}`, imports: []string{"strings", "unsafe"}, - support: `type S struct { a [1]string }`, - body: `s := S{a:[1]string{strings.Repeat("a", 2)}}; C.f(unsafe.Pointer(&s.a[0]))`, + support: `type S24 struct { a [1]string }`, + body: `s := S24{a:[1]string{strings.Repeat("a", 2)}}; C.f24(unsafe.Pointer(&s.a[0]))`, fail: true, }, { // Exported functions may not return strings. - name: "ret-string", - c: `extern void f();`, + name: "retstring", + c: `extern void f25();`, imports: []string{"strings"}, - support: `//export GoStr - func GoStr() string { return strings.Repeat("a", 2) }`, - body: `C.f()`, - extra: []extra{ - { - "call.c", - `#include - typedef struct { const char *p; ptrdiff_t n; } gostring; - extern gostring GoStr(); - void f() { GoStr(); }`, - }, - }, + support: `//export GoStr25 + func GoStr25() string { return strings.Repeat("a", 2) }`, + body: `C.f25()`, + c1: `#include + typedef struct { const char *p; ptrdiff_t n; } gostring25; + extern gostring25 GoStr25(); + void f25() { GoStr25(); }`, fail: true, }, { @@ -296,37 +295,37 @@ var ptrTests = []ptrTest{ // that is, we are testing something that is not unsafe. name: "ptrdata1", c: `#include - void f(void* p) {}`, + void f26(void* p) {}`, imports: []string{"unsafe"}, - support: `type S struct { p *int; a [8*8]byte; u uintptr }`, - body: `i := 0; p := &S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(*p)))); *q = *p; C.f(unsafe.Pointer(q))`, + support: `type S26 struct { p *int; a [8*8]byte; u uintptr }`, + body: `i := 0; p := &S26{u:uintptr(unsafe.Pointer(&i))}; q := (*S26)(C.malloc(C.size_t(unsafe.Sizeof(*p)))); *q = *p; C.f26(unsafe.Pointer(q))`, fail: false, }, { // Like ptrdata1, but with a type that uses a GC program. name: "ptrdata2", c: `#include - void f(void* p) {}`, + void f27(void* p) {}`, imports: []string{"unsafe"}, - support: `type S struct { p *int; a [32769*8]byte; q *int; u uintptr }`, - body: `i := 0; p := S{u:uintptr(unsafe.Pointer(&i))}; q := (*S)(C.malloc(C.size_t(unsafe.Sizeof(p)))); *q = p; C.f(unsafe.Pointer(q))`, + support: `type S27 struct { p *int; a [32769*8]byte; q *int; u uintptr }`, + body: `i := 0; p := S27{u:uintptr(unsafe.Pointer(&i))}; q := (*S27)(C.malloc(C.size_t(unsafe.Sizeof(p)))); *q = p; C.f27(unsafe.Pointer(q))`, fail: false, }, { // Check deferred pointers when they are used, not // when the defer statement is run. - name: "defer", - c: `typedef struct s { int *p; } s; void f(s *ps) {}`, - body: `p := &C.s{}; defer C.f(p); p.p = new(C.int)`, + name: "defer1", + c: `typedef struct s28 { int *p; } s28; void f28(s28 *ps) {}`, + body: `p := &C.s28{}; defer C.f28(p); p.p = new(C.int)`, fail: true, }, { // Check a pointer to a union if the union has any // pointer fields. name: "union1", - c: `typedef union { char **p; unsigned long i; } u; void f(u *pu) {}`, + c: `typedef union { char **p; unsigned long i; } u29; void f29(u29 *pu) {}`, imports: []string{"unsafe"}, - body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`, + body: `var b C.char; p := &b; C.f29((*C.u29)(unsafe.Pointer(&p)))`, fail: true, }, { @@ -336,55 +335,55 @@ var ptrTests = []ptrTest{ // integer that happens to have the same // representation as a pointer. name: "union2", - c: `typedef union { unsigned long i; } u; void f(u *pu) {}`, + c: `typedef union { unsigned long i; } u39; void f39(u39 *pu) {}`, imports: []string{"unsafe"}, - body: `var b C.char; p := &b; C.f((*C.u)(unsafe.Pointer(&p)))`, + body: `var b C.char; p := &b; C.f39((*C.u39)(unsafe.Pointer(&p)))`, fail: false, }, { // Test preemption while entering a cgo call. Issue #21306. - name: "preempt-during-call", - c: `void f() {}`, + name: "preemptduringcall", + c: `void f30() {}`, imports: []string{"runtime", "sync"}, - body: `var wg sync.WaitGroup; wg.Add(100); for i := 0; i < 100; i++ { go func(i int) { for j := 0; j < 100; j++ { C.f(); runtime.GOMAXPROCS(i) }; wg.Done() }(i) }; wg.Wait()`, + body: `var wg sync.WaitGroup; wg.Add(100); for i := 0; i < 100; i++ { go func(i int) { for j := 0; j < 100; j++ { C.f30(); runtime.GOMAXPROCS(i) }; wg.Done() }(i) }; wg.Wait()`, fail: false, }, { // Test poller deadline with cgocheck=2. Issue #23435. name: "deadline", - c: `#define US 10`, + c: `#define US31 10`, imports: []string{"os", "time"}, - body: `r, _, _ := os.Pipe(); r.SetDeadline(time.Now().Add(C.US * time.Microsecond))`, + body: `r, _, _ := os.Pipe(); r.SetDeadline(time.Now().Add(C.US31 * time.Microsecond))`, fail: false, }, { // Test for double evaluation of channel receive. - name: "chan-recv", - c: `void f(char** p) {}`, + name: "chanrecv", + c: `void f32(char** p) {}`, imports: []string{"time"}, - body: `c := make(chan []*C.char, 2); c <- make([]*C.char, 1); go func() { time.Sleep(10 * time.Second); panic("received twice from chan") }(); C.f(&(<-c)[0]);`, + body: `c := make(chan []*C.char, 2); c <- make([]*C.char, 1); go func() { time.Sleep(10 * time.Second); panic("received twice from chan") }(); C.f32(&(<-c)[0]);`, fail: false, }, { // Test that converting the address of a struct field // to unsafe.Pointer still just checks that field. // Issue #25941. - name: "struct-field", - c: `void f(void* p) {}`, + name: "structfield", + c: `void f33(void* p) {}`, imports: []string{"unsafe"}, - support: `type S struct { p *int; a [8]byte; u uintptr }`, - body: `s := &S{p: new(int)}; C.f(unsafe.Pointer(&s.a))`, + support: `type S33 struct { p *int; a [8]byte; u uintptr }`, + body: `s := &S33{p: new(int)}; C.f33(unsafe.Pointer(&s.a))`, fail: false, }, { // Test that converting multiple struct field // addresses to unsafe.Pointer still just checks those // fields. Issue #25941. - name: "struct-field-2", - c: `void f(void* p, int r, void* s) {}`, + name: "structfield2", + c: `void f34(void* p, int r, void* s) {}`, imports: []string{"unsafe"}, - support: `type S struct { a [8]byte; p *int; b int64; }`, - body: `s := &S{p: new(int)}; C.f(unsafe.Pointer(&s.a), 32, unsafe.Pointer(&s.b))`, + support: `type S34 struct { a [8]byte; p *int; b int64; }`, + body: `s := &S34{p: new(int)}; C.f34(unsafe.Pointer(&s.a), 32, unsafe.Pointer(&s.b))`, fail: false, }, { @@ -392,18 +391,18 @@ var ptrTests = []ptrTest{ // evaluated when a deferred function is deferred, not // when it is run. name: "defer2", - c: `void f(char **pc) {}`, - support: `type S1 struct { s []*C.char }; type S2 struct { ps *S1 }`, - body: `p := &S2{&S1{[]*C.char{nil}}}; defer C.f(&p.ps.s[0]); p.ps = nil`, + c: `void f35(char **pc) {}`, + support: `type S35a struct { s []*C.char }; type S35b struct { ps *S35a }`, + body: `p := &S35b{&S35a{[]*C.char{nil}}}; defer C.f35(&p.ps.s[0]); p.ps = nil`, fail: false, }, { // Test that indexing into a function call still // examines only the slice being indexed. name: "buffer", - c: `void f(void *p) {}`, + c: `void f36(void *p) {}`, imports: []string{"bytes", "unsafe"}, - body: `var b bytes.Buffer; b.WriteString("a"); C.f(unsafe.Pointer(&b.Bytes()[0]))`, + body: `var b bytes.Buffer; b.WriteString("a"); C.f36(unsafe.Pointer(&b.Bytes()[0]))`, fail: false, }, { @@ -411,8 +410,8 @@ var ptrTests = []ptrTest{ name: "finalizer", c: `// Nothing to declare.`, imports: []string{"os"}, - support: `func open() { os.Open(os.Args[0]) }; var G [][]byte`, - body: `for i := 0; i < 10000; i++ { G = append(G, make([]byte, 4096)); if i % 100 == 0 { G = nil; open() } }`, + support: `func open37() { os.Open(os.Args[0]) }; var G37 [][]byte`, + body: `for i := 0; i < 10000; i++ { G37 = append(G37, make([]byte, 4096)); if i % 100 == 0 { G37 = nil; open37() } }`, fail: false, }, { @@ -420,103 +419,155 @@ var ptrTests = []ptrTest{ name: "structof", c: `// Nothing to declare.`, imports: []string{"reflect"}, - support: `type MyInt int; func (i MyInt) Get() int { return int(i) }; type Getter interface { Get() int }`, - body: `t := reflect.StructOf([]reflect.StructField{{Name: "MyInt", Type: reflect.TypeOf(MyInt(0)), Anonymous: true}}); v := reflect.New(t).Elem(); v.Interface().(Getter).Get()`, + support: `type MyInt38 int; func (i MyInt38) Get() int { return int(i) }; type Getter38 interface { Get() int }`, + body: `t := reflect.StructOf([]reflect.StructField{{Name: "MyInt38", Type: reflect.TypeOf(MyInt38(0)), Anonymous: true}}); v := reflect.New(t).Elem(); v.Interface().(Getter38).Get()`, fail: false, }, } func TestPointerChecks(t *testing.T) { + dir, exe := buildPtrTests(t) + + // We (TestPointerChecks) return before the parallel subtest functions do, + // so we can't just defer os.RemoveAll(dir). Instead we have to wait for + // the parallel subtests to finish. This code looks racy but is not: + // the add +1 run in serial before testOne blocks. The -1 run in parallel + // after testOne finishes. + var pending int32 for _, pt := range ptrTests { pt := pt t.Run(pt.name, func(t *testing.T) { - testOne(t, pt) + atomic.AddInt32(&pending, +1) + defer func() { + if atomic.AddInt32(&pending, -1) == 0 { + println("removing", dir) + os.RemoveAll(dir) + } + }() + testOne(t, pt, exe) }) } } -func testOne(t *testing.T, pt ptrTest) { - t.Parallel() - - gopath, err := ioutil.TempDir("", filepath.Base(t.Name())) - if err != nil { - t.Fatal(err) +func buildPtrTests(t *testing.T) (dir, exe string) { + var gopath string + if *tmp != "" { + gopath = *tmp + dir = "" + } else { + d, err := ioutil.TempDir("", filepath.Base(t.Name())) + if err != nil { + t.Fatal(err) + } + dir = d + gopath = d } - defer os.RemoveAll(gopath) src := filepath.Join(gopath, "src", "ptrtest") if err := os.MkdirAll(src, 0777); err != nil { t.Fatal(err) } - name := filepath.Join(src, fmt.Sprintf("%s.go", filepath.Base(t.Name()))) - f, err := os.Create(name) - if err != nil { - t.Fatal(err) - } + // Prepare two cgo inputs: one for standard cgo and one for //export cgo. + // (The latter cannot have C definitions, only declarations.) + var cgo1, cgo2 bytes.Buffer + fmt.Fprintf(&cgo1, "package main\n\n/*\n") + fmt.Fprintf(&cgo2, "package main\n\n/*\n") - b := bufio.NewWriter(f) - fmt.Fprintln(b, `package main`) - fmt.Fprintln(b) - fmt.Fprintln(b, `/*`) - fmt.Fprintln(b, pt.c) - fmt.Fprintln(b, `*/`) - fmt.Fprintln(b, `import "C"`) - fmt.Fprintln(b) - for _, imp := range pt.imports { - fmt.Fprintln(b, `import "`+imp+`"`) + // C code + for _, pt := range ptrTests { + cgo := &cgo1 + if strings.Contains(pt.support, "//export") { + cgo = &cgo2 + } + fmt.Fprintf(cgo, "%s\n", pt.c) + fmt.Fprintf(&cgo1, "%s\n", pt.c1) } - if len(pt.imports) > 0 { - fmt.Fprintln(b) - } - if len(pt.support) > 0 { - fmt.Fprintln(b, pt.support) - fmt.Fprintln(b) - } - fmt.Fprintln(b, `func main() {`) - fmt.Fprintln(b, pt.body) - fmt.Fprintln(b, `}`) + fmt.Fprintf(&cgo1, "*/\nimport \"C\"\n\n") + fmt.Fprintf(&cgo2, "*/\nimport \"C\"\n\n") - if err := b.Flush(); err != nil { - t.Fatalf("flushing %s: %v", name, err) - } - if err := f.Close(); err != nil { - t.Fatalf("closing %s: %v", name, err) - } + // Imports + did1 := make(map[string]bool) + did2 := make(map[string]bool) + did1["os"] = true // for ptrTestMain + fmt.Fprintf(&cgo1, "import \"os\"\n") - for _, e := range pt.extra { - if err := ioutil.WriteFile(filepath.Join(src, e.name), []byte(e.contents), 0644); err != nil { - t.Fatalf("writing %s: %v", e.name, err) + for _, pt := range ptrTests { + did := did1 + cgo := &cgo1 + if strings.Contains(pt.support, "//export") { + did = did2 + cgo = &cgo2 + } + for _, imp := range pt.imports { + if !did[imp] { + did[imp] = true + fmt.Fprintf(cgo, "import %q\n", imp) + } } } - gomod := fmt.Sprintf("module %s\n", filepath.Base(src)) - if err := ioutil.WriteFile(filepath.Join(src, "go.mod"), []byte(gomod), 0666); err != nil { - t.Fatalf("writing go.mod: %v", err) + // Func support and bodies. + for _, pt := range ptrTests { + cgo := &cgo1 + if strings.Contains(pt.support, "//export") { + cgo = &cgo2 + } + fmt.Fprintf(cgo, "%s\nfunc %s() {\n%s\n}\n", pt.support, pt.name, pt.body) } - args := func(cmd *exec.Cmd) string { - return strings.Join(cmd.Args, " ") + // Func list and main dispatch. + fmt.Fprintf(&cgo1, "var funcs = map[string]func() {\n") + for _, pt := range ptrTests { + fmt.Fprintf(&cgo1, "\t%q: %s,\n", pt.name, pt.name) + } + fmt.Fprintf(&cgo1, "}\n\n") + fmt.Fprintf(&cgo1, "%s\n", ptrTestMain) + + if err := ioutil.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil { + t.Fatal(err) + } + if err := ioutil.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil { + t.Fatal(err) } - cmd := exec.Command("go", "build") + cmd := exec.Command("go", "build", "-o", "ptrtest.exe") cmd.Dir = src cmd.Env = append(os.Environ(), "GOPATH="+gopath) - buf, err := cmd.CombinedOutput() + out, err := cmd.CombinedOutput() if err != nil { - t.Logf("%#q:\n%s", args(cmd), buf) - t.Fatalf("failed to build: %v", err) + t.Fatalf("go build: %v\n%s", err, out) } - exe := filepath.Join(src, filepath.Base(src)) - cmd = exec.Command(exe) - cmd.Dir = src + return dir, filepath.Join(src, "ptrtest.exe") +} + +const ptrTestMain = ` +func main() { + for _, arg := range os.Args[1:] { + f := funcs[arg] + if f == nil { + panic("missing func "+arg) + } + f() + } +} +` + +func testOne(t *testing.T, pt ptrTest, exe string) { + t.Parallel() + + newcmd := func(cgocheck string) *exec.Cmd { + cmd := exec.Command(exe, pt.name) + cmd.Env = append(os.Environ(), "GODEBUG=cgocheck="+cgocheck) + return cmd + } if pt.expensive { - cmd.Env = cgocheckEnv("1") + cmd := newcmd("1") buf, err := cmd.CombinedOutput() if err != nil { - t.Logf("%#q:\n%s", args(cmd), buf) + t.Logf("%s", buf) if pt.fail { t.Fatalf("test marked expensive, but failed when not expensive: %v", err) } else { @@ -524,54 +575,45 @@ func testOne(t *testing.T, pt ptrTest) { } } - cmd = exec.Command(exe) - cmd.Dir = src } + cmd := newcmd("") if pt.expensive { - cmd.Env = cgocheckEnv("2") + cmd = newcmd("2") } - buf, err = cmd.CombinedOutput() + buf, err := cmd.CombinedOutput() if pt.fail { if err == nil { - t.Logf("%#q:\n%s", args(cmd), buf) + t.Logf("%s", buf) t.Fatalf("did not fail as expected") } else if !bytes.Contains(buf, []byte("Go pointer")) { - t.Logf("%#q:\n%s", args(cmd), buf) + t.Logf("%s", buf) t.Fatalf("did not print expected error (failed with %v)", err) } } else { if err != nil { - t.Logf("%#q:\n%s", args(cmd), buf) + t.Logf("%s", buf) t.Fatalf("failed unexpectedly: %v", err) } if !pt.expensive { // Make sure it passes with the expensive checks. - cmd := exec.Command(exe) - cmd.Dir = src - cmd.Env = cgocheckEnv("2") + cmd := newcmd("2") buf, err := cmd.CombinedOutput() if err != nil { - t.Logf("%#q:\n%s", args(cmd), buf) + t.Logf("%s", buf) t.Fatalf("failed unexpectedly with expensive checks: %v", err) } } } if pt.fail { - cmd = exec.Command(exe) - cmd.Dir = src - cmd.Env = cgocheckEnv("0") + cmd := newcmd("0") buf, err := cmd.CombinedOutput() if err != nil { - t.Logf("%#q:\n%s", args(cmd), buf) + t.Logf("%s", buf) t.Fatalf("failed unexpectedly with GODEBUG=cgocheck=0: %v", err) } } } - -func cgocheckEnv(val string) []string { - return append(os.Environ(), "GODEBUG=cgocheck="+val) -} diff --git a/misc/cgo/errors/testdata/err1.go b/misc/cgo/errors/testdata/err1.go index 2c232cf58a..ced7443599 100644 --- a/misc/cgo/errors/testdata/err1.go +++ b/misc/cgo/errors/testdata/err1.go @@ -10,6 +10,10 @@ package main void test() { xxx; // ERROR HERE } + +// Issue 8442. Cgo output unhelpful error messages for +// invalid C preambles. +void issue8442foo(UNDEF*); // ERROR HERE */ import "C" diff --git a/misc/cgo/errors/testdata/err2.go b/misc/cgo/errors/testdata/err2.go index 3ab410bbaa..1d22401aee 100644 --- a/misc/cgo/errors/testdata/err2.go +++ b/misc/cgo/errors/testdata/err2.go @@ -4,10 +4,99 @@ package main +/* +#include + +typedef struct foo foo_t; +typedef struct bar bar_t; + +foo_t *foop; + +long double x = 0; + +static int transform(int x) { return x; } + +typedef void v; +void F(v** p) {} + +void fvi(void *p, int x) {} + +void fppi(int** p) {} + +int i; +void fi(int i) {} +*/ import "C" +import ( + "unsafe" +) func main() { s := "" _ = s C.malloc(s) // ERROR HERE + + x := (*C.bar_t)(nil) + C.foop = x // ERROR HERE + + // issue 13129: used to output error about C.unsignedshort with CC=clang + var x C.ushort + x = int(0) // ERROR HERE: C\.ushort + + // issue 13423 + _ = C.fopen() // ERROR HERE + + // issue 13467 + var x rune = '✈' + var _ rune = C.transform(x) // ERROR HERE: C\.int + + // issue 13635: used to output error about C.unsignedchar. + // This test tests all such types. + var ( + _ C.uchar = "uc" // ERROR HERE: C\.uchar + _ C.schar = "sc" // ERROR HERE: C\.schar + _ C.ushort = "us" // ERROR HERE: C\.ushort + _ C.uint = "ui" // ERROR HERE: C\.uint + _ C.ulong = "ul" // ERROR HERE: C\.ulong + _ C.longlong = "ll" // ERROR HERE: C\.longlong + _ C.ulonglong = "ull" // ERROR HERE: C\.ulonglong + _ C.complexfloat = "cf" // ERROR HERE: C\.complexfloat + _ C.complexdouble = "cd" // ERROR HERE: C\.complexdouble + ) + + // issue 13830 + // cgo converts C void* to Go unsafe.Pointer, so despite appearances C + // void** is Go *unsafe.Pointer. This test verifies that we detect the + // problem at build time. + { + type v [0]byte + + f := func(p **v) { + C.F((**C.v)(unsafe.Pointer(p))) // ERROR HERE + } + var p *v + f(&p) + } + + // issue 16116 + _ = C.fvi(1) // ERROR HERE + + // Issue 16591: Test that we detect an invalid call that was being + // hidden by a type conversion inserted by cgo checking. + { + type x *C.int + var p *x + C.fppi(p) // ERROR HERE + } + + // issue 26745 + _ = func(i int) int { + return C.i + 1 // ERROR HERE: :13 + } + _ = func(i int) { + C.fi(i) // ERROR HERE: :6 + } + + C.fi = C.fi // ERROR HERE + } diff --git a/misc/cgo/errors/testdata/err3.go b/misc/cgo/errors/testdata/err3.go deleted file mode 100644 index 609e1a0b74..0000000000 --- a/misc/cgo/errors/testdata/err3.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 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. - -package main - -/* -typedef struct foo foo_t; -typedef struct bar bar_t; - -foo_t *foop; -*/ -import "C" - -func main() { - x := (*C.bar_t)(nil) - C.foop = x // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue13129.go b/misc/cgo/errors/testdata/issue13129.go deleted file mode 100644 index 057bce4b82..0000000000 --- a/misc/cgo/errors/testdata/issue13129.go +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -// issue 13129: used to output error about C.unsignedshort with CC=clang - -package main - -import "C" - -func main() { - var x C.ushort - x = int(0) // ERROR HERE: C\.ushort -} diff --git a/misc/cgo/errors/testdata/issue13423.go b/misc/cgo/errors/testdata/issue13423.go deleted file mode 100644 index fc19157237..0000000000 --- a/misc/cgo/errors/testdata/issue13423.go +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -package main - -// #include -import "C" - -func main() { - _ = C.fopen() // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue13467.go b/misc/cgo/errors/testdata/issue13467.go deleted file mode 100644 index e061880dda..0000000000 --- a/misc/cgo/errors/testdata/issue13467.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 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. - -package p - -/* -static int transform(int x) { return x; } -*/ -import "C" - -func F() { - var x rune = '✈' - var _ rune = C.transform(x) // ERROR HERE: C\.int -} diff --git a/misc/cgo/errors/testdata/issue13635.go b/misc/cgo/errors/testdata/issue13635.go deleted file mode 100644 index 3f38f5df4b..0000000000 --- a/misc/cgo/errors/testdata/issue13635.go +++ /dev/null @@ -1,24 +0,0 @@ -// 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. - -// issue 13635: used to output error about C.unsignedchar. -// This test tests all such types. - -package pkg - -import "C" - -func main() { - var ( - _ C.uchar = "uc" // ERROR HERE: C\.uchar - _ C.schar = "sc" // ERROR HERE: C\.schar - _ C.ushort = "us" // ERROR HERE: C\.ushort - _ C.uint = "ui" // ERROR HERE: C\.uint - _ C.ulong = "ul" // ERROR HERE: C\.ulong - _ C.longlong = "ll" // ERROR HERE: C\.longlong - _ C.ulonglong = "ull" // ERROR HERE: C\.ulonglong - _ C.complexfloat = "cf" // ERROR HERE: C\.complexfloat - _ C.complexdouble = "cd" // ERROR HERE: C\.complexdouble - ) -} diff --git a/misc/cgo/errors/testdata/issue13830.go b/misc/cgo/errors/testdata/issue13830.go deleted file mode 100644 index ac20c82b81..0000000000 --- a/misc/cgo/errors/testdata/issue13830.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016 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. - -// cgo converts C void* to Go unsafe.Pointer, so despite appearances C -// void** is Go *unsafe.Pointer. This test verifies that we detect the -// problem at build time. - -package main - -// typedef void v; -// void F(v** p) {} -import "C" - -import "unsafe" - -type v [0]byte - -func f(p **v) { - C.F((**C.v)(unsafe.Pointer(p))) // ERROR HERE -} - -func main() { - var p *v - f(&p) -} diff --git a/misc/cgo/errors/testdata/issue16116.go b/misc/cgo/errors/testdata/issue16116.go deleted file mode 100644 index 1e01cab844..0000000000 --- a/misc/cgo/errors/testdata/issue16116.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2016 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. - -package main - -// void f(void *p, int x) {} -import "C" - -func main() { - _ = C.f(1) // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue16591.go b/misc/cgo/errors/testdata/issue16591.go deleted file mode 100644 index 10eb8403cf..0000000000 --- a/misc/cgo/errors/testdata/issue16591.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2016 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. - -// Issue 16591: Test that we detect an invalid call that was being -// hidden by a type conversion inserted by cgo checking. - -package p - -// void f(int** p) { } -import "C" - -type x *C.int - -func F(p *x) { - C.f(p) // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue26745.go b/misc/cgo/errors/testdata/issue26745.go deleted file mode 100644 index 0e224538db..0000000000 --- a/misc/cgo/errors/testdata/issue26745.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2018 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. - -package main - -// int a; -// void CF(int i) {} -import "C" - -func F1(i int) int { - return C.a + 1 // ERROR HERE: :13 -} - -func F2(i int) { - C.CF(i) // ERROR HERE: :6 -} diff --git a/misc/cgo/errors/testdata/issue7757.go b/misc/cgo/errors/testdata/issue7757.go deleted file mode 100644 index 0426e9fb7e..0000000000 --- a/misc/cgo/errors/testdata/issue7757.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2014 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. - -package main - -/* -void foo() {} -*/ -import "C" - -func main() { - C.foo = C.foo // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue8442.go b/misc/cgo/errors/testdata/issue8442.go deleted file mode 100644 index 60477ad345..0000000000 --- a/misc/cgo/errors/testdata/issue8442.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 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. - -package main - -// Issue 8442. Cgo output unhelpful error messages for -// invalid C preambles. - -/* -void issue8442foo(UNDEF*); // ERROR HERE -*/ -import "C" - -func main() { - C.issue8442foo(nil) -} diff --git a/misc/cgo/test/align.go b/misc/cgo/test/align.go deleted file mode 100644 index a23b44fc38..0000000000 --- a/misc/cgo/test/align.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2010 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. - -package cgotest - -/* -#include - -typedef unsigned char Uint8; -typedef unsigned short Uint16; - -typedef enum { - MOD1 = 0x0000, - MODX = 0x8000 -} SDLMod; - -typedef enum { - A = 1, - B = 322, - SDLK_LAST -} SDLKey; - -typedef struct SDL_keysym { - Uint8 scancode; - SDLKey sym; - SDLMod mod; - Uint16 unicode; -} SDL_keysym; - -typedef struct SDL_KeyboardEvent { - Uint8 typ; - Uint8 which; - Uint8 state; - SDL_keysym keysym; -} SDL_KeyboardEvent; - -void makeEvent(SDL_KeyboardEvent *event) { - unsigned char *p; - int i; - - p = (unsigned char*)event; - for (i=0; ityp == typ && e->which == which && e->state == state && e->keysym.scancode == scan && e->keysym.sym == sym && e->keysym.mod == mod && e->keysym.unicode == uni; -} - -void cTest(SDL_KeyboardEvent *event) { - printf("C: %#x %#x %#x %#x %#x %#x %#x\n", event->typ, event->which, event->state, - event->keysym.scancode, event->keysym.sym, event->keysym.mod, event->keysym.unicode); - fflush(stdout); -} - -*/ -import "C" - -import ( - "testing" -) - -func testAlign(t *testing.T) { - var evt C.SDL_KeyboardEvent - C.makeEvent(&evt) - if C.same(&evt, evt.typ, evt.which, evt.state, evt.keysym.scancode, evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) == 0 { - t.Error("*** bad alignment") - C.cTest(&evt) - t.Errorf("Go: %#x %#x %#x %#x %#x %#x %#x\n", - evt.typ, evt.which, evt.state, evt.keysym.scancode, - evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) - t.Error(evt) - } -} diff --git a/misc/cgo/test/api.go b/misc/cgo/test/api.go deleted file mode 100644 index d2b09cbeff..0000000000 --- a/misc/cgo/test/api.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 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. - -// API Compatibility Checks for cgo - -package cgotest - -// #include -// -// // Test for issue 17723. -// typedef char *cstring_pointer; -// static void cstring_pointer_fun(cstring_pointer dummy) { } -// -// const char *api_hello = "hello!"; -import "C" -import "unsafe" - -func testAPI() { - var cs *C.char - cs = C.CString("hello") - defer C.free(unsafe.Pointer(cs)) - var s string - s = C.GoString((*C.char)(C.api_hello)) - s = C.GoStringN((*C.char)(C.api_hello), C.int(6)) - var b []byte - b = C.GoBytes(unsafe.Pointer(C.api_hello), C.int(6)) - _, _ = s, b - C.cstring_pointer_fun(nil) -} diff --git a/misc/cgo/test/basic.go b/misc/cgo/test/basic.go deleted file mode 100644 index 2655a66e38..0000000000 --- a/misc/cgo/test/basic.go +++ /dev/null @@ -1,181 +0,0 @@ -// Copyright 2010 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. - -// Basic test cases for cgo. - -package cgotest - -/* -#include -#include -#include -#include - -#define SHIFT(x, y) ((x)<<(y)) -#define KILO SHIFT(1, 10) -#define UINT32VAL 0xc008427bU - -enum E { - Enum1 = 1, - Enum2 = 2, -}; - -typedef unsigned char cgo_uuid_t[20]; - -void uuid_generate(cgo_uuid_t x) { - x[0] = 0; -} - -struct S { - int x; -}; - -const char *cstr = "abcefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - -extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter); - -enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; } - -// issue 1222 -typedef union { - long align; -} xxpthread_mutex_t; - -struct ibv_async_event { - union { - int x; - } element; -}; - -struct ibv_context { - xxpthread_mutex_t mutex; -}; - -int add(int x, int y) { - return x+y; -}; -*/ -import "C" -import ( - "runtime" - "syscall" - "testing" - "unsafe" -) - -const EINVAL = C.EINVAL /* test #define */ - -var KILO = C.KILO - -func uuidgen() { - var uuid C.cgo_uuid_t - C.uuid_generate(&uuid[0]) -} - -func Strtol(s string, base int) (int, error) { - p := C.CString(s) - n, err := C.strtol(p, nil, C.int(base)) - C.free(unsafe.Pointer(p)) - return int(n), err -} - -func Atol(s string) int { - p := C.CString(s) - n := C.atol(p) - C.free(unsafe.Pointer(p)) - return int(n) -} - -func testConst(t *testing.T) { - C.myConstFunc(nil, 0, nil) -} - -func testEnum(t *testing.T) { - if C.Enum1 != 1 || C.Enum2 != 2 { - t.Error("bad enum", C.Enum1, C.Enum2) - } -} - -func testAtol(t *testing.T) { - l := Atol("123") - if l != 123 { - t.Error("Atol 123: ", l) - } -} - -func testErrno(t *testing.T) { - p := C.CString("no-such-file") - m := C.CString("r") - f, err := C.fopen(p, m) - C.free(unsafe.Pointer(p)) - C.free(unsafe.Pointer(m)) - if err == nil { - C.fclose(f) - t.Fatalf("C.fopen: should fail") - } - if err != syscall.ENOENT { - t.Fatalf("C.fopen: unexpected error: %v", err) - } -} - -func testMultipleAssign(t *testing.T) { - p := C.CString("234") - n, m := C.strtol(p, nil, 345), C.strtol(p, nil, 10) - if runtime.GOOS == "openbsd" { - // Bug in OpenBSD strtol(3) - base > 36 succeeds. - if (n != 0 && n != 239089) || m != 234 { - t.Fatal("Strtol x2: ", n, m) - } - } else if n != 0 || m != 234 { - t.Fatal("Strtol x2: ", n, m) - } - C.free(unsafe.Pointer(p)) -} - -var ( - cuint = (C.uint)(0) - culong C.ulong - cchar C.char -) - -type Context struct { - ctx *C.struct_ibv_context -} - -func benchCgoCall(b *testing.B) { - const x = C.int(2) - const y = C.int(3) - for i := 0; i < b.N; i++ { - C.add(x, y) - } -} - -var sinkString string - -func benchGoString(b *testing.B) { - for i := 0; i < b.N; i++ { - sinkString = C.GoString(C.cstr) - } - const want = "abcefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ1234567890" - if sinkString != want { - b.Fatalf("%q != %q", sinkString, want) - } -} - -// Issue 2470. -func testUnsignedInt(t *testing.T) { - a := (int64)(C.UINT32VAL) - b := (int64)(0xc008427b) - if a != b { - t.Errorf("Incorrect unsigned int - got %x, want %x", a, b) - } -} - -// Static (build-time) test that syntax traversal visits all operands of s[i:j:k]. -func sliceOperands(array [2000]int) { - _ = array[C.KILO:C.KILO:C.KILO] // no type error -} - -// set in cgo_thread_lock.go init -var testThreadLockFunc = func(*testing.T) {} diff --git a/misc/cgo/test/cflags.go b/misc/cgo/test/cflags.go deleted file mode 100644 index bc290bfcd5..0000000000 --- a/misc/cgo/test/cflags.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 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. - -// Test that the #cgo CFLAGS directive works, -// with and without platform filters. -// See https://golang.org/issue/5224 for details. -package cgotest - -/* -#cgo CFLAGS: -DCOMMON_VALUE=123 -#cgo windows CFLAGS: -DIS_WINDOWS=1 -#cgo !windows CFLAGS: -DIS_WINDOWS=0 -int common = COMMON_VALUE; -int is_windows = IS_WINDOWS; -*/ -import "C" - -import ( - "runtime" - "testing" -) - -func testCflags(t *testing.T) { - is_windows := C.is_windows == 1 - if is_windows != (runtime.GOOS == "windows") { - t.Errorf("is_windows: %v, runtime.GOOS: %s", is_windows, runtime.GOOS) - } - if C.common != 123 { - t.Errorf("common: %v (expected 123)", C.common) - } -} diff --git a/misc/cgo/test/cgo_stubs_android_test.go b/misc/cgo/test/cgo_stubs_android_test.go index 710e094cf7..a1c2482ab8 100644 --- a/misc/cgo/test/cgo_stubs_android_test.go +++ b/misc/cgo/test/cgo_stubs_android_test.go @@ -8,6 +8,5 @@ import "testing" // Stubs for tests that fails to build on Android func test6997(t *testing.T) {} -func test3775(t *testing.T) {} func test8694(t *testing.T) {} func testSigaltstack(t *testing.T) {} diff --git a/misc/cgo/test/checkconst.go b/misc/cgo/test/checkconst.go deleted file mode 100644 index 0160c1e0ce..0000000000 --- a/misc/cgo/test/checkconst.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2016 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. - -// Test a constant in conjunction with pointer checking. - -package cgotest - -/* -#include - -#define CheckConstVal 0 - -typedef struct { - int *p; -} CheckConstStruct; - -static void CheckConstFunc(CheckConstStruct *p, int e) { -} -*/ -import "C" - -import ( - "testing" - "unsafe" -) - -func testCheckConst(t *testing.T) { - // The test is that this compiles successfully. - p := C.malloc(C.size_t(unsafe.Sizeof(C.int(0)))) - defer C.free(p) - C.CheckConstFunc(&C.CheckConstStruct{(*C.int)(p)}, C.CheckConstVal) -} diff --git a/misc/cgo/test/complex.go b/misc/cgo/test/complex.go deleted file mode 100644 index ca0a97d9b3..0000000000 --- a/misc/cgo/test/complex.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2016 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. - -package cgotest - -/* -struct { - float x; - _Complex float y; -} cplxAlign = { 3.14, 2.17 }; -*/ -import "C" - -import "testing" - -func TestComplexAlign(t *testing.T) { - if C.cplxAlign.x != 3.14 { - t.Errorf("got %v, expected 3.14", C.cplxAlign.x) - } - if C.cplxAlign.y != 2.17 { - t.Errorf("got %v, expected 2.17", C.cplxAlign.y) - } -} diff --git a/misc/cgo/test/cthread.go b/misc/cgo/test/cthread.go deleted file mode 100644 index af44911756..0000000000 --- a/misc/cgo/test/cthread.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -// extern void doAdd(int, int); -import "C" - -import ( - "runtime" - "sync" - "testing" -) - -var sum struct { - sync.Mutex - i int -} - -//export Add -func Add(x int) { - defer func() { - recover() - }() - sum.Lock() - sum.i += x - sum.Unlock() - var p *int - *p = 2 -} - -func testCthread(t *testing.T) { - if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { - t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add") - } - sum.i = 0 - C.doAdd(10, 6) - - want := 10 * (10 - 1) / 2 * 6 - if sum.i != want { - t.Fatalf("sum=%d, want %d", sum.i, want) - } -} diff --git a/misc/cgo/test/duplicate_symbol.go b/misc/cgo/test/duplicate_symbol.go deleted file mode 100644 index 6144271321..0000000000 --- a/misc/cgo/test/duplicate_symbol.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2010 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. - -// This file contains test cases for cgo. - -package cgotest - -/* -int base_symbol = 0; - -#define alias_one base_symbol -#define alias_two base_symbol -*/ -import "C" - -import "fmt" - -func duplicateSymbols() { - fmt.Printf("%v %v %v\n", C.base_symbol, C.alias_one, C.alias_two) -} diff --git a/misc/cgo/test/env.go b/misc/cgo/test/env.go deleted file mode 100644 index e0703e1452..0000000000 --- a/misc/cgo/test/env.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2011 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. - -package cgotest - -/* -#include -*/ -import "C" -import ( - "os" - "runtime" - "testing" - "unsafe" -) - -// This is really an os package test but here for convenience. -func testSetEnv(t *testing.T) { - if runtime.GOOS == "windows" { - // Go uses SetEnvironmentVariable on windows. However, - // C runtime takes a *copy* at process startup of the - // OS environment, and stores it in environ/envp. - // It is this copy that getenv/putenv manipulate. - t.Logf("skipping test") - return - } - const key = "CGO_OS_TEST_KEY" - const val = "CGO_OS_TEST_VALUE" - os.Setenv(key, val) - keyc := C.CString(key) - defer C.free(unsafe.Pointer(keyc)) - v := C.getenv(keyc) - if uintptr(unsafe.Pointer(v)) == 0 { - t.Fatal("getenv returned NULL") - } - vs := C.GoString(v) - if vs != val { - t.Fatalf("getenv() = %q; want %q", vs, val) - } -} diff --git a/misc/cgo/test/exports.go b/misc/cgo/test/exports.go deleted file mode 100644 index 71e5dcdd3d..0000000000 --- a/misc/cgo/test/exports.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2011 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. - -package cgotest - -import "C" -import "runtime" - -//export ReturnIntLong -func ReturnIntLong() (int, C.long) { - return 1, 2 -} - -//export gc -func gc() { - runtime.GC() -} diff --git a/misc/cgo/test/fpvar.go b/misc/cgo/test/fpvar.go deleted file mode 100644 index 7aab8ca2fc..0000000000 --- a/misc/cgo/test/fpvar.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 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. - -// This file contains test cases for cgo with function pointer variables. - -package cgotest - -/* -typedef int (*intFunc) (); - -int -bridge_int_func(intFunc f) -{ - return f(); -} - -int fortytwo() -{ - return 42; -} - -*/ -import "C" -import "testing" - -func callBridge(f C.intFunc) int { - return int(C.bridge_int_func(f)) -} - -func callCBridge(f C.intFunc) C.int { - return C.bridge_int_func(f) -} - -func testFpVar(t *testing.T) { - const expected = 42 - f := C.intFunc(C.fortytwo) - res1 := C.bridge_int_func(f) - if r1 := int(res1); r1 != expected { - t.Errorf("got %d, want %d", r1, expected) - } - res2 := callCBridge(f) - if r2 := int(res2); r2 != expected { - t.Errorf("got %d, want %d", r2, expected) - } - r3 := callBridge(f) - if r3 != expected { - t.Errorf("got %d, want %d", r3, expected) - } -} diff --git a/misc/cgo/test/helpers.go b/misc/cgo/test/helpers.go deleted file mode 100644 index f6a822a106..0000000000 --- a/misc/cgo/test/helpers.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2011 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. - -package cgotest - -// const char *greeting = "hello, world"; -import "C" - -import ( - "reflect" - "testing" - "unsafe" -) - -const greeting = "hello, world" - -type testPair struct { - Name string - Got, Want interface{} -} - -var testPairs = []testPair{ - {"GoString", C.GoString(C.greeting), greeting}, - {"GoStringN", C.GoStringN(C.greeting, 5), greeting[:5]}, - {"GoBytes", C.GoBytes(unsafe.Pointer(C.greeting), 5), []byte(greeting[:5])}, -} - -func testHelpers(t *testing.T) { - for _, pair := range testPairs { - if !reflect.DeepEqual(pair.Got, pair.Want) { - t.Errorf("%s: got %#v, want %#v", pair.Name, pair.Got, pair.Want) - } - } -} diff --git a/misc/cgo/test/issue10303.go b/misc/cgo/test/issue10303.go deleted file mode 100644 index 66e2644d06..0000000000 --- a/misc/cgo/test/issue10303.go +++ /dev/null @@ -1,76 +0,0 @@ -// 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. - -// Issue 10303. Pointers passed to C were not marked as escaping (bug in cgo). - -package cgotest - -import "runtime" - -/* -typedef int *intptr; - -void setintstar(int *x) { - *x = 1; -} - -void setintptr(intptr x) { - *x = 1; -} - -void setvoidptr(void *x) { - *(int*)x = 1; -} - -typedef struct Struct Struct; -struct Struct { - int *P; -}; - -void setstruct(Struct s) { - *s.P = 1; -} - -*/ -import "C" - -import ( - "testing" - "unsafe" -) - -func test10303(t *testing.T, n int) { - if runtime.Compiler == "gccgo" { - t.Skip("gccgo permits C pointers on the stack") - } - - // Run at a few different stack depths just to avoid an unlucky pass - // due to variables ending up on different pages. - if n > 0 { - test10303(t, n-1) - } - if t.Failed() { - return - } - var x, y, z, v, si C.int - var s C.Struct - C.setintstar(&x) - C.setintptr(&y) - C.setvoidptr(unsafe.Pointer(&v)) - s.P = &si - C.setstruct(s) - - if uintptr(unsafe.Pointer(&x))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { - t.Error("C int* argument on stack") - } - if uintptr(unsafe.Pointer(&y))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { - t.Error("C intptr argument on stack") - } - if uintptr(unsafe.Pointer(&v))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { - t.Error("C void* argument on stack") - } - if uintptr(unsafe.Pointer(&si))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { - t.Error("C struct field pointer on stack") - } -} diff --git a/misc/cgo/test/issue11925.go b/misc/cgo/test/issue11925.go deleted file mode 100644 index c5c8a269f7..0000000000 --- a/misc/cgo/test/issue11925.go +++ /dev/null @@ -1,37 +0,0 @@ -// 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. - -// Issue 11925. Structs with zero-length trailing fields are now -// padded by the Go compiler. - -package cgotest - -/* -struct a11925 { - int i; - char a[0]; - char b[0]; -}; - -struct b11925 { - int i; - char a[0]; - char b[]; -}; -*/ -import "C" - -import ( - "testing" - "unsafe" -) - -func test11925(t *testing.T) { - if C.sizeof_struct_a11925 != unsafe.Sizeof(C.struct_a11925{}) { - t.Errorf("size of a changed: C %d, Go %d", C.sizeof_struct_a11925, unsafe.Sizeof(C.struct_a11925{})) - } - if C.sizeof_struct_b11925 != unsafe.Sizeof(C.struct_b11925{}) { - t.Errorf("size of b changed: C %d, Go %d", C.sizeof_struct_b11925, unsafe.Sizeof(C.struct_b11925{})) - } -} diff --git a/misc/cgo/test/issue12030.go b/misc/cgo/test/issue12030.go deleted file mode 100644 index f863c58aa2..0000000000 --- a/misc/cgo/test/issue12030.go +++ /dev/null @@ -1,35 +0,0 @@ -// 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. - -// Issue 12030. sprintf is defined in both ntdll and msvcrt, -// Normally we want the one in the msvcrt. - -package cgotest - -/* -#include -#include -void issue12030conv(char *buf, double x) { - sprintf(buf, "d=%g", x); -} -*/ -import "C" - -import ( - "fmt" - "testing" - "unsafe" -) - -func test12030(t *testing.T) { - buf := (*C.char)(C.malloc(256)) - defer C.free(unsafe.Pointer(buf)) - for _, f := range []float64{1.0, 2.0, 3.14} { - C.issue12030conv(buf, C.double(f)) - got := C.GoString(buf) - if want := fmt.Sprintf("d=%g", f); got != want { - t.Fatalf("C.sprintf failed for %g: %q != %q", f, got, want) - } - } -} diff --git a/misc/cgo/test/issue1222.go b/misc/cgo/test/issue1222.go deleted file mode 100644 index 4868da8e18..0000000000 --- a/misc/cgo/test/issue1222.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2010 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. - -// This file contains test cases for cgo. - -package cgotest - -/* -// issue 1222 -typedef union { - long align; -} xxpthread_mutex_t; - -struct ibv_async_event { - union { - int x; - } element; -}; - -struct ibv_context { - xxpthread_mutex_t mutex; -}; -*/ -import "C" - -type AsyncEvent struct { - event C.struct_ibv_async_event -} diff --git a/misc/cgo/test/issue1328.go b/misc/cgo/test/issue1328.go deleted file mode 100644 index 2401c10e30..0000000000 --- a/misc/cgo/test/issue1328.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2011 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. - -package cgotest - -import "testing" - -// extern void BackIntoGo(void); -// void IntoC(void); -import "C" - -//export BackIntoGo -func BackIntoGo() { - x := 1 - - for i := 0; i < 10000; i++ { - xvariadic(x) - if x != 1 { - panic("x is not 1?") - } - } -} - -func xvariadic(x ...interface{}) { -} - -func test1328(t *testing.T) { - C.IntoC() -} diff --git a/misc/cgo/test/issue13930.go b/misc/cgo/test/issue13930.go deleted file mode 100644 index c4a08ee7c9..0000000000 --- a/misc/cgo/test/issue13930.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2016 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. - -// Issue 13930. Test that cgo's multiple-value special form for -// C function calls works in variable declaration statements. - -package cgotest - -// #include -import "C" - -var _, _ = C.abs(0) diff --git a/misc/cgo/test/issue14838.go b/misc/cgo/test/issue14838.go deleted file mode 100644 index c8e1681295..0000000000 --- a/misc/cgo/test/issue14838.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 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. - -// Issue 14838. add CBytes function - -package cgotest - -/* -#include - -int check_cbytes(char *b, size_t l) { - int i; - for (i = 0; i < l; i++) { - if (b[i] != i) { - return 0; - } - } - return 1; -} -*/ -import "C" - -import ( - "testing" - "unsafe" -) - -func test14838(t *testing.T) { - data := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} - cData := C.CBytes(data) - defer C.free(cData) - - if C.check_cbytes((*C.char)(cData), C.size_t(len(data))) == 0 { - t.Fatalf("mismatched data: expected %v, got %v", data, (*(*[10]byte)(unsafe.Pointer(cData)))[:]) - } -} diff --git a/misc/cgo/test/issue1560.go b/misc/cgo/test/issue1560.go deleted file mode 100644 index 30f6152225..0000000000 --- a/misc/cgo/test/issue1560.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2011 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. - -package cgotest - -/* -// mysleep returns the absolute start time in ms. -long long mysleep(int seconds); - -// twoSleep returns the absolute start time of the first sleep -// in ms. -long long twoSleep(int); -*/ -import "C" - -import ( - "testing" - "time" -) - -var sleepDone = make(chan int64) - -// parallelSleep returns the absolute difference between the start time -// of the two sleeps. -func parallelSleep(n int) int64 { - t := int64(C.twoSleep(C.int(n))) - <-sleepDone - if t < 0 { - return -t - } - return t -} - -//export BackgroundSleep -func BackgroundSleep(n int32) { - go func() { - sleepDone <- int64(C.mysleep(C.int(n))) - }() -} - -func testParallelSleep(t *testing.T) { - sleepSec := 1 - dt := time.Duration(parallelSleep(sleepSec)) * time.Millisecond - t.Logf("difference in start time for two sleep(%d) is %v", sleepSec, dt) - // bug used to run sleeps in serial, producing a 2*sleepSec-second delay. - // we detect if the start times of those sleeps are > 0.5*sleepSec-second. - if dt >= time.Duration(sleepSec)*time.Second/2 { - t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds()) - } -} diff --git a/misc/cgo/test/issue1635.go b/misc/cgo/test/issue1635.go deleted file mode 100644 index 25899271c9..0000000000 --- a/misc/cgo/test/issue1635.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2012 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. - -package cgotest - -/* -// Mac OS X's gcc will generate scattered relocation 2/1 for -// this function on Darwin/386, and 8l couldn't handle it. -// this example is in issue 1635 -#include -void scatter() { - void *p = scatter; - printf("scatter = %p\n", p); -} - -// Adding this explicit extern declaration makes this a test for -// https://gcc.gnu.org/PR68072 aka https://golang.org/issue/13344 . -// It used to cause a cgo error when building with GCC 6. -extern int hola; - -// this example is in issue 3253 -int hola = 0; -int testHola() { return hola; } -*/ -import "C" - -import "testing" - -func test1635(t *testing.T) { - C.scatter() - if v := C.hola; v != 0 { - t.Fatalf("C.hola is %d, should be 0", v) - } - if v := C.testHola(); v != 0 { - t.Fatalf("C.testHola() is %d, should be 0", v) - } -} diff --git a/misc/cgo/test/issue17065.go b/misc/cgo/test/issue17065.go deleted file mode 100644 index ede30bc3e6..0000000000 --- a/misc/cgo/test/issue17065.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2016 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. - -package cgotest - -/* -// Test that C symbols larger than a page play nicely with the race detector. -// See issue 17065. - -int ii[65537]; -*/ -import "C" - -import ( - "runtime" - "testing" -) - -var sink C.int - -func test17065(t *testing.T) { - if runtime.GOOS == "darwin" { - t.Skip("broken on darwin; issue 17065") - } - for i := range C.ii { - sink = C.ii[i] - } -} diff --git a/misc/cgo/test/issue17537.go b/misc/cgo/test/issue17537.go deleted file mode 100644 index 777104e512..0000000000 --- a/misc/cgo/test/issue17537.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 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. - -// Issue 17537. The void* cast introduced by cgo to avoid problems -// with const/volatile qualifiers breaks C preprocessor macros that -// emulate functions. - -package cgotest - -/* -#include - -typedef struct { - int i; -} S17537; - -int I17537(S17537 *p); - -#define I17537(p) ((p)->i) - -// Calling this function used to fail without the cast. -const int F17537(const char **p) { - return **p; -} - -// Calling this function used to trigger an error from the C compiler -// (issue 18298). -void F18298(const void *const *p) { -} - -// Test that conversions between typedefs work as they used to. -typedef const void *T18298_1; -struct S18298 { int i; }; -typedef const struct S18298 *T18298_2; -void G18298(T18298_1 t) { -} -*/ -import "C" - -import "testing" - -func test17537(t *testing.T) { - v := C.S17537{i: 17537} - if got, want := C.I17537(&v), C.int(17537); got != want { - t.Errorf("got %d, want %d", got, want) - } - - p := (*C.char)(C.malloc(1)) - *p = 17 - if got, want := C.F17537(&p), C.int(17); got != want { - t.Errorf("got %d, want %d", got, want) - } - - C.F18298(nil) - var v18298 C.T18298_2 - C.G18298(C.T18298_1(v18298)) -} diff --git a/misc/cgo/test/issue18126.go b/misc/cgo/test/issue18126.go deleted file mode 100644 index ac94a66aab..0000000000 --- a/misc/cgo/test/issue18126.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2016 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. - -// Issue 18126: cgo check of void function returning errno. - -package cgotest - -/* -#include - -void Issue18126C(void **p) { -} -*/ -import "C" - -import ( - "testing" -) - -func test18126(t *testing.T) { - p := C.malloc(1) - _, err := C.Issue18126C(&p) - C.free(p) - _ = err -} diff --git a/misc/cgo/test/issue18146.go b/misc/cgo/test/issue18146.go index 0605a24ee9..196d98f507 100644 --- a/misc/cgo/test/issue18146.go +++ b/misc/cgo/test/issue18146.go @@ -8,8 +8,6 @@ package cgotest -import "C" - import ( "bytes" "crypto/md5" diff --git a/misc/cgo/test/issue18720.go b/misc/cgo/test/issue18720.go deleted file mode 100644 index 3d64003be7..0000000000 --- a/misc/cgo/test/issue18720.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -/* -#define HELLO "hello" -#define WORLD "world" -#define HELLO_WORLD HELLO "\000" WORLD - -struct foo { char c; }; -#define SIZE_OF(x) sizeof(x) -#define SIZE_OF_FOO SIZE_OF(struct foo) -#define VAR1 VAR -#define VAR var -int var = 5; - -#define ADDR &var - -#define CALL fn() -int fn(void) { - return ++var; -} -*/ -import "C" -import "testing" - -func test18720(t *testing.T) { - if got, want := C.HELLO_WORLD, "hello\000world"; got != want { - t.Errorf("C.HELLO_WORLD == %q, expected %q", got, want) - } - - if got, want := C.VAR1, C.int(5); got != want { - t.Errorf("C.VAR1 == %v, expected %v", got, want) - } - - if got, want := *C.ADDR, C.int(5); got != want { - t.Errorf("*C.ADDR == %v, expected %v", got, want) - } - - if got, want := C.CALL, C.int(6); got != want { - t.Errorf("C.CALL == %v, expected %v", got, want) - } - - if got, want := C.CALL, C.int(7); got != want { - t.Errorf("C.CALL == %v, expected %v", got, want) - } - - // Issue 20125. - if got, want := C.SIZE_OF_FOO, 1; got != want { - t.Errorf("C.SIZE_OF_FOO == %v, expected %v", got, want) - } -} diff --git a/misc/cgo/test/issue20129.go b/misc/cgo/test/issue20129.go deleted file mode 100644 index e69e0e16ef..0000000000 --- a/misc/cgo/test/issue20129.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -/* -int issue20129 = 0; -typedef void issue20129Void; -issue20129Void issue20129Foo() { - issue20129 = 1; -} -typedef issue20129Void issue20129Void2; -issue20129Void2 issue20129Bar() { - issue20129 = 2; -} -*/ -import "C" -import "testing" - -func test20129(t *testing.T) { - if C.issue20129 != 0 { - t.Fatal("test is broken") - } - C.issue20129Foo() - if C.issue20129 != 1 { - t.Errorf("got %v but expected %v", C.issue20129, 1) - } - C.issue20129Bar() - if C.issue20129 != 2 { - t.Errorf("got %v but expected %v", C.issue20129, 2) - } -} diff --git a/misc/cgo/test/issue20369.go b/misc/cgo/test/issue20369.go deleted file mode 100644 index 37b4b78dfe..0000000000 --- a/misc/cgo/test/issue20369.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -/* -#define UINT64_MAX 18446744073709551615ULL -*/ -import "C" -import ( - "math" - "testing" -) - -func test20369(t *testing.T) { - if C.UINT64_MAX != math.MaxUint64 { - t.Fatalf("got %v, want %v", uint64(C.UINT64_MAX), uint64(math.MaxUint64)) - } -} diff --git a/misc/cgo/test/issue20910.go b/misc/cgo/test/issue20910.go deleted file mode 100644 index 69d7d9249a..0000000000 --- a/misc/cgo/test/issue20910.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -//void callMulti(void); -import "C" - -import "testing" - -//export multi -func multi() (*C.char, C.int) { - return C.CString("multi"), 0 -} - -func test20910(t *testing.T) { - C.callMulti() -} diff --git a/misc/cgo/test/issue21668.go b/misc/cgo/test/issue21668.go deleted file mode 100644 index f15b9202ac..0000000000 --- a/misc/cgo/test/issue21668.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 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. - -// Fail to guess the kind of the constant "x". -// No runtime test; just make sure it compiles. - -package cgotest - -// const int x = 42; -import "C" - -var issue21668_X = C.x diff --git a/misc/cgo/test/issue21708.go b/misc/cgo/test/issue21708.go deleted file mode 100644 index d413e3c57a..0000000000 --- a/misc/cgo/test/issue21708.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -// #include -// #define CAST_TO_INT64 (int64_t)(-1) -import "C" -import "testing" - -func test21708(t *testing.T) { - if got, want := C.CAST_TO_INT64, -1; got != want { - t.Errorf("C.CAST_TO_INT64 == %v, expected %v", got, want) - } -} diff --git a/misc/cgo/test/issue21809.go b/misc/cgo/test/issue21809.go deleted file mode 100644 index a3a6b88897..0000000000 --- a/misc/cgo/test/issue21809.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -// Issue 21809. Compile C `typedef` to go type aliases. - -// typedef long MySigned_t; -// /* tests alias-to-alias */ -// typedef MySigned_t MySigned2_t; -// -// long takes_long(long x) { return x * x; } -// MySigned_t takes_typedef(MySigned_t x) { return x * x; } -import "C" - -import "testing" - -func test21809(t *testing.T) { - longVar := C.long(3) - typedefVar := C.MySigned_t(4) - typedefTypedefVar := C.MySigned2_t(5) - - // all three should be considered identical to `long` - if ret := C.takes_long(longVar); ret != 9 { - t.Errorf("got %v but expected %v", ret, 9) - } - if ret := C.takes_long(typedefVar); ret != 16 { - t.Errorf("got %v but expected %v", ret, 16) - } - if ret := C.takes_long(typedefTypedefVar); ret != 25 { - t.Errorf("got %v but expected %v", ret, 25) - } - - // They should also be identical to the typedef'd type - if ret := C.takes_typedef(longVar); ret != 9 { - t.Errorf("got %v but expected %v", ret, 9) - } - if ret := C.takes_typedef(typedefVar); ret != 16 { - t.Errorf("got %v but expected %v", ret, 16) - } - if ret := C.takes_typedef(typedefTypedefVar); ret != 25 { - t.Errorf("got %v but expected %v", ret, 25) - } -} diff --git a/misc/cgo/test/issue22958.go b/misc/cgo/test/issue22958.go deleted file mode 100644 index a5f058fdae..0000000000 --- a/misc/cgo/test/issue22958.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -// Test handling of bitfields. - -/* -typedef struct { - unsigned long long f8 : 8; - unsigned long long f16 : 16; - unsigned long long f24 : 24; - unsigned long long f32 : 32; - unsigned long long f40 : 40; - unsigned long long f48 : 48; - unsigned long long f56 : 56; - unsigned long long f64 : 64; -} issue22958Type; -*/ -import "C" - -// Nothing to run, just make sure this compiles. -var Vissue22958 C.issue22958Type diff --git a/misc/cgo/test/issue23356.go b/misc/cgo/test/issue23356.go deleted file mode 100644 index 1c390120c8..0000000000 --- a/misc/cgo/test/issue23356.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 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. - -package cgotest - -// int a(void) { return 5; }; -// int r(void) { return 3; }; -import "C" -import "testing" - -func test23356(t *testing.T) { - if got, want := C.a(), C.int(5); got != want { - t.Errorf("C.a() == %v, expected %v", got, want) - } - if got, want := C.r(), C.int(3); got != want { - t.Errorf("C.r() == %v, expected %v", got, want) - } -} diff --git a/misc/cgo/test/issue23720.go b/misc/cgo/test/issue23720.go deleted file mode 100644 index 934fff3420..0000000000 --- a/misc/cgo/test/issue23720.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2018 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. - -// Test that we can pass compatible typedefs. -// No runtime test; just make sure it compiles. - -package cgotest - -/* -typedef int *issue23720A; - -typedef const int *issue23720B; - -void issue23720F(issue23720B a) {} -*/ -import "C" - -func Issue23720F() { - var x C.issue23720A - C.issue23720F(x) -} diff --git a/misc/cgo/test/issue24206.go b/misc/cgo/test/issue24206.go deleted file mode 100644 index 5fec68e880..0000000000 --- a/misc/cgo/test/issue24206.go +++ /dev/null @@ -1,54 +0,0 @@ -// +build amd64,linux - -// Copyright 2018 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. - -package cgotest - -// Test that C.GoString uses IndexByte in safe manner. - -/* -#include - -// Returns string with null byte at the last valid address -char* dangerousString1() { - int pageSize = 4096; - char *data = mmap(0, 2 * pageSize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0); - mprotect(data + pageSize,pageSize,PROT_NONE); - int start = pageSize - 123 - 1; // last 123 bytes of first page + 1 null byte - int i = start; - for (; i < pageSize; i++) { - data[i] = 'x'; - } - data[pageSize -1 ] = 0; - return data+start; -} - -char* dangerousString2() { - int pageSize = 4096; - char *data = mmap(0, 3 * pageSize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0); - mprotect(data + 2 * pageSize,pageSize,PROT_NONE); - int start = pageSize - 123 - 1; // last 123 bytes of first page + 1 null byte - int i = start; - for (; i < 2 * pageSize; i++) { - data[i] = 'x'; - } - data[2*pageSize -1 ] = 0; - return data+start; -} -*/ -import "C" - -import ( - "testing" -) - -func test24206(t *testing.T) { - if l := len(C.GoString(C.dangerousString1())); l != 123 { - t.Errorf("Incorrect string length - got %d, want 123", l) - } - if l := len(C.GoString(C.dangerousString2())); l != 4096+123 { - t.Errorf("Incorrect string length - got %d, want %d", l, 4096+123) - } -} diff --git a/misc/cgo/test/issue24206_generic.go b/misc/cgo/test/issue24206_generic.go deleted file mode 100644 index 27c4d65f28..0000000000 --- a/misc/cgo/test/issue24206_generic.go +++ /dev/null @@ -1,13 +0,0 @@ -// +build !amd64 !linux - -// Copyright 2018 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. - -package cgotest - -import "testing" - -func test24206(t *testing.T) { - t.Skip("Skipping on non-amd64 or non-linux system") -} diff --git a/misc/cgo/test/issue2462.go b/misc/cgo/test/issue2462.go deleted file mode 100644 index febca1eb08..0000000000 --- a/misc/cgo/test/issue2462.go +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2011 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. - -package cgotest - -import "C" - -//export exportbyte -func exportbyte() byte { - return 0 -} - -//export exportbool -func exportbool() bool { - return false -} - -//export exportrune -func exportrune() rune { - return 0 -} - -//export exporterror -func exporterror() error { - return nil -} - -//export exportint -func exportint() int { - return 0 -} - -//export exportuint -func exportuint() uint { - return 0 -} - -//export exportuintptr -func exportuintptr() uintptr { - return (uintptr)(0) -} - -//export exportint8 -func exportint8() int8 { - return 0 -} - -//export exportuint8 -func exportuint8() uint8 { - return 0 -} - -//export exportint16 -func exportint16() int16 { - return 0 -} - -//export exportuint16 -func exportuint16() uint16 { - return 0 -} - -//export exportint32 -func exportint32() int32 { - return 0 -} - -//export exportuint32 -func exportuint32() uint32 { - return 0 -} - -//export exportint64 -func exportint64() int64 { - return 0 -} - -//export exportuint64 -func exportuint64() uint64 { - return 0 -} - -//export exportfloat32 -func exportfloat32() float32 { - return 0 -} - -//export exportfloat64 -func exportfloat64() float64 { - return 0 -} - -//export exportcomplex64 -func exportcomplex64() complex64 { - return 0 -} - -//export exportcomplex128 -func exportcomplex128() complex128 { - return 0 -} diff --git a/misc/cgo/test/issue25143.go b/misc/cgo/test/issue25143.go deleted file mode 100644 index 607bfe4ba0..0000000000 --- a/misc/cgo/test/issue25143.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2018 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. - -package cgotest - -import "C" -import "testing" - -func issue25143sum(ns ...C.int) C.int { - total := C.int(0) - for _, n := range ns { - total += n - } - return total -} - -func test25143(t *testing.T) { - if got, want := issue25143sum(1, 2, 3), C.int(6); got != want { - t.Errorf("issue25143sum(1, 2, 3) == %v, expected %v", got, want) - } -} diff --git a/misc/cgo/test/issue26066.go b/misc/cgo/test/issue26066.go deleted file mode 100644 index 21028e7479..0000000000 --- a/misc/cgo/test/issue26066.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 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. - -// Wrong type of constant with GCC 8 and newer. - -package cgotest - -// const unsigned long long int issue26066 = (const unsigned long long) -1; -import "C" - -import "testing" - -func test26066(t *testing.T) { - var i = int64(C.issue26066) - if i != -1 { - t.Errorf("got %d, want -1", i) - } -} diff --git a/misc/cgo/test/issue26517.go b/misc/cgo/test/issue26517.go deleted file mode 100644 index c1bf1c9213..0000000000 --- a/misc/cgo/test/issue26517.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2018 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. - -package cgotest - -// Introduce two pointer types which are distinct, but have the same -// base type. Make sure that both of those pointer types get resolved -// correctly. Before the fix for 26517 if one of these pointer types -// was resolved before the other one was processed, the second one -// would never be resolved. -// Before this issue was fixed this test failed on Windows, -// where va_list expands to a named char* type. - -/* -#include -typedef va_list TypeOne; -typedef char *TypeTwo; -*/ -import "C" - -var a C.TypeOne -var b C.TypeTwo diff --git a/misc/cgo/test/issue28545.go b/misc/cgo/test/issue28545.go deleted file mode 100644 index 8419b89c0a..0000000000 --- a/misc/cgo/test/issue28545.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2018 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. - -// Failed to add type conversion for negative constant. -// Issue 28772: Failed to add type conversion for Go constant set to C constant. -// No runtime test; just make sure it compiles. - -package cgotest - -/* -#include - -#define issue28772Constant 1 - -static void issue28545F(char **p, int n, complex double a) {} -*/ -import "C" - -const issue28772Constant = C.issue28772Constant - -func issue28545G(p **C.char) { - C.issue28545F(p, -1, (0)) - C.issue28545F(p, 2+3, complex(1, 1)) - C.issue28545F(p, issue28772Constant, issue28772Constant2) -} diff --git a/misc/cgo/test/issue28772.go b/misc/cgo/test/issue28772.go deleted file mode 100644 index bed786bf30..0000000000 --- a/misc/cgo/test/issue28772.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2018 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. - -package cgotest - -// Constants didn't work if defined in different source file. - -// #define issue28772Constant2 2 -import "C" - -const issue28772Constant2 = C.issue28772Constant2 diff --git a/misc/cgo/test/issue28896.go b/misc/cgo/test/issue28896.go deleted file mode 100644 index 8796040f18..0000000000 --- a/misc/cgo/test/issue28896.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2018 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. - -// cgo was incorrectly adding padding after a packed struct. - -package cgotest - -/* -#include -#include -#include - -typedef struct { - void *f1; - uint32_t f2; -} __attribute__((__packed__)) innerPacked; - -typedef struct { - innerPacked g1; - uint64_t g2; -} outerPacked; - -typedef struct { - void *f1; - uint32_t f2; -} innerUnpacked; - -typedef struct { - innerUnpacked g1; - uint64_t g2; -} outerUnpacked; - -size_t offset(int x) { - switch (x) { - case 0: - return offsetof(innerPacked, f2); - case 1: - return offsetof(outerPacked, g2); - case 2: - return offsetof(innerUnpacked, f2); - case 3: - return offsetof(outerUnpacked, g2); - default: - abort(); - } -} -*/ -import "C" - -import ( - "testing" - "unsafe" -) - -func offset(i int) uintptr { - var pi C.innerPacked - var po C.outerPacked - var ui C.innerUnpacked - var uo C.outerUnpacked - switch i { - case 0: - return unsafe.Offsetof(pi.f2) - case 1: - return unsafe.Offsetof(po.g2) - case 2: - return unsafe.Offsetof(ui.f2) - case 3: - return unsafe.Offsetof(uo.g2) - default: - panic("can't happen") - } -} - -func test28896(t *testing.T) { - for i := 0; i < 4; i++ { - c := uintptr(C.offset(C.int(i))) - g := offset(i) - if c != g { - t.Errorf("%d: C: %d != Go %d", i, c, g) - } - } -} diff --git a/misc/cgo/test/issue29383.go b/misc/cgo/test/issue29383.go deleted file mode 100644 index 462c9a37df..0000000000 --- a/misc/cgo/test/issue29383.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2018 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. - -// cgo's /*line*/ comments failed when inserted after '/', -// because the result looked like a "//" comment. -// No runtime test; just make sure it compiles. - -package cgotest - -// #include -import "C" - -func Issue29383(n, size uint) int { - if ^C.size_t(0)/C.size_t(n) < C.size_t(size) { - return 0 - } - return 0 -} diff --git a/misc/cgo/test/issue29748.go b/misc/cgo/test/issue29748.go deleted file mode 100644 index 8229b3bcf0..0000000000 --- a/misc/cgo/test/issue29748.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 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. - -// Error handling a struct initializer that requires pointer checking. -// Compilation test only, nothing to run. - -package cgotest - -// typedef struct { char **p; } S29748; -// static int f29748(S29748 *p) { return 0; } -import "C" - -var Vissue29748 = C.f29748(&C.S29748{ - nil, -}) - -func Fissue299748() { - C.f29748(&C.S29748{ - nil, - }) -} diff --git a/misc/cgo/test/issue29781.go b/misc/cgo/test/issue29781.go deleted file mode 100644 index c80919dc17..0000000000 --- a/misc/cgo/test/issue29781.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2019 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. - -// Error with newline inserted into constant expression. -// Compilation test only, nothing to run. - -package cgotest - -// static void issue29781F(char **p, int n) {} -// #define ISSUE29781C 0 -import "C" - -var issue29781X struct{ X int } - -func issue29781F(...int) int { return 0 } - -func issue29781G() { - var p *C.char - C.issue29781F(&p, C.ISSUE29781C+1) - C.issue29781F(nil, (C.int)( - 0)) - C.issue29781F(&p, (C.int)(0)) - C.issue29781F(&p, (C.int)( - 0)) - C.issue29781F(&p, (C.int)(issue29781X. - X)) -} diff --git a/misc/cgo/test/issue29878.go b/misc/cgo/test/issue29878.go deleted file mode 100644 index c1aeaf9709..0000000000 --- a/misc/cgo/test/issue29878.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2019 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. - -package cgotest - -// #include -// uint64_t issue29878exported(int8_t); // prototype must match -// int16_t issue29878function(uint32_t arg) { return issue29878exported(arg); } -import "C" - -import "testing" - -func test29878(t *testing.T) { - const arg uint32 = 123 // fits into all integer types - var ret int16 = C.issue29878function(arg) // no conversions needed - if int64(ret) != int64(arg) { - t.Errorf("return value unexpected: got %d, want %d", ret, arg) - } -} diff --git a/misc/cgo/test/issue30065.go b/misc/cgo/test/issue30065.go deleted file mode 100644 index 396d437f7a..0000000000 --- a/misc/cgo/test/issue30065.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2019 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. - -// Don't make a private copy of an array when taking the address of an -// element. - -package cgotest - -// #include -import "C" - -import ( - "testing" - "unsafe" -) - -func test30065(t *testing.T) { - var a [256]byte - b := []byte("a") - C.memcpy(unsafe.Pointer(&a), unsafe.Pointer(&b[0]), 1) - if a[0] != 'a' { - t.Errorf("&a failed: got %c, want %c", a[0], 'a') - } - - b = []byte("b") - C.memcpy(unsafe.Pointer(&a[0]), unsafe.Pointer(&b[0]), 1) - if a[0] != 'b' { - t.Errorf("&a[0] failed: got %c, want %c", a[0], 'b') - } - - d := make([]byte, 256) - b = []byte("c") - C.memcpy(unsafe.Pointer(&d[0]), unsafe.Pointer(&b[0]), 1) - if d[0] != 'c' { - t.Errorf("&d[0] failed: got %c, want %c", d[0], 'c') - } -} diff --git a/misc/cgo/test/issue3250.go b/misc/cgo/test/issue3250.go deleted file mode 100644 index f85c16b2dc..0000000000 --- a/misc/cgo/test/issue3250.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2013 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. - -// +build !windows - -package cgotest - -/* -#include -#include -#include -#include - -static void *thread(void *p) { - const int M = 100; - int i; - (void)p; - for (i = 0; i < M; i++) { - pthread_kill(pthread_self(), SIGCHLD); - usleep(rand() % 20 + 5); - } - return NULL; -} -void testSendSIG() { - const int N = 20; - int i; - pthread_t tid[N]; - for (i = 0; i < N; i++) { - usleep(rand() % 200 + 100); - pthread_create(&tid[i], 0, thread, NULL); - } - for (i = 0; i < N; i++) - pthread_join(tid[i], 0); -} -*/ -import "C" - -import ( - "os" - "os/signal" - "syscall" - "testing" - "time" -) - -func test3250(t *testing.T) { - t.Skip("skipped, see golang.org/issue/5885") - const ( - thres = 1 - sig = syscall.SIGCHLD - ) - type result struct { - n int - sig os.Signal - } - var ( - sigCh = make(chan os.Signal, 10) - waitStart = make(chan struct{}) - waitDone = make(chan result) - ) - - signal.Notify(sigCh, sig) - - go func() { - n := 0 - alarm := time.After(time.Second * 3) - for { - select { - case <-waitStart: - waitStart = nil - case v := <-sigCh: - n++ - if v != sig || n > thres { - waitDone <- result{n, v} - return - } - case <-alarm: - waitDone <- result{n, sig} - return - } - } - }() - - waitStart <- struct{}{} - C.testSendSIG() - r := <-waitDone - if r.sig != sig { - t.Fatalf("received signal %v, but want %v", r.sig, sig) - } - t.Logf("got %d signals\n", r.n) - if r.n <= thres { - t.Fatalf("expected more than %d", thres) - } -} diff --git a/misc/cgo/test/issue3250w.go b/misc/cgo/test/issue3250w.go deleted file mode 100644 index c2193aa1f1..0000000000 --- a/misc/cgo/test/issue3250w.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2013 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. - -// +build windows - -package cgotest - -import "testing" - -func test3250(t *testing.T) {} diff --git a/misc/cgo/test/issue3261.go b/misc/cgo/test/issue3261.go deleted file mode 100644 index 71375698d3..0000000000 --- a/misc/cgo/test/issue3261.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2012 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. - -package cgotest - -/* -// libgcc on ARM might be compiled as thumb code, but our 5l -// can't handle that, so we have to disable this test on arm. -#ifdef __ARMEL__ -#include -int vabs(int x) { - puts("testLibgcc is disabled on ARM because 5l cannot handle thumb library."); - return (x < 0) ? -x : x; -} -#elif defined(__arm64__) && defined(__clang__) -#include -int vabs(int x) { - puts("testLibgcc is disabled on ARM64 with clang due to lack of libgcc."); - return (x < 0) ? -x : x; -} -#else -int __absvsi2(int); // dummy prototype for libgcc function -// we shouldn't name the function abs, as gcc might use -// the builtin one. -int vabs(int x) { return __absvsi2(x); } -#endif -*/ -import "C" - -import "testing" - -func testLibgcc(t *testing.T) { - var table = []struct { - in, out C.int - }{ - {0, 0}, - {1, 1}, - {-42, 42}, - {1000300, 1000300}, - {1 - 1<<31, 1<<31 - 1}, - } - for _, v := range table { - if o := C.vabs(v.in); o != v.out { - t.Fatalf("abs(%d) got %d, should be %d", v.in, o, v.out) - return - } - } -} diff --git a/misc/cgo/test/issue3729.go b/misc/cgo/test/issue3729.go deleted file mode 100644 index 947b90a00d..0000000000 --- a/misc/cgo/test/issue3729.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2012 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. - -// Issue 3729: cmd/cgo: access errno from void C function -// void f(void) returns [0]byte, error in Go world. - -// +build !windows - -package cgotest - -/* -#include - -void g(void) { - errno = E2BIG; -} - -// try to pass some non-trivial arguments to function g2 -const char _expA = 0x42; -const float _expB = 3.14159; -const short _expC = 0x55aa; -const int _expD = 0xdeadbeef; -void g2(int x, char a, float b, short c, int d) { - if (a == _expA && b == _expB && c == _expC && d == _expD) - errno = x; - else - errno = -1; -} -*/ -import "C" - -import ( - "syscall" - "testing" -) - -func test3729(t *testing.T) { - _, e := C.g() - if e != syscall.E2BIG { - t.Errorf("got %q, expect %q", e, syscall.E2BIG) - } - _, e = C.g2(C.EINVAL, C._expA, C._expB, C._expC, C._expD) - if e != syscall.EINVAL { - t.Errorf("got %q, expect %q", e, syscall.EINVAL) - } -} diff --git a/misc/cgo/test/issue3729w.go b/misc/cgo/test/issue3729w.go deleted file mode 100644 index 69296b506e..0000000000 --- a/misc/cgo/test/issue3729w.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2012 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. - -// Issue 3729: cmd/cgo: access errno from void C function -// void f(void) returns [0]byte, error in Go world. - -// +build windows - -package cgotest - -import "testing" - -func test3729(t *testing.T) { - t.Log("skip errno test on Windows") -} diff --git a/misc/cgo/test/issue3741.go b/misc/cgo/test/issue3741.go deleted file mode 100644 index 314038c1fe..0000000000 --- a/misc/cgo/test/issue3741.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 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. - -package cgotest - -import "C" - -//export exportSliceIn -func exportSliceIn(s []byte) bool { - return len(s) == cap(s) -} - -//export exportSliceOut -func exportSliceOut() []byte { - return []byte{1} -} - -//export exportSliceInOut -func exportSliceInOut(s []byte) []byte { - return s -} diff --git a/misc/cgo/test/issue3775.go b/misc/cgo/test/issue3775.go deleted file mode 100644 index 5aca7602c0..0000000000 --- a/misc/cgo/test/issue3775.go +++ /dev/null @@ -1,39 +0,0 @@ -// +build !android - -package cgotest - -/* -void lockOSThreadCallback(void); -inline static void lockOSThreadC(void) -{ - lockOSThreadCallback(); -} -int usleep(unsigned usec); -*/ -import "C" - -import ( - "runtime" - "testing" -) - -func init() { - // Same as test3775 but run during init so that - // there are two levels of internal runtime lock - // (1 for init, 1 for cgo). - // This would have been broken by CL 11663043. - C.lockOSThreadC() -} - -func test3775(t *testing.T) { - // Used to panic because of the UnlockOSThread below. - C.lockOSThreadC() -} - -//export lockOSThreadCallback -func lockOSThreadCallback() { - runtime.LockOSThread() - runtime.UnlockOSThread() - go C.usleep(10000) - runtime.Gosched() -} diff --git a/misc/cgo/test/issue3945.go b/misc/cgo/test/issue3945.go deleted file mode 100644 index 2f9fe23b8d..0000000000 --- a/misc/cgo/test/issue3945.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2012 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. - -package cgotest - -// Test that cgo reserves enough stack space during cgo call. -// See https://golang.org/issue/3945 for details. - -// #include -// -// void say() { -// printf("%s from C\n", "hello"); -// } -// -import "C" - -import "testing" - -func testPrintf(t *testing.T) { - C.say() -} diff --git a/misc/cgo/test/issue4054a.go b/misc/cgo/test/issue4054a.go deleted file mode 100644 index 2abdac5904..0000000000 --- a/misc/cgo/test/issue4054a.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 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. - -package cgotest - -/* -typedef enum { - A = 0, - B, - C, - D, - E, - F, - G, - H, - I, - J, -} issue4054a; -*/ -import "C" - -var issue4054a = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J} diff --git a/misc/cgo/test/issue4054b.go b/misc/cgo/test/issue4054b.go deleted file mode 100644 index 048964c893..0000000000 --- a/misc/cgo/test/issue4054b.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 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. - -package cgotest - -/* -typedef enum { - A = 0, - B, - C, - D, - E, - F, - G, - H, - I, - J, -} issue4054b; -*/ -import "C" - -var issue4054b = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J} diff --git a/misc/cgo/test/issue4339.go b/misc/cgo/test/issue4339.go deleted file mode 100644 index 3715fde575..0000000000 --- a/misc/cgo/test/issue4339.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -/* -// We've historically permitted #include <>, so test it here. Issue 29333. -#include -*/ -import "C" - -import "testing" - -func test4339(t *testing.T) { - C.handle4339(&C.exported4339) -} diff --git a/misc/cgo/test/issue4417.go b/misc/cgo/test/issue4417.go deleted file mode 100644 index 9b182870d8..0000000000 --- a/misc/cgo/test/issue4417.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2012 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. - -// Issue 4417: cmd/cgo: bool alignment/padding issue. -// bool alignment is wrong and causing wrong arguments when calling functions. -// - -package cgotest - -/* -#include - -static int c_bool(bool a, bool b, int c, bool d, bool e) { - return c; -} -*/ -import "C" -import "testing" - -func testBoolAlign(t *testing.T) { - b := C.c_bool(true, true, 10, true, false) - if b != 10 { - t.Fatalf("found %d expected 10\n", b) - } - b = C.c_bool(true, true, 5, true, true) - if b != 5 { - t.Fatalf("found %d expected 5\n", b) - } - b = C.c_bool(true, true, 3, true, false) - if b != 3 { - t.Fatalf("found %d expected 3\n", b) - } - b = C.c_bool(false, false, 1, true, false) - if b != 1 { - t.Fatalf("found %d expected 1\n", b) - } - b = C.c_bool(false, true, 200, true, false) - if b != 200 { - t.Fatalf("found %d expected 200\n", b) - } -} diff --git a/misc/cgo/test/issue4857.go b/misc/cgo/test/issue4857.go deleted file mode 100644 index b18979b5f7..0000000000 --- a/misc/cgo/test/issue4857.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -/* -#cgo CFLAGS: -Werror -const struct { int a; } *issue4857() { return (void *)0; } -*/ -import "C" - -func test4857() { - _ = C.issue4857() -} diff --git a/misc/cgo/test/issue5227.go b/misc/cgo/test/issue5227.go deleted file mode 100644 index 53c3bf12d7..0000000000 --- a/misc/cgo/test/issue5227.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2013 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. - -// Issue 5227: linker incorrectly treats common symbols and -// leaves them undefined. - -package cgotest - -/* -typedef struct { - int Count; -} Fontinfo; - -Fontinfo SansTypeface; - -extern void init(); - -Fontinfo loadfont() { - Fontinfo f = {0}; - return f; -} - -void init() { - SansTypeface = loadfont(); -} -*/ -import "C" - -import "testing" - -func test5227(t *testing.T) { - C.init() -} - -func selectfont() C.Fontinfo { - return C.SansTypeface -} diff --git a/misc/cgo/test/issue5242.go b/misc/cgo/test/issue5242.go deleted file mode 100644 index c81cd40919..0000000000 --- a/misc/cgo/test/issue5242.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 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. - -// Issue 5242. Cgo incorrectly computed the alignment of structs -// with no Go accessible fields as 0, and then panicked on -// modulo-by-zero computations. - -package cgotest - -/* -typedef struct { -} foo; - -typedef struct { - int x : 1; -} bar; - -int issue5242(foo f, bar b) { - return 5242; -} -*/ -import "C" - -import "testing" - -func test5242(t *testing.T) { - if got := C.issue5242(C.foo{}, C.bar{}); got != 5242 { - t.Errorf("got %v", got) - } -} diff --git a/misc/cgo/test/issue5337.go b/misc/cgo/test/issue5337.go deleted file mode 100644 index 9041d95168..0000000000 --- a/misc/cgo/test/issue5337.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 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. - -// +build !windows - -package cgotest - -/* -#include -#include - -static void *thread1(void *p) { - (void)p; - pthread_kill(pthread_self(), SIGPROF); - return NULL; -} -void test5337() { - pthread_t tid; - pthread_create(&tid, 0, thread1, NULL); - pthread_join(tid, 0); -} -*/ -import "C" - -import "testing" - -// Verify that we can withstand SIGPROF received on foreign threads -func test5337(t *testing.T) { - C.test5337() -} diff --git a/misc/cgo/test/issue5337w.go b/misc/cgo/test/issue5337w.go deleted file mode 100644 index 7b46757700..0000000000 --- a/misc/cgo/test/issue5337w.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2013 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. - -// +build windows - -package cgotest - -import "testing" - -func test5337(t *testing.T) {} diff --git a/misc/cgo/test/issue5548.go b/misc/cgo/test/issue5548.go deleted file mode 100644 index 0710da7950..0000000000 --- a/misc/cgo/test/issue5548.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -import "testing" - -/* -extern int issue5548_in_c(void); -*/ -import "C" - -//export issue5548FromC -func issue5548FromC(s string, i int) int { - if len(s) == 4 && s == "test" && i == 42 { - return 12345 - } - println("got", len(s), i) - return 9876 -} - -func test5548(t *testing.T) { - if x := C.issue5548_in_c(); x != 12345 { - t.Errorf("issue5548_in_c = %d, want %d", x, 12345) - } -} diff --git a/misc/cgo/test/issue5603.go b/misc/cgo/test/issue5603.go deleted file mode 100644 index ab84339e10..0000000000 --- a/misc/cgo/test/issue5603.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -/* -const long long issue5603exp = 0x12345678; -long long issue5603foo0() { return issue5603exp; } -long long issue5603foo1(void *p) { return issue5603exp; } -long long issue5603foo2(void *p, void *q) { return issue5603exp; } -long long issue5603foo3(void *p, void *q, void *r) { return issue5603exp; } -long long issue5603foo4(void *p, void *q, void *r, void *s) { return issue5603exp; } -*/ -import "C" - -import "testing" - -func test5603(t *testing.T) { - var x [5]int64 - exp := int64(C.issue5603exp) - x[0] = int64(C.issue5603foo0()) - x[1] = int64(C.issue5603foo1(nil)) - x[2] = int64(C.issue5603foo2(nil, nil)) - x[3] = int64(C.issue5603foo3(nil, nil, nil)) - x[4] = int64(C.issue5603foo4(nil, nil, nil, nil)) - for i, v := range x { - if v != exp { - t.Errorf("issue5603foo%d() returns %v, expected %v", i, v, exp) - } - } -} diff --git a/misc/cgo/test/issue5740.go b/misc/cgo/test/issue5740.go deleted file mode 100644 index 059e316119..0000000000 --- a/misc/cgo/test/issue5740.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -// int test5740a(void), test5740b(void); -import "C" -import "testing" - -func test5740(t *testing.T) { - if v := C.test5740a() + C.test5740b(); v != 5 { - t.Errorf("expected 5, got %v", v) - } -} diff --git a/misc/cgo/test/issue5986.go b/misc/cgo/test/issue5986.go deleted file mode 100644 index 9be1614233..0000000000 --- a/misc/cgo/test/issue5986.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -/* -#cgo LDFLAGS: -lm -#include -#include - -static void output5986() -{ - int current_row = 0, row_count = 0; - double sum_squares = 0; - double d; - do { - if (current_row == 10) { - current_row = 0; - } - ++row_count; - } - while (current_row++ != 1); - d = sqrt(sum_squares / row_count); - printf("sqrt is: %g\n", d); -} -*/ -import "C" -import "testing" - -func test5986(t *testing.T) { - C.output5986() -} diff --git a/misc/cgo/test/issue6128.go b/misc/cgo/test/issue6128.go deleted file mode 100644 index 9832d799b9..0000000000 --- a/misc/cgo/test/issue6128.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -// Test handling of #defined names in clang. -// golang.org/issue/6128. - -/* -// NOTE: Must use hex, or else a shortcut for decimals -// in cgo avoids trying to pass this to clang. -#define X 0x1 -*/ -import "C" - -func test6128() { - // nothing to run, just make sure this compiles. - _ = C.X -} diff --git a/misc/cgo/test/issue6390.go b/misc/cgo/test/issue6390.go deleted file mode 100644 index 5642899c58..0000000000 --- a/misc/cgo/test/issue6390.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -// #include -import "C" - -import "testing" - -func test6390(t *testing.T) { - p1 := C.malloc(1024) - if p1 == nil { - t.Fatalf("C.malloc(1024) returned nil") - } - p2 := C.malloc(0) - if p2 == nil { - t.Fatalf("C.malloc(0) returned nil") - } - C.free(p1) - C.free(p2) -} diff --git a/misc/cgo/test/issue6472.go b/misc/cgo/test/issue6472.go deleted file mode 100644 index d416a05e29..0000000000 --- a/misc/cgo/test/issue6472.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -/* -typedef struct -{ - struct - { - int x; - } y[16]; -} z; -*/ -import "C" - -func test6472() { - // nothing to run, just make sure this compiles - s := new(C.z) - println(s.y[0].x) -} diff --git a/misc/cgo/test/issue6506.go b/misc/cgo/test/issue6506.go deleted file mode 100644 index c54b54b64f..0000000000 --- a/misc/cgo/test/issue6506.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -// Test handling of size_t in the face of incorrect clang debug information. -// golang.org/issue/6506. - -/* -#include -#include -*/ -import "C" - -func test6506() { - // nothing to run, just make sure this compiles - var x C.size_t - - C.calloc(x, x) - C.malloc(x) - C.realloc(nil, x) - C.memcpy(nil, nil, x) - C.memcmp(nil, nil, x) - C.memmove(nil, nil, x) - C.strncpy(nil, nil, x) - C.strncmp(nil, nil, x) - C.strncat(nil, nil, x) - x = C.strxfrm(nil, nil, x) - C.memchr(nil, 0, x) - x = C.strcspn(nil, nil) - x = C.strspn(nil, nil) - C.memset(nil, 0, x) - x = C.strlen(nil) - _ = x -} diff --git a/misc/cgo/test/issue6612.go b/misc/cgo/test/issue6612.go deleted file mode 100644 index 15a12fab38..0000000000 --- a/misc/cgo/test/issue6612.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2013 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. - -// golang.org/issue/6612 -// Test new scheme for deciding whether C.name is an expression, type, constant. -// Clang silences some warnings when the name is a #defined macro, so test those too -// (even though we now use errors exclusively, not warnings). - -package cgotest - -/* -void myfunc(void) {} -int myvar = 5; -const char *mytext = "abcdef"; -typedef int mytype; -enum { - myenum = 1234, -}; - -#define myfunc_def myfunc -#define myvar_def myvar -#define mytext_def mytext -#define mytype_def mytype -#define myenum_def myenum -#define myint_def 12345 -#define myfloat_def 1.5 -#define mystring_def "hello" -*/ -import "C" - -import "testing" - -func testNaming(t *testing.T) { - C.myfunc() - C.myfunc_def() - if v := C.myvar; v != 5 { - t.Errorf("C.myvar = %d, want 5", v) - } - if v := C.myvar_def; v != 5 { - t.Errorf("C.myvar_def = %d, want 5", v) - } - if s := C.GoString(C.mytext); s != "abcdef" { - t.Errorf("C.mytext = %q, want %q", s, "abcdef") - } - if s := C.GoString(C.mytext_def); s != "abcdef" { - t.Errorf("C.mytext_def = %q, want %q", s, "abcdef") - } - if c := C.myenum; c != 1234 { - t.Errorf("C.myenum = %v, want 1234", c) - } - if c := C.myenum_def; c != 1234 { - t.Errorf("C.myenum_def = %v, want 1234", c) - } - { - const c = C.myenum - if c != 1234 { - t.Errorf("C.myenum as const = %v, want 1234", c) - } - } - { - const c = C.myenum_def - if c != 1234 { - t.Errorf("C.myenum as const = %v, want 1234", c) - } - } - if c := C.myint_def; c != 12345 { - t.Errorf("C.myint_def = %v, want 12345", c) - } - { - const c = C.myint_def - if c != 12345 { - t.Errorf("C.myint as const = %v, want 12345", c) - } - } - - if c := C.myfloat_def; c != 1.5 { - t.Errorf("C.myint_def = %v, want 1.5", c) - } - { - const c = C.myfloat_def - if c != 1.5 { - t.Errorf("C.myint as const = %v, want 1.5", c) - } - } - - if s := C.mystring_def; s != "hello" { - t.Errorf("C.mystring_def = %q, want %q", s, "hello") - } -} diff --git a/misc/cgo/test/issue6833.go b/misc/cgo/test/issue6833.go deleted file mode 100644 index de60dbfcf2..0000000000 --- a/misc/cgo/test/issue6833.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -/* -extern unsigned long long issue6833Func(unsigned int, unsigned long long); -*/ -import "C" - -import "testing" - -//export GoIssue6833Func -func GoIssue6833Func(aui uint, aui64 uint64) uint64 { - return aui64 + uint64(aui) -} - -func test6833(t *testing.T) { - ui := 7 - ull := uint64(0x4000300020001000) - v := uint64(C.issue6833Func(C.uint(ui), C.ulonglong(ull))) - exp := uint64(ui) + ull - if v != exp { - t.Errorf("issue6833Func() returns %x, expected %x", v, exp) - } -} diff --git a/misc/cgo/test/issue6907.go b/misc/cgo/test/issue6907.go deleted file mode 100644 index 00495ab8e2..0000000000 --- a/misc/cgo/test/issue6907.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -/* -#include -#include - -char* Issue6907CopyString(_GoString_ s) { - size_t n; - const char *p; - char *r; - - n = _GoStringLen(s); - p = _GoStringPtr(s); - r = malloc(n + 1); - memmove(r, p, n); - r[n] = '\0'; - return r; -} -*/ -import "C" - -import "testing" - -func test6907(t *testing.T) { - want := "yarn" - if got := C.GoString(C.Issue6907CopyString(want)); got != want { - t.Errorf("C.GoString(C.Issue6907CopyString(%q)) == %q, want %q", want, got, want) - } -} diff --git a/misc/cgo/test/issue6907export.go b/misc/cgo/test/issue6907export.go deleted file mode 100644 index d41899e1a6..0000000000 --- a/misc/cgo/test/issue6907export.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2017 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. - -package cgotest - -/* -extern int CheckIssue6907C(_GoString_); -*/ -import "C" - -import ( - "testing" -) - -const CString = "C string" - -//export CheckIssue6907Go -func CheckIssue6907Go(s string) C.int { - if s == CString { - return 1 - } - return 0 -} - -func test6907Go(t *testing.T) { - if got := C.CheckIssue6907C(CString); got != 1 { - t.Errorf("C.CheckIssue6907C() == %d, want %d", got, 1) - } -} diff --git a/misc/cgo/test/issue7560.go b/misc/cgo/test/issue7560.go deleted file mode 100644 index f36d8a1023..0000000000 --- a/misc/cgo/test/issue7560.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2014 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. - -package cgotest - -/* -#include - -typedef struct { - char x; - long y; -} __attribute__((__packed__)) misaligned; - -int -offset7560(void) -{ - return (uintptr_t)&((misaligned*)0)->y; -} -*/ -import "C" - -import ( - "reflect" - "testing" -) - -func test7560(t *testing.T) { - // some mingw don't implement __packed__ correctly. - if C.offset7560() != 1 { - t.Skip("C compiler did not pack struct") - } - - // C.misaligned should have x but then a padding field to get to the end of the struct. - // There should not be a field named 'y'. - var v C.misaligned - rt := reflect.TypeOf(&v).Elem() - if rt.NumField() != 2 || rt.Field(0).Name != "x" || rt.Field(1).Name != "_" { - t.Errorf("unexpected fields in C.misaligned:\n") - for i := 0; i < rt.NumField(); i++ { - t.Logf("%+v\n", rt.Field(i)) - } - } -} diff --git a/misc/cgo/test/issue7665.go b/misc/cgo/test/issue7665.go deleted file mode 100644 index ce0345845f..0000000000 --- a/misc/cgo/test/issue7665.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2013 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. - -package cgotest - -import ( - "testing" - "unsafe" -) - -// extern void f7665(void); -import "C" - -//export f7665 -func f7665() {} - -var bad7665 unsafe.Pointer = C.f7665 -var good7665 uintptr = uintptr(C.f7665) - -func test7665(t *testing.T) { - if bad7665 == nil || uintptr(bad7665) != good7665 { - t.Errorf("ptrs = %p, %#x, want same non-nil pointer", bad7665, good7665) - } -} diff --git a/misc/cgo/test/issue7786.go b/misc/cgo/test/issue7786.go deleted file mode 100644 index 1344e9eda6..0000000000 --- a/misc/cgo/test/issue7786.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2013 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. - -// Issue 7786. No runtime test, just make sure that typedef and struct/union/class are interchangeable at compile time. - -package cgotest - -// struct test7786; -// typedef struct test7786 typedef_test7786; -// void f7786(struct test7786 *ctx) {} -// void g7786(typedef_test7786 *ctx) {} -// -// typedef struct body7786 typedef_body7786; -// struct body7786 { int x; }; -// void b7786(struct body7786 *ctx) {} -// void c7786(typedef_body7786 *ctx) {} -// -// typedef union union7786 typedef_union7786; -// void u7786(union union7786 *ctx) {} -// void v7786(typedef_union7786 *ctx) {} -import "C" - -func f() { - var x1 *C.typedef_test7786 - var x2 *C.struct_test7786 - x1 = x2 - x2 = x1 - C.f7786(x1) - C.f7786(x2) - C.g7786(x1) - C.g7786(x2) - - var b1 *C.typedef_body7786 - var b2 *C.struct_body7786 - b1 = b2 - b2 = b1 - C.b7786(b1) - C.b7786(b2) - C.c7786(b1) - C.c7786(b2) - - var u1 *C.typedef_union7786 - var u2 *C.union_union7786 - u1 = u2 - u2 = u1 - C.u7786(u1) - C.u7786(u2) - C.v7786(u1) - C.v7786(u2) -} diff --git a/misc/cgo/test/issue7978.go b/misc/cgo/test/issue7978.go deleted file mode 100644 index b057e3eacb..0000000000 --- a/misc/cgo/test/issue7978.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2014 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. - -// Issue 7978. Stack tracing didn't work during cgo code after calling a Go -// callback. Make sure GC works and the stack trace is correct. - -package cgotest - -/* -#include - -void issue7978cb(void); - -#if defined(__APPLE__) && defined(__arm__) -// on Darwin/ARM, libSystem doesn't provide implementation of the __sync_fetch_and_add -// primitive, and although gcc supports it, it doesn't inline its definition. -// Clang could inline its definition, so we require clang on Darwin/ARM. -#if defined(__clang__) -#define HAS_SYNC_FETCH_AND_ADD 1 -#else -#define HAS_SYNC_FETCH_AND_ADD 0 -#endif -#else -#define HAS_SYNC_FETCH_AND_ADD 1 -#endif - -// use ugly atomic variable sync since that doesn't require calling back into -// Go code or OS dependencies -static void issue7978c(uint32_t *sync) { -#if HAS_SYNC_FETCH_AND_ADD - while(__sync_fetch_and_add(sync, 0) != 0) - ; - __sync_fetch_and_add(sync, 1); - while(__sync_fetch_and_add(sync, 0) != 2) - ; - issue7978cb(); - __sync_fetch_and_add(sync, 1); - while(__sync_fetch_and_add(sync, 0) != 6) - ; -#endif -} -*/ -import "C" - -import ( - "runtime" - "runtime/debug" - "strings" - "sync/atomic" - "testing" -) - -var issue7978sync uint32 - -func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) { - runtime.GC() - buf := make([]byte, 65536) - trace := string(buf[:runtime.Stack(buf, true)]) - for _, goroutine := range strings.Split(trace, "\n\n") { - if strings.Contains(goroutine, "test.issue7978go") { - trace := strings.Split(goroutine, "\n") - // look for the expected function in the stack - for i := 0; i < depth; i++ { - if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) { - t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine) - return - } - if strings.Contains(trace[1+2*i], wantFunc) { - return - } - } - t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine) - return - } - } - t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace) -} - -func issue7978wait(store uint32, wait uint32) { - if store != 0 { - atomic.StoreUint32(&issue7978sync, store) - } - for atomic.LoadUint32(&issue7978sync) != wait { - runtime.Gosched() - } -} - -//export issue7978cb -func issue7978cb() { - // Force a stack growth from the callback to put extra - // pressure on the runtime. See issue #17785. - growStack(64) - issue7978wait(3, 4) -} - -func growStack(n int) int { - var buf [128]int - if n == 0 { - return 0 - } - return buf[growStack(n-1)] -} - -func issue7978go() { - C.issue7978c((*C.uint32_t)(&issue7978sync)) - issue7978wait(7, 8) -} - -func test7978(t *testing.T) { - if runtime.Compiler == "gccgo" { - t.Skip("gccgo can not do stack traces of C code") - } - if C.HAS_SYNC_FETCH_AND_ADD == 0 { - t.Skip("clang required for __sync_fetch_and_add support on darwin/arm") - } - debug.SetTraceback("2") - issue7978sync = 0 - go issue7978go() - // test in c code, before callback - issue7978wait(0, 1) - issue7978check(t, "_Cfunc_issue7978c(", "", 1) - // test in go code, during callback - issue7978wait(2, 3) - issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3) - // test in c code, after callback - issue7978wait(4, 5) - issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1) - // test in go code, after return from cgo - issue7978wait(6, 7) - issue7978check(t, "test.issue7978go(", "", 3) - atomic.StoreUint32(&issue7978sync, 8) -} diff --git a/misc/cgo/test/issue8092.go b/misc/cgo/test/issue8092.go deleted file mode 100644 index 19123e79cf..0000000000 --- a/misc/cgo/test/issue8092.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2014 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. - -// Issue 8092. Test that linker defined symbols (e.g., text, data) don't -// conflict with C symbols. - -package cgotest - -/* -char text[] = "text"; -char data[] = "data"; -char *ctext(void) { return text; } -char *cdata(void) { return data; } -*/ -import "C" - -import "testing" - -func test8092(t *testing.T) { - tests := []struct { - s string - a, b *C.char - }{ - {"text", &C.text[0], C.ctext()}, - {"data", &C.data[0], C.cdata()}, - } - for _, test := range tests { - if test.a != test.b { - t.Errorf("%s: pointer mismatch: %v != %v", test.s, test.a, test.b) - } - if got := C.GoString(test.a); got != test.s { - t.Errorf("%s: points at %#v, want %#v", test.s, got, test.s) - } - } -} diff --git a/misc/cgo/test/issue8331a.go b/misc/cgo/test/issue8331a.go deleted file mode 100644 index 92e2579e7a..0000000000 --- a/misc/cgo/test/issue8331a.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 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. - -// Issue 8331. A typedef of an unnamed struct is the same struct when -// #include'd twice. No runtime test; just make sure it compiles. - -package cgotest - -// #include "issue8331.h" -import "C" - -func issue8331a() C.issue8331 { - return issue8331Var -} diff --git a/misc/cgo/test/issue8331b.go b/misc/cgo/test/issue8331b.go deleted file mode 100644 index 5324aa2a17..0000000000 --- a/misc/cgo/test/issue8331b.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 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. - -// Issue 8331. A typedef of an unnamed struct is the same struct when -// #include'd twice. No runtime test; just make sure it compiles. - -package cgotest - -// #include "issue8331.h" -import "C" - -var issue8331Var C.issue8331 diff --git a/misc/cgo/test/issue8428.go b/misc/cgo/test/issue8428.go deleted file mode 100644 index 2e5a555b58..0000000000 --- a/misc/cgo/test/issue8428.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2014 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. - -// This test fails on older versions of OS X because they use older buggy -// versions of Clang that emit ambiguous DWARF info. See issue 8611. -// +build !darwin - -package cgotest - -// Issue 8428. Cgo inconsistently translated zero size arrays. - -/* -struct issue8428one { - char b; - char rest[]; -}; - -struct issue8428two { - void *p; - char b; - char rest[0]; - char pad; -}; - -struct issue8428three { - char w[1][2][3][0]; - char x[2][3][0][1]; - char y[3][0][1][2]; - char z[0][1][2][3]; -}; -*/ -import "C" - -import "unsafe" - -var _ = C.struct_issue8428one{ - b: C.char(0), - // The trailing rest field is not available in cgo. - // See issue 11925. - // rest: [0]C.char{}, -} - -var _ = C.struct_issue8428two{ - p: unsafe.Pointer(nil), - b: C.char(0), - rest: [0]C.char{}, -} - -var _ = C.struct_issue8428three{ - w: [1][2][3][0]C.char{}, - x: [2][3][0][1]C.char{}, - y: [3][0][1][2]C.char{}, - z: [0][1][2][3]C.char{}, -} diff --git a/misc/cgo/test/issue8441.go b/misc/cgo/test/issue8441.go deleted file mode 100644 index 4489ca9eb6..0000000000 --- a/misc/cgo/test/issue8441.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 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. - -// Issue 8368 and 8441. Recursive struct definitions didn't work. -// No runtime test; just make sure it compiles. - -package cgotest - -/* -typedef struct one one; -typedef struct two two; -struct one { - two *x; -}; -struct two { - one *x; -}; -*/ -import "C" - -func issue8368(one *C.struct_one, two *C.struct_two) { -} - -func issue8441(one *C.one, two *C.two) { - issue8441(two.x, one.x) -} diff --git a/misc/cgo/test/issue8811.go b/misc/cgo/test/issue8811.go deleted file mode 100644 index f812732cfd..0000000000 --- a/misc/cgo/test/issue8811.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 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. - -package cgotest - -/* -extern int issue8811Initialized; -extern void issue8811Init(); - -void issue8811Execute() { - if(!issue8811Initialized) - issue8811Init(); -} -*/ -import "C" - -import "testing" - -func test8811(t *testing.T) { - C.issue8811Execute() -} diff --git a/misc/cgo/test/issue9557.go b/misc/cgo/test/issue9557.go deleted file mode 100644 index 4e8922a69c..0000000000 --- a/misc/cgo/test/issue9557.go +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -// cgo rewrote C.var to *_Cvar_var, but left -// C.var.field as _Cvar.var.field. It now rewrites -// the latter as (*_Cvar_var).field. -// See https://golang.org/issue/9557. - -package cgotest - -// struct issue9557_t { -// int a; -// } test9557bar = { 42 }; -// -// struct issue9557_t *issue9557foo = &test9557bar; -import "C" -import "testing" - -func test9557(t *testing.T) { - // implicitly dereference a Go variable - foo := C.issue9557foo - if v := foo.a; v != 42 { - t.Fatalf("foo.a expected 42, but got %d", v) - } - - // explicitly dereference a C variable - if v := (*C.issue9557foo).a; v != 42 { - t.Fatalf("(*C.issue9557foo).a expected 42, but is %d", v) - } - - // implicitly dereference a C variable - if v := C.issue9557foo.a; v != 42 { - t.Fatalf("C.issue9557foo.a expected 42, but is %d", v) - } -} diff --git a/misc/cgo/test/test.go b/misc/cgo/test/test.go new file mode 100644 index 0000000000..b23fca0d0f --- /dev/null +++ b/misc/cgo/test/test.go @@ -0,0 +1,2087 @@ +// Copyright 2010 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. + +// Test cases for cgo. +// Both the import "C" prologue and the main file are sorted by issue number. +// This file contains C definitions (not just declarations) +// and so it must NOT contain any //export directives on Go functions. +// See testx.go for exports. + +package cgotest + +/* +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#cgo LDFLAGS: -lm + +#ifndef WIN32 +#include +#include +#endif + +// alignment tests + +typedef unsigned char Uint8; +typedef unsigned short Uint16; + +typedef enum { + MOD1 = 0x0000, + MODX = 0x8000 +} SDLMod; + +typedef enum { + A1 = 1, + B1 = 322, + SDLK_LAST +} SDLKey; + +typedef struct SDL_keysym { + Uint8 scancode; + SDLKey sym; + SDLMod mod; + Uint16 unicode; +} SDL_keysym; + +typedef struct SDL_KeyboardEvent { + Uint8 typ; + Uint8 which; + Uint8 state; + SDL_keysym keysym; +} SDL_KeyboardEvent; + +void makeEvent(SDL_KeyboardEvent *event) { + unsigned char *p; + int i; + + p = (unsigned char*)event; + for (i=0; ityp == typ && e->which == which && e->state == state && e->keysym.scancode == scan && e->keysym.sym == sym && e->keysym.mod == mod && e->keysym.unicode == uni; +} + +void cTest(SDL_KeyboardEvent *event) { + printf("C: %#x %#x %#x %#x %#x %#x %#x\n", event->typ, event->which, event->state, + event->keysym.scancode, event->keysym.sym, event->keysym.mod, event->keysym.unicode); + fflush(stdout); +} + +// api + +const char *greeting = "hello, world"; + +// basic test cases + +#define SHIFT(x, y) ((x)<<(y)) +#define KILO SHIFT(1, 10) +#define UINT32VAL 0xc008427bU + +enum E { + Enum1 = 1, + Enum2 = 2, +}; + +typedef unsigned char cgo_uuid_t[20]; + +void uuid_generate(cgo_uuid_t x) { + x[0] = 0; +} + +struct S { + int x; +}; + +const char *cstr = "abcefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + +extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter); + +enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; } + +int add(int x, int y) { + return x+y; +}; + +// complex alignment + +struct { + float x; + _Complex float y; +} cplxAlign = { 3.14, 2.17 }; + +// constants and pointer checking + +#define CheckConstVal 0 + +typedef struct { + int *p; +} CheckConstStruct; + +static void CheckConstFunc(CheckConstStruct *p, int e) {} + +// duplicate symbol + +int base_symbol = 0; +#define alias_one base_symbol +#define alias_two base_symbol + +// function pointer variables + +typedef int (*intFunc) (); + +int +bridge_int_func(intFunc f) +{ + return f(); +} + +int fortytwo() +{ + return 42; +} + +// issue 1222 +typedef union { + long align; +} xxpthread_mutex_t; +struct ibv_async_event { + union { + int x; + } element; +}; +struct ibv_context { + xxpthread_mutex_t mutex; +}; + +// issue 1635 +// Mac OS X's gcc will generate scattered relocation 2/1 for +// this function on Darwin/386, and 8l couldn't handle it. +// this example is in issue 1635 +void scatter() { + void *p = scatter; + printf("scatter = %p\n", p); +} + +// Adding this explicit extern declaration makes this a test for +// https://gcc.gnu.org/PR68072 aka https://golang.org/issue/13344 . +// It used to cause a cgo error when building with GCC 6. +extern int hola; + +// this example is in issue 3253 +int hola = 0; +int testHola() { return hola; } + +// issue 3250 +#ifdef WIN32 +void testSendSIG() {} +#else +static void *thread(void *p) { + const int M = 100; + int i; + (void)p; + for (i = 0; i < M; i++) { + pthread_kill(pthread_self(), SIGCHLD); + usleep(rand() % 20 + 5); + } + return NULL; +} +void testSendSIG() { + const int N = 20; + int i; + pthread_t tid[N]; + for (i = 0; i < N; i++) { + usleep(rand() % 200 + 100); + pthread_create(&tid[i], 0, thread, NULL); + } + for (i = 0; i < N; i++) + pthread_join(tid[i], 0); +} +#endif + +// issue 3261 +// libgcc on ARM might be compiled as thumb code, but our 5l +// can't handle that, so we have to disable this test on arm. +#ifdef __ARMEL__ +int vabs(int x) { + puts("testLibgcc is disabled on ARM because 5l cannot handle thumb library."); + return (x < 0) ? -x : x; +} +#elif defined(__arm64__) && defined(__clang__) +int vabs(int x) { + puts("testLibgcc is disabled on ARM64 with clang due to lack of libgcc."); + return (x < 0) ? -x : x; +} +#else +int __absvsi2(int); // dummy prototype for libgcc function +// we shouldn't name the function abs, as gcc might use +// the builtin one. +int vabs(int x) { return __absvsi2(x); } +#endif + + +// issue 3729 +// access errno from void C function +const char _expA = 0x42; +const float _expB = 3.14159; +const short _expC = 0x55aa; +const int _expD = 0xdeadbeef; + +#ifdef WIN32 +void g(void) {} +void g2(int x, char a, float b, short c, int d) {} +#else + +void g(void) { + errno = E2BIG; +} + +// try to pass some non-trivial arguments to function g2 +void g2(int x, char a, float b, short c, int d) { + if (a == _expA && b == _expB && c == _expC && d == _expD) + errno = x; + else + errno = -1; +} +#endif + +// issue 3945 +// Test that cgo reserves enough stack space during cgo call. +// See https://golang.org/issue/3945 for details. +void say() { + printf("%s from C\n", "hello"); +} + +// issue 4054 part 1 - other half in testx.go + +typedef enum { + A = 0, + B, + C, + D, + E, + F, + G, + H, + II, + J, +} issue4054a; + +// issue 4339 +// We've historically permitted #include <>, so test it here. Issue 29333. +#include + +// issue 4417 +// cmd/cgo: bool alignment/padding issue. +// bool alignment is wrong and causing wrong arguments when calling functions. +static int c_bool(bool a, bool b, int c, bool d, bool e) { + return c; +} + +// issue 4857 +#cgo CFLAGS: -Werror +const struct { int a; } *issue4857() { return (void *)0; } + +// issue 5224 +// Test that the #cgo CFLAGS directive works, +// with and without platform filters. +#cgo CFLAGS: -DCOMMON_VALUE=123 +#cgo windows CFLAGS: -DIS_WINDOWS=1 +#cgo !windows CFLAGS: -DIS_WINDOWS=0 +int common = COMMON_VALUE; +int is_windows = IS_WINDOWS; + +// issue 5227 +// linker incorrectly treats common symbols and +// leaves them undefined. + +typedef struct { + int Count; +} Fontinfo; + +Fontinfo SansTypeface; + +extern void init(); + +Fontinfo loadfont() { + Fontinfo f = {0}; + return f; +} + +void init() { + SansTypeface = loadfont(); +} + +// issue 5242 +// Cgo incorrectly computed the alignment of structs +// with no Go accessible fields as 0, and then panicked on +// modulo-by-zero computations. +typedef struct { +} foo; + +typedef struct { + int x : 1; +} bar; + +int issue5242(foo f, bar b) { + return 5242; +} + +// issue 5337 +// Verify that we can withstand SIGPROF received on foreign threads + +#ifdef WIN32 +void test5337() {} +#else +static void *thread1(void *p) { + (void)p; + pthread_kill(pthread_self(), SIGPROF); + return NULL; +} +void test5337() { + pthread_t tid; + pthread_create(&tid, 0, thread1, NULL); + pthread_join(tid, 0); +} +#endif + +// issue 5603 + +const long long issue5603exp = 0x12345678; +long long issue5603foo0() { return issue5603exp; } +long long issue5603foo1(void *p) { return issue5603exp; } +long long issue5603foo2(void *p, void *q) { return issue5603exp; } +long long issue5603foo3(void *p, void *q, void *r) { return issue5603exp; } +long long issue5603foo4(void *p, void *q, void *r, void *s) { return issue5603exp; } + +// issue 5740 + +int test5740a(void), test5740b(void); + +// issue 5986 +static void output5986() +{ + int current_row = 0, row_count = 0; + double sum_squares = 0; + double d; + do { + if (current_row == 10) { + current_row = 0; + } + ++row_count; + } + while (current_row++ != 1); + d = sqrt(sum_squares / row_count); + printf("sqrt is: %g\n", d); +} + +// issue 6128 +// Test handling of #defined names in clang. +// NOTE: Must use hex, or else a shortcut for decimals +// in cgo avoids trying to pass this to clang. +#define X 0x1 + +// issue 6472 +typedef struct +{ + struct + { + int x; + } y[16]; +} z; + +// issue 6612 +// Test new scheme for deciding whether C.name is an expression, type, constant. +// Clang silences some warnings when the name is a #defined macro, so test those too +// (even though we now use errors exclusively, not warnings). + +void myfunc(void) {} +int myvar = 5; +const char *mytext = "abcdef"; +typedef int mytype; +enum { + myenum = 1234, +}; + +#define myfunc_def myfunc +#define myvar_def myvar +#define mytext_def mytext +#define mytype_def mytype +#define myenum_def myenum +#define myint_def 12345 +#define myfloat_def 1.5 +#define mystring_def "hello" + +// issue 6907 +char* Issue6907CopyString(_GoString_ s) { + size_t n; + const char *p; + char *r; + + n = _GoStringLen(s); + p = _GoStringPtr(s); + r = malloc(n + 1); + memmove(r, p, n); + r[n] = '\0'; + return r; +} + +// issue 7560 +typedef struct { + char x; + long y; +} __attribute__((__packed__)) misaligned; + +int +offset7560(void) +{ + return (uintptr_t)&((misaligned*)0)->y; +} + +// issue 7786 +// No runtime test, just make sure that typedef and struct/union/class are interchangeable at compile time. + +struct test7786; +typedef struct test7786 typedef_test7786; +void f7786(struct test7786 *ctx) {} +void g7786(typedef_test7786 *ctx) {} + +typedef struct body7786 typedef_body7786; +struct body7786 { int x; }; +void b7786(struct body7786 *ctx) {} +void c7786(typedef_body7786 *ctx) {} + +typedef union union7786 typedef_union7786; +void u7786(union union7786 *ctx) {} +void v7786(typedef_union7786 *ctx) {} + +// issue 8092 +// Test that linker defined symbols (e.g., text, data) don't +// conflict with C symbols. +char text[] = "text"; +char data[] = "data"; +char *ctext(void) { return text; } +char *cdata(void) { return data; } + +// issue 8428 +// Cgo inconsistently translated zero size arrays. + +struct issue8428one { + char b; + char rest[]; +}; + +struct issue8428two { + void *p; + char b; + char rest[0]; + char pad; +}; + +struct issue8428three { + char w[1][2][3][0]; + char x[2][3][0][1]; + char y[3][0][1][2]; + char z[0][1][2][3]; +}; + +// issue 8331 part 1 - part 2 in testx.go +// A typedef of an unnamed struct is the same struct when +// #include'd twice. No runtime test; just make sure it compiles. +#include "issue8331.h" + +// issue 8368 and 8441 +// Recursive struct definitions didn't work. +// No runtime test; just make sure it compiles. +typedef struct one one; +typedef struct two two; +struct one { + two *x; +}; +struct two { + one *x; +}; + +// issue 8811 + +extern int issue8811Initialized; +extern void issue8811Init(); + +void issue8811Execute() { + if(!issue8811Initialized) + issue8811Init(); +} + +// issue 9557 + +struct issue9557_t { + int a; +} test9557bar = { 42 }; +struct issue9557_t *issue9557foo = &test9557bar; + +// issue 10303 +// Pointers passed to C were not marked as escaping (bug in cgo). + +typedef int *intptr; + +void setintstar(int *x) { + *x = 1; +} + +void setintptr(intptr x) { + *x = 1; +} + +void setvoidptr(void *x) { + *(int*)x = 1; +} + +typedef struct Struct Struct; +struct Struct { + int *P; +}; + +void setstruct(Struct s) { + *s.P = 1; +} + +// issue 11925 +// Structs with zero-length trailing fields are now padded by the Go compiler. + +struct a11925 { + int i; + char a[0]; + char b[0]; +}; + +struct b11925 { + int i; + char a[0]; + char b[]; +}; + +// issue 12030 +void issue12030conv(char *buf, double x) { + sprintf(buf, "d=%g", x); +} + +// issue 14838 + +int check_cbytes(char *b, size_t l) { + int i; + for (i = 0; i < l; i++) { + if (b[i] != i) { + return 0; + } + } + return 1; +} + +// issue 17065 +// Test that C symbols larger than a page play nicely with the race detector. +int ii[65537]; + +// issue 17537 +// The void* cast introduced by cgo to avoid problems +// with const/volatile qualifiers breaks C preprocessor macros that +// emulate functions. + +typedef struct { + int i; +} S17537; + +int I17537(S17537 *p); + +#define I17537(p) ((p)->i) + +// Calling this function used to fail without the cast. +const int F17537(const char **p) { + return **p; +} + +// issue 17723 +// API compatibility checks + +typedef char *cstring_pointer; +static void cstring_pointer_fun(cstring_pointer dummy) { } +const char *api_hello = "hello!"; + +// Calling this function used to trigger an error from the C compiler +// (issue 18298). +void F18298(const void *const *p) { +} + +// Test that conversions between typedefs work as they used to. +typedef const void *T18298_1; +struct S18298 { int i; }; +typedef const struct S18298 *T18298_2; +void G18298(T18298_1 t) { +} + +// issue 18126 +// cgo check of void function returning errno. +void Issue18126C(void **p) {} + +// issue 18720 + +#define HELLO "hello" +#define WORLD "world" +#define HELLO_WORLD HELLO "\000" WORLD + +struct foo { char c; }; +#define SIZE_OF(x) sizeof(x) +#define SIZE_OF_FOO SIZE_OF(struct foo) +#define VAR1 VAR +#define VAR var +int var = 5; + +#define ADDR &var + +#define CALL fn() +int fn(void) { + return ++var; +} + +// issue 20129 + +int issue20129 = 0; +typedef void issue20129Void; +issue20129Void issue20129Foo() { + issue20129 = 1; +} +typedef issue20129Void issue20129Void2; +issue20129Void2 issue20129Bar() { + issue20129 = 2; +} + +// issue 20369 +#define XUINT64_MAX 18446744073709551615ULL + +// issue 21668 +// Fail to guess the kind of the constant "x". +// No runtime test; just make sure it compiles. +const int x21668 = 42; + +// issue 21708 +#define CAST_TO_INT64 (int64_t)(-1) + +// issue 21809 +// Compile C `typedef` to go type aliases. + +typedef long MySigned_t; +// tests alias-to-alias +typedef MySigned_t MySigned2_t; +long takes_long(long x) { return x * x; } +MySigned_t takes_typedef(MySigned_t x) { return x * x; } + +// issue 22906 + +// It's going to be hard to include a whole real JVM to test this. +// So we'll simulate a really easy JVM using just the parts we need. +// This is the relevant part of jni.h. + +struct _jobject; + +typedef struct _jobject *jobject; +typedef jobject jclass; +typedef jobject jthrowable; +typedef jobject jstring; +typedef jobject jarray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jarray jobjectArray; + +typedef jobject jweak; + +// Note: jvalue is already a non-pointer type due to it being a C union. + +// issue 22958 + +typedef struct { + unsigned long long f8 : 8; + unsigned long long f16 : 16; + unsigned long long f24 : 24; + unsigned long long f32 : 32; + unsigned long long f40 : 40; + unsigned long long f48 : 48; + unsigned long long f56 : 56; + unsigned long long f64 : 64; +} issue22958Type; + +// issue 23356 +int a(void) { return 5; }; +int r(void) { return 3; }; + +// issue 23720 +typedef int *issue23720A; +typedef const int *issue23720B; +void issue23720F(issue23720B a) {} + +// issue 24206 +#if defined(__linux__) && defined(__x86_64__) +#include +// Returns string with null byte at the last valid address +char* dangerousString1() { + int pageSize = 4096; + char *data = mmap(0, 2 * pageSize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0); + mprotect(data + pageSize,pageSize,PROT_NONE); + int start = pageSize - 123 - 1; // last 123 bytes of first page + 1 null byte + int i = start; + for (; i < pageSize; i++) { + data[i] = 'x'; + } + data[pageSize -1 ] = 0; + return data+start; +} + +char* dangerousString2() { + int pageSize = 4096; + char *data = mmap(0, 3 * pageSize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0); + mprotect(data + 2 * pageSize,pageSize,PROT_NONE); + int start = pageSize - 123 - 1; // last 123 bytes of first page + 1 null byte + int i = start; + for (; i < 2 * pageSize; i++) { + data[i] = 'x'; + } + data[2*pageSize -1 ] = 0; + return data+start; +} +#else +char *dangerousString1() { return NULL; } +char *dangerousString2() { return NULL; } +#endif + +// issue 26066 +const unsigned long long int issue26066 = (const unsigned long long) -1; + +// issue 26517 +// Introduce two pointer types which are distinct, but have the same +// base type. Make sure that both of those pointer types get resolved +// correctly. Before the fix for 26517 if one of these pointer types +// was resolved before the other one was processed, the second one +// would never be resolved. +// Before this issue was fixed this test failed on Windows, +// where va_list expands to a named char* type. +typedef va_list TypeOne; +typedef char *TypeTwo; + +// issue 28540 + +static void twoargs1(void *p, int n) {} +static void *twoargs2() { return 0; } +static int twoargs3(void * p) { return 0; } + +// issue 28545 +// Failed to add type conversion for negative constant. + +static void issue28545F(char **p, int n, complex double a) {} + +// issue 28772 part 1 - part 2 in testx.go +// Failed to add type conversion for Go constant set to C constant. +// No runtime test; just make sure it compiles. + +#define issue28772Constant 1 + +// issue 28896 +// cgo was incorrectly adding padding after a packed struct. +typedef struct { + void *f1; + uint32_t f2; +} __attribute__((__packed__)) innerPacked; + +typedef struct { + innerPacked g1; + uint64_t g2; +} outerPacked; + +typedef struct { + void *f1; + uint32_t f2; +} innerUnpacked; + +typedef struct { + innerUnpacked g1; + uint64_t g2; +} outerUnpacked; + +size_t offset(int x) { + switch (x) { + case 0: + return offsetof(innerPacked, f2); + case 1: + return offsetof(outerPacked, g2); + case 2: + return offsetof(innerUnpacked, f2); + case 3: + return offsetof(outerUnpacked, g2); + default: + abort(); + } +} + +// issue 29748 + +typedef struct { char **p; } S29748; +static int f29748(S29748 *p) { return 0; } + +// issue 29781 +// Error with newline inserted into constant expression. +// Compilation test only, nothing to run. + +static void issue29781F(char **p, int n) {} +#define ISSUE29781C 0 + +// issue 29878 +uint64_t issue29878exported(int8_t); // prototype must match +int16_t issue29878function(uint32_t arg) { return issue29878exported(arg); } + +*/ +import "C" + +import ( + "context" + "fmt" + "math" + "math/rand" + "os" + "os/signal" + "reflect" + "runtime" + "sync" + "syscall" + "testing" + "time" + "unsafe" +) + +// alignment + +func testAlign(t *testing.T) { + var evt C.SDL_KeyboardEvent + C.makeEvent(&evt) + if C.same(&evt, evt.typ, evt.which, evt.state, evt.keysym.scancode, evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) == 0 { + t.Error("*** bad alignment") + C.cTest(&evt) + t.Errorf("Go: %#x %#x %#x %#x %#x %#x %#x\n", + evt.typ, evt.which, evt.state, evt.keysym.scancode, + evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) + t.Error(evt) + } +} + +// api + +const greeting = "hello, world" + +type testPair struct { + Name string + Got, Want interface{} +} + +var testPairs = []testPair{ + {"GoString", C.GoString(C.greeting), greeting}, + {"GoStringN", C.GoStringN(C.greeting, 5), greeting[:5]}, + {"GoBytes", C.GoBytes(unsafe.Pointer(C.greeting), 5), []byte(greeting[:5])}, +} + +func testHelpers(t *testing.T) { + for _, pair := range testPairs { + if !reflect.DeepEqual(pair.Got, pair.Want) { + t.Errorf("%s: got %#v, want %#v", pair.Name, pair.Got, pair.Want) + } + } +} + +// basic test cases + +const EINVAL = C.EINVAL /* test #define */ + +var KILO = C.KILO + +func uuidgen() { + var uuid C.cgo_uuid_t + C.uuid_generate(&uuid[0]) +} + +func Strtol(s string, base int) (int, error) { + p := C.CString(s) + n, err := C.strtol(p, nil, C.int(base)) + C.free(unsafe.Pointer(p)) + return int(n), err +} + +func Atol(s string) int { + p := C.CString(s) + n := C.atol(p) + C.free(unsafe.Pointer(p)) + return int(n) +} + +func testConst(t *testing.T) { + C.myConstFunc(nil, 0, nil) +} + +func testEnum(t *testing.T) { + if C.Enum1 != 1 || C.Enum2 != 2 { + t.Error("bad enum", C.Enum1, C.Enum2) + } +} + +func testAtol(t *testing.T) { + l := Atol("123") + if l != 123 { + t.Error("Atol 123: ", l) + } +} + +func testErrno(t *testing.T) { + p := C.CString("no-such-file") + m := C.CString("r") + f, err := C.fopen(p, m) + C.free(unsafe.Pointer(p)) + C.free(unsafe.Pointer(m)) + if err == nil { + C.fclose(f) + t.Fatalf("C.fopen: should fail") + } + if err != syscall.ENOENT { + t.Fatalf("C.fopen: unexpected error: %v", err) + } +} + +func testMultipleAssign(t *testing.T) { + p := C.CString("234") + n, m := C.strtol(p, nil, 345), C.strtol(p, nil, 10) + if runtime.GOOS == "openbsd" { + // Bug in OpenBSD strtol(3) - base > 36 succeeds. + if (n != 0 && n != 239089) || m != 234 { + t.Fatal("Strtol x2: ", n, m) + } + } else if n != 0 || m != 234 { + t.Fatal("Strtol x2: ", n, m) + } + C.free(unsafe.Pointer(p)) +} + +var ( + cuint = (C.uint)(0) + culong C.ulong + cchar C.char +) + +type Context struct { + ctx *C.struct_ibv_context +} + +func benchCgoCall(b *testing.B) { + const x = C.int(2) + const y = C.int(3) + for i := 0; i < b.N; i++ { + C.add(x, y) + } +} + +var sinkString string + +func benchGoString(b *testing.B) { + for i := 0; i < b.N; i++ { + sinkString = C.GoString(C.cstr) + } + const want = "abcefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ1234567890" + if sinkString != want { + b.Fatalf("%q != %q", sinkString, want) + } +} + +// Static (build-time) test that syntax traversal visits all operands of s[i:j:k]. +func sliceOperands(array [2000]int) { + _ = array[C.KILO:C.KILO:C.KILO] // no type error +} + +// set in cgo_thread_lock.go init +var testThreadLockFunc = func(*testing.T) {} + +// complex alignment + +func TestComplexAlign(t *testing.T) { + if C.cplxAlign.x != 3.14 { + t.Errorf("got %v, expected 3.14", C.cplxAlign.x) + } + if C.cplxAlign.y != 2.17 { + t.Errorf("got %v, expected 2.17", C.cplxAlign.y) + } +} + +// constants and pointer checking + +func testCheckConst(t *testing.T) { + // The test is that this compiles successfully. + p := C.malloc(C.size_t(unsafe.Sizeof(C.int(0)))) + defer C.free(p) + C.CheckConstFunc(&C.CheckConstStruct{(*C.int)(p)}, C.CheckConstVal) +} + +// duplicate symbol + +func duplicateSymbols() { + fmt.Printf("%v %v %v\n", C.base_symbol, C.alias_one, C.alias_two) +} + +// environment + +// This is really an os package test but here for convenience. +func testSetEnv(t *testing.T) { + if runtime.GOOS == "windows" { + // Go uses SetEnvironmentVariable on windows. However, + // C runtime takes a *copy* at process startup of the + // OS environment, and stores it in environ/envp. + // It is this copy that getenv/putenv manipulate. + t.Logf("skipping test") + return + } + const key = "CGO_OS_TEST_KEY" + const val = "CGO_OS_TEST_VALUE" + os.Setenv(key, val) + keyc := C.CString(key) + defer C.free(unsafe.Pointer(keyc)) + v := C.getenv(keyc) + if uintptr(unsafe.Pointer(v)) == 0 { + t.Fatal("getenv returned NULL") + } + vs := C.GoString(v) + if vs != val { + t.Fatalf("getenv() = %q; want %q", vs, val) + } +} + +// function pointer variables + +func callBridge(f C.intFunc) int { + return int(C.bridge_int_func(f)) +} + +func callCBridge(f C.intFunc) C.int { + return C.bridge_int_func(f) +} + +func testFpVar(t *testing.T) { + const expected = 42 + f := C.intFunc(C.fortytwo) + res1 := C.bridge_int_func(f) + if r1 := int(res1); r1 != expected { + t.Errorf("got %d, want %d", r1, expected) + } + res2 := callCBridge(f) + if r2 := int(res2); r2 != expected { + t.Errorf("got %d, want %d", r2, expected) + } + r3 := callBridge(f) + if r3 != expected { + t.Errorf("got %d, want %d", r3, expected) + } +} + +// issue 1222 +type AsyncEvent struct { + event C.struct_ibv_async_event +} + +// issue 1635 + +func test1635(t *testing.T) { + C.scatter() + if v := C.hola; v != 0 { + t.Fatalf("C.hola is %d, should be 0", v) + } + if v := C.testHola(); v != 0 { + t.Fatalf("C.testHola() is %d, should be 0", v) + } +} + +// issue 2470 + +func testUnsignedInt(t *testing.T) { + a := (int64)(C.UINT32VAL) + b := (int64)(0xc008427b) + if a != b { + t.Errorf("Incorrect unsigned int - got %x, want %x", a, b) + } +} + +// issue 3250 + +func test3250(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("not applicable on windows") + } + + t.Skip("skipped, see golang.org/issue/5885") + var ( + thres = 1 + sig = syscall_dot_SIGCHLD + ) + type result struct { + n int + sig os.Signal + } + var ( + sigCh = make(chan os.Signal, 10) + waitStart = make(chan struct{}) + waitDone = make(chan result) + ) + + signal.Notify(sigCh, sig) + + go func() { + n := 0 + alarm := time.After(time.Second * 3) + for { + select { + case <-waitStart: + waitStart = nil + case v := <-sigCh: + n++ + if v != sig || n > thres { + waitDone <- result{n, v} + return + } + case <-alarm: + waitDone <- result{n, sig} + return + } + } + }() + + waitStart <- struct{}{} + C.testSendSIG() + r := <-waitDone + if r.sig != sig { + t.Fatalf("received signal %v, but want %v", r.sig, sig) + } + t.Logf("got %d signals\n", r.n) + if r.n <= thres { + t.Fatalf("expected more than %d", thres) + } +} + +// issue 3261 + +func testLibgcc(t *testing.T) { + var table = []struct { + in, out C.int + }{ + {0, 0}, + {1, 1}, + {-42, 42}, + {1000300, 1000300}, + {1 - 1<<31, 1<<31 - 1}, + } + for _, v := range table { + if o := C.vabs(v.in); o != v.out { + t.Fatalf("abs(%d) got %d, should be %d", v.in, o, v.out) + return + } + } +} + +// issue 3729 + +func test3729(t *testing.T) { + if runtime.GOOS == "windows" { + t.Skip("skipping on windows") + } + + _, e := C.g() + if e != syscall.E2BIG { + t.Errorf("got %q, expect %q", e, syscall.E2BIG) + } + _, e = C.g2(C.EINVAL, C._expA, C._expB, C._expC, C._expD) + if e != syscall.EINVAL { + t.Errorf("got %q, expect %q", e, syscall.EINVAL) + } +} + +// issue 3945 + +func testPrintf(t *testing.T) { + C.say() +} + +// issue 4054 + +var issue4054a = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J} + +// issue 4339 + +func test4339(t *testing.T) { + C.handle4339(&C.exported4339) +} + +// issue 4417 + +func testBoolAlign(t *testing.T) { + b := C.c_bool(true, true, 10, true, false) + if b != 10 { + t.Fatalf("found %d expected 10\n", b) + } + b = C.c_bool(true, true, 5, true, true) + if b != 5 { + t.Fatalf("found %d expected 5\n", b) + } + b = C.c_bool(true, true, 3, true, false) + if b != 3 { + t.Fatalf("found %d expected 3\n", b) + } + b = C.c_bool(false, false, 1, true, false) + if b != 1 { + t.Fatalf("found %d expected 1\n", b) + } + b = C.c_bool(false, true, 200, true, false) + if b != 200 { + t.Fatalf("found %d expected 200\n", b) + } +} + +// issue 4857 + +func test4857() { + _ = C.issue4857() +} + +// issue 5224 + +func testCflags(t *testing.T) { + is_windows := C.is_windows == 1 + if is_windows != (runtime.GOOS == "windows") { + t.Errorf("is_windows: %v, runtime.GOOS: %s", is_windows, runtime.GOOS) + } + if C.common != 123 { + t.Errorf("common: %v (expected 123)", C.common) + } +} + +// issue 5227 + +func test5227(t *testing.T) { + C.init() +} + +func selectfont() C.Fontinfo { + return C.SansTypeface +} + +// issue 5242 + +func test5242(t *testing.T) { + if got := C.issue5242(C.foo{}, C.bar{}); got != 5242 { + t.Errorf("got %v", got) + } +} + +func test5603(t *testing.T) { + var x [5]int64 + exp := int64(C.issue5603exp) + x[0] = int64(C.issue5603foo0()) + x[1] = int64(C.issue5603foo1(nil)) + x[2] = int64(C.issue5603foo2(nil, nil)) + x[3] = int64(C.issue5603foo3(nil, nil, nil)) + x[4] = int64(C.issue5603foo4(nil, nil, nil, nil)) + for i, v := range x { + if v != exp { + t.Errorf("issue5603foo%d() returns %v, expected %v", i, v, exp) + } + } +} + +// issue 5337 + +func test5337(t *testing.T) { + C.test5337() +} + +// issue 5740 + +func test5740(t *testing.T) { + if v := C.test5740a() + C.test5740b(); v != 5 { + t.Errorf("expected 5, got %v", v) + } +} + +// issue 5986 + +func test5986(t *testing.T) { + C.output5986() +} + +// issue 6128 + +func test6128() { + // nothing to run, just make sure this compiles. + _ = C.X +} + +// issue 6390 + +func test6390(t *testing.T) { + p1 := C.malloc(1024) + if p1 == nil { + t.Fatalf("C.malloc(1024) returned nil") + } + p2 := C.malloc(0) + if p2 == nil { + t.Fatalf("C.malloc(0) returned nil") + } + C.free(p1) + C.free(p2) +} + +func test6472() { + // nothing to run, just make sure this compiles + s := new(C.z) + println(s.y[0].x) +} + +// issue 6506 + +func test6506() { + // nothing to run, just make sure this compiles + var x C.size_t + + C.calloc(x, x) + C.malloc(x) + C.realloc(nil, x) + C.memcpy(nil, nil, x) + C.memcmp(nil, nil, x) + C.memmove(nil, nil, x) + C.strncpy(nil, nil, x) + C.strncmp(nil, nil, x) + C.strncat(nil, nil, x) + x = C.strxfrm(nil, nil, x) + C.memchr(nil, 0, x) + x = C.strcspn(nil, nil) + x = C.strspn(nil, nil) + C.memset(nil, 0, x) + x = C.strlen(nil) + _ = x +} + +// issue 6612 + +func testNaming(t *testing.T) { + C.myfunc() + C.myfunc_def() + if v := C.myvar; v != 5 { + t.Errorf("C.myvar = %d, want 5", v) + } + if v := C.myvar_def; v != 5 { + t.Errorf("C.myvar_def = %d, want 5", v) + } + if s := C.GoString(C.mytext); s != "abcdef" { + t.Errorf("C.mytext = %q, want %q", s, "abcdef") + } + if s := C.GoString(C.mytext_def); s != "abcdef" { + t.Errorf("C.mytext_def = %q, want %q", s, "abcdef") + } + if c := C.myenum; c != 1234 { + t.Errorf("C.myenum = %v, want 1234", c) + } + if c := C.myenum_def; c != 1234 { + t.Errorf("C.myenum_def = %v, want 1234", c) + } + { + const c = C.myenum + if c != 1234 { + t.Errorf("C.myenum as const = %v, want 1234", c) + } + } + { + const c = C.myenum_def + if c != 1234 { + t.Errorf("C.myenum as const = %v, want 1234", c) + } + } + if c := C.myint_def; c != 12345 { + t.Errorf("C.myint_def = %v, want 12345", c) + } + { + const c = C.myint_def + if c != 12345 { + t.Errorf("C.myint as const = %v, want 12345", c) + } + } + + if c := C.myfloat_def; c != 1.5 { + t.Errorf("C.myint_def = %v, want 1.5", c) + } + { + const c = C.myfloat_def + if c != 1.5 { + t.Errorf("C.myint as const = %v, want 1.5", c) + } + } + + if s := C.mystring_def; s != "hello" { + t.Errorf("C.mystring_def = %q, want %q", s, "hello") + } +} + +// issue 6907 + +func test6907(t *testing.T) { + want := "yarn" + if got := C.GoString(C.Issue6907CopyString(want)); got != want { + t.Errorf("C.GoString(C.Issue6907CopyString(%q)) == %q, want %q", want, got, want) + } +} + +// issue 7560 + +func test7560(t *testing.T) { + // some mingw don't implement __packed__ correctly. + if C.offset7560() != 1 { + t.Skip("C compiler did not pack struct") + } + + // C.misaligned should have x but then a padding field to get to the end of the struct. + // There should not be a field named 'y'. + var v C.misaligned + rt := reflect.TypeOf(&v).Elem() + if rt.NumField() != 2 || rt.Field(0).Name != "x" || rt.Field(1).Name != "_" { + t.Errorf("unexpected fields in C.misaligned:\n") + for i := 0; i < rt.NumField(); i++ { + t.Logf("%+v\n", rt.Field(i)) + } + } +} + +// issue 7786 + +func f() { + var x1 *C.typedef_test7786 + var x2 *C.struct_test7786 + x1 = x2 + x2 = x1 + C.f7786(x1) + C.f7786(x2) + C.g7786(x1) + C.g7786(x2) + + var b1 *C.typedef_body7786 + var b2 *C.struct_body7786 + b1 = b2 + b2 = b1 + C.b7786(b1) + C.b7786(b2) + C.c7786(b1) + C.c7786(b2) + + var u1 *C.typedef_union7786 + var u2 *C.union_union7786 + u1 = u2 + u2 = u1 + C.u7786(u1) + C.u7786(u2) + C.v7786(u1) + C.v7786(u2) +} + +// issue 8092 + +func test8092(t *testing.T) { + tests := []struct { + s string + a, b *C.char + }{ + {"text", &C.text[0], C.ctext()}, + {"data", &C.data[0], C.cdata()}, + } + for _, test := range tests { + if test.a != test.b { + t.Errorf("%s: pointer mismatch: %v != %v", test.s, test.a, test.b) + } + if got := C.GoString(test.a); got != test.s { + t.Errorf("%s: points at %#v, want %#v", test.s, got, test.s) + } + } +} + +// issues 8368 and 8441 + +func issue8368(one *C.struct_one, two *C.struct_two) { +} + +func issue8441(one *C.one, two *C.two) { + issue8441(two.x, one.x) +} + +// issue 8428 + +var _ = C.struct_issue8428one{ + b: C.char(0), + // The trailing rest field is not available in cgo. + // See issue 11925. + // rest: [0]C.char{}, +} + +var _ = C.struct_issue8428two{ + p: unsafe.Pointer(nil), + b: C.char(0), + rest: [0]C.char{}, +} + +var _ = C.struct_issue8428three{ + w: [1][2][3][0]C.char{}, + x: [2][3][0][1]C.char{}, + y: [3][0][1][2]C.char{}, + z: [0][1][2][3]C.char{}, +} + +// issue 8811 + +func test8811(t *testing.T) { + C.issue8811Execute() +} + +// issue 9557 + +func test9557(t *testing.T) { + // implicitly dereference a Go variable + foo := C.issue9557foo + if v := foo.a; v != 42 { + t.Fatalf("foo.a expected 42, but got %d", v) + } + + // explicitly dereference a C variable + if v := (*C.issue9557foo).a; v != 42 { + t.Fatalf("(*C.issue9557foo).a expected 42, but is %d", v) + } + + // implicitly dereference a C variable + if v := C.issue9557foo.a; v != 42 { + t.Fatalf("C.issue9557foo.a expected 42, but is %d", v) + } +} + +// issue 8331 part 1 + +func issue8331a() C.issue8331 { + return issue8331Var +} + +// issue 10303 + +func test10303(t *testing.T, n int) { + if runtime.Compiler == "gccgo" { + t.Skip("gccgo permits C pointers on the stack") + } + + // Run at a few different stack depths just to avoid an unlucky pass + // due to variables ending up on different pages. + if n > 0 { + test10303(t, n-1) + } + if t.Failed() { + return + } + var x, y, z, v, si C.int + var s C.Struct + C.setintstar(&x) + C.setintptr(&y) + C.setvoidptr(unsafe.Pointer(&v)) + s.P = &si + C.setstruct(s) + + if uintptr(unsafe.Pointer(&x))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { + t.Error("C int* argument on stack") + } + if uintptr(unsafe.Pointer(&y))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { + t.Error("C intptr argument on stack") + } + if uintptr(unsafe.Pointer(&v))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { + t.Error("C void* argument on stack") + } + if uintptr(unsafe.Pointer(&si))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { + t.Error("C struct field pointer on stack") + } +} + +// issue 11925 + +func test11925(t *testing.T) { + if C.sizeof_struct_a11925 != unsafe.Sizeof(C.struct_a11925{}) { + t.Errorf("size of a changed: C %d, Go %d", C.sizeof_struct_a11925, unsafe.Sizeof(C.struct_a11925{})) + } + if C.sizeof_struct_b11925 != unsafe.Sizeof(C.struct_b11925{}) { + t.Errorf("size of b changed: C %d, Go %d", C.sizeof_struct_b11925, unsafe.Sizeof(C.struct_b11925{})) + } +} + +// issue 12030 + +func test12030(t *testing.T) { + buf := (*C.char)(C.malloc(256)) + defer C.free(unsafe.Pointer(buf)) + for _, f := range []float64{1.0, 2.0, 3.14} { + C.issue12030conv(buf, C.double(f)) + got := C.GoString(buf) + if want := fmt.Sprintf("d=%g", f); got != want { + t.Fatalf("C.sprintf failed for %g: %q != %q", f, got, want) + } + } +} + +// issue 13402 + +var _ C.complexfloat +var _ C.complexdouble + +// issue 13930 +// Test that cgo's multiple-value special form for +// C function calls works in variable declaration statements. + +var _, _ = C.abs(0) + +// issue 14838 + +func test14838(t *testing.T) { + data := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + cData := C.CBytes(data) + defer C.free(cData) + + if C.check_cbytes((*C.char)(cData), C.size_t(len(data))) == 0 { + t.Fatalf("mismatched data: expected %v, got %v", data, (*(*[10]byte)(unsafe.Pointer(cData)))[:]) + } +} + +// issue 17065 + +var sink C.int + +func test17065(t *testing.T) { + if runtime.GOOS == "darwin" { + t.Skip("broken on darwin; issue 17065") + } + for i := range C.ii { + sink = C.ii[i] + } +} + +// issue 17537 + +func test17537(t *testing.T) { + v := C.S17537{i: 17537} + if got, want := C.I17537(&v), C.int(17537); got != want { + t.Errorf("got %d, want %d", got, want) + } + + p := (*C.char)(C.malloc(1)) + *p = 17 + if got, want := C.F17537(&p), C.int(17); got != want { + t.Errorf("got %d, want %d", got, want) + } + + C.F18298(nil) + var v18298 C.T18298_2 + C.G18298(C.T18298_1(v18298)) +} + +// issue 17723 + +func testAPI() { + var cs *C.char + cs = C.CString("hello") + defer C.free(unsafe.Pointer(cs)) + var s string + s = C.GoString((*C.char)(C.api_hello)) + s = C.GoStringN((*C.char)(C.api_hello), C.int(6)) + var b []byte + b = C.GoBytes(unsafe.Pointer(C.api_hello), C.int(6)) + _, _ = s, b + C.cstring_pointer_fun(nil) +} + +// issue 18126 + +func test18126(t *testing.T) { + p := C.malloc(1) + _, err := C.Issue18126C(&p) + C.free(p) + _ = err +} + +// issue 18720 + +func test18720(t *testing.T) { + if got, want := C.HELLO_WORLD, "hello\000world"; got != want { + t.Errorf("C.HELLO_WORLD == %q, expected %q", got, want) + } + + if got, want := C.VAR1, C.int(5); got != want { + t.Errorf("C.VAR1 == %v, expected %v", got, want) + } + + if got, want := *C.ADDR, C.int(5); got != want { + t.Errorf("*C.ADDR == %v, expected %v", got, want) + } + + if got, want := C.CALL, C.int(6); got != want { + t.Errorf("C.CALL == %v, expected %v", got, want) + } + + if got, want := C.CALL, C.int(7); got != want { + t.Errorf("C.CALL == %v, expected %v", got, want) + } + + // Issue 20125. + if got, want := C.SIZE_OF_FOO, 1; got != want { + t.Errorf("C.SIZE_OF_FOO == %v, expected %v", got, want) + } +} + +// issue 20129 + +func test20129(t *testing.T) { + if C.issue20129 != 0 { + t.Fatal("test is broken") + } + C.issue20129Foo() + if C.issue20129 != 1 { + t.Errorf("got %v but expected %v", C.issue20129, 1) + } + C.issue20129Bar() + if C.issue20129 != 2 { + t.Errorf("got %v but expected %v", C.issue20129, 2) + } +} + +// issue 20369 + +func test20369(t *testing.T) { + if C.XUINT64_MAX != math.MaxUint64 { + t.Fatalf("got %v, want %v", uint64(C.XUINT64_MAX), uint64(math.MaxUint64)) + } +} + +// issue 21668 + +var issue21668_X = C.x21668 + +// issue 21708 + +func test21708(t *testing.T) { + if got, want := C.CAST_TO_INT64, -1; got != want { + t.Errorf("C.CAST_TO_INT64 == %v, expected %v", got, want) + } +} + +// issue 21809 + +func test21809(t *testing.T) { + longVar := C.long(3) + typedefVar := C.MySigned_t(4) + typedefTypedefVar := C.MySigned2_t(5) + + // all three should be considered identical to `long` + if ret := C.takes_long(longVar); ret != 9 { + t.Errorf("got %v but expected %v", ret, 9) + } + if ret := C.takes_long(typedefVar); ret != 16 { + t.Errorf("got %v but expected %v", ret, 16) + } + if ret := C.takes_long(typedefTypedefVar); ret != 25 { + t.Errorf("got %v but expected %v", ret, 25) + } + + // They should also be identical to the typedef'd type + if ret := C.takes_typedef(longVar); ret != 9 { + t.Errorf("got %v but expected %v", ret, 9) + } + if ret := C.takes_typedef(typedefVar); ret != 16 { + t.Errorf("got %v but expected %v", ret, 16) + } + if ret := C.takes_typedef(typedefTypedefVar); ret != 25 { + t.Errorf("got %v but expected %v", ret, 25) + } +} + +// issue 22906 + +func test22906(t *testing.T) { + var x1 C.jobject = 0 // Note: 0, not nil. That makes sure we use uintptr for these types. + _ = x1 + var x2 C.jclass = 0 + _ = x2 + var x3 C.jthrowable = 0 + _ = x3 + var x4 C.jstring = 0 + _ = x4 + var x5 C.jarray = 0 + _ = x5 + var x6 C.jbooleanArray = 0 + _ = x6 + var x7 C.jbyteArray = 0 + _ = x7 + var x8 C.jcharArray = 0 + _ = x8 + var x9 C.jshortArray = 0 + _ = x9 + var x10 C.jintArray = 0 + _ = x10 + var x11 C.jlongArray = 0 + _ = x11 + var x12 C.jfloatArray = 0 + _ = x12 + var x13 C.jdoubleArray = 0 + _ = x13 + var x14 C.jobjectArray = 0 + _ = x14 + var x15 C.jweak = 0 + _ = x15 +} + +// issue 22958 +// Nothing to run, just make sure this compiles. +var Vissue22958 C.issue22958Type + +func test23356(t *testing.T) { + if got, want := C.a(), C.int(5); got != want { + t.Errorf("C.a() == %v, expected %v", got, want) + } + if got, want := C.r(), C.int(3); got != want { + t.Errorf("C.r() == %v, expected %v", got, want) + } +} + +// issue 23720 + +func Issue23720F() { + var x C.issue23720A + C.issue23720F(x) +} + +// issue 24206 + +func test24206(t *testing.T) { + if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { + t.Skipf("skipping on %s/%s", runtime.GOOS, runtime.GOARCH) + } + + if l := len(C.GoString(C.dangerousString1())); l != 123 { + t.Errorf("Incorrect string length - got %d, want 123", l) + } + if l := len(C.GoString(C.dangerousString2())); l != 4096+123 { + t.Errorf("Incorrect string length - got %d, want %d", l, 4096+123) + } +} + +// issue 25143 + +func issue25143sum(ns ...C.int) C.int { + total := C.int(0) + for _, n := range ns { + total += n + } + return total +} + +func test25143(t *testing.T) { + if got, want := issue25143sum(1, 2, 3), C.int(6); got != want { + t.Errorf("issue25143sum(1, 2, 3) == %v, expected %v", got, want) + } +} + +// issue 26066 +// Wrong type of constant with GCC 8 and newer. + +func test26066(t *testing.T) { + var i = int64(C.issue26066) + if i != -1 { + t.Errorf("got %d, want -1", i) + } +} + +// issue 26517 +var a C.TypeOne +var b C.TypeTwo + +// issue 27660 +// Stress the interaction between the race detector and cgo in an +// attempt to reproduce the memory corruption described in #27660. +// The bug was very timing sensitive; at the time of writing this +// test would only trigger the bug about once out of every five runs. + +func test27660(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + ints := make([]int, 100) + locks := make([]sync.Mutex, 100) + // Slowly create threads so that ThreadSanitizer is forced to + // frequently resize its SyncClocks. + for i := 0; i < 100; i++ { + go func() { + for ctx.Err() == nil { + // Sleep in C for long enough that it is likely that the runtime + // will retake this goroutine's currently wired P. + C.usleep(1000 /* 1ms */) + runtime.Gosched() // avoid starvation (see #28701) + } + }() + go func() { + // Trigger lots of synchronization and memory reads/writes to + // increase the likelihood that the race described in #27660 + // results in corruption of ThreadSanitizer's internal state + // and thus an assertion failure or segfault. + for ctx.Err() == nil { + j := rand.Intn(100) + locks[j].Lock() + ints[j]++ + locks[j].Unlock() + } + }() + time.Sleep(time.Millisecond) + } +} + +// issue 28540 + +func twoargsF() { + v := []string{} + C.twoargs1(C.twoargs2(), C.twoargs3(unsafe.Pointer(&v))) +} + +// issue 28545 + +func issue28545G(p **C.char) { + C.issue28545F(p, -1, (0)) + C.issue28545F(p, 2+3, complex(1, 1)) + C.issue28545F(p, issue28772Constant, issue28772Constant2) +} + +// issue 28772 part 1 - part 2 in testx.go + +const issue28772Constant = C.issue28772Constant + +// issue 28896 + +func offset(i int) uintptr { + var pi C.innerPacked + var po C.outerPacked + var ui C.innerUnpacked + var uo C.outerUnpacked + switch i { + case 0: + return unsafe.Offsetof(pi.f2) + case 1: + return unsafe.Offsetof(po.g2) + case 2: + return unsafe.Offsetof(ui.f2) + case 3: + return unsafe.Offsetof(uo.g2) + default: + panic("can't happen") + } +} + +func test28896(t *testing.T) { + for i := 0; i < 4; i++ { + c := uintptr(C.offset(C.int(i))) + g := offset(i) + if c != g { + t.Errorf("%d: C: %d != Go %d", i, c, g) + } + } +} + +// issue 29383 +// cgo's /*line*/ comments failed when inserted after '/', +// because the result looked like a "//" comment. +// No runtime test; just make sure it compiles. + +func Issue29383(n, size uint) int { + if ^C.size_t(0)/C.size_t(n) < C.size_t(size) { + return 0 + } + return 0 +} + +// issue 29748 +// Error handling a struct initializer that requires pointer checking. +// Compilation test only, nothing to run. + +var Vissue29748 = C.f29748(&C.S29748{ + nil, +}) + +func Fissue299748() { + C.f29748(&C.S29748{ + nil, + }) +} + +// issue 29781 + +var issue29781X struct{ X int } + +func issue29781F(...int) int { return 0 } + +func issue29781G() { + var p *C.char + C.issue29781F(&p, C.ISSUE29781C+1) + C.issue29781F(nil, (C.int)( + 0)) + C.issue29781F(&p, (C.int)(0)) + C.issue29781F(&p, (C.int)( + 0)) + C.issue29781F(&p, (C.int)(issue29781X. + X)) +} + +func test29878(t *testing.T) { + const arg uint32 = 123 // fits into all integer types + var ret int16 = C.issue29878function(arg) // no conversions needed + if int64(ret) != int64(arg) { + t.Errorf("return value unexpected: got %d, want %d", ret, arg) + } +} + +// issue 30065 + +func test30065(t *testing.T) { + var a [256]byte + b := []byte("a") + C.memcpy(unsafe.Pointer(&a), unsafe.Pointer(&b[0]), 1) + if a[0] != 'a' { + t.Errorf("&a failed: got %c, want %c", a[0], 'a') + } + + b = []byte("b") + C.memcpy(unsafe.Pointer(&a[0]), unsafe.Pointer(&b[0]), 1) + if a[0] != 'b' { + t.Errorf("&a[0] failed: got %c, want %c", a[0], 'b') + } + + d := make([]byte, 256) + b = []byte("c") + C.memcpy(unsafe.Pointer(&d[0]), unsafe.Pointer(&b[0]), 1) + if d[0] != 'c' { + t.Errorf("&d[0] failed: got %c, want %c", d[0], 'c') + } +} diff --git a/misc/cgo/test/test22906.go b/misc/cgo/test/test22906.go deleted file mode 100644 index 02bae9cfa7..0000000000 --- a/misc/cgo/test/test22906.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2017 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. - -// +build cgo - -package cgotest - -/* - -// It's going to be hard to include a whole real JVM to test this. -// So we'll simulate a really easy JVM using just the parts we need. - -// This is the relevant part of jni.h. - -struct _jobject; - -typedef struct _jobject *jobject; -typedef jobject jclass; -typedef jobject jthrowable; -typedef jobject jstring; -typedef jobject jarray; -typedef jarray jbooleanArray; -typedef jarray jbyteArray; -typedef jarray jcharArray; -typedef jarray jshortArray; -typedef jarray jintArray; -typedef jarray jlongArray; -typedef jarray jfloatArray; -typedef jarray jdoubleArray; -typedef jarray jobjectArray; - -typedef jobject jweak; - -// Note: jvalue is already a non-pointer type due to it being a C union. - -*/ -import "C" -import ( - "testing" -) - -func test22906(t *testing.T) { - var x1 C.jobject = 0 // Note: 0, not nil. That makes sure we use uintptr for these types. - _ = x1 - var x2 C.jclass = 0 - _ = x2 - var x3 C.jthrowable = 0 - _ = x3 - var x4 C.jstring = 0 - _ = x4 - var x5 C.jarray = 0 - _ = x5 - var x6 C.jbooleanArray = 0 - _ = x6 - var x7 C.jbyteArray = 0 - _ = x7 - var x8 C.jcharArray = 0 - _ = x8 - var x9 C.jshortArray = 0 - _ = x9 - var x10 C.jintArray = 0 - _ = x10 - var x11 C.jlongArray = 0 - _ = x11 - var x12 C.jfloatArray = 0 - _ = x12 - var x13 C.jdoubleArray = 0 - _ = x13 - var x14 C.jobjectArray = 0 - _ = x14 - var x15 C.jweak = 0 - _ = x15 -} diff --git a/misc/cgo/test/test27660.go b/misc/cgo/test/test27660.go deleted file mode 100644 index 8c23b7dc58..0000000000 --- a/misc/cgo/test/test27660.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2018 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. - -// Stress the interaction between the race detector and cgo in an -// attempt to reproduce the memory corruption described in #27660. -// The bug was very timing sensitive; at the time of writing this -// test would only trigger the bug about once out of every five runs. - -package cgotest - -// #include -import "C" - -import ( - "context" - "math/rand" - "runtime" - "sync" - "testing" - "time" -) - -func test27660(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - ints := make([]int, 100) - locks := make([]sync.Mutex, 100) - // Slowly create threads so that ThreadSanitizer is forced to - // frequently resize its SyncClocks. - for i := 0; i < 100; i++ { - go func() { - for ctx.Err() == nil { - // Sleep in C for long enough that it is likely that the runtime - // will retake this goroutine's currently wired P. - C.usleep(1000 /* 1ms */) - runtime.Gosched() // avoid starvation (see #28701) - } - }() - go func() { - // Trigger lots of synchronization and memory reads/writes to - // increase the likelihood that the race described in #27660 - // results in corruption of ThreadSanitizer's internal state - // and thus an assertion failure or segfault. - for ctx.Err() == nil { - j := rand.Intn(100) - locks[j].Lock() - ints[j]++ - locks[j].Unlock() - } - }() - time.Sleep(time.Millisecond) - } -} diff --git a/misc/cgo/test/issue29878export.go b/misc/cgo/test/test_unix.go similarity index 63% rename from misc/cgo/test/issue29878export.go rename to misc/cgo/test/test_unix.go index 59727c72fc..4a234469db 100644 --- a/misc/cgo/test/issue29878export.go +++ b/misc/cgo/test/test_unix.go @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// +build !windows + package cgotest -import "C" +import "syscall" -//export issue29878exported -func issue29878exported(arg int8) uint64 { - return uint64(arg) -} +var syscall_dot_SIGCHLD = syscall.SIGCHLD diff --git a/misc/cgo/test/issue13402.go b/misc/cgo/test/test_windows.go similarity index 52% rename from misc/cgo/test/issue13402.go rename to misc/cgo/test/test_windows.go index 3af24c2d3c..7bfb33a83c 100644 --- a/misc/cgo/test/issue13402.go +++ b/misc/cgo/test/test_windows.go @@ -1,10 +1,9 @@ -// Copyright 2015 The Go Authors. All rights reserved. +// Copyright 2019 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. package cgotest -import "C" +import "syscall" -var _ C.complexfloat -var _ C.complexdouble +var syscall_dot_SIGCHLD syscall.Signal diff --git a/misc/cgo/test/testx.go b/misc/cgo/test/testx.go new file mode 100644 index 0000000000..b0b23e3011 --- /dev/null +++ b/misc/cgo/test/testx.go @@ -0,0 +1,542 @@ +// Copyright 2011 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. + +// Test cases for cgo. +// Both the import "C" prologue and the main file are sorted by issue number. +// This file contains //export directives on Go functions +// and so it must NOT contain C definitions (only declarations). +// See test.go for C definitions. + +package cgotest + +import ( + "runtime" + "runtime/debug" + "strings" + "sync" + "sync/atomic" + "testing" + "time" + "unsafe" +) + +/* +// threads +extern void doAdd(int, int); + +// issue 1328 +extern void BackIntoGo(void); +void IntoC(void); + +// issue 1560 +// mysleep returns the absolute start time in ms. +long long mysleep(int seconds); + +// twoSleep returns the absolute start time of the first sleep +// in ms. +long long twoSleep(int); + +// issue 3775 +void lockOSThreadCallback(void); +inline static void lockOSThreadC(void) +{ + lockOSThreadCallback(); +} +int usleep(unsigned usec); + +// issue 4054 part 2 - part 1 in test.go +typedef enum { + A = 0, + B, + C, + D, + E, + F, + G, + H, + II, + J, +} issue4054b; + +// issue 5548 + +extern int issue5548_in_c(void); + +// issue 6833 + +extern unsigned long long issue6833Func(unsigned int, unsigned long long); + +// issue 6907 + +extern int CheckIssue6907C(_GoString_); + +// issue 7665 + +extern void f7665(void); + +// issue 7978 +// Stack tracing didn't work during cgo code after calling a Go +// callback. Make sure GC works and the stack trace is correct. + +#include + +void issue7978cb(void); + +#if defined(__APPLE__) && defined(__arm__) +// on Darwin/ARM, libSystem doesn't provide implementation of the __sync_fetch_and_add +// primitive, and although gcc supports it, it doesn't inline its definition. +// Clang could inline its definition, so we require clang on Darwin/ARM. +#if defined(__clang__) +#define HAS_SYNC_FETCH_AND_ADD 1 +#else +#define HAS_SYNC_FETCH_AND_ADD 0 +#endif +#else +#define HAS_SYNC_FETCH_AND_ADD 1 +#endif + +// use ugly atomic variable sync since that doesn't require calling back into +// Go code or OS dependencies +static void issue7978c(uint32_t *sync) { +#if HAS_SYNC_FETCH_AND_ADD + while(__sync_fetch_and_add(sync, 0) != 0) + ; + __sync_fetch_and_add(sync, 1); + while(__sync_fetch_and_add(sync, 0) != 2) + ; + issue7978cb(); + __sync_fetch_and_add(sync, 1); + while(__sync_fetch_and_add(sync, 0) != 6) + ; +#endif +} + +// issue 8331 part 2 - part 1 in test.go +// A typedef of an unnamed struct is the same struct when +// #include'd twice. No runtime test; just make sure it compiles. +#include "issue8331.h" + +// issue 20910 +void callMulti(void); + +// issue 28772 part 2 - part 1 in issuex.go +#define issue28772Constant2 2 + +*/ +import "C" + +// exports + +//export ReturnIntLong +func ReturnIntLong() (int, C.long) { + return 1, 2 +} + +//export gc +func gc() { + runtime.GC() +} + +// threads + +var sum struct { + sync.Mutex + i int +} + +//export Add +func Add(x int) { + defer func() { + recover() + }() + sum.Lock() + sum.i += x + sum.Unlock() + var p *int + *p = 2 +} + +func testCthread(t *testing.T) { + if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") { + t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add") + } + sum.i = 0 + C.doAdd(10, 6) + + want := 10 * (10 - 1) / 2 * 6 + if sum.i != want { + t.Fatalf("sum=%d, want %d", sum.i, want) + } +} + +// issue 1328 + +//export BackIntoGo +func BackIntoGo() { + x := 1 + + for i := 0; i < 10000; i++ { + xvariadic(x) + if x != 1 { + panic("x is not 1?") + } + } +} + +func xvariadic(x ...interface{}) { +} + +func test1328(t *testing.T) { + C.IntoC() +} + +// issue 1560 + +var sleepDone = make(chan int64) + +// parallelSleep returns the absolute difference between the start time +// of the two sleeps. +func parallelSleep(n int) int64 { + t := int64(C.twoSleep(C.int(n))) - <-sleepDone + if t < 0 { + return -t + } + return t +} + +//export BackgroundSleep +func BackgroundSleep(n int32) { + go func() { + sleepDone <- int64(C.mysleep(C.int(n))) + }() +} + +func testParallelSleep(t *testing.T) { + sleepSec := 1 + dt := time.Duration(parallelSleep(sleepSec)) * time.Millisecond + t.Logf("difference in start time for two sleep(%d) is %v", sleepSec, dt) + // bug used to run sleeps in serial, producing a 2*sleepSec-second delay. + // we detect if the start times of those sleeps are > 0.5*sleepSec-second. + if dt >= time.Duration(sleepSec)*time.Second/2 { + t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds()) + } +} + +// issue 2462 + +//export exportbyte +func exportbyte() byte { + return 0 +} + +//export exportbool +func exportbool() bool { + return false +} + +//export exportrune +func exportrune() rune { + return 0 +} + +//export exporterror +func exporterror() error { + return nil +} + +//export exportint +func exportint() int { + return 0 +} + +//export exportuint +func exportuint() uint { + return 0 +} + +//export exportuintptr +func exportuintptr() uintptr { + return (uintptr)(0) +} + +//export exportint8 +func exportint8() int8 { + return 0 +} + +//export exportuint8 +func exportuint8() uint8 { + return 0 +} + +//export exportint16 +func exportint16() int16 { + return 0 +} + +//export exportuint16 +func exportuint16() uint16 { + return 0 +} + +//export exportint32 +func exportint32() int32 { + return 0 +} + +//export exportuint32 +func exportuint32() uint32 { + return 0 +} + +//export exportint64 +func exportint64() int64 { + return 0 +} + +//export exportuint64 +func exportuint64() uint64 { + return 0 +} + +//export exportfloat32 +func exportfloat32() float32 { + return 0 +} + +//export exportfloat64 +func exportfloat64() float64 { + return 0 +} + +//export exportcomplex64 +func exportcomplex64() complex64 { + return 0 +} + +//export exportcomplex128 +func exportcomplex128() complex128 { + return 0 +} + +// issue 3741 + +//export exportSliceIn +func exportSliceIn(s []byte) bool { + return len(s) == cap(s) +} + +//export exportSliceOut +func exportSliceOut() []byte { + return []byte{1} +} + +//export exportSliceInOut +func exportSliceInOut(s []byte) []byte { + return s +} + +// issue 3775 + +func init() { + if runtime.GOOS == "android" { + return + } + // Same as test3775 but run during init so that + // there are two levels of internal runtime lock + // (1 for init, 1 for cgo). + // This would have been broken by CL 11663043. + C.lockOSThreadC() +} + +func test3775(t *testing.T) { + if runtime.GOOS == "android" { + return + } + // Used to panic because of the UnlockOSThread below. + C.lockOSThreadC() +} + +//export lockOSThreadCallback +func lockOSThreadCallback() { + runtime.LockOSThread() + runtime.UnlockOSThread() + go C.usleep(10000) + runtime.Gosched() +} + +// issue 4054 part 2 - part 1 in test.go + +var issue4054b = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.II, C.J} + +//export issue5548FromC +func issue5548FromC(s string, i int) int { + if len(s) == 4 && s == "test" && i == 42 { + return 12345 + } + println("got", len(s), i) + return 9876 +} + +func test5548(t *testing.T) { + if x := C.issue5548_in_c(); x != 12345 { + t.Errorf("issue5548_in_c = %d, want %d", x, 12345) + } +} + +// issue 6833 + +//export GoIssue6833Func +func GoIssue6833Func(aui uint, aui64 uint64) uint64 { + return aui64 + uint64(aui) +} + +func test6833(t *testing.T) { + ui := 7 + ull := uint64(0x4000300020001000) + v := uint64(C.issue6833Func(C.uint(ui), C.ulonglong(ull))) + exp := uint64(ui) + ull + if v != exp { + t.Errorf("issue6833Func() returns %x, expected %x", v, exp) + } +} + +// issue 6907 + +const CString = "C string" + +//export CheckIssue6907Go +func CheckIssue6907Go(s string) C.int { + if s == CString { + return 1 + } + return 0 +} + +func test6907Go(t *testing.T) { + if got := C.CheckIssue6907C(CString); got != 1 { + t.Errorf("C.CheckIssue6907C() == %d, want %d", got, 1) + } +} + +// issue 7665 + +//export f7665 +func f7665() {} + +var bad7665 unsafe.Pointer = C.f7665 +var good7665 uintptr = uintptr(C.f7665) + +func test7665(t *testing.T) { + if bad7665 == nil || uintptr(bad7665) != good7665 { + t.Errorf("ptrs = %p, %#x, want same non-nil pointer", bad7665, good7665) + } +} + +// issue 7978 + +var issue7978sync uint32 + +func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) { + runtime.GC() + buf := make([]byte, 65536) + trace := string(buf[:runtime.Stack(buf, true)]) + for _, goroutine := range strings.Split(trace, "\n\n") { + if strings.Contains(goroutine, "test.issue7978go") { + trace := strings.Split(goroutine, "\n") + // look for the expected function in the stack + for i := 0; i < depth; i++ { + if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) { + t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine) + return + } + if strings.Contains(trace[1+2*i], wantFunc) { + return + } + } + t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine) + return + } + } + t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace) +} + +func issue7978wait(store uint32, wait uint32) { + if store != 0 { + atomic.StoreUint32(&issue7978sync, store) + } + for atomic.LoadUint32(&issue7978sync) != wait { + runtime.Gosched() + } +} + +//export issue7978cb +func issue7978cb() { + // Force a stack growth from the callback to put extra + // pressure on the runtime. See issue #17785. + growStack(64) + issue7978wait(3, 4) +} + +func growStack(n int) int { + var buf [128]int + if n == 0 { + return 0 + } + return buf[growStack(n-1)] +} + +func issue7978go() { + C.issue7978c((*C.uint32_t)(&issue7978sync)) + issue7978wait(7, 8) +} + +func test7978(t *testing.T) { + if runtime.Compiler == "gccgo" { + t.Skip("gccgo can not do stack traces of C code") + } + if C.HAS_SYNC_FETCH_AND_ADD == 0 { + t.Skip("clang required for __sync_fetch_and_add support on darwin/arm") + } + debug.SetTraceback("2") + issue7978sync = 0 + go issue7978go() + // test in c code, before callback + issue7978wait(0, 1) + issue7978check(t, "_Cfunc_issue7978c(", "", 1) + // test in go code, during callback + issue7978wait(2, 3) + issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3) + // test in c code, after callback + issue7978wait(4, 5) + issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1) + // test in go code, after return from cgo + issue7978wait(6, 7) + issue7978check(t, "test.issue7978go(", "", 3) + atomic.StoreUint32(&issue7978sync, 8) +} + +// issue 8331 part 2 + +var issue8331Var C.issue8331 + +// issue 20910 + +//export multi +func multi() (*C.char, C.int) { + return C.CString("multi"), 0 +} + +func test20910(t *testing.T) { + C.callMulti() +} + +// issue 28772 part 2 + +const issue28772Constant2 = C.issue28772Constant2 + +//export issue29878exported +func issue29878exported(arg int8) uint64 { + return uint64(arg) +} diff --git a/misc/cgo/test/twoargs.go b/misc/cgo/test/twoargs.go deleted file mode 100644 index ca0534ca31..0000000000 --- a/misc/cgo/test/twoargs.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2018 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. - -// Crash from call with two arguments that need pointer checking. -// No runtime test; just make sure it compiles. - -package cgotest - -/* -static void twoargs1(void *p, int n) {} -static void *twoargs2() { return 0; } -static int twoargs3(void * p) { return 0; } -*/ -import "C" - -import "unsafe" - -func twoargsF() { - v := []string{} - C.twoargs1(C.twoargs2(), C.twoargs3(unsafe.Pointer(&v))) -} diff --git a/src/archive/zip/zip_test.go b/src/archive/zip/zip_test.go index efdb5bd044..b3a7caac7f 100644 --- a/src/archive/zip/zip_test.go +++ b/src/archive/zip/zip_test.go @@ -11,7 +11,6 @@ import ( "errors" "fmt" "hash" - "internal/race" "internal/testenv" "io" "io/ioutil" @@ -309,7 +308,7 @@ func TestZip64EdgeCase(t *testing.T) { // Tests that we generate a zip64 file if the directory at offset // 0xFFFFFFFF, but not before. func TestZip64DirectoryOffset(t *testing.T) { - if testing.Short() && race.Enabled { + if testing.Short() { t.Skip("skipping in short mode") } t.Parallel() @@ -354,7 +353,7 @@ func TestZip64DirectoryOffset(t *testing.T) { // At 16k records, we need to generate a zip64 file. func TestZip64ManyRecords(t *testing.T) { - if testing.Short() && race.Enabled { + if testing.Short() { t.Skip("skipping in short mode") } t.Parallel() diff --git a/src/bufio/scan.go b/src/bufio/scan.go index cefd261464..4e787c4b0a 100644 --- a/src/bufio/scan.go +++ b/src/bufio/scan.go @@ -73,7 +73,7 @@ var ( const ( // MaxScanTokenSize is the maximum size used to buffer a token - // unless the user provides an explicit buffer with Scan.Buffer. + // unless the user provides an explicit buffer with Scanner.Buffer. // The actual maximum token size may be smaller as the buffer // may need to include, for instance, a newline. MaxScanTokenSize = 64 * 1024 diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index c74ee9bfa2..b46b310267 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -144,7 +144,7 @@ func main() { } else { stds, err := exec.Command(goCmd(), "list", "std").Output() if err != nil { - log.Fatal(err) + log.Fatalf("go list std: %v\n%s", err, stds) } for _, pkg := range strings.Fields(string(stds)) { if !internalPkg.MatchString(pkg) { @@ -153,10 +153,25 @@ func main() { } } + importDir, importMap := loadImports() + + // The code below assumes that the import map can vary + // by package, so that an import in one package (directory) might mean + // something different from the same import in another. + // While this can happen in GOPATH mode with vendoring, + // it is not possible in the standard library: the one importMap + // returned by loadImports applies to all packages. + // Construct a per-directory importMap that resolves to + // that single map for all packages. + importMapForDir := make(map[string]map[string]string) + for _, dir := range importDir { + importMapForDir[dir] = importMap + } var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true for _, context := range contexts { w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src")) - w.loadImports(pkgNames, w.context) + w.importDir = importDir + w.importMap = importMapForDir for _, name := range pkgNames { // Vendored packages do not contribute to our @@ -440,58 +455,58 @@ func tagKey(dir string, context *build.Context, tags []string) string { return key } -func (w *Walker) loadImports(paths []string, context *build.Context) { - if context == nil { - context = &build.Default - } - - var ( - tags = context.BuildTags - cgoEnabled = "0" - ) - if context.CgoEnabled { - tags = append(tags[:len(tags):len(tags)], "cgo") - cgoEnabled = "1" - } - - // TODO(golang.org/issue/29666): Request only the fields that we need. - cmd := exec.Command(goCmd(), "list", "-e", "-deps", "-json") - if len(tags) > 0 { - cmd.Args = append(cmd.Args, "-tags", strings.Join(tags, " ")) - } - cmd.Args = append(cmd.Args, paths...) - - cmd.Env = append(os.Environ(), - "GOOS="+context.GOOS, - "GOARCH="+context.GOARCH, - "CGO_ENABLED="+cgoEnabled, - ) - - stdout := new(bytes.Buffer) - cmd.Stdout = stdout - cmd.Stderr = new(strings.Builder) - err := cmd.Run() +// loadImports returns information about the packages in the standard library +// and the packages they themselves import. +// importDir maps expanded import path to the directory containing that package. +// importMap maps source import path to expanded import path. +// The source import path and expanded import path are identical except for vendored packages. +// For example, on return: +// +// importMap["math"] = "math" +// importDir["math"] = "/src/math" +// +// importMap["golang.org/x/net/route"] = "vendor/golang.org/x/net/route" +// importDir["vendor/golang.org/x/net/route"] = "/src/vendor/golang.org/x/net/route" +// +// There are a few imports that only appear on certain platforms, +// including it turns out x/net/route, and we add those explicitly. +func loadImports() (importDir map[string]string, importMap map[string]string) { + out, err := exec.Command(goCmd(), "list", "-e", "-deps", "-json", "std").CombinedOutput() if err != nil { - log.Fatalf("%s failed: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) + log.Fatalf("loading imports: %v\n%s", err, out) } - w.importDir = make(map[string]string) - w.importMap = make(map[string]map[string]string) - dec := json.NewDecoder(stdout) + importDir = make(map[string]string) + importMap = make(map[string]string) + dec := json.NewDecoder(bytes.NewReader(out)) for { var pkg struct { ImportPath, Dir string ImportMap map[string]string } - if err := dec.Decode(&pkg); err == io.EOF { + err := dec.Decode(&pkg) + if err == io.EOF { break - } else if err != nil { - log.Fatalf("%s: invalid output: %v", strings.Join(cmd.Args, " "), err) + } + if err != nil { + log.Fatalf("go list: invalid output: %v", err) } - w.importDir[pkg.ImportPath] = pkg.Dir - w.importMap[pkg.Dir] = pkg.ImportMap + importDir[pkg.ImportPath] = pkg.Dir + for k, v := range pkg.ImportMap { + importMap[k] = v + } } + + // Fixup for vendor packages listed in args above. + fixup := []string{ + "vendor/golang.org/x/net/route", + } + for _, pkg := range fixup { + importDir[pkg] = filepath.Join(build.Default.GOROOT, "src", pkg) + importMap[strings.TrimPrefix(pkg, "vendor/")] = pkg + } + return } // Importing is a sentinel taking the place in Walker.imported @@ -523,7 +538,7 @@ func (w *Walker) ImportFrom(fromPath, fromDir string, mode types.ImportMode) (*t dir = filepath.Join(w.root, filepath.FromSlash(name)) } if fi, err := os.Stat(dir); err != nil || !fi.IsDir() { - log.Fatalf("no source in tree for import %q: %v", name, err) + log.Fatalf("no source in tree for import %q (from import %s in %s): %v", name, fromPath, fromDir, err) } context := w.context diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 89e2a4ef00..397162dac8 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -186,7 +186,7 @@ func capturevars(xfunc *Node) { outermost := v.Name.Defn // out parameters will be assigned to implicitly upon return. - if outer.Class() != PPARAMOUT && !outermost.Addrtaken() && !outermost.Assigned() && v.Type.Width <= 128 { + if outermost.Class() != PPARAMOUT && !outermost.Addrtaken() && !outermost.Assigned() && v.Type.Width <= 128 { v.Name.SetByval(true) } else { outermost.SetAddrtaken(true) diff --git a/src/cmd/compile/internal/gc/init.go b/src/cmd/compile/internal/gc/init.go index 6467aafd53..8157292216 100644 --- a/src/cmd/compile/internal/gc/init.go +++ b/src/cmd/compile/internal/gc/init.go @@ -37,10 +37,8 @@ func fninit(n []*Node) { var fns []*obj.LSym // functions to call for package initialization // Find imported packages with init tasks. - for _, p := range types.ImportedPkgList() { - if s, ok := p.LookupOK(".inittask"); ok { - deps = append(deps, s.Linksym()) - } + for _, s := range types.InitSyms { + deps = append(deps, s.Linksym()) } // Make a function that contains all the initialization statements. diff --git a/src/cmd/compile/internal/gc/norace.go b/src/cmd/compile/internal/gc/norace.go deleted file mode 100644 index e00f0c4a84..0000000000 --- a/src/cmd/compile/internal/gc/norace.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2017 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. - -// +build !race - -package gc - -const raceEnabled = false diff --git a/src/cmd/compile/internal/gc/pgen.go b/src/cmd/compile/internal/gc/pgen.go index 2ae7452e7d..dd2294e37f 100644 --- a/src/cmd/compile/internal/gc/pgen.go +++ b/src/cmd/compile/internal/gc/pgen.go @@ -13,6 +13,7 @@ import ( "cmd/internal/src" "cmd/internal/sys" "fmt" + "internal/race" "math/rand" "sort" "sync" @@ -325,7 +326,7 @@ func compileSSA(fn *Node, worker int) { } func init() { - if raceEnabled { + if race.Enabled { rand.Seed(time.Now().UnixNano()) } } @@ -336,7 +337,7 @@ func init() { func compileFunctions() { if len(compilequeue) != 0 { sizeCalculationDisabled = true // not safe to calculate sizes concurrently - if raceEnabled { + if race.Enabled { // Randomize compilation order to try to shake out races. tmp := make([]*Node, len(compilequeue)) perm := rand.Perm(len(compilequeue)) diff --git a/src/cmd/compile/internal/gc/race.go b/src/cmd/compile/internal/gc/race.go deleted file mode 100644 index 78e1997cf9..0000000000 --- a/src/cmd/compile/internal/gc/race.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2017 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. - -// +build race - -package gc - -const raceEnabled = true diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index cafff01ddc..f9ccf84f72 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -5123,7 +5123,7 @@ func (s *SSAGenState) Br(op obj.As, target *ssa.Block) *obj.Prog { return p } -// DebugFriendlySetPos adjusts Pos.IsStmt subject to heuristics +// DebugFriendlySetPosFrom adjusts Pos.IsStmt subject to heuristics // that reduce "jumpy" line number churn when debugging. // Spill/fill/copy instructions from the register allocator, // phi functions, and instructions with a no-pos position diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 12bc9c3ae6..9f6646af44 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -280,7 +280,7 @@ func (n *Node) isMethodExpression() bool { return n.Op == ONAME && n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME } -// funcname returns the name of the function n. +// funcname returns the name (without the package) of the function n. func (n *Node) funcname() string { if n == nil || n.Func == nil || n.Func.Nname == nil { return "" diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 81f59013f4..4cb28d6100 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3671,7 +3671,11 @@ func typecheckdef(n *Node) { n.SetDiag(true) goto ret } - n.Sym.Def = asTypesNode(p.Ntype) + // For package-level type aliases, set n.Sym.Def so we can identify + // it as a type alias during export. See also #31959. + if n.Name.Curfn == nil { + n.Sym.Def = asTypesNode(p.Ntype) + } } break } diff --git a/src/cmd/compile/internal/ssa/dom.go b/src/cmd/compile/internal/ssa/dom.go index ee2748e6df..3d186fc562 100644 --- a/src/cmd/compile/internal/ssa/dom.go +++ b/src/cmd/compile/internal/ssa/dom.go @@ -20,7 +20,7 @@ const ( // postorder computes a postorder traversal ordering for the // basic blocks in f. Unreachable blocks will not appear. func postorder(f *Func) []*Block { - return postorderWithNumbering(f, []int32{}) + return postorderWithNumbering(f, nil) } type blockAndIndex struct { @@ -34,7 +34,7 @@ func postorderWithNumbering(f *Func, ponums []int32) []*Block { mark := make([]markKind, f.NumBlocks()) // result ordering - var order []*Block + order := make([]*Block, 0, len(f.Blocks)) // stack of blocks and next child to visit // A constant bound allows this to be stack-allocated. 32 is diff --git a/src/cmd/compile/internal/types/pkg.go b/src/cmd/compile/internal/types/pkg.go index e502b986ae..bcc6789509 100644 --- a/src/cmd/compile/internal/types/pkg.go +++ b/src/cmd/compile/internal/types/pkg.go @@ -84,6 +84,7 @@ func (pkg *Pkg) Lookup(name string) *Sym { return s } +// List of .inittask entries in imported packages, in source code order. var InitSyms []*Sym // LookupOK looks up name in pkg and reports whether it previously existed. @@ -100,7 +101,7 @@ func (pkg *Pkg) LookupOK(name string) (s *Sym, existed bool) { Name: name, Pkg: pkg, } - if name == "init" { + if name == ".inittask" { InitSyms = append(InitSyms, s) } pkg.Syms[name] = s diff --git a/src/cmd/compile/internal/types/sym.go b/src/cmd/compile/internal/types/sym.go index 13761c7615..2779c368a9 100644 --- a/src/cmd/compile/internal/types/sym.go +++ b/src/cmd/compile/internal/types/sym.go @@ -11,14 +11,20 @@ import ( "unicode/utf8" ) -// Sym represents an object name. Most commonly, this is a Go identifier naming -// an object declared within a package, but Syms are also used to name internal -// synthesized objects. +// Sym represents an object name in a segmented (pkg, name) namespace. +// Most commonly, this is a Go identifier naming an object declared within a package, +// but Syms are also used to name internal synthesized objects. // // As an exception, field and method names that are exported use the Sym // associated with localpkg instead of the package that declared them. This // allows using Sym pointer equality to test for Go identifier uniqueness when // handling selector expressions. +// +// Ideally, Sym should be used for representing Go language constructs, +// while cmd/internal/obj.LSym is used for representing emitted artifacts. +// +// NOTE: In practice, things can be messier than the description above +// for various reasons (historical, convenience). type Sym struct { Importdef *Pkg // where imported definition was found Linkname string // link name diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 190b592b6e..b434d4f60f 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -90,6 +90,7 @@ var bootstrapDirs = []string{ "debug/macho", "debug/pe", "internal/goversion", + "internal/race", "internal/xcoff", "math/big", "math/bits", diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 56ab64b8cf..f63c94697c 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -12,6 +12,7 @@ import ( "log" "os" "os/exec" + "path" "path/filepath" "reflect" "regexp" @@ -277,8 +278,17 @@ func (t *tester) tags() string { return "-tags=" } +// timeoutDuration converts the provided number of seconds into a +// time.Duration, scaled by the t.timeoutScale factor. +func (t *tester) timeoutDuration(sec int) time.Duration { + return time.Duration(sec) * time.Second * time.Duration(t.timeoutScale) +} + +// timeout returns the "-timeout=" string argument to "go test" given +// the number of seconds of timeout. It scales it by the +// t.timeoutScale factor. func (t *tester) timeout(sec int) string { - return "-timeout=" + fmt.Sprint(time.Duration(sec)*time.Second*time.Duration(t.timeoutScale)) + return "-timeout=" + t.timeoutDuration(sec).String() } // ranGoTest and stdMatches are state closed over by the stdlib @@ -319,6 +329,11 @@ func (t *tester) registerStdTest(pkg string) { break } } + // Special case for our slow cross-compiled + // qemu builders: + if t.shouldUsePrecompiledStdTest() { + return t.runPrecompiledStdTest(t.timeoutDuration(timeoutSec)) + } args := []string{ "test", short(), @@ -551,7 +566,9 @@ func (t *tester) registerTests() { name: "nolibgcc:" + pkg, heading: "Testing without libgcc.", fn: func(dt *distTest) error { - t.addCmd(dt, "src", t.goTest(), "-ldflags=-linkmode=internal -libgcc=none", pkg, t.runFlag(run)) + // What matters is that the tests build and start up. + // Skip expensive tests, especially x509 TestSystemRoots. + t.addCmd(dt, "src", t.goTest(), "-ldflags=-linkmode=internal -libgcc=none", "-run=^Test[^CS]", pkg, t.runFlag(run)) return nil }, }) @@ -693,7 +710,10 @@ func (t *tester) registerTests() { } if goos != "android" && !t.iOS() { - t.registerTest("bench_go1", "../test/bench/go1", t.goTest(), t.timeout(600)) + // There are no tests in this directory, only benchmarks. + // Check that the test binary builds but don't bother running it. + // (It has init-time work to set up for the benchmarks that is not worth doing unnecessarily.) + t.registerTest("bench_go1", "../test/bench/go1", t.goTest(), "-c", "-o="+os.DevNull) } if goos != "android" && !t.iOS() { // Only start multiple test dir shards on builders, @@ -1292,8 +1312,12 @@ func (t *tester) raceTest(dt *distTest) error { // TODO(iant): Figure out how to catch this. // t.addCmd(dt, "src", t.goTest(), "-race", "-run=TestParallelTest", "cmd/go") if t.cgoEnabled { - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-race") - cmd.Env = append(os.Environ(), "GOTRACEBACK=2") + // Building misc/cgo/test takes a long time. + // There are already cgo-enabled packages being tested with the race detector. + // We shouldn't need to redo all of misc/cgo/test too. + // The race buildler will take care of this. + // cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-race") + // cmd.Env = append(os.Environ(), "GOTRACEBACK=2") } if t.extLink() { // Test with external linking; see issue 9133. @@ -1407,6 +1431,60 @@ func (t *tester) makeGOROOTUnwritable() { } } +// shouldUsePrecompiledStdTest reports whether "dist test" should use +// a pre-compiled go test binary on disk rather than running "go test" +// and compiling it again. This is used by our slow qemu-based builder +// that do full processor emulation where we cross-compile the +// make.bash step as well as pre-compile each std test binary. +// +// This only reports true if dist is run with an single go_test:foo +// argument (as the build coordinator does with our slow qemu-based +// builders), we're in a builder environment ("GO_BUILDER_NAME" is set), +// and the pre-built test binary exists. +func (t *tester) shouldUsePrecompiledStdTest() bool { + bin := t.prebuiltGoPackageTestBinary() + if bin == "" { + return false + } + _, err := os.Stat(bin) + return err == nil +} + +// prebuiltGoPackageTestBinary returns the path where we'd expect +// the pre-built go test binary to be on disk when dist test is run with +// a single argument. +// It returns an empty string if a pre-built binary should not be used. +func (t *tester) prebuiltGoPackageTestBinary() string { + if len(stdMatches) != 1 || t.race || t.compileOnly || os.Getenv("GO_BUILDER_NAME") == "" { + return "" + } + pkg := stdMatches[0] + return filepath.Join(os.Getenv("GOROOT"), "src", pkg, path.Base(pkg)+".test") +} + +// runPrecompiledStdTest runs the pre-compiled standard library package test binary. +// See shouldUsePrecompiledStdTest above; it must return true for this to be called. +func (t *tester) runPrecompiledStdTest(timeout time.Duration) error { + bin := t.prebuiltGoPackageTestBinary() + fmt.Fprintf(os.Stderr, "# %s: using pre-built %s...\n", stdMatches[0], bin) + cmd := exec.Command(bin, "-test.short", "-test.timeout="+timeout.String()) + cmd.Dir = filepath.Dir(bin) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Start(); err != nil { + return err + } + // And start a timer to kill the process if it doesn't kill + // itself in the prescribed timeout. + const backupKillFactor = 1.05 // add 5% + timer := time.AfterFunc(time.Duration(float64(timeout)*backupKillFactor), func() { + fmt.Fprintf(os.Stderr, "# %s: timeout running %s; killing...\n", stdMatches[0], bin) + cmd.Process.Kill() + }) + defer timer.Stop() + return cmd.Wait() +} + // raceDetectorSupported is a copy of the function // cmd/internal/sys.RaceDetectorSupported, which can't be used here // because cmd/dist has to be buildable by Go 1.4. diff --git a/src/cmd/doc/doc_test.go b/src/cmd/doc/doc_test.go index 22468db1ff..bc870aca58 100644 --- a/src/cmd/doc/doc_test.go +++ b/src/cmd/doc/doc_test.go @@ -602,6 +602,19 @@ var tests = []test{ `Comment about exported interface`, }, }, + // Interface method at package level. + { + "interface method at package level", + []string{p, `ExportedMethod`}, + []string{ + `func \(ExportedType\) ExportedMethod\(a int\) bool`, + `Comment about exported method`, + }, + []string{ + `Comment before exported method.*\n.*ExportedMethod\(\)` + + `.*Comment on line with exported method`, + }, + }, // Method. { diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index 12b76c2ad0..32810bd581 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -914,8 +914,8 @@ func trimUnexportedFields(fields *ast.FieldList, isInterface bool) *ast.FieldLis } // printMethodDoc prints the docs for matches of symbol.method. -// If symbol is empty, it prints all methods that match the name. -// It reports whether it found any methods. +// If symbol is empty, it prints all methods for any concrete type +// that match the name. It reports whether it found any methods. func (pkg *Package) printMethodDoc(symbol, method string) bool { defer pkg.flush() types := pkg.findTypes(symbol) @@ -937,6 +937,9 @@ func (pkg *Package) printMethodDoc(symbol, method string) bool { } continue } + if symbol == "" { + continue + } // Type may be an interface. The go/doc package does not attach // an interface's methods to the doc.Type. We need to dig around. spec := pkg.findTypeSpec(typ.Decl, typ.Name) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index b774ac2da7..26fb337f86 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -557,7 +557,7 @@ // // Usage: // -// go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages] +// go get [-d] [-m] [-t] [-u] [-v] [-insecure] [build flags] [packages] // // Get resolves and adds dependencies to the current development module // and then builds and installs them. @@ -600,6 +600,9 @@ // are competing requirements for a particular module, then 'go get' resolves // those requirements by taking the maximum requested version.) // +// The -t flag instructs get to consider modules needed to build tests of +// packages specified on the command line. +// // The -u flag instructs get to update dependencies to use newer minor or // patch releases when available. Continuing the previous example, // 'go get -u A' will use the latest A with B v1.3.1 (not B v1.2.3). @@ -610,6 +613,9 @@ // 'go get -u=patch A@latest' will use the latest A with B v1.2.4 (not B v1.2.3), // while 'go get -u=patch A' will use a patch release of A instead. // +// When the -t and -u flags are used together, get will update +// test dependencies as well. +// // In general, adding a new dependency may require upgrading // existing dependencies to keep a working build, and 'go get' does // this automatically. Similarly, downgrading one dependency may @@ -2014,21 +2020,6 @@ // // Module proxy protocol // -// The go command by default downloads modules from version control systems -// directly, just as 'go get' always has. The GOPROXY environment variable allows -// further control over the download source. If GOPROXY is unset, is the empty string, -// or is the string "direct", downloads use the default direct connection to version -// control systems. Setting GOPROXY to "off" disallows downloading modules from -// any source. Otherwise, GOPROXY is expected to be a comma-separated list of -// the URLs of module proxies, in which case the go command will fetch modules -// from those proxies. For each request, the go command tries each proxy in sequence, -// only moving to the next if the current proxy returns a 404 or 410 HTTP response. -// The string "direct" may appear in the proxy list, to cause a direct connection to -// be attempted at that point in the search. -// -// No matter the source of the modules, downloaded modules must match existing -// entries in go.sum (see 'go help modules' for discussion of verification). -// // A Go module proxy is any web server that can respond to GET requests for // URLs of a specified form. The requests have no query parameters, so even // a site serving from a fixed file system (including a file:/// URL) @@ -2585,16 +2576,43 @@ // // Module downloading and verification // -// The go command checks downloads against known checksums, -// to detect unexpected changes in the content of any specific module -// version from one day to the next. See 'go help module-auth' for details. +// The go command can fetch modules from a proxy or connect to source control +// servers directly, according to the setting of the GOPROXY environment +// variable (see 'go help env'). The default setting for GOPROXY is +// "https://proxy.golang.org", the Go module mirror run by Google. +// See https://proxy.golang.org/privacy for the service's privacy policy. +// If GOPROXY is set to the string "direct", downloads use a direct connection +// to source control servers. Setting GOPROXY to "off" disallows downloading +// modules from any source. Otherwise, GOPROXY is expected to be a comma-separated +// list of the URLs of module proxies, in which case the go command will fetch +// modules from those proxies. For each request, the go command tries each proxy +// in sequence, only moving to the next if the current proxy returns a 404 or 410 +// HTTP response. The string "direct" may appear in the proxy list, +// to cause a direct connection to be attempted at that point in the search. +// Any proxies listed after "direct" are never consulted. // -// The go command can fetch modules from a proxy instead of connecting -// to source control systems directly, according to the setting of the GOPROXY -// environment variable. +// The GONOPROXY environment variable is a comma-separated list of +// glob patterns (in the syntax of Go's path.Match) of module path prefixes +// that should always be fetched directly, ignoring the GOPROXY setting. +// For example, // -// See 'go help goproxy' for details about the proxy and also the format of -// the cached downloaded packages. +// GONOPROXY=*.corp.example.com,rsc.io/private +// +// forces a direct connection to download modules with path prefixes matching +// either pattern, including "git.corp.example.com/xyzzy", "rsc.io/private", +// and "rsc.io/private/quux". +// +// The 'go env -w' command (see 'go help env') can be used to set these variables +// for future go command invocations. +// +// No matter the source of the modules, the go command checks downloads against +// known checksums, to detect unexpected changes in the content of any specific +// module version from one day to the next. This check first consults the current +// module's go.sum file but falls back to the Go checksum database. +// See 'go help module-auth' for details. +// +// See 'go help goproxy' for details about the proxy protocol and also +// the format of the cached downloaded packages. // // Modules and vendoring // @@ -2772,18 +2790,17 @@ // database requires giving the public key explicitly. The URL defaults to // "https://" followed by the database name. // -// GOSUMDB defaults to "sum.golang.org" when GOPROXY="https://proxy.golang.org" -// and otherwise defaults to "off". NOTE: The GOSUMDB will later default to -// "sum.golang.org" unconditionally. +// GOSUMDB defaults to "sum.golang.org", the Go checksum database run by Google. +// See https://sum.golang.org/privacy for the service's privacy policy. // // If GOSUMDB is set to "off", or if "go get" is invoked with the -insecure flag, -// the checksum database is never consulted, but at the cost of giving up the -// security guarantee of verified repeatable downloads for all modules. -// A better way to bypass the checksum database for specific modules is -// to use the GONOSUMDB environment variable. +// the checksum database is not consulted, and all unrecognized modules are +// accepted, at the cost of giving up the security guarantee of verified repeatable +// downloads for all modules. A better way to bypass the checksum database +// for specific modules is to use the GONOSUMDB environment variable. // // The GONOSUMDB environment variable is a comma-separated list of -// patterns (in the syntax of Go's path.Match) of module path prefixes +// glob patterns (in the syntax of Go's path.Match) of module path prefixes // that should not be compared against the checksum database. // For example, // @@ -2793,6 +2810,9 @@ // either pattern, including "git.corp.example.com/xyzzy", "rsc.io/private", // and "rsc.io/private/quux". // +// The 'go env -w' command (see 'go help env') can be used to set these variables +// for future go command invocations. +// // // Testing flags // diff --git a/src/cmd/go/internal/cache/cache_test.go b/src/cmd/go/internal/cache/cache_test.go index 7229bc4cec..1988c34502 100644 --- a/src/cmd/go/internal/cache/cache_test.go +++ b/src/cmd/go/internal/cache/cache_test.go @@ -78,7 +78,7 @@ func TestGrowth(t *testing.T) { n := 10000 if testing.Short() { - n = 1000 + n = 10 } for i := 0; i < n; i++ { diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 2d17d104a6..77d8bab14f 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -303,13 +303,6 @@ func goproxy() string { return v } - // Proxy is off by default for now. - // TODO(rsc): Remove this condition, turning it on always. - // (But do NOT do this without approval from rsc.) - if true { - return "direct" - } - return "https://proxy.golang.org" } @@ -319,13 +312,6 @@ func gosumdb() string { return v } - // Checksum database is off by default except when GOPROXY is proxy.golang.org. - // TODO(rsc): Remove this condition, turning it on always. - // (But do NOT do this without approval from rsc.) - if !strings.HasPrefix(GOPROXY, "https://proxy.golang.org") { - return "off" - } - return "sum.golang.org" } diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 00f10977bb..b3d12dd681 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -66,6 +66,7 @@ func MkEnv() []cfg.EnvVar { envFile, _ := cfg.EnvFile() env := []cfg.EnvVar{ + {Name: "GO111MODULE", Value: cfg.Getenv("GO111MODULE")}, {Name: "GOARCH", Value: cfg.Goarch}, {Name: "GOBIN", Value: cfg.GOBIN}, {Name: "GOCACHE", Value: cache.DefaultDir()}, diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index 817f7657e2..d40d2c6fac 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -702,18 +702,17 @@ The go command knows the public key of sum.golang.org; use of any other database requires giving the public key explicitly. The URL defaults to "https://" followed by the database name. -GOSUMDB defaults to "sum.golang.org" when GOPROXY="https://proxy.golang.org" -and otherwise defaults to "off". NOTE: The GOSUMDB will later default to -"sum.golang.org" unconditionally. +GOSUMDB defaults to "sum.golang.org", the Go checksum database run by Google. +See https://sum.golang.org/privacy for the service's privacy policy. If GOSUMDB is set to "off", or if "go get" is invoked with the -insecure flag, -the checksum database is never consulted, but at the cost of giving up the -security guarantee of verified repeatable downloads for all modules. -A better way to bypass the checksum database for specific modules is -to use the GONOSUMDB environment variable. +the checksum database is not consulted, and all unrecognized modules are +accepted, at the cost of giving up the security guarantee of verified repeatable +downloads for all modules. A better way to bypass the checksum database +for specific modules is to use the GONOSUMDB environment variable. The GONOSUMDB environment variable is a comma-separated list of -patterns (in the syntax of Go's path.Match) of module path prefixes +glob patterns (in the syntax of Go's path.Match) of module path prefixes that should not be compared against the checksum database. For example, @@ -722,5 +721,8 @@ For example, disables checksum database lookups for modules with path prefixes matching either pattern, including "git.corp.example.com/xyzzy", "rsc.io/private", and "rsc.io/private/quux". + +The 'go env -w' command (see 'go help env') can be used to set these variables +for future go command invocations. `, } diff --git a/src/cmd/go/internal/modfetch/proxy.go b/src/cmd/go/internal/modfetch/proxy.go index 605c72c0ab..5f0432ceed 100644 --- a/src/cmd/go/internal/modfetch/proxy.go +++ b/src/cmd/go/internal/modfetch/proxy.go @@ -32,21 +32,6 @@ var HelpGoproxy = &base.Command{ UsageLine: "goproxy", Short: "module proxy protocol", Long: ` -The go command by default downloads modules from version control systems -directly, just as 'go get' always has. The GOPROXY environment variable allows -further control over the download source. If GOPROXY is unset, is the empty string, -or is the string "direct", downloads use the default direct connection to version -control systems. Setting GOPROXY to "off" disallows downloading modules from -any source. Otherwise, GOPROXY is expected to be a comma-separated list of -the URLs of module proxies, in which case the go command will fetch modules -from those proxies. For each request, the go command tries each proxy in sequence, -only moving to the next if the current proxy returns a 404 or 410 HTTP response. -The string "direct" may appear in the proxy list, to cause a direct connection to -be attempted at that point in the search. - -No matter the source of the modules, downloaded modules must match existing -entries in go.sum (see 'go help modules' for discussion of verification). - A Go module proxy is any web server that can respond to GET requests for URLs of a specified form. The requests have no query parameters, so even a site serving from a fixed file system (including a file:/// URL) diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 7a5d550997..d5ab59490c 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -31,7 +31,7 @@ import ( var CmdGet = &base.Command{ // Note: -d -m -u are listed explicitly because they are the most common get flags. // Do not send CLs removing them because they're covered by [get flags]. - UsageLine: "go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]", + UsageLine: "go get [-d] [-m] [-t] [-u] [-v] [-insecure] [build flags] [packages]", Short: "add dependencies to current module and install them", Long: ` Get resolves and adds dependencies to the current development module @@ -75,6 +75,9 @@ will use the latest A but then use B v1.2.3, as requested by A. (If there are competing requirements for a particular module, then 'go get' resolves those requirements by taking the maximum requested version.) +The -t flag instructs get to consider modules needed to build tests of +packages specified on the command line. + The -u flag instructs get to update dependencies to use newer minor or patch releases when available. Continuing the previous example, 'go get -u A' will use the latest A with B v1.3.1 (not B v1.2.3). @@ -85,6 +88,9 @@ Continuing the previous example, 'go get -u=patch A@latest' will use the latest A with B v1.2.4 (not B v1.2.3), while 'go get -u=patch A' will use a patch release of A instead. +When the -t and -u flags are used together, get will update +test dependencies as well. + In general, adding a new dependency may require upgrading existing dependencies to keep a working build, and 'go get' does this automatically. Similarly, downgrading one dependency may @@ -261,9 +267,7 @@ func runGet(cmd *base.Command, args []string) { if *getFix { fmt.Fprintf(os.Stderr, "go get: -fix flag is a no-op when using modules\n") } - if *getT { - fmt.Fprintf(os.Stderr, "go get: -t flag is a no-op when using modules\n") - } + modload.LoadTests = *getT if cfg.BuildMod == "vendor" { base.Fatalf("go get: disabled by -mod=%s", cfg.BuildMod) @@ -781,25 +785,26 @@ func newUpgrader(cmdline map[string]*query, pkgs map[string]bool) *upgrader { // Initialize work queue with root packages. seen := make(map[string]bool) var work []string - for pkg := range pkgs { - seen[pkg] = true - for _, imp := range modload.PackageImports(pkg) { - if !pkgs[imp] && !seen[imp] { - seen[imp] = true - work = append(work, imp) - } + add := func(path string) { + if !seen[path] { + seen[path] = true + work = append(work, path) } } + for pkg := range pkgs { + add(pkg) + } for len(work) > 0 { pkg := work[0] work = work[1:] m := modload.PackageModule(pkg) u.upgrade[m.Path] = true - for _, imp := range modload.PackageImports(pkg) { - if !seen[imp] { - seen[imp] = true - work = append(work, imp) - } + imports, testImports := modload.PackageImports(pkg) + for _, imp := range imports { + add(imp) + } + for _, imp := range testImports { + add(imp) } } } diff --git a/src/cmd/go/internal/modload/help.go b/src/cmd/go/internal/modload/help.go index c1685ff08e..96fec8451e 100644 --- a/src/cmd/go/internal/modload/help.go +++ b/src/cmd/go/internal/modload/help.go @@ -328,16 +328,43 @@ module file trees. Module downloading and verification -The go command checks downloads against known checksums, -to detect unexpected changes in the content of any specific module -version from one day to the next. See 'go help module-auth' for details. +The go command can fetch modules from a proxy or connect to source control +servers directly, according to the setting of the GOPROXY environment +variable (see 'go help env'). The default setting for GOPROXY is +"https://proxy.golang.org", the Go module mirror run by Google. +See https://proxy.golang.org/privacy for the service's privacy policy. +If GOPROXY is set to the string "direct", downloads use a direct connection +to source control servers. Setting GOPROXY to "off" disallows downloading +modules from any source. Otherwise, GOPROXY is expected to be a comma-separated +list of the URLs of module proxies, in which case the go command will fetch +modules from those proxies. For each request, the go command tries each proxy +in sequence, only moving to the next if the current proxy returns a 404 or 410 +HTTP response. The string "direct" may appear in the proxy list, +to cause a direct connection to be attempted at that point in the search. +Any proxies listed after "direct" are never consulted. -The go command can fetch modules from a proxy instead of connecting -to source control systems directly, according to the setting of the GOPROXY -environment variable. +The GONOPROXY environment variable is a comma-separated list of +glob patterns (in the syntax of Go's path.Match) of module path prefixes +that should always be fetched directly, ignoring the GOPROXY setting. +For example, -See 'go help goproxy' for details about the proxy and also the format of -the cached downloaded packages. + GONOPROXY=*.corp.example.com,rsc.io/private + +forces a direct connection to download modules with path prefixes matching +either pattern, including "git.corp.example.com/xyzzy", "rsc.io/private", +and "rsc.io/private/quux". + +The 'go env -w' command (see 'go help env') can be used to set these variables +for future go command invocations. + +No matter the source of the modules, the go command checks downloads against +known checksums, to detect unexpected changes in the content of any specific +module version from one day to the next. This check first consults the current +module's go.sum file but falls back to the Go checksum database. +See 'go help module-auth' for details. + +See 'go help goproxy' for details about the proxy protocol and also +the format of the cached downloaded packages. Modules and vendoring diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 579ef50382..b64b5b68cd 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -496,17 +496,26 @@ func PackageModule(path string) module.Version { } // PackageImports returns the imports for the package named by the import path. -// It does not include test imports. It returns nil for unknown packages. -func PackageImports(path string) []string { +// Test imports will be returned as well if tests were loaded for the package +// (i.e., if "all" was loaded or if LoadTests was set and the path was matched +// by a command line argument). PackageImports will return nil for +// unknown package paths. +func PackageImports(path string) (imports, testImports []string) { pkg, ok := loaded.pkgCache.Get(path).(*loadPkg) if !ok { - return nil + return nil, nil } - imports := make([]string, len(pkg.imports)) + imports = make([]string, len(pkg.imports)) for i, p := range pkg.imports { imports[i] = p.path } - return imports + if pkg.test != nil { + testImports = make([]string, len(pkg.test.imports)) + for i, p := range pkg.test.imports { + testImports[i] = p.path + } + } + return imports, testImports } // ModuleUsedDirectly reports whether the main module directly imports diff --git a/src/cmd/go/internal/mvs/mvs.go b/src/cmd/go/internal/mvs/mvs.go index 90f8f269b5..04273e733c 100644 --- a/src/cmd/go/internal/mvs/mvs.go +++ b/src/cmd/go/internal/mvs/mvs.go @@ -13,7 +13,6 @@ import ( "sync" "sync/atomic" - "cmd/go/internal/base" "cmd/go/internal/module" "cmd/go/internal/par" ) @@ -118,7 +117,7 @@ func BuildList(target module.Version, reqs Reqs) ([]module.Version, error) { return buildList(target, reqs, nil) } -func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) module.Version) ([]module.Version, error) { +func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (module.Version, error)) ([]module.Version, error) { // Explore work graph in parallel in case reqs.Required // does high-latency network operations. type modGraphNode struct { @@ -133,6 +132,10 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) mo min = map[string]string{} // maps module path to minimum required version haveErr int32 ) + setErr := func(n *modGraphNode, err error) { + n.err = err + atomic.StoreInt32(&haveErr, 1) + } var work par.Work work.Add(target) @@ -149,8 +152,7 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) mo required, err := reqs.Required(m) if err != nil { - node.err = err - atomic.StoreInt32(&haveErr, 1) + setErr(node, err) return } node.required = required @@ -159,9 +161,9 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) mo } if upgrade != nil { - u := upgrade(m) - if u.Path == "" { - base.Errorf("Upgrade(%v) returned zero module", m) + u, err := upgrade(m) + if err != nil { + setErr(node, err) return } if u != m { @@ -332,17 +334,12 @@ func Req(target module.Version, list []module.Version, base []string, reqs Reqs) // UpgradeAll returns a build list for the target module // in which every module is upgraded to its latest version. func UpgradeAll(target module.Version, reqs Reqs) ([]module.Version, error) { - return buildList(target, reqs, func(m module.Version) module.Version { + return buildList(target, reqs, func(m module.Version) (module.Version, error) { if m.Path == target.Path { - return target + return target, nil } - latest, err := reqs.Upgrade(m) - if err != nil { - panic(err) // TODO - } - m.Version = latest.Version - return m + return reqs.Upgrade(m) }) } @@ -351,7 +348,7 @@ func UpgradeAll(target module.Version, reqs Reqs) ([]module.Version, error) { func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]module.Version, error) { list, err := reqs.Required(target) if err != nil { - panic(err) // TODO + return nil, err } // TODO: Maybe if an error is given, // rerun with BuildList(upgrade[0], reqs) etc @@ -370,7 +367,7 @@ func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]mod func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([]module.Version, error) { list, err := reqs.Required(target) if err != nil { - panic(err) // TODO + return nil, err } max := make(map[string]string) for _, r := range list { @@ -409,7 +406,17 @@ func Downgrade(target module.Version, reqs Reqs, downgrade ...module.Version) ([ } list, err := reqs.Required(m) if err != nil { - panic(err) // TODO + // If we can't load the requirements, we couldn't load the go.mod file. + // There are a number of reasons this can happen, but this usually + // means an older version of the module had a missing or invalid + // go.mod file. For example, if example.com/mod released v2.0.0 before + // migrating to modules (v2.0.0+incompatible), then added a valid go.mod + // in v2.0.1, downgrading from v2.0.1 would cause this error. + // + // TODO(golang.org/issue/31730, golang.org/issue/30134): if the error + // is transient (we couldn't download go.mod), return the error from + // Downgrade. Currently, we can't tell what kind of error it is. + exclude(m) } for _, r := range list { add(r) @@ -429,7 +436,12 @@ List: for excluded[r] { p, err := reqs.Previous(r) if err != nil { - return nil, err // TODO + // This is likely a transient error reaching the repository, + // rather than a permanent error with the retrieved version. + // + // TODO(golang.org/issue/31730, golang.org/issue/30134): + // decode what to do based on the actual error. + return nil, err } // If the target version is a pseudo-version, it may not be // included when iterating over prior versions using reqs.Previous. diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 1a98980915..1f6d1e8e77 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -159,7 +159,7 @@ func hashToString(h [cache.HashSize]byte) string { // which influences the action ID half of the build ID, is based on the content ID, // then the Linux compiler binary and Mac compiler binary will have different tool IDs // and therefore produce executables with different action IDs. -// To avoids this problem, for releases we use the release version string instead +// To avoid this problem, for releases we use the release version string instead // of the compiler binary's content hash. This assumes that all compilers built // on all different systems are semantically equivalent, which is of course only true // modulo bugs. (Producing the exact same executables also requires that the different @@ -215,7 +215,7 @@ func (b *Builder) toolID(name string) string { } // gccToolID returns the unique ID to use for a tool that is invoked -// by the GCC driver. This is in particular gccgo, but this can also +// by the GCC driver. This is used particularly for gccgo, but this can also // be used for gcc, g++, gfortran, etc.; those tools all use the GCC // driver under different names. The approach used here should also // work for sufficiently new versions of clang. Unlike toolID, the diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 35e70ddb1e..6f2d319bc2 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -211,6 +211,9 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID { fmt.Fprintf(h, "goos %s goarch %s\n", cfg.Goos, cfg.Goarch) fmt.Fprintf(h, "import %q\n", p.ImportPath) fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) + if cfg.BuildTrimpath { + fmt.Fprintln(h, "trimpath") + } if p.Internal.ForceLibrary { fmt.Fprintf(h, "forcelibrary\n") } @@ -1116,6 +1119,9 @@ func (b *Builder) linkActionID(a *Action) cache.ActionID { fmt.Fprintf(h, "buildmode %s goos %s goarch %s\n", cfg.BuildBuildmode, cfg.Goos, cfg.Goarch) fmt.Fprintf(h, "import %q\n", p.ImportPath) fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) + if cfg.BuildTrimpath { + fmt.Fprintln(h, "trimpath") + } // Toolchain-dependent configuration, shared with b.linkSharedActionID. b.printLinkerConfig(h, p) diff --git a/src/cmd/go/testdata/mod/example.com_downgrade_v2.0.0.txt b/src/cmd/go/testdata/mod/example.com_downgrade_v2.0.0.txt new file mode 100644 index 0000000000..88d50e5bba --- /dev/null +++ b/src/cmd/go/testdata/mod/example.com_downgrade_v2.0.0.txt @@ -0,0 +1,9 @@ +example.com/downgrade v2.0.0 +written by hand + +-- .mod -- +module example.com/downgrade + +require rsc.io/quote v1.5.2 +-- .info -- +{"Version":"v2.0.0"} diff --git a/src/cmd/go/testdata/mod/example.com_downgrade_v2_v2.0.1.txt b/src/cmd/go/testdata/mod/example.com_downgrade_v2_v2.0.1.txt new file mode 100644 index 0000000000..a4d665ff1b --- /dev/null +++ b/src/cmd/go/testdata/mod/example.com_downgrade_v2_v2.0.1.txt @@ -0,0 +1,13 @@ +example.com/downgrade/v2 v2.0.1 +written by hand + +-- .mod -- +module example.com/downgrade/v2 + +require rsc.io/quote v1.5.2 +-- .info -- +{"Version":"v2.0.1"} +-- go.mod -- +module example.com/downgrade/v2 + +require rsc.io/quote v1.5.2 diff --git a/src/cmd/go/testdata/mod/example.com_latemigrate_v2_v2.0.0.txt b/src/cmd/go/testdata/mod/example.com_latemigrate_v2_v2.0.0.txt new file mode 100644 index 0000000000..25bd3d9d8f --- /dev/null +++ b/src/cmd/go/testdata/mod/example.com_latemigrate_v2_v2.0.0.txt @@ -0,0 +1,14 @@ +example.com/latemigrate/v2 v2.0.0 +written by hand + +This repository migrated to modules in v2.0.1 after v2.0.0 was already tagged. +All versions require rsc.io/quote so we can test downgrades. + +v2.0.0 is technically part of example.com/latemigrate as v2.0.0+incompatible. +Proxies may serve it as part of the version list for example.com/latemigrate/v2. +'go get' must be able to ignore these versions. + +-- .mod -- +module example.com/latemigrate +-- .info -- +{"Version":"v2.0.0"} diff --git a/src/cmd/go/testdata/mod/example.com_latemigrate_v2_v2.0.1.txt b/src/cmd/go/testdata/mod/example.com_latemigrate_v2_v2.0.1.txt new file mode 100644 index 0000000000..be427a3185 --- /dev/null +++ b/src/cmd/go/testdata/mod/example.com_latemigrate_v2_v2.0.1.txt @@ -0,0 +1,20 @@ +example.com/latemigrate/v2 v2.0.1 +written by hand + +This repository migrated to modules in v2.0.1 after v2.0.0 was already tagged. +All versions require rsc.io/quote so we can test downgrades. + +v2.0.1 belongs to example.com/latemigrate/v2. + +-- .mod -- +module example.com/latemigrate/v2 + +require rsc.io/quote v1.3.0 +-- .info -- +{"Version":"v2.0.1"} +-- go.mod -- +module example.com/latemigrate/v2 + +require rsc.io/quote v1.3.0 +-- late.go -- +package late diff --git a/src/cmd/go/testdata/script/build_cache_trimpath.txt b/src/cmd/go/testdata/script/build_cache_trimpath.txt new file mode 100644 index 0000000000..39367ae380 --- /dev/null +++ b/src/cmd/go/testdata/script/build_cache_trimpath.txt @@ -0,0 +1,20 @@ +env GO111MODULE=on + +# Set up fresh GOCACHE. +env GOCACHE=$WORK/gocache +mkdir $GOCACHE + +cd $WORK +go build -o a.out + +# Varying -trimpath should cause a rebuild. +go build -x -o a.out -trimpath +stderr '(compile|gccgo)( |\.exe)' +stderr 'link( |\.exe)' + +-- $WORK/hello.go -- +package main +func main() { println("hello") } + +-- $WORK/go.mod -- +module m diff --git a/src/cmd/go/testdata/script/mod_get_downgrade.txt b/src/cmd/go/testdata/script/mod_get_downgrade.txt index 00cd93e598..ee9ac96475 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade.txt @@ -2,6 +2,7 @@ env GO111MODULE=on [short] skip # downgrade sampler should downgrade quote +cp go.mod.orig go.mod go get rsc.io/sampler@v1.0.0 go list -m all stdout 'rsc.io/quote v1.4.0' @@ -31,9 +32,21 @@ stdout 'rsc.io/quote v1.4.0' stdout 'rsc.io/sampler v1.0.0' ! stdout golang.org/x/text --- go.mod -- +# downgrading away quote should also downgrade away latemigrate/v2, +# since there are no older versions. v2.0.0 is incompatible. +cp go.mod.orig go.mod +go list -m -versions example.com/latemigrate/v2 +stdout v2.0.0 # proxy may serve incompatible versions +go get rsc.io/quote@none +go list -m all +! stdout 'example.com/latemigrate/v2' + +-- go.mod.orig -- module x -require rsc.io/quote v1.5.1 +require ( + rsc.io/quote v1.5.1 + example.com/latemigrate/v2 v2.0.1 +) -- go.mod.empty -- module x -- x.go -- diff --git a/src/cmd/go/testdata/script/mod_get_test.txt b/src/cmd/go/testdata/script/mod_get_test.txt new file mode 100644 index 0000000000..f921168ad4 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_test.txt @@ -0,0 +1,58 @@ +env GO111MODULE=on + +# By default, 'go get' should ignore tests +cp go.mod.empty go.mod +go get m/a +! grep rsc.io/quote go.mod + +# 'go get -t' should consider test dependencies of the named package. +cp go.mod.empty go.mod +go get -d -t m/a +grep 'rsc.io/quote v1.5.2$' go.mod + +# 'go get -t' should not consider test dependencies of imported packages, +# including packages imported from tests. +cp go.mod.empty go.mod +go get -d -t m/b +! grep rsc.io/quote go.mod + +# 'go get -t -u' should update test dependencies of the named package. +cp go.mod.empty go.mod +go mod edit -require=rsc.io/quote@v1.5.1 +go get -d -t -u m/a +grep 'rsc.io/quote v1.5.2$' go.mod + +# 'go get -t -u' should not add or update test dependencies +# of imported packages, including packages imported from tests. +cp go.mod.empty go.mod +go get -d -t -u m/b +! grep rsc.io/quote go.mod +go mod edit -require=rsc.io/quote@v1.5.1 +go get -d -t -u m/b +grep 'rsc.io/quote v1.5.1$' go.mod + +# 'go get all' should consider test dependencies with or without -t. +cp go.mod.empty go.mod +go get all +grep 'rsc.io/quote v1.5.2$' go.mod + +-- go.mod.empty -- +module m + +-- a/a.go -- +package a + +-- a/a_test.go -- +package a_test + +import _ "rsc.io/quote" + +-- b/b.go -- +package b + +import _ "m/a" + +-- b/b_test.go -- +package b_test + +import _ "m/a" diff --git a/src/cmd/go/testdata/script/mod_sumdb_golang.txt b/src/cmd/go/testdata/script/mod_sumdb_golang.txt index ca040c5dcf..0eb0fc84a7 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_golang.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_golang.txt @@ -1,16 +1,16 @@ -[!net] skip - +# Test default GOPROXY and GOSUMDB env GOPROXY= env GOSUMDB= go env GOPROXY -stdout '^direct$' +stdout '^https://proxy.golang.org$' go env GOSUMDB -stdout '^off$' +stdout '^sum.golang.org$' env GOPROXY=https://proxy.golang.org go env GOSUMDB stdout '^sum.golang.org$' # download direct from github +[!net] skip env GOSUMDB=sum.golang.org env GOPROXY=direct go get -m rsc.io/quote diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index 3ea29a87a9..66748b25d2 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -377,6 +377,7 @@ const ( ) // An LSym is the sort of symbol that is written to an object file. +// It represents Go symbols in a flat pkg+"."+name namespace. type LSym struct { Name string Type objabi.SymKind diff --git a/src/cmd/internal/obj/x86/pcrelative_test.go b/src/cmd/internal/obj/x86/pcrelative_test.go index 51b60cf93e..487a65d8dc 100644 --- a/src/cmd/internal/obj/x86/pcrelative_test.go +++ b/src/cmd/internal/obj/x86/pcrelative_test.go @@ -96,6 +96,9 @@ LOOP: for idx := len(data) - 1; idx >= 0; idx-- { // check that RET wasn't overwritten. if bytes.Index(data[idx], []byte("RET")) != -1 { + if testing.Short() { + break LOOP + } continue LOOP } } diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go index 235db39dda..e52e26af49 100644 --- a/src/cmd/link/dwarf_test.go +++ b/src/cmd/link/dwarf_test.go @@ -165,8 +165,10 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string) func TestDWARF(t *testing.T) { testDWARF(t, "", true) - if runtime.GOOS == "darwin" { - testDWARF(t, "c-archive", true) + if runtime.GOOS == "darwin" && !testing.Short() { + t.Run("c-archive", func(t *testing.T) { + testDWARF(t, "c-archive", true) + }) } } diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index a783bddc50..29b98e9c32 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -170,7 +170,7 @@ main.x: relocation target main.zero not defined } } -func TestBuildFortvOS(t *testing.T) { +func TestBuildForTvOS(t *testing.T) { testenv.MustHaveCGO(t) testenv.MustHaveGoBuild(t) @@ -178,6 +178,9 @@ func TestBuildFortvOS(t *testing.T) { if runtime.GOARCH != "amd64" || runtime.GOOS != "darwin" { t.Skip("skipping on non-darwin/amd64 platform") } + if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { + t.Skip("skipping in -short mode with $GO_BUILDER_NAME empty") + } if err := exec.Command("xcrun", "--help").Run(); err != nil { t.Skipf("error running xcrun, required for iOS cross build: %v", err) } diff --git a/src/cmd/pack/pack_test.go b/src/cmd/pack/pack_test.go index b2217c090f..6121bf08c0 100644 --- a/src/cmd/pack/pack_test.go +++ b/src/cmd/pack/pack_test.go @@ -231,6 +231,9 @@ func TestHello(t *testing.T) { // Test that pack works with very long lines in PKGDEF. func TestLargeDefs(t *testing.T) { + if testing.Short() { + t.Skip("skipping in -short mode") + } testenv.MustHaveGoBuild(t) dir := tmpDir(t) diff --git a/src/compress/flate/deflate_test.go b/src/compress/flate/deflate_test.go index 079c03c283..4b1ed549a4 100644 --- a/src/compress/flate/deflate_test.go +++ b/src/compress/flate/deflate_test.go @@ -345,6 +345,9 @@ func testToFromWithLimit(t *testing.T, input []byte, name string, limit [11]int) func TestDeflateInflate(t *testing.T) { t.Parallel() for i, h := range deflateInflateTests { + if testing.Short() && len(h.in) > 10000 { + continue + } testToFromWithLimit(t, h.in, fmt.Sprintf("#%d", i), [11]int{}) } } @@ -591,6 +594,9 @@ func TestBestSpeed(t *testing.T) { } for i, tc := range testCases { + if i >= 3 && testing.Short() { + break + } for _, firstN := range []int{1, 65534, 65535, 65536, 65537, 131072} { tc[0] = firstN outer: diff --git a/src/container/ring/ring_test.go b/src/container/ring/ring_test.go index 552f0e24b5..41d18abf8b 100644 --- a/src/container/ring/ring_test.go +++ b/src/container/ring/ring_test.go @@ -179,7 +179,7 @@ func TestLink2(t *testing.T) { func TestLink3(t *testing.T) { var r Ring n := 1 - for i := 1; i < 100; i++ { + for i := 1; i < 10; i++ { n += i verify(t, r.Link(New(i)), n, -1) } diff --git a/src/context/context.go b/src/context/context.go index 0f36881b1e..05d01d0294 100644 --- a/src/context/context.go +++ b/src/context/context.go @@ -220,6 +220,7 @@ func TODO() Context { // A CancelFunc tells an operation to abandon its work. // A CancelFunc does not wait for the work to stop. +// A CancelFunc may be called by multiple goroutines simultaneously. // After the first call, subsequent calls to a CancelFunc do nothing. type CancelFunc func() diff --git a/src/crypto/cipher/xor_test.go b/src/crypto/cipher/xor_test.go index d49f1da77c..40d4e5afa3 100644 --- a/src/crypto/cipher/xor_test.go +++ b/src/crypto/cipher/xor_test.go @@ -20,6 +20,9 @@ func TestXOR(t *testing.T) { testenv.SkipFlaky(t, 31812) } for j := 1; j <= 1024; j++ { + if testing.Short() && j > 16 { + break + } for alignP := 0; alignP < 2; alignP++ { for alignQ := 0; alignQ < 2; alignQ++ { for alignD := 0; alignD < 2; alignD++ { diff --git a/src/crypto/elliptic/fuzz_test.go b/src/crypto/elliptic/fuzz_test.go index 10196cf0bc..eaeed0dacc 100644 --- a/src/crypto/elliptic/fuzz_test.go +++ b/src/crypto/elliptic/fuzz_test.go @@ -22,7 +22,7 @@ func TestFuzz(t *testing.T) { var timeout *time.Timer if testing.Short() { - timeout = time.NewTimer(500 * time.Millisecond) + timeout = time.NewTimer(10 * time.Millisecond) } else { timeout = time.NewTimer(2 * time.Second) } diff --git a/src/crypto/rand/util_test.go b/src/crypto/rand/util_test.go index 685624e1b3..e76ce2018a 100644 --- a/src/crypto/rand/util_test.go +++ b/src/crypto/rand/util_test.go @@ -84,6 +84,9 @@ func TestIntMask(t *testing.T) { for max := 1; max <= 256; max++ { t.Run(fmt.Sprintf("max=%d", max), func(t *testing.T) { for i := 0; i < max; i++ { + if testing.Short() && i == 0 { + i = max - 1 + } var b bytes.Buffer b.WriteByte(byte(i)) n, err := rand.Int(&b, big.NewInt(int64(max))) diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go index 7f380b6ec4..d412474034 100644 --- a/src/crypto/rsa/pkcs1v15_test.go +++ b/src/crypto/rsa/pkcs1v15_test.go @@ -274,8 +274,8 @@ func TestShortSessionKey(t *testing.T) { } } -// In order to generate new test vectors you'll need the PEM form of this key: -// -----BEGIN RSA PRIVATE KEY----- +// In order to generate new test vectors you'll need the PEM form of this key (and s/TESTING/PRIVATE/): +// -----BEGIN RSA TESTING KEY----- // MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 // fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu // /ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu @@ -283,7 +283,7 @@ func TestShortSessionKey(t *testing.T) { // EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A // IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS // tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V -// -----END RSA PRIVATE KEY----- +// -----END RSA TESTING KEY----- var rsaPrivateKey = &PrivateKey{ PublicKey: PublicKey{ diff --git a/src/crypto/sha1/sha1.go b/src/crypto/sha1/sha1.go index dee290c654..329435f282 100644 --- a/src/crypto/sha1/sha1.go +++ b/src/crypto/sha1/sha1.go @@ -10,6 +10,7 @@ package sha1 import ( "crypto" + "encoding/binary" "errors" "hash" ) @@ -81,13 +82,13 @@ func (d *digest) UnmarshalBinary(b []byte) error { func appendUint64(b []byte, x uint64) []byte { var a [8]byte - putUint64(a[:], x) + binary.BigEndian.PutUint64(a[:], x) return append(b, a[:]...) } func appendUint32(b []byte, x uint32) []byte { var a [4]byte - putUint32(a[:], x) + binary.BigEndian.PutUint32(a[:], x) return append(b, a[:]...) } @@ -175,7 +176,7 @@ func (d *digest) checkSum() [Size]byte { // Length in bits. len <<= 3 - putUint64(tmp[:], len) + binary.BigEndian.PutUint64(tmp[:], len) d.Write(tmp[0:8]) if d.nx != 0 { @@ -184,11 +185,11 @@ func (d *digest) checkSum() [Size]byte { var digest [Size]byte - putUint32(digest[0:], d.h[0]) - putUint32(digest[4:], d.h[1]) - putUint32(digest[8:], d.h[2]) - putUint32(digest[12:], d.h[3]) - putUint32(digest[16:], d.h[4]) + binary.BigEndian.PutUint32(digest[0:], d.h[0]) + binary.BigEndian.PutUint32(digest[4:], d.h[1]) + binary.BigEndian.PutUint32(digest[8:], d.h[2]) + binary.BigEndian.PutUint32(digest[12:], d.h[3]) + binary.BigEndian.PutUint32(digest[16:], d.h[4]) return digest } @@ -275,23 +276,3 @@ func Sum(data []byte) [Size]byte { d.Write(data) return d.checkSum() } - -func putUint64(x []byte, s uint64) { - _ = x[7] - x[0] = byte(s >> 56) - x[1] = byte(s >> 48) - x[2] = byte(s >> 40) - x[3] = byte(s >> 32) - x[4] = byte(s >> 24) - x[5] = byte(s >> 16) - x[6] = byte(s >> 8) - x[7] = byte(s) -} - -func putUint32(x []byte, s uint32) { - _ = x[3] - x[0] = byte(s >> 24) - x[1] = byte(s >> 16) - x[2] = byte(s >> 8) - x[3] = byte(s) -} diff --git a/src/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go index 8e4915a7d8..faf29f25ad 100644 --- a/src/crypto/sha256/sha256.go +++ b/src/crypto/sha256/sha256.go @@ -9,6 +9,7 @@ package sha256 import ( "crypto" "crypto/internal/boring" + "encoding/binary" "errors" "hash" ) @@ -105,35 +106,15 @@ func (d *digest) UnmarshalBinary(b []byte) error { return nil } -func putUint32(x []byte, s uint32) { - _ = x[3] - x[0] = byte(s >> 24) - x[1] = byte(s >> 16) - x[2] = byte(s >> 8) - x[3] = byte(s) -} - -func putUint64(x []byte, s uint64) { - _ = x[7] - x[0] = byte(s >> 56) - x[1] = byte(s >> 48) - x[2] = byte(s >> 40) - x[3] = byte(s >> 32) - x[4] = byte(s >> 24) - x[5] = byte(s >> 16) - x[6] = byte(s >> 8) - x[7] = byte(s) -} - func appendUint64(b []byte, x uint64) []byte { var a [8]byte - putUint64(a[:], x) + binary.BigEndian.PutUint64(a[:], x) return append(b, a[:]...) } func appendUint32(b []byte, x uint32) []byte { var a [4]byte - putUint32(a[:], x) + binary.BigEndian.PutUint32(a[:], x) return append(b, a[:]...) } @@ -255,7 +236,7 @@ func (d *digest) checkSum() [Size]byte { // Length in bits. len <<= 3 - putUint64(tmp[:], len) + binary.BigEndian.PutUint64(tmp[:], len) d.Write(tmp[0:8]) if d.nx != 0 { @@ -264,15 +245,15 @@ func (d *digest) checkSum() [Size]byte { var digest [Size]byte - putUint32(digest[0:], d.h[0]) - putUint32(digest[4:], d.h[1]) - putUint32(digest[8:], d.h[2]) - putUint32(digest[12:], d.h[3]) - putUint32(digest[16:], d.h[4]) - putUint32(digest[20:], d.h[5]) - putUint32(digest[24:], d.h[6]) + binary.BigEndian.PutUint32(digest[0:], d.h[0]) + binary.BigEndian.PutUint32(digest[4:], d.h[1]) + binary.BigEndian.PutUint32(digest[8:], d.h[2]) + binary.BigEndian.PutUint32(digest[12:], d.h[3]) + binary.BigEndian.PutUint32(digest[16:], d.h[4]) + binary.BigEndian.PutUint32(digest[20:], d.h[5]) + binary.BigEndian.PutUint32(digest[24:], d.h[6]) if !d.is224 { - putUint32(digest[28:], d.h[7]) + binary.BigEndian.PutUint32(digest[28:], d.h[7]) } return digest diff --git a/src/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go index 394e001eee..3fefd65c65 100644 --- a/src/crypto/sha512/sha512.go +++ b/src/crypto/sha512/sha512.go @@ -13,6 +13,7 @@ package sha512 import ( "crypto" "crypto/internal/boring" + "encoding/binary" "errors" "hash" ) @@ -196,21 +197,9 @@ func (d *digest) UnmarshalBinary(b []byte) error { return nil } -func putUint64(x []byte, s uint64) { - _ = x[7] - x[0] = byte(s >> 56) - x[1] = byte(s >> 48) - x[2] = byte(s >> 40) - x[3] = byte(s >> 32) - x[4] = byte(s >> 24) - x[5] = byte(s >> 16) - x[6] = byte(s >> 8) - x[7] = byte(s) -} - func appendUint64(b []byte, x uint64) []byte { var a [8]byte - putUint64(a[:], x) + binary.BigEndian.PutUint64(a[:], x) return append(b, a[:]...) } @@ -329,8 +318,8 @@ func (d *digest) checkSum() [Size]byte { // Length in bits. len <<= 3 - putUint64(tmp[0:], 0) // upper 64 bits are always zero, because len variable has type uint64 - putUint64(tmp[8:], len) + binary.BigEndian.PutUint64(tmp[0:], 0) // upper 64 bits are always zero, because len variable has type uint64 + binary.BigEndian.PutUint64(tmp[8:], len) d.Write(tmp[0:16]) if d.nx != 0 { @@ -338,15 +327,15 @@ func (d *digest) checkSum() [Size]byte { } var digest [Size]byte - putUint64(digest[0:], d.h[0]) - putUint64(digest[8:], d.h[1]) - putUint64(digest[16:], d.h[2]) - putUint64(digest[24:], d.h[3]) - putUint64(digest[32:], d.h[4]) - putUint64(digest[40:], d.h[5]) + binary.BigEndian.PutUint64(digest[0:], d.h[0]) + binary.BigEndian.PutUint64(digest[8:], d.h[1]) + binary.BigEndian.PutUint64(digest[16:], d.h[2]) + binary.BigEndian.PutUint64(digest[24:], d.h[3]) + binary.BigEndian.PutUint64(digest[32:], d.h[4]) + binary.BigEndian.PutUint64(digest[40:], d.h[5]) if d.function != crypto.SHA384 { - putUint64(digest[48:], d.h[6]) - putUint64(digest[56:], d.h[7]) + binary.BigEndian.PutUint64(digest[48:], d.h[6]) + binary.BigEndian.PutUint64(digest[56:], d.h[7]) } return digest diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go index 40311b0a66..a27f107ba7 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go @@ -880,6 +880,9 @@ func TestResumption(t *testing.T) { } func testResumption(t *testing.T, version uint16) { + if testing.Short() { + t.Skip("skipping in -short mode") + } serverConfig := &Config{ MaxVersion: version, CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA}, @@ -1727,6 +1730,9 @@ func TestAlertFlushing(t *testing.T) { } func TestHandshakeRace(t *testing.T) { + if testing.Short() { + t.Skip("skipping in -short mode") + } t.Parallel() // This test races a Read and Write to try and complete a handshake in // order to provide some evidence that there are no races or deadlocks diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 131de0f2fc..843a0a70f0 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -1351,8 +1351,8 @@ o0RIvFkTgxYEiKSBXCUNmAysEbEoVr4dzWFihAm/1oDGRY2CLLTYg5vbySK3KhIR e/oCO8HJ/+rJnahJ05XX1Q7lNQ== -----END CERTIFICATE-----` -const clientKeyPEM = ` ------BEGIN RSA PRIVATE KEY----- +var clientKeyPEM = testingKey(` +-----BEGIN RSA TESTING KEY----- MIICXQIBAAKBgQC6b6qGvc+/n/LvXJRgeG/oE/LRlm/N2TJuIjfOQfnKXSms4Sfa YaLugcsQx980WJWG6T0Z5lwnc2DIjXgC9B2kmAmjGXBpPCViZiqrIiPFe4U4Ty4J czKnvT6brcqEB+YPOv93xZ1BhQCKtpvusKQ/LUxM5kI+u1HI3UhU9AyORwIDAQAB @@ -1366,7 +1366,7 @@ jUCVJzJA5ORJrn8g64u2eGK28z/LFQbv9wXgCwfc72R468BdawFSLa/m2EECQGbZ rWiFla26IVXV0xcD98VWJsTBZMlgPnSOqoMdM1kSEd4fUmlAYI/dFzV1XYSkOmVr FhdZnklmpVDeu27P4c0CQQCuCOup0FlJSBpWY1TTfun/KMBkBatMz0VMA3d7FKIU csPezl677Yjo8u1r/KzeI6zLg87Z8E6r6ZWNc9wBSZK6 ------END RSA PRIVATE KEY-----` +-----END RSA TESTING KEY-----`) const clientECDSACertificatePEM = ` -----BEGIN CERTIFICATE----- @@ -1383,17 +1383,17 @@ C3JosDJdYUoCdFzCgbkWqD8pyDbHgf9stlvZcPE4O1BIKJTLCRpS8V3ujfK58PDa jWVim34BmT0Y9hCaOGGbLlfk+syxis7iI6CH8OFnUes= -----END CERTIFICATE-----` -const clientECDSAKeyPEM = ` +var clientECDSAKeyPEM = testingKey(` -----BEGIN EC PARAMETERS----- BgUrgQQAIw== -----END EC PARAMETERS----- ------BEGIN EC PRIVATE KEY----- +-----BEGIN EC TESTING KEY----- MIHcAgEBBEIBkJN9X4IqZIguiEVKMqeBUP5xtRsEv4HJEtOpOGLELwO53SD78Ew8 k+wLWoqizS3NpQyMtrU8JFdWfj+C57UNkOugBwYFK4EEACOhgYkDgYYABACVjJF1 FMBexFe01MNvja5oHt1vzobhfm6ySD6B5U7ixohLZNz1MLvT/2XMW/TdtWo+PtAd 3kfDdq0Z9kUsjLzYHQFMH3CQRnZIi4+DzEpcj0B22uCJ7B0rxE4wdihBsmKo+1vx +U56jb0JuK7qixgnTy5w/hOWusPTQBbNZU6sER7m8Q== ------END EC PRIVATE KEY-----` +-----END EC TESTING KEY-----`) const clientEd25519CertificatePEM = ` -----BEGIN CERTIFICATE----- @@ -1406,10 +1406,10 @@ QQD8GRcqlKUx+inILn9boF2KTjRAOdazENwZ/qAicbP1j6FYDc308YUkv+Y9FN/f 7Q7hF9gRomDQijcjKsJGqjoI -----END CERTIFICATE-----` -const clientEd25519KeyPEM = ` ------BEGIN PRIVATE KEY----- +var clientEd25519KeyPEM = testingKey(` +-----BEGIN TESTING KEY----- MC4CAQAwBQYDK2VwBCIEINifzf07d9qx3d44e0FSbV4mC/xQxT644RRbpgNpin7I ------END PRIVATE KEY-----` +-----END TESTING KEY-----`) func TestClientAuth(t *testing.T) { var certPath, keyPath, ecdsaCertPath, ecdsaKeyPath, ed25519CertPath, ed25519KeyPath string @@ -1761,7 +1761,7 @@ nIPhKls4T0hFoLvjJnXpAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUE DDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2CC2V4YW1wbGUu Y29tMA0GCSqGSIb3DQEBCwUAA0EAxDuUS+BrrS3c+h+k+fQPOmOScy6yTX9mHw0Q KbucGamXYEy0URIwOdO0tQ3LHPc1YGvYSPwkDjkjqECs2Vm/AA== ------END CERTIFICATE-----`), []byte(`-----BEGIN RSA PRIVATE KEY----- +-----END CERTIFICATE-----`), []byte(testingKey(`-----BEGIN RSA TESTING KEY----- MIIBOgIBAAJBAN17PWsVQPBrHYdPFtycVQ/0CFyAQYwdVXaefhVURYUkHojwL82T HRfLJCWuYVgHMRCcg+EqWzhPSEWgu+MmdekCAwEAAQJBALjQYNTdXF4CFBbXwUz/ yt9QFDYT9B5WT/12jeGAe653gtYS6OOi/+eAkGmzg1GlRnw6fOfn+HYNFDORST7z @@ -1769,7 +1769,7 @@ yt9QFDYT9B5WT/12jeGAe653gtYS6OOi/+eAkGmzg1GlRnw6fOfn+HYNFDORST7z nKpbtU22+PbIMSJ+e80fmY9LIPx5N4HTAiAthGSimMR9bloz0EY3GyuUEyqoDgMd hXxjuno2WesoJQIgemilbcALXpxsLmZLgcQ2KSmaVr7jb5ECx9R+hYKTw1sCIG4s T+E0J8wlH24pgwQHzy7Ko2qLwn1b5PW8ecrlvP1g ------END RSA PRIVATE KEY-----`)) +-----END RSA TESTING KEY-----`))) if err != nil { t.Fatal(err) } diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go index 0a3aeeff73..a07727c92b 100644 --- a/src/crypto/tls/tls_test.go +++ b/src/crypto/tls/tls_test.go @@ -37,7 +37,7 @@ r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V -----END CERTIFICATE----- ` -var rsaKeyPEM = `-----BEGIN RSA PRIVATE KEY----- +var rsaKeyPEM = testingKey(`-----BEGIN RSA TESTING KEY----- MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G 6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N @@ -45,12 +45,12 @@ MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g== ------END RSA PRIVATE KEY----- -` +-----END RSA TESTING KEY----- +`) // keyPEM is the same as rsaKeyPEM, but declares itself as just // "PRIVATE KEY", not "RSA PRIVATE KEY". https://golang.org/issue/4477 -var keyPEM = `-----BEGIN PRIVATE KEY----- +var keyPEM = testingKey(`-----BEGIN TESTING KEY----- MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G 6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N @@ -58,8 +58,8 @@ MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g== ------END PRIVATE KEY----- -` +-----END TESTING KEY----- +`) var ecdsaCertPEM = `-----BEGIN CERTIFICATE----- MIIB/jCCAWICCQDscdUxw16XFDAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw @@ -76,17 +76,17 @@ H5jBImIxPL4WxQNiBTexAkF8D1EtpYuWdlVQ80/h/f4pBcGiXPqX5h2PQSQY7hP1 -----END CERTIFICATE----- ` -var ecdsaKeyPEM = `-----BEGIN EC PARAMETERS----- +var ecdsaKeyPEM = testingKey(`-----BEGIN EC PARAMETERS----- BgUrgQQAIw== -----END EC PARAMETERS----- ------BEGIN EC PRIVATE KEY----- +-----BEGIN EC TESTING KEY----- MIHcAgEBBEIBrsoKp0oqcv6/JovJJDoDVSGWdirrkgCWxrprGlzB9o0X8fV675X0 NwuBenXFfeZvVcwluO7/Q9wkYoPd/t3jGImgBwYFK4EEACOhgYkDgYYABAFj36bL 06h5JRGUNB1X/Hwuw64uKW2GGJLVPPhoYMcg/ALWaW+d/t+DmV5xikwKssuFq4Bz VQldyCXTXGgu7OC0AQCC/Y/+ODK3NFKlRi+AsG3VQDSV4tgHLqZBBus0S6pPcg1q kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ== ------END EC PRIVATE KEY----- -` +-----END EC TESTING KEY----- +`) var keyPairTests = []struct { algo string @@ -372,7 +372,9 @@ func testVerifyHostnameResumed(t *testing.T, version uint16) { ClientSessionCache: NewLRUClientSessionCache(32), } for i := 0; i < 2; i++ { - c, err := Dial("tcp", "mail.google.com:https", config) + c, err := DialWithDialer(&net.Dialer{ + Timeout: 10 * time.Second, + }, "tcp", "mail.google.com:https", config) if err != nil { t.Fatalf("Dial #%d: %v", i, err) } @@ -389,12 +391,13 @@ func testVerifyHostnameResumed(t *testing.T, version uint16) { if err := c.VerifyHostname("mail.google.com"); err != nil { t.Fatalf("verify mail.google.com #%d: %v", i, err) } - // Give the client a chance to read the server session tickets. - c.SetReadDeadline(time.Now().Add(500 * time.Millisecond)) + // Have the server send some data so session tickets are delivered. + c.SetDeadline(time.Now().Add(5 * time.Second)) + if _, err := io.WriteString(c, "HEAD / HTTP/1.0\n\n"); err != nil { + t.Fatal(err) + } if _, err := c.Read(make([]byte, 1)); err != nil { - if err, ok := err.(net.Error); !ok || !err.Timeout() { - t.Fatal(err) - } + t.Fatal(err) } c.Close() } @@ -1139,3 +1142,5 @@ func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) { t.Fatalf("Certificates were mutated by BuildNameToCertificate\nGot: %#v\nWant: %#v\n", got, want) } } + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/src/crypto/x509/pem_decrypt_test.go b/src/crypto/x509/pem_decrypt_test.go index 685d5ee156..dacef8b861 100644 --- a/src/crypto/x509/pem_decrypt_test.go +++ b/src/crypto/x509/pem_decrypt_test.go @@ -80,8 +80,8 @@ var testData = []struct { { kind: PEMCipherDES, password: []byte("asdf"), - pemData: []byte(` ------BEGIN RSA PRIVATE KEY----- + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-CBC,34F09A4FC8DE22B5 @@ -92,7 +92,7 @@ qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm 4C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug== ------END RSA PRIVATE KEY-----`), +-----END RSA TESTING KEY-----`)), plainDER: ` MIIBPAIBAAJBAPASZe+tCPU6p80AjHhDkVsLYa51D35e/YGa8QcZyooeZM8EHozo KD0fNiKI+53bHdy07N+81VQ8/ejPcRoXPlsCAwEAAQJBAMTxIuSq27VpR+zZ7WJf @@ -105,8 +105,8 @@ glcRgT6QCEtz2wIhANSyqaFtosIkHKqrDUGfz/bb5tqMYTAnBruVPaf/WEOBAiEA { kind: PEMCipher3DES, password: []byte("asdf"), - pemData: []byte(` ------BEGIN RSA PRIVATE KEY----- + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7 @@ -117,7 +117,7 @@ Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w 3z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk= ------END RSA PRIVATE KEY-----`), +-----END RSA TESTING KEY-----`)), plainDER: ` MIIBOwIBAAJBANOCXKdoNS/iP/MAbl9cf1/SF3P+Ns7ZeNL27CfmDh0O6Zduaax5 NBiumd2PmjkaCu7lQ5JOibHfWn+xJsc3kw0CAwEAAQJANX/W8d1Q/sCqzkuAn4xl @@ -130,8 +130,8 @@ tZZZxCtPAm7shftEib0VU77Lk8MsXJcx2C4voRsjEw==`, { kind: PEMCipherAES128, password: []byte("asdf"), - pemData: []byte(` ------BEGIN RSA PRIVATE KEY----- + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A @@ -142,7 +142,7 @@ GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D 3NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E 080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0= ------END RSA PRIVATE KEY-----`), +-----END RSA TESTING KEY-----`)), plainDER: ` MIIBOgIBAAJBAMBlj5FxYtqbcy8wY89d/S7n0+r5MzD9F63BA/Lpl78vQKtdJ5dT cDGh/rBt1ufRrNp0WihcmZi7Mpl/3jHjiWECAwEAAQJABNOHYnKhtDIqFYj1OAJ3 @@ -155,8 +155,8 @@ B3WlRNTXR2WsJ5JdByezg9xzdXzULqmga0OE339a`, { kind: PEMCipherAES192, password: []byte("asdf"), - pemData: []byte(` ------BEGIN RSA PRIVATE KEY----- + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369 @@ -167,7 +167,7 @@ Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6 xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw= ------END RSA PRIVATE KEY-----`), +-----END RSA TESTING KEY-----`)), plainDER: ` MIIBOwIBAAJBAMGcRrZiNNmtF20zyS6MQ7pdGx17aFDl+lTl+qnLuJRUCMUG05xs OmxmL/O1Qlf+bnqR8Bgg65SfKg21SYuLhiMCAwEAAQJBAL94uuHyO4wux2VC+qpj @@ -180,8 +180,8 @@ uZ3pWbaXf5PNuQIgAcdXarvhelH2w2piY1g3BPeFqhzBSCK/yLGxR82KIh8CIQDD { kind: PEMCipherAES256, password: []byte("asdf"), - pemData: []byte(` ------BEGIN RSA PRIVATE KEY----- + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD @@ -192,7 +192,7 @@ Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/ 2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0= ------END RSA PRIVATE KEY-----`), +-----END RSA TESTING KEY-----`)), plainDER: ` MIIBOgIBAAJBAKy3GFkstoCHIEeUU/qO8207m8WSrjksR+p9B4tf1w5k+2O1V/GY AQ5WFCApItcOkQe/I0yZZJk/PmCqMzSxrc8CAwEAAQJAOCAz0F7AW9oNelVQSP8F @@ -207,15 +207,15 @@ PXHYtPqxQIbD2pScR5qum7iGUh11lEUPkmt+2uqS`, // openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128 kind: PEMCipherAES128, password: []byte("asdf"), - pemData: []byte(` ------BEGIN RSA PRIVATE KEY----- + pemData: []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7 6ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3 eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD hTP8O1mS/MHl92NE0nhv0w== ------END RSA PRIVATE KEY-----`), +-----END RSA TESTING KEY-----`)), plainDER: ` MGMCAQACEQC6ssxmYuauuHGOCDAI54RdAgMBAAECEQCWIn6Yv2O+kBcDF7STctKB AgkA8SEfu/2i3g0CCQDGNlXbBHX7kQIIK3Ww5o0cYbECCQDCimPb0dYGsQIIeQ7A @@ -223,14 +223,14 @@ jryIst8=`, }, } -const incompleteBlockPEM = ` ------BEGIN RSA PRIVATE KEY----- +var incompleteBlockPEM = testingKey(` +-----BEGIN RSA TESTING KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7 6L8yXK2MTQUWBk4ZD6OvCiYp+mXyR1594TQ1K38MxGvDw5pwcDME2Lek8RrR5fd40P2XsL2Z4KKt ai+OP1BZUetfK6AW4MiqB2FDyIdOAJ8XeWuZy21Wtsh8wPD6yYOFM/w7WZL8weX3Y0TSeG/T ------END RSA PRIVATE KEY-----` +-----END RSA TESTING KEY-----`) func TestIncompleteBlock(t *testing.T) { // incompleteBlockPEM contains ciphertext that is not a multiple of the @@ -245,3 +245,5 @@ func TestIncompleteBlock(t *testing.T) { t.Fatalf("Expected error containing %q but got: %q", expectedSubstr, e) } } + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/src/crypto/x509/root_cgo_darwin.go b/src/crypto/x509/root_cgo_darwin.go index e6332072d6..255a8d3525 100644 --- a/src/crypto/x509/root_cgo_darwin.go +++ b/src/crypto/x509/root_cgo_darwin.go @@ -16,7 +16,7 @@ package x509 #include #include -static bool isSSLPolicy(SecPolicyRef policyRef) { +static Boolean isSSLPolicy(SecPolicyRef policyRef) { if (!policyRef) { return false; } @@ -24,13 +24,13 @@ static bool isSSLPolicy(SecPolicyRef policyRef) { if (properties == NULL) { return false; } + Boolean isSSL = false; CFTypeRef value = NULL; if (CFDictionaryGetValueIfPresent(properties, kSecPolicyOid, (const void **)&value)) { - CFRelease(properties); - return CFEqual(value, kSecPolicyAppleSSL); + isSSL = CFEqual(value, kSecPolicyAppleSSL); } CFRelease(properties); - return false; + return isSSL; } // sslTrustSettingsResult obtains the final kSecTrustSettingsResult value @@ -51,6 +51,7 @@ static SInt32 sslTrustSettingsResult(SecCertificateRef cert) { } // > no trust settings [...] means "this certificate must be verified to a known trusted certificate” + // (Should this cause a fallback from user to admin domain? It's unclear.) if (err != errSecSuccess || trustSettings == NULL) { if (trustSettings != NULL) CFRelease(trustSettings); return kSecTrustSettingsResultUnspecified; @@ -77,16 +78,12 @@ static SInt32 sslTrustSettingsResult(SecCertificateRef cert) { for (m = 0; m < CFArrayGetCount(trustSettings); m++) { CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, m); - // First, check if this trust setting applies to our policy. We assume - // only one will. The docs suggest that there might be multiple applying - // but don't explain how to combine them. + // First, check if this trust setting is constrained to a non-SSL policy. SecPolicyRef policyRef; if (CFDictionaryGetValueIfPresent(tSetting, _kSecTrustSettingsPolicy, (const void**)&policyRef)) { if (!isSSLPolicy(policyRef)) { continue; } - } else { - continue; } if (CFDictionaryContainsKey(tSetting, _kSecTrustSettingsPolicyString)) { @@ -98,13 +95,23 @@ static SInt32 sslTrustSettingsResult(SecCertificateRef cert) { if (CFDictionaryGetValueIfPresent(tSetting, _kSecTrustSettingsResult, (const void**)&cfNum)) { CFNumberGetValue(cfNum, kCFNumberSInt32Type, &result); } else { - // > If the value of the kSecTrustSettingsResult component is not - // > kSecTrustSettingsResultUnspecified for a usage constraints dictionary that has - // > no constraints, the default value kSecTrustSettingsResultTrustRoot is assumed. + // > If this key is not present, a default value of + // > kSecTrustSettingsResultTrustRoot is assumed. result = kSecTrustSettingsResultTrustRoot; } - break; + // If multiple dictionaries match, we are supposed to "OR" them, + // the semantics of which are not clear. Since TrustRoot and TrustAsRoot + // are mutually exclusive, Deny should probably override, and Invalid and + // Unspecified be overridden, approximate this by stopping at the first + // TrustRoot, TrustAsRoot or Deny. + if (result == kSecTrustSettingsResultTrustRoot) { + break; + } else if (result == kSecTrustSettingsResultTrustAsRoot) { + break; + } else if (result == kSecTrustSettingsResultDeny) { + break; + } } // If trust settings are present, but none of them match the policy... @@ -143,7 +150,7 @@ static Boolean isRootCertificate(SecCertificateRef cert, CFErrorRef *errRef) { return equal; } -// FetchPEMRoots fetches the system's list of trusted X.509 root certificates +// CopyPEMRoots fetches the system's list of trusted X.509 root certificates // for the kSecTrustSettingsPolicy SSL. // // On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root @@ -152,15 +159,15 @@ static Boolean isRootCertificate(SecCertificateRef cert, CFErrorRef *errRef) { // // Note: The CFDataRef returned in pemRoots and untrustedPemRoots must // be released (using CFRelease) after we've consumed its content. -int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugDarwinRoots) { +int CopyPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugDarwinRoots) { int i; if (debugDarwinRoots) { - printf("crypto/x509: kSecTrustSettingsResultInvalid = %d\n", kSecTrustSettingsResultInvalid); - printf("crypto/x509: kSecTrustSettingsResultTrustRoot = %d\n", kSecTrustSettingsResultTrustRoot); - printf("crypto/x509: kSecTrustSettingsResultTrustAsRoot = %d\n", kSecTrustSettingsResultTrustAsRoot); - printf("crypto/x509: kSecTrustSettingsResultDeny = %d\n", kSecTrustSettingsResultDeny); - printf("crypto/x509: kSecTrustSettingsResultUnspecified = %d\n", kSecTrustSettingsResultUnspecified); + fprintf(stderr, "crypto/x509: kSecTrustSettingsResultInvalid = %d\n", kSecTrustSettingsResultInvalid); + fprintf(stderr, "crypto/x509: kSecTrustSettingsResultTrustRoot = %d\n", kSecTrustSettingsResultTrustRoot); + fprintf(stderr, "crypto/x509: kSecTrustSettingsResultTrustAsRoot = %d\n", kSecTrustSettingsResultTrustAsRoot); + fprintf(stderr, "crypto/x509: kSecTrustSettingsResultDeny = %d\n", kSecTrustSettingsResultDeny); + fprintf(stderr, "crypto/x509: kSecTrustSettingsResultUnspecified = %d\n", kSecTrustSettingsResultUnspecified); } // Get certificates from all domains, not just System, this lets @@ -170,7 +177,7 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugD kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainUser }; int numDomains = sizeof(domains)/sizeof(SecTrustSettingsDomain); - if (pemRoots == NULL) { + if (pemRoots == NULL || untrustedPemRoots == NULL) { return -1; } @@ -186,8 +193,6 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugD CFIndex numCerts = CFArrayGetCount(certs); for (j = 0; j < numCerts; j++) { - CFDataRef data = NULL; - CFArrayRef trustSettings = NULL; SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, j); if (cert == NULL) { continue; @@ -206,7 +211,7 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugD CFErrorRef errRef = NULL; CFStringRef summary = SecCertificateCopyShortDescription(NULL, cert, &errRef); if (errRef != NULL) { - printf("crypto/x509: SecCertificateCopyShortDescription failed\n"); + fprintf(stderr, "crypto/x509: SecCertificateCopyShortDescription failed\n"); CFRelease(errRef); continue; } @@ -215,7 +220,7 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugD CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; char *buffer = malloc(maxSize); if (CFStringGetCString(summary, buffer, maxSize, kCFStringEncodingUTF8)) { - printf("crypto/x509: %s returned %d\n", buffer, (int)result); + fprintf(stderr, "crypto/x509: %s returned %d\n", buffer, (int)result); } free(buffer); CFRelease(summary); @@ -246,11 +251,16 @@ int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugD } else if (result == kSecTrustSettingsResultDeny) { appendTo = combinedUntrustedData; } else if (result == kSecTrustSettingsResultUnspecified) { + // Certificates with unspecified trust should probably be added to a pool of + // intermediates for chain building, or checked for transitive trust and + // added to the root pool (which is an imprecise approximation because it + // cuts chains short) but we don't support either at the moment. TODO. continue; } else { continue; } + CFDataRef data = NULL; err = SecItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data); if (err != noErr) { continue; @@ -274,22 +284,22 @@ import ( ) func loadSystemRoots() (*CertPool, error) { - roots := NewCertPool() - - var data C.CFDataRef = 0 - var untrustedData C.CFDataRef = 0 - err := C.FetchPEMRoots(&data, &untrustedData, C.bool(debugDarwinRoots)) + var data, untrustedData C.CFDataRef + err := C.CopyPEMRoots(&data, &untrustedData, C.bool(debugDarwinRoots)) if err == -1 { return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo") } - defer C.CFRelease(C.CFTypeRef(data)) + defer C.CFRelease(C.CFTypeRef(untrustedData)) + buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data))) + roots := NewCertPool() roots.AppendCertsFromPEM(buf) - if untrustedData == 0 { + + if C.CFDataGetLength(untrustedData) == 0 { return roots, nil } - defer C.CFRelease(C.CFTypeRef(untrustedData)) + buf = C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(untrustedData)), C.int(C.CFDataGetLength(untrustedData))) untrustedRoots := NewCertPool() untrustedRoots.AppendCertsFromPEM(buf) diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go index 1165a97e20..0a1529e833 100644 --- a/src/crypto/x509/root_darwin_test.go +++ b/src/crypto/x509/root_darwin_test.go @@ -120,12 +120,10 @@ func TestSystemRoots(t *testing.T) { if t.Failed() && debugDarwinRoots { cmd := exec.Command("security", "dump-trust-settings") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + cmd.Stdout, cmd.Stderr = os.Stderr, os.Stderr cmd.Run() cmd = exec.Command("security", "dump-trust-settings", "-d") - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + cmd.Stdout, cmd.Stderr = os.Stderr, os.Stderr cmd.Run() } } diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 7dadb77dfd..171509f7c4 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -112,8 +112,8 @@ FF53oIpvxe/SCOymfWq/LW849Ytv3Xwod0+wzAP8STXG4HSELS4UedPYeHJJJYcZ -----END PUBLIC KEY----- ` -var pemPrivateKey = ` ------BEGIN RSA PRIVATE KEY----- +var pemPrivateKey = testingKey(` +-----BEGIN RSA TESTING KEY----- MIICXAIBAAKBgQCxoeCUW5KJxNPxMp+KmCxKLc1Zv9Ny+4CFqcUXVUYH69L3mQ7v IWrJ9GBfcaA7BPQqUlWxWM+OCEQZH1EZNIuqRMNQVuIGCbz5UQ8w6tS0gcgdeGX7 J7jgCQ4RK3F/PuCM38QBLaHx988qG8NMc6VKErBjctCXFHQt14lerd5KpQIDAQAB @@ -127,8 +127,8 @@ MTXIvf7Wmv6E++eFcnT461FlGAUHRV+bQQXGsItR/opIG7mGogIkVXa3E1MCQARX AAA7eoZ9AEHflUeuLn9QJI/r0hyQQLEtrpwv6rDT1GCWaLII5HJ6NUFVf4TTcqxo 6vdM4QGKTJoO+SaCyP0CQFdpcxSAuzpFcKv0IlJ8XzS/cy+mweCMwyJ1PFEc4FX6 wg/HcAJWY60xZTJDFN+Qfx8ZQvBEin6c2/h+zZi5IVY= ------END RSA PRIVATE KEY----- -` +-----END RSA TESTING KEY----- +`) // pemEd25519Key is the example from RFC 8410, Secrion 4. var pemEd25519Key = ` @@ -1243,10 +1243,13 @@ func TestParsePEMCRL(t *testing.T) { } func TestImports(t *testing.T) { + if testing.Short() { + t.Skip("skipping in -short mode") + } testenv.MustHaveGoRun(t) - if err := exec.Command(testenv.GoToolPath(t), "run", "x509_test_import.go").Run(); err != nil { - t.Errorf("failed to run x509_test_import.go: %s", err) + if out, err := exec.Command(testenv.GoToolPath(t), "run", "x509_test_import.go").CombinedOutput(); err != nil { + t.Errorf("failed to run x509_test_import.go: %s\n%s", err, out) } } diff --git a/src/crypto/x509/x509_test_import.go b/src/crypto/x509/x509_test_import.go index 3fda7da188..b778df261a 100644 --- a/src/crypto/x509/x509_test_import.go +++ b/src/crypto/x509/x509_test_import.go @@ -15,6 +15,7 @@ import ( "crypto/x509/pkix" "encoding/pem" "math/big" + "strings" "time" ) @@ -41,7 +42,7 @@ func main() { } } -var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY----- +var pemPrivateKey = testingKey(`-----BEGIN RSA TESTING KEY----- MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu /ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu @@ -49,5 +50,7 @@ RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V ------END RSA PRIVATE KEY----- -` +-----END RSA TESTING KEY----- +`) + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go index ef644f8454..6baa53defd 100644 --- a/src/debug/gosym/pclntab_test.go +++ b/src/debug/gosym/pclntab_test.go @@ -196,6 +196,9 @@ func TestLineAline(t *testing.T) { } func TestPCLine(t *testing.T) { + if testing.Short() { + t.Skip("skipping in -short mode") + } dotest(t) defer endtest() diff --git a/src/encoding/gob/decgen.go b/src/encoding/gob/decgen.go index bad4fe5d92..1c31e66625 100644 --- a/src/encoding/gob/decgen.go +++ b/src/encoding/gob/decgen.go @@ -185,10 +185,12 @@ func main() { log.Fatal("source format error:", err) } fd, err := os.Create(*output) - _, err = fd.Write(source) if err != nil { log.Fatal(err) } + if _, err := fd.Write(source); err != nil { + log.Fatal(err) + } } func printMaps(b *bytes.Buffer, upperClass string) { diff --git a/src/encoding/gob/encgen.go b/src/encoding/gob/encgen.go index 0c051d2e84..409b8c9d95 100644 --- a/src/encoding/gob/encgen.go +++ b/src/encoding/gob/encgen.go @@ -164,10 +164,12 @@ func main() { log.Fatal("source format error:", err) } fd, err := os.Create(*output) - _, err = fd.Write(source) if err != nil { log.Fatal(err) } + if _, err := fd.Write(source); err != nil { + log.Fatal(err) + } } func printMaps(b *bytes.Buffer, upperClass string) { diff --git a/src/encoding/json/encode_test.go b/src/encoding/json/encode_test.go index cd5eadf3c1..bdf2a9f079 100644 --- a/src/encoding/json/encode_test.go +++ b/src/encoding/json/encode_test.go @@ -580,6 +580,9 @@ func TestStringBytes(t *testing.T) { // Test that encodeState.stringBytes and encodeState.string use the same encoding. var r []rune for i := '\u0000'; i <= unicode.MaxRune; i++ { + if testing.Short() && i > 1000 { + i = unicode.MaxRune + } r = append(r, i) } s := string(r) + "\xff\xff\xffhello" // some invalid UTF-8 too @@ -864,6 +867,9 @@ func TestMarshalFloat(t *testing.T) { var digits = "1.2345678901234567890123" for i := len(digits); i >= 2; i-- { + if testing.Short() && i < len(digits)-4 { + break + } for exp := -30; exp <= 30; exp++ { for _, sign := range "+-" { for bits := 32; bits <= 64; bits += 32 { diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go index 204611bda0..8515b46498 100644 --- a/src/encoding/pem/pem_test.go +++ b/src/encoding/pem/pem_test.go @@ -285,7 +285,7 @@ func BenchmarkDecode(b *testing.B) { } } -var pemData = `verify return:0 +var pemData = testingKey(`verify return:0 -----BEGIN CERTIFICATE----- sdlfkjskldfj -----BEGIN CERTIFICATE----- @@ -296,13 +296,13 @@ Certificate chain -----BEGIN CERTIFICATE----- testing -----BEGIN CERTIFICATE----- ------BEGIN CERTIFICATE----- +-----BEGIN CERTIFICATE----- MIID6TCCA1ICAQEwDQYJKoZIhvcNAQEFBQAwgYsxCzAJBgNVBAYTAlVTMRMwEQYD VQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQK -EwtHb29nbGUgSW5jLjEMMAoGA1UECxMDRW5nMQwwCgYDVQQDEwNhZ2wxHTAbBgkq -hkiG9w0BCQEWDmFnbEBnb29nbGUuY29tMB4XDTA5MDkwOTIyMDU0M1oXDTEwMDkw -OTIyMDU0M1owajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAf -BgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMaZXVyb3Bh +EwtHb29nbGUgSW5jLjEMMAoGA1UECxMDRW5nMQwwCgYDVQQDEwNhZ2wxHTAbBgkq +hkiG9w0BCQEWDmFnbEBnb29nbGUuY29tMB4XDTA5MDkwOTIyMDU0M1oXDTEwMDkw +OTIyMDU0M1owajELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAf +BgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEjMCEGA1UEAxMaZXVyb3Bh LnNmby5jb3JwLmdvb2dsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK AoICAQC6pgYt7/EibBDumASF+S0qvqdL/f+nouJw2T1Qc8GmXF/iiUcrsgzh/Fd8 pDhz/T96Qg9IyR4ztuc2MXrmPra+zAuSf5bevFReSqvpIt8Duv0HbDbcqs/XKPfB @@ -318,15 +318,15 @@ Pomjn71GNTtDeWAXibjCgdL6iHACCF6Htbl0zGlG0OAK+bdn0QIDAQABMA0GCSqG SIb3DQEBBQUAA4GBAOKnQDtqBV24vVqvesL5dnmyFpFPXBn3WdFfwD6DzEb21UVG 5krmJiu+ViipORJPGMkgoL6BjU21XI95VQbun5P8vvg8Z+FnFsvRFY3e1CCzAVQY ZsUkLw2I7zI/dNlWdB8Xp7v+3w9sX5N3J/WuJ1KOO5m26kRlHQo7EzT3974g ------END CERTIFICATE----- +-----END CERTIFICATE----- 1 s:/C=ZA/O=Ca Inc./CN=CA Inc ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,80C7C7A09690757A - +-----BEGIN RSA TESTING KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,80C7C7A09690757A + eQp5ZkH6CyHBz7BZfUPxyLCCmftsBJ7HlqGb8Ld21cSwnzWZ4/SIlhyrUtsfw7VR -2TTwA+odo9ex7GdxOTaH8oZFumIRoiEjHsk8U7Bhntp+ekkPP79xunnN7hb7hkhr +2TTwA+odo9ex7GdxOTaH8oZFumIRoiEjHsk8U7Bhntp+ekkPP79xunnN7hb7hkhr yGDQZgA7s2cQHQ71v3gwT2BACAft26jCjbM1wgNzBnJ8M0Rzn68YWqaPtdBu8qb/ zVR5JB1mnqvTSbFsfF5yMc6o2WQ9jJCl6KypnMl+BpL+dlvdjYVK4l9lYsB1Hs3d +zDBbWxos818zzhS8/y6eIfiSG27cqrbhURbmgiSfDXjncK4m/pLcQ7mmBL6mFOr @@ -338,7 +338,7 @@ BTiHcL3s3KrJu1vDVrshvxfnz71KTeNnZH8UbOqT5i7fPGyXtY1XJddcbI/Q6tXf wHFsZc20TzSdsVLBtwksUacpbDogcEVMctnNrB8FIrB3vZEv9Q0Z1VeY7nmTpF+6 a+z2P7acL7j6A6Pr3+q8P9CPiPC7zFonVzuVPyB8GchGR2hytyiOVpuD9+k8hcuw ZWAaUoVtWIQ52aKS0p19G99hhb+IVANC4akkdHV4SP8i7MVNZhfUmg== ------END RSA PRIVATE KEY----- +-----END RSA TESTING KEY----- -----BEGIN EMPTY----- @@ -363,7 +363,7 @@ Header: 1 -----BEGIN HEADERS----- Header: 1 ------END HEADERS-----` +-----END HEADERS-----`) var certificate = &Block{Type: "CERTIFICATE", Headers: map[string]string{}, @@ -582,7 +582,7 @@ var privateKey2 = &Block{ }, } -var pemPrivateKey2 = `-----BEGIN RSA PRIVATE KEY----- +var pemPrivateKey2 = testingKey(`-----BEGIN RSA TESTING KEY----- Proc-Type: 4,ENCRYPTED Content-Domain: RFC822 DEK-Info: AES-128-CBC,BFCD243FEDBB40A4AA6DDAA1335473A4 @@ -594,8 +594,8 @@ y9QEsXO5czLWesYpJaXaF5N6EOhB+6UXIPhO6eOPUSATu963k64TivYJ9KZB4CtR GjA4DbE7Z4dk9coyZ9HIpT0jcsQGr497Jqw8dZGhABPGXEnVPOeyspng1SX64hKA N4XPksobn/NO2IDvPM7N9ZCe+aeyDEkE8QmP6mPScLuGvzSrsgOxWTMWF7Dbdzj0 tJQLJRZ+ItT5Irl4owSEBNLahC1j3fhQavbj9WVAfKk= ------END RSA PRIVATE KEY----- -` +-----END RSA TESTING KEY----- +`) func TestBadEncode(t *testing.T) { b := &Block{Type: "BAD", Headers: map[string]string{"X:Y": "Z"}} @@ -610,3 +610,5 @@ func TestBadEncode(t *testing.T) { t.Fatalf("EncodeToMemory returned non-nil data") } } + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/src/errors/example_test.go b/src/errors/example_test.go index 7724c16cdf..d7dd782bef 100644 --- a/src/errors/example_test.go +++ b/src/errors/example_test.go @@ -36,11 +36,12 @@ func Example() { } func ExampleAs() { - _, err := os.Open("non-existing") - if err != nil { + if _, err := os.Open("non-existing"); err != nil { var pathError *os.PathError if errors.As(err, &pathError) { fmt.Println("Failed at path:", pathError.Path) + } else { + fmt.Println(err) } } diff --git a/src/errors/wrap.go b/src/errors/wrap.go index 62332b1a88..760a08a4ef 100644 --- a/src/errors/wrap.go +++ b/src/errors/wrap.go @@ -8,8 +8,9 @@ import ( "internal/reflectlite" ) -// Unwrap returns the result of calling the Unwrap method on err, if err -// implements Wrapper. Otherwise, Unwrap returns nil. +// Unwrap returns the result of calling the Unwrap method on err, if err's +// type contains an Unwrap method returning error. +// Otherwise, Unwrap returns nil. func Unwrap(err error) error { u, ok := err.(interface { Unwrap() error diff --git a/src/fmt/print.go b/src/fmt/print.go index 3253e8042e..595869140a 100644 --- a/src/fmt/print.go +++ b/src/fmt/print.go @@ -122,7 +122,7 @@ type pp struct { panicking bool // erroring is set when printing an error string to guard against calling handleMethods. erroring bool - // wrapErrors is set when the format string may contain a %w verb. + // wrapErrs is set when the format string may contain a %w verb. wrapErrs bool // wrappedErr records the target of the %w verb. wrappedErr error @@ -137,6 +137,7 @@ func newPrinter() *pp { p := ppFree.Get().(*pp) p.panicking = false p.erroring = false + p.wrapErrs = false p.fmt.init(&p.buf) return p } diff --git a/src/go/internal/srcimporter/srcimporter_test.go b/src/go/internal/srcimporter/srcimporter_test.go index 087f97461e..56549434d1 100644 --- a/src/go/internal/srcimporter/srcimporter_test.go +++ b/src/go/internal/srcimporter/srcimporter_test.go @@ -81,10 +81,10 @@ func TestImportStdLib(t *testing.T) { t.Skip("no source code available") } - dt := maxTime if testing.Short() && testenv.Builder() == "" { - dt = 500 * time.Millisecond + t.Skip("skipping in -short mode") } + dt := maxTime nimports, _ := walkDir(t, "", time.Now().Add(dt)) // installed packages t.Logf("tested %d imports", nimports) } diff --git a/src/image/decode_test.go b/src/image/decode_test.go index 85e235e729..2b3ff6ba58 100644 --- a/src/image/decode_test.go +++ b/src/image/decode_test.go @@ -123,6 +123,10 @@ loop: continue } c, _, err := decodeConfig(it.filename) + if err != nil { + t.Errorf("%s: %v", it.filename, err) + continue loop + } if m.ColorModel() != c.ColorModel { t.Errorf("%s: color models differ", it.filename) continue loop diff --git a/src/image/gif/writer.go b/src/image/gif/writer.go index 5819df0dd0..7220446de5 100644 --- a/src/image/gif/writer.go +++ b/src/image/gif/writer.go @@ -433,8 +433,18 @@ func Encode(w io.Writer, m image.Image, o *Options) error { opts.Drawer = draw.FloydSteinberg } - pm, ok := m.(*image.Paletted) - if !ok || len(pm.Palette) > opts.NumColors { + pm, _ := m.(*image.Paletted) + if pm == nil { + if cp, ok := m.ColorModel().(color.Palette); ok { + pm = image.NewPaletted(b, cp) + for y := b.Min.Y; y < b.Max.Y; y++ { + for x := b.Min.X; x < b.Max.X; x++ { + pm.Set(x, y, cp.Convert(m.At(x, y))) + } + } + } + } + if pm == nil || len(pm.Palette) > opts.NumColors { // Set pm to be a palettedized copy of m, including its bounds, which // might not start at (0, 0). // diff --git a/src/image/gif/writer_test.go b/src/image/gif/writer_test.go index 91275bb907..0bc24d1bee 100644 --- a/src/image/gif/writer_test.go +++ b/src/image/gif/writer_test.go @@ -48,11 +48,17 @@ func delta(u0, u1 uint32) int64 { // have the same bounds. func averageDelta(m0, m1 image.Image) int64 { b := m0.Bounds() + return averageDeltaBound(m0, m1, b, b) +} + +// averageDeltaBounds returns the average delta in RGB space. The average delta is +// calulated in the specified bounds. +func averageDeltaBound(m0, m1 image.Image, b0, b1 image.Rectangle) int64 { var sum, n int64 - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { + for y := b0.Min.Y; y < b0.Max.Y; y++ { + for x := b0.Min.X; x < b0.Max.X; x++ { c0 := m0.At(x, y) - c1 := m1.At(x, y) + c1 := m1.At(x-b0.Min.X+b1.Min.X, y-b0.Min.Y+b1.Min.Y) r0, g0, b0, _ := c0.RGBA() r1, g1, b1, _ := c1.RGBA() sum += delta(r0, r1) @@ -581,6 +587,75 @@ func TestEncodeCroppedSubImages(t *testing.T) { } } +type offsetImage struct { + image.Image + Rect image.Rectangle +} + +func (i offsetImage) Bounds() image.Rectangle { + return i.Rect +} + +func TestEncodeWrappedImage(t *testing.T) { + m0, err := readImg("../testdata/video-001.gif") + if err != nil { + t.Fatalf("readImg: %v", err) + } + + // Case 1: Enocde a wrapped image.Image + buf := new(bytes.Buffer) + w0 := offsetImage{m0, m0.Bounds()} + err = Encode(buf, w0, nil) + if err != nil { + t.Fatalf("Encode: %v", err) + } + w1, err := Decode(buf) + if err != nil { + t.Fatalf("Dencode: %v", err) + } + avgDelta := averageDelta(m0, w1) + if avgDelta > 0 { + t.Fatalf("Wrapped: average delta is too high. expected: 0, got %d", avgDelta) + } + + // Case 2: Enocde a wrapped image.Image with offset + b0 := image.Rectangle{ + Min: image.Point{ + X: 128, + Y: 64, + }, + Max: image.Point{ + X: 256, + Y: 128, + }, + } + w0 = offsetImage{m0, b0} + buf = new(bytes.Buffer) + err = Encode(buf, w0, nil) + if err != nil { + t.Fatalf("Encode: %v", err) + } + w1, err = Decode(buf) + if err != nil { + t.Fatalf("Dencode: %v", err) + } + + b1 := image.Rectangle{ + Min: image.Point{ + X: 0, + Y: 0, + }, + Max: image.Point{ + X: 128, + Y: 64, + }, + } + avgDelta = averageDeltaBound(m0, w1, b0, b1) + if avgDelta > 0 { + t.Fatalf("Wrapped and offset: average delta is too high. expected: 0, got %d", avgDelta) + } +} + func BenchmarkEncode(b *testing.B) { bo := image.Rect(0, 0, 640, 480) rnd := rand.New(rand.NewSource(123)) diff --git a/src/image/testdata/triangle-001.gif b/src/image/testdata/triangle-001.gif new file mode 100644 index 0000000000..f3d45bbfa4 Binary files /dev/null and b/src/image/testdata/triangle-001.gif differ diff --git a/src/internal/poll/writev.go b/src/internal/poll/writev.go index a48a38be08..6050d1f642 100644 --- a/src/internal/poll/writev.go +++ b/src/internal/poll/writev.go @@ -64,6 +64,9 @@ func (fd *FD) Writev(v *[][]byte) (int64, error) { TestHookDidWritev(int(wrote)) n += int64(wrote) consume(v, int64(wrote)) + for i := range iovecs { + iovecs[i] = syscall.Iovec{} + } if err != nil { if err.(syscall.Errno) == syscall.EAGAIN { if err = fd.pd.waitWrite(fd.isFile); err == nil { diff --git a/src/internal/trace/gc_test.go b/src/internal/trace/gc_test.go index da1cb90f5c..4f9c77041a 100644 --- a/src/internal/trace/gc_test.go +++ b/src/internal/trace/gc_test.go @@ -79,6 +79,10 @@ func TestMMU(t *testing.T) { func TestMMUTrace(t *testing.T) { // Can't be t.Parallel() because it modifies the // testingOneBand package variable. + if testing.Short() { + // test input too big for all.bash + t.Skip("skipping in -short mode") + } data, err := ioutil.ReadFile("testdata/stress_1_10_good") if err != nil { diff --git a/src/internal/trace/parser_test.go b/src/internal/trace/parser_test.go index c9afa68c3c..6d87970157 100644 --- a/src/internal/trace/parser_test.go +++ b/src/internal/trace/parser_test.go @@ -7,6 +7,7 @@ package trace import ( "bytes" "io/ioutil" + "os" "path/filepath" "strings" "testing" @@ -38,9 +39,17 @@ func TestParseCanned(t *testing.T) { t.Fatalf("failed to read ./testdata: %v", err) } for _, f := range files { - data, err := ioutil.ReadFile(filepath.Join("./testdata", f.Name())) + name := filepath.Join("./testdata", f.Name()) + info, err := os.Stat(name) if err != nil { - t.Fatalf("failed to read input file: %v", err) + t.Fatal(err) + } + if testing.Short() && info.Size() > 10000 { + continue + } + data, err := ioutil.ReadFile(name) + if err != nil { + t.Fatal(err) } // Instead of Parse that requires a proper binary name for old traces, // we use 'parse' that omits symbol lookup if an empty string is given. diff --git a/src/math/big/floatmarsh_test.go b/src/math/big/floatmarsh_test.go index 5bd906ddae..c056d78b80 100644 --- a/src/math/big/floatmarsh_test.go +++ b/src/math/big/floatmarsh_test.go @@ -109,6 +109,9 @@ func TestFloatJSONEncoding(t *testing.T) { for _, test := range floatVals { for _, sign := range []string{"", "+", "-"} { for _, prec := range []uint{0, 1, 2, 10, 53, 64, 100, 1000} { + if prec > 53 && testing.Short() { + continue + } x := sign + test var tx Float _, _, err := tx.SetPrec(prec).Parse(x, 0) diff --git a/src/math/big/natconv_test.go b/src/math/big/natconv_test.go index 9c2acca07e..d390272108 100644 --- a/src/math/big/natconv_test.go +++ b/src/math/big/natconv_test.go @@ -446,6 +446,9 @@ func TestStringPowers(t *testing.T) { var p Word for b := 2; b <= 16; b++ { for p = 0; p <= 512; p++ { + if testing.Short() && p > 10 { + break + } x := nat(nil).expWW(Word(b), p) xs := x.utoa(b) xs2 := itoa(x, b) diff --git a/src/math/big/prime_test.go b/src/math/big/prime_test.go index bf50f34419..8596e33a13 100644 --- a/src/math/big/prime_test.go +++ b/src/math/big/prime_test.go @@ -125,11 +125,11 @@ func cutSpace(r rune) rune { func TestProbablyPrime(t *testing.T) { nreps := 20 if testing.Short() { - nreps = 3 + nreps = 1 } for i, s := range primes { p, _ := new(Int).SetString(s, 10) - if !p.ProbablyPrime(nreps) || !p.ProbablyPrime(1) || !p.ProbablyPrime(0) { + if !p.ProbablyPrime(nreps) || nreps != 1 && !p.ProbablyPrime(1) || !p.ProbablyPrime(0) { t.Errorf("#%d prime found to be non-prime (%s)", i, s) } } @@ -137,7 +137,7 @@ func TestProbablyPrime(t *testing.T) { for i, s := range composites { s = strings.Map(cutSpace, s) c, _ := new(Int).SetString(s, 10) - if c.ProbablyPrime(nreps) || c.ProbablyPrime(1) || c.ProbablyPrime(0) { + if c.ProbablyPrime(nreps) || nreps != 1 && c.ProbablyPrime(1) || c.ProbablyPrime(0) { t.Errorf("#%d composite found to be prime (%s)", i, s) } } @@ -197,6 +197,14 @@ func TestLucasPseudoprimes(t *testing.T) { func testPseudoprimes(t *testing.T, name string, cond func(nat) bool, want []int) { n := nat{1} for i := 3; i < 100000; i += 2 { + if testing.Short() { + if len(want) == 0 { + break + } + if i < want[0]-2 { + i = want[0] - 2 + } + } n[0] = Word(i) pseudo := cond(n) if pseudo && (len(want) == 0 || i != want[0]) { diff --git a/src/math/big/sqrt_test.go b/src/math/big/sqrt_test.go index 6a412d61fb..d314711d74 100644 --- a/src/math/big/sqrt_test.go +++ b/src/math/big/sqrt_test.go @@ -15,6 +15,9 @@ import ( // behaves like float math.Sqrt. func TestFloatSqrt64(t *testing.T) { for i := 0; i < 1e5; i++ { + if i == 1e2 && testing.Short() { + break + } r := rand.Float64() got := new(Float).SetPrec(53) diff --git a/src/math/bits/bits.go b/src/math/bits/bits.go index 24d910c27e..385c0648e3 100644 --- a/src/math/bits/bits.go +++ b/src/math/bits/bits.go @@ -165,6 +165,8 @@ func OnesCount64(x uint64) int { // RotateLeft returns the value of x rotated left by (k mod UintSize) bits. // To rotate x right by k bits, call RotateLeft(x, -k). +// +// This function's execution time does not depend on the inputs. func RotateLeft(x uint, k int) uint { if UintSize == 32 { return uint(RotateLeft32(uint32(x), k)) @@ -174,6 +176,8 @@ func RotateLeft(x uint, k int) uint { // RotateLeft8 returns the value of x rotated left by (k mod 8) bits. // To rotate x right by k bits, call RotateLeft8(x, -k). +// +// This function's execution time does not depend on the inputs. func RotateLeft8(x uint8, k int) uint8 { const n = 8 s := uint(k) & (n - 1) @@ -182,6 +186,8 @@ func RotateLeft8(x uint8, k int) uint8 { // RotateLeft16 returns the value of x rotated left by (k mod 16) bits. // To rotate x right by k bits, call RotateLeft16(x, -k). +// +// This function's execution time does not depend on the inputs. func RotateLeft16(x uint16, k int) uint16 { const n = 16 s := uint(k) & (n - 1) @@ -190,6 +196,8 @@ func RotateLeft16(x uint16, k int) uint16 { // RotateLeft32 returns the value of x rotated left by (k mod 32) bits. // To rotate x right by k bits, call RotateLeft32(x, -k). +// +// This function's execution time does not depend on the inputs. func RotateLeft32(x uint32, k int) uint32 { const n = 32 s := uint(k) & (n - 1) @@ -198,6 +206,8 @@ func RotateLeft32(x uint32, k int) uint32 { // RotateLeft64 returns the value of x rotated left by (k mod 64) bits. // To rotate x right by k bits, call RotateLeft64(x, -k). +// +// This function's execution time does not depend on the inputs. func RotateLeft64(x uint64, k int) uint64 { const n = 64 s := uint(k) & (n - 1) @@ -245,6 +255,8 @@ func Reverse64(x uint64) uint64 { // --- ReverseBytes --- // ReverseBytes returns the value of x with its bytes in reversed order. +// +// This function's execution time does not depend on the inputs. func ReverseBytes(x uint) uint { if UintSize == 32 { return uint(ReverseBytes32(uint32(x))) @@ -253,11 +265,15 @@ func ReverseBytes(x uint) uint { } // ReverseBytes16 returns the value of x with its bytes in reversed order. +// +// This function's execution time does not depend on the inputs. func ReverseBytes16(x uint16) uint16 { return x>>8 | x<<8 } // ReverseBytes32 returns the value of x with its bytes in reversed order. +// +// This function's execution time does not depend on the inputs. func ReverseBytes32(x uint32) uint32 { const m = 1<<32 - 1 x = x>>8&(m3&m) | x&(m3&m)<<8 @@ -265,6 +281,8 @@ func ReverseBytes32(x uint32) uint32 { } // ReverseBytes64 returns the value of x with its bytes in reversed order. +// +// This function's execution time does not depend on the inputs. func ReverseBytes64(x uint64) uint64 { const m = 1<<64 - 1 x = x>>8&(m3&m) | x&(m3&m)<<8 @@ -331,36 +349,40 @@ func Len64(x uint64) (n int) { // Add returns the sum with carry of x, y and carry: sum = x + y + carry. // The carry input must be 0 or 1; otherwise the behavior is undefined. // The carryOut output is guaranteed to be 0 or 1. +// +// This function's execution time does not depend on the inputs. func Add(x, y, carry uint) (sum, carryOut uint) { - yc := y + carry - sum = x + yc - if sum < x || yc < y { - carryOut = 1 + if UintSize == 32 { + s32, c32 := Add32(uint32(x), uint32(y), uint32(carry)) + return uint(s32), uint(c32) } - return + s64, c64 := Add64(uint64(x), uint64(y), uint64(carry)) + return uint(s64), uint(c64) } // Add32 returns the sum with carry of x, y and carry: sum = x + y + carry. // The carry input must be 0 or 1; otherwise the behavior is undefined. // The carryOut output is guaranteed to be 0 or 1. +// +// This function's execution time does not depend on the inputs. func Add32(x, y, carry uint32) (sum, carryOut uint32) { - yc := y + carry - sum = x + yc - if sum < x || yc < y { - carryOut = 1 - } + sum64 := uint64(x) + uint64(y) + uint64(carry) + sum = uint32(sum64) + carryOut = uint32(sum64 >> 32) return } // Add64 returns the sum with carry of x, y and carry: sum = x + y + carry. // The carry input must be 0 or 1; otherwise the behavior is undefined. // The carryOut output is guaranteed to be 0 or 1. +// +// This function's execution time does not depend on the inputs. func Add64(x, y, carry uint64) (sum, carryOut uint64) { - yc := y + carry - sum = x + yc - if sum < x || yc < y { - carryOut = 1 - } + sum = x + y + carry + // The sum will overflow if both top bits are set (x & y) or if one of them + // is (x | y), and a carry from the lower place happened. If such a carry + // happens, the top bit will be 1 + 0 + 1 = 0 (&^ sum). + carryOut = ((x & y) | ((x | y) &^ sum)) >> 63 return } @@ -369,36 +391,41 @@ func Add64(x, y, carry uint64) (sum, carryOut uint64) { // Sub returns the difference of x, y and borrow: diff = x - y - borrow. // The borrow input must be 0 or 1; otherwise the behavior is undefined. // The borrowOut output is guaranteed to be 0 or 1. +// +// This function's execution time does not depend on the inputs. func Sub(x, y, borrow uint) (diff, borrowOut uint) { - yb := y + borrow - diff = x - yb - if diff > x || yb < y { - borrowOut = 1 + if UintSize == 32 { + d32, b32 := Sub32(uint32(x), uint32(y), uint32(borrow)) + return uint(d32), uint(b32) } - return + d64, b64 := Sub64(uint64(x), uint64(y), uint64(borrow)) + return uint(d64), uint(b64) } // Sub32 returns the difference of x, y and borrow, diff = x - y - borrow. // The borrow input must be 0 or 1; otherwise the behavior is undefined. // The borrowOut output is guaranteed to be 0 or 1. +// +// This function's execution time does not depend on the inputs. func Sub32(x, y, borrow uint32) (diff, borrowOut uint32) { - yb := y + borrow - diff = x - yb - if diff > x || yb < y { - borrowOut = 1 - } + diff = x - y - borrow + // The difference will underflow if the top bit of x is not set and the top + // bit of y is set (^x & y) or if they are the same (^(x ^ y)) and a borrow + // from the lower place happens. If that borrow happens, the result will be + // 1 - 1 - 1 = 0 - 0 - 1 = 1 (& diff). + borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 31 return } // Sub64 returns the difference of x, y and borrow: diff = x - y - borrow. // The borrow input must be 0 or 1; otherwise the behavior is undefined. // The borrowOut output is guaranteed to be 0 or 1. +// +// This function's execution time does not depend on the inputs. func Sub64(x, y, borrow uint64) (diff, borrowOut uint64) { - yb := y + borrow - diff = x - yb - if diff > x || yb < y { - borrowOut = 1 - } + diff = x - y - borrow + // See Sub32 for the bit logic. + borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63 return } @@ -407,6 +434,8 @@ func Sub64(x, y, borrow uint64) (diff, borrowOut uint64) { // Mul returns the full-width product of x and y: (hi, lo) = x * y // with the product bits' upper half returned in hi and the lower // half returned in lo. +// +// This function's execution time does not depend on the inputs. func Mul(x, y uint) (hi, lo uint) { if UintSize == 32 { h, l := Mul32(uint32(x), uint32(y)) @@ -419,6 +448,8 @@ func Mul(x, y uint) (hi, lo uint) { // Mul32 returns the 64-bit product of x and y: (hi, lo) = x * y // with the product bits' upper half returned in hi and the lower // half returned in lo. +// +// This function's execution time does not depend on the inputs. func Mul32(x, y uint32) (hi, lo uint32) { tmp := uint64(x) * uint64(y) hi, lo = uint32(tmp>>32), uint32(tmp) @@ -428,6 +459,8 @@ func Mul32(x, y uint32) (hi, lo uint32) { // Mul64 returns the 128-bit product of x and y: (hi, lo) = x * y // with the product bits' upper half returned in hi and the lower // half returned in lo. +// +// This function's execution time does not depend on the inputs. func Mul64(x, y uint64) (hi, lo uint64) { const mask32 = 1<<32 - 1 x0 := x & mask32 diff --git a/src/math/bits/example_test.go b/src/math/bits/example_test.go index 18e026b9b4..b2ed2cba4b 100644 --- a/src/math/bits/example_test.go +++ b/src/math/bits/example_test.go @@ -59,6 +59,12 @@ func ExampleTrailingZeros64() { // TrailingZeros64(0000000000000000000000000000000000000000000000000000000000001110) = 1 } +func ExampleOnesCount() { + fmt.Printf("OnesCount(%b) = %d\n", 14, bits.OnesCount(14)) + // Output: + // OnesCount(1110) = 3 +} + func ExampleOnesCount8() { fmt.Printf("OnesCount8(%08b) = %d\n", 14, bits.OnesCount8(14)) // Output: diff --git a/src/math/rand/rand_test.go b/src/math/rand/rand_test.go index e663b84f9f..ee9c8f8e84 100644 --- a/src/math/rand/rand_test.go +++ b/src/math/rand/rand_test.go @@ -486,7 +486,7 @@ func TestUniformFactorial(t *testing.T) { r := New(NewSource(testSeeds[0])) top := 6 if testing.Short() { - top = 4 + top = 3 } for n := 3; n <= top; n++ { t.Run(fmt.Sprintf("n=%d", n), func(t *testing.T) { diff --git a/src/mime/mediatype.go b/src/mime/mediatype.go index 05390773a8..56ceb48853 100644 --- a/src/mime/mediatype.go +++ b/src/mime/mediatype.go @@ -19,7 +19,7 @@ import ( // FormatMediaType returns the empty string. func FormatMediaType(t string, param map[string]string) string { var b strings.Builder - if slash := strings.Index(t, "/"); slash == -1 { + if slash := strings.IndexByte(t, '/'); slash == -1 { if !isToken(t) { return "" } @@ -48,7 +48,38 @@ func FormatMediaType(t string, param map[string]string) string { return "" } b.WriteString(strings.ToLower(attribute)) + + needEnc := needsEncoding(value) + if needEnc { + // RFC 2231 section 4 + b.WriteByte('*') + } b.WriteByte('=') + + if needEnc { + b.WriteString("utf-8''") + + offset := 0 + for index := 0; index < len(value); index++ { + ch := value[index] + // {RFC 2231 section 7} + // attribute-char := + if ch <= ' ' || ch >= 0x7F || + ch == '*' || ch == '\'' || ch == '%' || + isTSpecial(rune(ch)) { + + b.WriteString(value[offset:index]) + offset = index + 1 + + b.WriteByte('%') + b.WriteByte(upperhex[ch>>4]) + b.WriteByte(upperhex[ch&0x0F]) + } + } + b.WriteString(value[offset:]) + continue + } + if isToken(value) { b.WriteString(value) continue @@ -63,9 +94,6 @@ func FormatMediaType(t string, param map[string]string) string { offset = index b.WriteByte('\\') } - if character&0x80 != 0 { - return "" - } } b.WriteString(value[offset:]) b.WriteByte('"') diff --git a/src/mime/mediatype_test.go b/src/mime/mediatype_test.go index 945a8189e1..e91ff38d68 100644 --- a/src/mime/mediatype_test.go +++ b/src/mime/mediatype_test.go @@ -6,6 +6,7 @@ package mime import ( "reflect" + "strings" "testing" ) @@ -481,8 +482,9 @@ var formatTests = []formatTest{ {"noslash", map[string]string{"X": "Y"}, "noslash; x=Y"}, // e.g. Content-Disposition values (RFC 2183); issue 11289 {"foo bar/baz", nil, ""}, {"foo/bar baz", nil, ""}, - {"attachment", map[string]string{"filename": "ĄĄŽŽČČŠŠ"}, ""}, - {"attachment", map[string]string{"filename": "ÁÁÊÊÇÇÎÎ"}, ""}, + {"attachment", map[string]string{"filename": "ĄĄŽŽČČŠŠ"}, "attachment; filename*=utf-8''%C4%84%C4%84%C5%BD%C5%BD%C4%8C%C4%8C%C5%A0%C5%A0"}, + {"attachment", map[string]string{"filename": "ÁÁÊÊÇÇÎÎ"}, "attachment; filename*=utf-8''%C3%81%C3%81%C3%8A%C3%8A%C3%87%C3%87%C3%8E%C3%8E"}, + {"attachment", map[string]string{"filename": "数据统计.png"}, "attachment; filename*=utf-8''%E6%95%B0%E6%8D%AE%E7%BB%9F%E8%AE%A1.png"}, {"foo/BAR", nil, "foo/bar"}, {"foo/BAR", map[string]string{"X": "Y"}, "foo/bar; x=Y"}, {"foo/BAR", map[string]string{"space": "With space"}, `foo/bar; space="With space"`}, @@ -491,7 +493,8 @@ var formatTests = []formatTest{ {"foo/BAR", map[string]string{"both": `With \backslash and "quote`}, `foo/bar; both="With \\backslash and \"quote"`}, {"foo/BAR", map[string]string{"": "empty attribute"}, ""}, {"foo/BAR", map[string]string{"bad attribute": "baz"}, ""}, - {"foo/BAR", map[string]string{"nonascii": "not an ascii character: ä"}, ""}, + {"foo/BAR", map[string]string{"nonascii": "not an ascii character: ä"}, "foo/bar; nonascii*=utf-8''not%20an%20ascii%20character%3A%20%C3%A4"}, + {"foo/BAR", map[string]string{"ctl": "newline: \n nil: \000"}, "foo/bar; ctl*=utf-8''newline%3A%20%0A%20nil%3A%20%00"}, {"foo/bar", map[string]string{"a": "av", "b": "bv", "c": "cv"}, "foo/bar; a=av; b=bv; c=cv"}, {"foo/bar", map[string]string{"0": "'", "9": "'"}, "foo/bar; 0='; 9='"}, {"foo", map[string]string{"bar": ""}, `foo; bar=""`}, @@ -503,5 +506,21 @@ func TestFormatMediaType(t *testing.T) { if got != tt.want { t.Errorf("%d. FormatMediaType(%q, %v) = %q; want %q", i, tt.typ, tt.params, got, tt.want) } + if got == "" { + continue + } + typ, params, err := ParseMediaType(got) + if err != nil { + t.Errorf("%d. ParseMediaType(%q) err: %v", i, got, err) + } + if typ != strings.ToLower(tt.typ) { + t.Errorf("%d. ParseMediaType(%q) typ = %q; want %q", i, got, typ, tt.typ) + } + for k, v := range tt.params { + k = strings.ToLower(k) + if params[k] != v { + t.Errorf("%d. ParseMediaType(%q) params[%s] = %q; want %q", i, got, k, params[k], v) + } + } } } diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go index 105a82c417..7d756c8c24 100644 --- a/src/mime/multipart/formdata_test.go +++ b/src/mime/multipart/formdata_test.go @@ -176,7 +176,11 @@ func (r *failOnReadAfterErrorReader) Read(p []byte) (n int, err error) { // TestReadForm_NonFileMaxMemory asserts that the ReadForm maxMemory limit is applied // while processing non-file form data as well as file form data. func TestReadForm_NonFileMaxMemory(t *testing.T) { - largeTextValue := strings.Repeat("1", (10<<20)+25) + n := 10<<20 + 25 + if testing.Short() { + n = 10<<10 + 25 + } + largeTextValue := strings.Repeat("1", n) message := `--MyBoundary Content-Disposition: form-data; name="largetext" @@ -196,6 +200,9 @@ Content-Disposition: form-data; name="largetext" } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { + if tc.maxMemory == 0 && testing.Short() { + t.Skip("skipping in -short mode") + } b := strings.NewReader(testBody) r := NewReader(b, boundary) f, err := r.ReadForm(tc.maxMemory) diff --git a/src/mime/multipart/multipart_test.go b/src/mime/multipart/multipart_test.go index 5a8102b822..5dc74b5ffe 100644 --- a/src/mime/multipart/multipart_test.go +++ b/src/mime/multipart/multipart_test.go @@ -832,7 +832,10 @@ func partsFromReader(r *Reader) ([]headerBody, error) { func TestParseAllSizes(t *testing.T) { t.Parallel() - const maxSize = 5 << 10 + maxSize := 5 << 10 + if testing.Short() { + maxSize = 512 + } var buf bytes.Buffer body := strings.Repeat("a", maxSize) bodyb := []byte(body) diff --git a/src/mime/quotedprintable/reader_test.go b/src/mime/quotedprintable/reader_test.go index f870bdaa8d..48a7ff6495 100644 --- a/src/mime/quotedprintable/reader_test.go +++ b/src/mime/quotedprintable/reader_test.go @@ -116,7 +116,11 @@ func TestExhaustive(t *testing.T) { var buf bytes.Buffer res := make(map[string]int) - everySequence("", "0A \r\n=", 6, func(s string) { + n := 6 + if testing.Short() { + n = 4 + } + everySequence("", "0A \r\n=", n, func(s string) { if strings.HasSuffix(s, "=") || strings.Contains(s, "==") { return } @@ -200,6 +204,13 @@ func TestExhaustive(t *testing.T) { invalid bytes after =: 3949 quotedprintable: invalid hex byte 0x0d: 2048 unexpected EOF: 194` + if testing.Short() { + want = `OK: 896 +invalid bytes after =: 100 +quotedprintable: invalid hex byte 0x0d: 26 +unexpected EOF: 3` + } + if got != want { t.Errorf("Got:\n%s\nWant:\n%s", got, want) } diff --git a/src/mime/type.go b/src/mime/type.go index bf10de8d69..ad763133e6 100644 --- a/src/mime/type.go +++ b/src/mime/type.go @@ -69,6 +69,7 @@ var builtinTypesLower = map[string]string{ ".png": "image/png", ".svg": "image/svg+xml", ".wasm": "application/wasm", + ".webp": "image/webp", ".xml": "text/xml; charset=utf-8", } diff --git a/src/net/http/httptest/recorder.go b/src/net/http/httptest/recorder.go index f2350f0a8d..d0bc0fade9 100644 --- a/src/net/http/httptest/recorder.go +++ b/src/net/http/httptest/recorder.go @@ -59,7 +59,10 @@ func NewRecorder() *ResponseRecorder { // an explicit DefaultRemoteAddr isn't set on ResponseRecorder. const DefaultRemoteAddr = "1.2.3.4" -// Header returns the response headers. +// Header implements http.ResponseWriter. It returns the response +// headers to mutate within a handler. To test the headers that were +// written after a handler completes, use the Result method and see +// the returned Response value's Header. func (rw *ResponseRecorder) Header() http.Header { m := rw.HeaderMap if m == nil { @@ -98,7 +101,8 @@ func (rw *ResponseRecorder) writeHeader(b []byte, str string) { rw.WriteHeader(200) } -// Write always succeeds and writes to rw.Body, if not nil. +// Write implements http.ResponseWriter. The data in buf is written to +// rw.Body, if not nil. func (rw *ResponseRecorder) Write(buf []byte) (int, error) { rw.writeHeader(buf, "") if rw.Body != nil { @@ -107,7 +111,8 @@ func (rw *ResponseRecorder) Write(buf []byte) (int, error) { return len(buf), nil } -// WriteString always succeeds and writes to rw.Body, if not nil. +// WriteString implements io.StringWriter. The data in str is written +// to rw.Body, if not nil. func (rw *ResponseRecorder) WriteString(str string) (int, error) { rw.writeHeader(nil, str) if rw.Body != nil { @@ -116,8 +121,7 @@ func (rw *ResponseRecorder) WriteString(str string) (int, error) { return len(str), nil } -// WriteHeader sets rw.Code. After it is called, changing rw.Header -// will not affect rw.HeaderMap. +// WriteHeader implements http.ResponseWriter. func (rw *ResponseRecorder) WriteHeader(code int) { if rw.wroteHeader { return @@ -130,7 +134,8 @@ func (rw *ResponseRecorder) WriteHeader(code int) { rw.snapHeader = rw.HeaderMap.Clone() } -// Flush sets rw.Flushed to true. +// Flush implements http.Flusher. To test whether Flush was +// called, see rw.Flushed. func (rw *ResponseRecorder) Flush() { if !rw.wroteHeader { rw.WriteHeader(200) diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index 7bb469e5c3..1d7b0efa11 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -51,8 +51,7 @@ type ReverseProxy struct { // ErrorLog specifies an optional logger for errors // that occur when attempting to proxy the request. - // If nil, logging goes to os.Stderr via the log package's - // standard logger. + // If nil, logging is done via the log package's standard logger. ErrorLog *log.Logger // BufferPool optionally specifies a buffer pool to diff --git a/src/net/http/internal/testcert.go b/src/net/http/internal/testcert.go index 407890920f..2284a836fb 100644 --- a/src/net/http/internal/testcert.go +++ b/src/net/http/internal/testcert.go @@ -4,6 +4,8 @@ package internal +import "strings" + // LocalhostCert is a PEM-encoded TLS cert with SAN IPs // "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT. // generated from src/crypto/tls: @@ -24,7 +26,7 @@ fblo6RBxUQ== -----END CERTIFICATE-----`) // LocalhostKey is the private key for localhostCert. -var LocalhostKey = []byte(`-----BEGIN RSA PRIVATE KEY----- +var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY----- MIICXgIBAAKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9 SjY1bIw4iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZB l2+XsDulrKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQAB @@ -38,4 +40,6 @@ fQtuUE9txblTu14q3N7gHRZB4ZMhFYyDy8CKrN2cPg/Fvyt0Xlp/DoCzjA0CQQDU y2ptGsuSmgUtWj3NM9xuwYPm+Z/F84K6+ARYiZ6PYj013sovGKUFfYAqVXVlxtIX qyUBnu3X9ps8ZfjLZO7BAkEAlT4R5Yl6cGhaJQYZHOde3JEMhNRcVFMO8dJDaFeo f9Oeos0UUothgiDktdQHxdNEwLjQf7lJJBzV+5OtwswCWA== ------END RSA PRIVATE KEY-----`) +-----END RSA TESTING KEY-----`)) + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 32ddd3dde9..d774915719 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -5758,8 +5758,12 @@ func TestServerDuplicateBackgroundRead(t *testing.T) { setParallel(t) defer afterTest(t) - const goroutines = 5 - const requests = 2000 + goroutines := 5 + requests := 2000 + if testing.Short() { + goroutines = 3 + requests = 100 + } hts := httptest.NewServer(HandlerFunc(NotFound)) defer hts.Close() diff --git a/src/net/smtp/smtp_test.go b/src/net/smtp/smtp_test.go index e366ef8015..8195f91419 100644 --- a/src/net/smtp/smtp_test.go +++ b/src/net/smtp/smtp_test.go @@ -900,8 +900,8 @@ tN8URjVmyEo= -----END CERTIFICATE-----`) // localhostKey is the private key for localhostCert. -var localhostKey = []byte(` ------BEGIN RSA PRIVATE KEY----- +var localhostKey = []byte(testingKey(` +-----BEGIN RSA TESTING KEY----- MIICXgIBAAKBgQDScVtBC45ayNsa16NylbPXnc6XOJkzhtWMn2Niu43DmfZHLq5h AB9+Gpok4icKaZxV7ayImCWzIf1pGHq8qKhsFshRddRTUAF3np5sDOW3QuhsuXHu lkQzLfQuoiL0TrOYvdi90bOliWQVGdGurAS1ZhsYF/fOc7bnRLnoIJYfZQIDAQAB @@ -915,4 +915,6 @@ vNjJu3yvoEZeIeuzouX9TJE21/33FaeDdsXbRhQEj23cqR38qFHsF1qAYNMCQQDP QXLEiJoClkR2orAmqjPLVhR3t2oB3INcnEjLNSq8LHyQEfXyaFfu4U9l5+fRPL2i jiC0k/9L5dHUsF0XZothAkEA23ddgRs+Id/HxtojqqUT27B8MT/IGNrYsp4DvS/c qgkeluku4GjxRlDMBuXk94xOBEinUs+p/hwP1Alll80Tpg== ------END RSA PRIVATE KEY-----`) +-----END RSA TESTING KEY-----`)) + +func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } diff --git a/src/net/url/url.go b/src/net/url/url.go index 9ff707b24e..7f6ff93ce4 100644 --- a/src/net/url/url.go +++ b/src/net/url/url.go @@ -337,10 +337,11 @@ func escape(s string, mode encoding) string { // Note that the Path field is stored in decoded form: /%47%6f%2f becomes /Go/. // A consequence is that it is impossible to tell which slashes in the Path were // slashes in the raw URL and which were %2f. This distinction is rarely important, -// but when it is, code must not use Path directly. -// The Parse function sets both Path and RawPath in the URL it returns, -// and URL's String method uses RawPath if it is a valid encoding of Path, -// by calling the EscapedPath method. +// but when it is, the code should use RawPath, an optional field which only gets +// set if the default encoding is different from Path. +// +// URL's String method uses the EscapedPath method to obtain the path. See the +// EscapedPath method for more details. type URL struct { Scheme string Opaque string // encoded opaque data diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index f9d73060a3..c9322f6b0f 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -691,6 +691,9 @@ func TestExtraFilesRace(t *testing.T) { } for i := 0; i < 10; i++ { + if testing.Short() && i >= 3 { + break + } la := listen() ca := helperCommand(t, "describefiles") ca.ExtraFiles = []*os.File{listenerFile(la)} diff --git a/src/regexp/syntax/parse_test.go b/src/regexp/syntax/parse_test.go index fe3d251761..5581ba1ca5 100644 --- a/src/regexp/syntax/parse_test.go +++ b/src/regexp/syntax/parse_test.go @@ -185,6 +185,7 @@ var parseTests = []parseTest{ {`(?-s).`, `dnl{}`}, {`(?:(?:^).)`, `cat{bol{}dot{}}`}, {`(?-s)(?:(?:^).)`, `cat{bol{}dnl{}}`}, + {`[\s\S]a`, `cat{cc{0x0-0x10ffff}lit{a}}`}, // RE2 prefix_tests {`abc|abd`, `cat{str{ab}cc{0x63-0x64}}`}, diff --git a/src/regexp/syntax/regexp.go b/src/regexp/syntax/regexp.go index ae5fa053f9..3a4d2d201c 100644 --- a/src/regexp/syntax/regexp.go +++ b/src/regexp/syntax/regexp.go @@ -139,7 +139,7 @@ func writeRegexp(b *strings.Builder, re *Regexp) { b.WriteRune('[') if len(re.Rune) == 0 { b.WriteString(`^\x00-\x{10FFFF}`) - } else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune { + } else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune && len(re.Rune) > 2 { // Contains 0 and MaxRune. Probably a negated class. // Print the gaps. b.WriteRune('^') diff --git a/src/runtime/internal/atomic/atomic_test.go b/src/runtime/internal/atomic/atomic_test.go index 25ece4354e..0ba75447e8 100644 --- a/src/runtime/internal/atomic/atomic_test.go +++ b/src/runtime/internal/atomic/atomic_test.go @@ -29,14 +29,18 @@ func runParallel(N, iter int, f func()) { } func TestXadduintptr(t *testing.T) { - const N = 20 - const iter = 100000 + N := 20 + iter := 100000 + if testing.Short() { + N = 10 + iter = 10000 + } inc := uintptr(100) total := uintptr(0) runParallel(N, iter, func() { atomic.Xadduintptr(&total, inc) }) - if want := uintptr(N * iter * inc); want != total { + if want := uintptr(N*iter) * inc; want != total { t.Fatalf("xadduintpr error, want %d, got %d", want, total) } total = 0 diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 59dee26867..53496371a0 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -159,12 +159,27 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri t.Skip("skipping on plan9") } - const maxDuration = 5 * time.Second + broken := false + switch runtime.GOOS { + case "darwin", "dragonfly", "netbsd", "illumos", "solaris": + broken = true + case "openbsd": + if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { + broken = true + } + } + + maxDuration := 5 * time.Second + if testing.Short() && broken { + // If it's expected to be broken, no point waiting around. + maxDuration /= 10 + } + // If we're running a long test, start with a long duration // for tests that try to make sure something *doesn't* happen. duration := 5 * time.Second if testing.Short() { - duration = 200 * time.Millisecond + duration = 100 * time.Millisecond } // Profiling tests are inherently flaky, especially on a @@ -190,14 +205,10 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []stri } } - switch runtime.GOOS { - case "darwin", "dragonfly", "netbsd", "illumos", "solaris": - t.Skipf("ignoring failure on %s; see golang.org/issue/13841", runtime.GOOS) - case "openbsd": - if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" { - t.Skipf("ignoring failure on %s/%s; see golang.org/issue/13841", runtime.GOOS, runtime.GOARCH) - } + if broken { + t.Skipf("ignoring failure on %s/%s; see golang.org/issue/13841", runtime.GOOS, runtime.GOARCH) } + // Ignore the failure if the tests are running in a QEMU-based emulator, // QEMU is not perfect at emulating everything. // IN_QEMU environmental variable is set by some of the Go builders. diff --git a/src/runtime/pprof/proto_test.go b/src/runtime/pprof/proto_test.go index 4452d51231..bcb4d3386d 100644 --- a/src/runtime/pprof/proto_test.go +++ b/src/runtime/pprof/proto_test.go @@ -207,11 +207,11 @@ ffffffffff600000-ffffffffff601000 r-xp 00000090 00:00 0 [vsysca 7ffc34343000 7ffc34345000 00000000 [vdso] ffffffffff600000 ffffffffff601000 00000090 [vsyscall] -00400000-07000000 r-xp 00000000 00:00 0 +00400000-07000000 r-xp 00000000 00:00 0 07000000-07093000 r-xp 06c00000 00:2e 536754 /path/to/gobench_server_main 07093000-0722d000 rw-p 06c92000 00:2e 536754 /path/to/gobench_server_main -0722d000-07b21000 rw-p 00000000 00:00 0 -c000000000-c000036000 rw-p 00000000 00:00 0 +0722d000-07b21000 rw-p 00000000 00:00 0 +c000000000-c000036000 rw-p 00000000 00:00 0 -> 07000000 07093000 06c00000 /path/to/gobench_server_main ` @@ -301,7 +301,7 @@ func TestProcSelfMaps(t *testing.T) { }) } -// TestMapping checkes the mapping section of CPU profiles +// TestMapping checks the mapping section of CPU profiles // has the HasFunctions field set correctly. If all PCs included // in the samples are successfully symbolized, the corresponding // mapping entry (in this test case, only one entry) should have diff --git a/src/runtime/pprof/testdata/mappingtest/main.go b/src/runtime/pprof/testdata/mappingtest/main.go index 7850faab0d..476b9e88a3 100644 --- a/src/runtime/pprof/testdata/mappingtest/main.go +++ b/src/runtime/pprof/testdata/mappingtest/main.go @@ -69,7 +69,7 @@ func main() { if err := pprof.StartCPUProfile(os.Stdout); err != nil { log.Fatal("can't start CPU profile: ", err) } - time.Sleep(1 * time.Second) + time.Sleep(200 * time.Millisecond) pprof.StopCPUProfile() if err := os.Stdout.Close(); err != nil { diff --git a/src/runtime/proc.go b/src/runtime/proc.go index bf7835eb19..e9eca23138 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -5211,15 +5211,6 @@ func doInit(t *initTask) { throw("recursive call during initialization - linker skew") default: // not initialized yet t.state = 1 // initialization in progress - if raceenabled { - // Randomize initialization order of packages t depends on. - // TODO: enable always instead of just for race? - s := *(*[]uintptr)(unsafe.Pointer(&slice{array: add(unsafe.Pointer(t), 3*sys.PtrSize), len: int(t.ndeps), cap: int(t.ndeps)})) - for i := len(s) - 1; i > 0; i-- { - j := int(fastrandn(uint32(i + 1))) - s[i], s[j] = s[j], s[i] - } - } for i := uintptr(0); i < t.ndeps; i++ { p := add(unsafe.Pointer(t), (3+i)*sys.PtrSize) t2 := *(**initTask)(p) diff --git a/src/runtime/semasleep_test.go b/src/runtime/semasleep_test.go index b931095619..f5b4a50697 100644 --- a/src/runtime/semasleep_test.go +++ b/src/runtime/semasleep_test.go @@ -7,11 +7,7 @@ package runtime_test import ( - "internal/testenv" - "io/ioutil" - "os" "os/exec" - "path/filepath" "syscall" "testing" "time" @@ -24,39 +20,14 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { if *flagQuick { t.Skip("-quick") } - testenv.MustHaveGoBuild(t) - tempDir, err := ioutil.TempDir("", "issue-27250") + + exe, err := buildTestProg(t, "testprog") if err != nil { - t.Fatalf("Failed to create the temp directory: %v", err) - } - defer os.RemoveAll(tempDir) - - repro := ` - package main - - import "time" - - func main() { - <-time.After(1 * time.Second) - } - ` - mainPath := filepath.Join(tempDir, "main.go") - if err := ioutil.WriteFile(mainPath, []byte(repro), 0644); err != nil { - t.Fatalf("Failed to create temp file for repro.go: %v", err) - } - binaryPath := filepath.Join(tempDir, "binary") - - // Build the binary so that we can send the signal to its PID. - out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", binaryPath, mainPath).CombinedOutput() - if err != nil { - t.Fatalf("Failed to compile the binary: err: %v\nOutput: %s\n", err, out) - } - if err := os.Chmod(binaryPath, 0755); err != nil { - t.Fatalf("Failed to chmod binary: %v", err) + t.Fatal(err) } - // Now run the binary. - cmd := exec.Command(binaryPath) + start := time.Now() + cmd := exec.Command(exe, "After1") if err := cmd.Start(); err != nil { t.Fatalf("Failed to start command: %v", err) } @@ -85,6 +56,9 @@ func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) { if err != nil { t.Fatalf("The program returned but unfortunately with an error: %v", err) } + if time.Since(start) < 100*time.Millisecond { + t.Fatalf("The program stopped too quickly.") + } return } } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index c0e8dc279b..c2f32e0e5d 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -52,6 +52,11 @@ type Frame struct { // if not known. If Func is not nil then Entry == // Func.Entry(). Entry uintptr + + // The runtime's internal view of the function. This field + // is set (funcInfo.valid() returns true) only for Go functions, + // not for C functions. + funcInfo funcInfo } // CallersFrames takes a slice of PC values returned by Callers and @@ -95,7 +100,6 @@ func (ci *Frames) Next() (frame Frame, more bool) { pc-- } name := funcname(funcInfo) - file, line := funcline1(funcInfo, pc, false) if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil { inltree := (*[1 << 20]inlinedCall)(inldata) ix := pcdatavalue(funcInfo, _PCDATA_InlTreeIndex, pc, nil) @@ -111,9 +115,9 @@ func (ci *Frames) Next() (frame Frame, more bool) { PC: pc, Func: f, Function: name, - File: file, - Line: int(line), Entry: entry, + funcInfo: funcInfo, + // Note: File,Line set below }) } @@ -121,6 +125,7 @@ func (ci *Frames) Next() (frame Frame, more bool) { // Avoid allocation in the common case, which is 1 or 2 frames. switch len(ci.frames) { case 0: // In the rare case when there are no frames at all, we return Frame{}. + return case 1: frame = ci.frames[0] ci.frames = ci.frameStore[:0] @@ -133,6 +138,13 @@ func (ci *Frames) Next() (frame Frame, more bool) { ci.frames = ci.frames[1:] } more = len(ci.frames) > 0 + if frame.funcInfo.valid() { + // Compute file/line just before we need to return it, + // as it can be expensive. This avoids computing file/line + // for the Frame we find but don't return. See issue 32093. + file, line := funcline1(frame.funcInfo, frame.PC, false) + frame.File, frame.Line = file, int(line) + } return } @@ -157,6 +169,8 @@ func expandCgoFrames(pc uintptr) []Frame { File: gostring(arg.file), Line: int(arg.lineno), Entry: arg.entry, + // funcInfo is zero, which implies !funcInfo.valid(). + // That ensures that we use the File/Line info given here. }) if arg.more == 0 { break diff --git a/src/runtime/testdata/testprog/deadlock.go b/src/runtime/testdata/testprog/deadlock.go index ca2be57911..5f0d120004 100644 --- a/src/runtime/testdata/testprog/deadlock.go +++ b/src/runtime/testdata/testprog/deadlock.go @@ -112,12 +112,16 @@ func RecursivePanic() { } func GoexitExit() { + println("t1") go func() { time.Sleep(time.Millisecond) }() i := 0 + println("t2") runtime.SetFinalizer(&i, func(p *int) {}) + println("t3") runtime.GC() + println("t4") runtime.Goexit() } diff --git a/src/runtime/testdata/testprog/gc.go b/src/runtime/testdata/testprog/gc.go index ea6604f132..cca9c4556b 100644 --- a/src/runtime/testdata/testprog/gc.go +++ b/src/runtime/testdata/testprog/gc.go @@ -127,59 +127,58 @@ func GCFairness2() { fmt.Println("OK") } -var maybeSaved []byte - func GCPhys() { - // In this test, we construct a very specific scenario. We first - // allocate N objects and drop half of their pointers on the floor, - // effectively creating N/2 'holes' in our allocated arenas. We then - // try to allocate objects twice as big. At the end, we measure the - // physical memory overhead of large objects. + // This test ensures that heap-growth scavenging is working as intended. // - // The purpose of this test is to ensure that the GC scavenges free - // spans eagerly to ensure high physical memory utilization even - // during fragmentation. + // It sets up a specific scenario: it allocates two pairs of objects whose + // sizes sum to size. One object in each pair is "small" (though must be + // large enough to be considered a large object by the runtime) and one is + // large. The small objects are kept while the large objects are freed, + // creating two large unscavenged holes in the heap. The heap goal should + // also be small as a result (so size must be at least as large as the + // minimum heap size). We then allocate one large object, bigger than both + // pairs of objects combined. This allocation, because it will tip + // HeapSys-HeapReleased well above the heap goal, should trigger heap-growth + // scavenging and scavenge most, if not all, of the large holes we created + // earlier. const ( - // Unfortunately, measuring actual used physical pages is - // difficult because HeapReleased doesn't include the parts - // of an arena that haven't yet been touched. So, we just - // make objects and size sufficiently large such that even - // 64 MB overhead is relatively small in the final - // calculation. - // - // Currently, we target 480MiB worth of memory for our test, - // computed as size * objects + (size*2) * (objects/2) - // = 2 * size * objects - // // Size must be also large enough to be considered a large // object (not in any size-segregated span). - size = 1 << 20 - objects = 240 + size = 4 << 20 + split = 64 << 10 + objects = 2 ) + // Set GOGC so that this test operates under consistent assumptions. + debug.SetGCPercent(100) // Save objects which we want to survive, and condemn objects which we don't. // Note that we condemn objects in this way and release them all at once in // order to avoid having the GC start freeing up these objects while the loop // is still running and filling in the holes we intend to make. - saved := make([][]byte, 0, objects) - condemned := make([][]byte, 0, objects/2+1) - for i := 0; i < objects; i++ { - // Write into a global, to prevent this from being optimized away by - // the compiler in the future. - maybeSaved = make([]byte, size) + saved := make([][]byte, 0, objects+1) + condemned := make([][]byte, 0, objects) + for i := 0; i < 2*objects; i++ { if i%2 == 0 { - saved = append(saved, maybeSaved) + saved = append(saved, make([]byte, split)) } else { - condemned = append(condemned, maybeSaved) + condemned = append(condemned, make([]byte, size-split)) } } condemned = nil // Clean up the heap. This will free up every other object created above // (i.e. everything in condemned) creating holes in the heap. + // Also, if the condemned objects are still being swept, its possible that + // the scavenging that happens as a result of the next allocation won't see + // the holes at all. We call runtime.GC() twice here so that when we allocate + // our large object there's no race with sweeping. runtime.GC() - // Allocate many new objects of 2x size. - for i := 0; i < objects/2; i++ { - saved = append(saved, make([]byte, size*2)) - } + runtime.GC() + // Perform one big allocation which should also scavenge any holes. + // + // The heap goal will rise after this object is allocated, so it's very + // important that we try to do all the scavenging in a single allocation + // that exceeds the heap goal. Otherwise the rising heap goal could foil our + // test. + saved = append(saved, make([]byte, objects*size)) // Clean up the heap again just to put it in a known state. runtime.GC() // heapBacked is an estimate of the amount of physical memory used by @@ -191,21 +190,29 @@ func GCPhys() { var stats runtime.MemStats runtime.ReadMemStats(&stats) heapBacked := stats.HeapSys - stats.HeapReleased - // If heapBacked exceeds the amount of memory actually used for heap - // allocated objects by 10% (post-GC HeapAlloc should be quite close to - // the size of the working set), then fail. + // If heapBacked does not exceed the heap goal by more than retainExtraPercent + // then the scavenger is working as expected; the newly-created holes have been + // scavenged immediately as part of the allocations which cannot fit in the holes. // - // In the context of this test, that indicates a large amount of - // fragmentation with physical pages that are otherwise unused but not - // returned to the OS. + // Since the runtime should scavenge the entirety of the remaining holes, + // theoretically there should be no more free and unscavenged memory. However due + // to other allocations that happen during this test we may still see some physical + // memory over-use. 10% here is an arbitrary but very conservative threshold which + // should easily account for any other allocations this test may have done. overuse := (float64(heapBacked) - float64(stats.HeapAlloc)) / float64(stats.HeapAlloc) - if overuse > 0.1 { - fmt.Printf("exceeded physical memory overuse threshold of 10%%: %3.2f%%\n"+ - "(alloc: %d, sys: %d, rel: %d, objs: %d)\n", overuse*100, stats.HeapAlloc, - stats.HeapSys, stats.HeapReleased, len(saved)) + if overuse <= 0.10 { + fmt.Println("OK") return } - fmt.Println("OK") + // Physical memory utilization exceeds the threshold, so heap-growth scavenging + // did not operate as expected. + // + // In the context of this test, this indicates a large amount of + // fragmentation with physical pages that are otherwise unused but not + // returned to the OS. + fmt.Printf("exceeded physical memory overuse threshold of 10%%: %3.2f%%\n"+ + "(alloc: %d, goal: %d, sys: %d, rel: %d, objs: %d)\n", overuse*100, + stats.HeapAlloc, stats.NextGC, stats.HeapSys, stats.HeapReleased, len(saved)) runtime.KeepAlive(saved) } diff --git a/src/runtime/testdata/testprog/sleep.go b/src/runtime/testdata/testprog/sleep.go new file mode 100644 index 0000000000..86e2f6cfe6 --- /dev/null +++ b/src/runtime/testdata/testprog/sleep.go @@ -0,0 +1,17 @@ +// Copyright 2019 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. + +package main + +import "time" + +// for golang.org/issue/27250 + +func init() { + register("After1", After1) +} + +func After1() { + <-time.After(1 * time.Second) +} diff --git a/src/runtime/trace/trace_test.go b/src/runtime/trace/trace_test.go index e289fa5e12..235845df4e 100644 --- a/src/runtime/trace/trace_test.go +++ b/src/runtime/trace/trace_test.go @@ -186,6 +186,10 @@ func TestTraceStress(t *testing.T) { if IsEnabled() { t.Skip("skipping because -test.trace is set") } + if testing.Short() { + t.Skip("skipping in -short mode") + } + var wg sync.WaitGroup done := make(chan bool) diff --git a/src/strconv/ftoa.go b/src/strconv/ftoa.go index 432521b24f..8ce6ef30b4 100644 --- a/src/strconv/ftoa.go +++ b/src/strconv/ftoa.go @@ -289,39 +289,80 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { // would round to the original mantissa and not the neighbors. inclusive := mant%2 == 0 + // As we walk the digits we want to know whether rounding up would fall + // within the upper bound. This is tracked by upperdelta: + // + // If upperdelta == 0, the digits of d and upper are the same so far. + // + // If upperdelta == 1, we saw a difference of 1 between d and upper on a + // previous digit and subsequently only 9s for d and 0s for upper. + // (Thus rounding up may fall outside the bound, if it is exclusive.) + // + // If upperdelta == 2, then the difference is greater than 1 + // and we know that rounding up falls within the bound. + var upperdelta uint8 + // Now we can figure out the minimum number of digits required. // Walk along until d has distinguished itself from upper and lower. - for i := 0; i < d.nd; i++ { - l := byte('0') // lower digit - if i < lower.nd { - l = lower.d[i] + for ui := 0; ; ui++ { + // lower, d, and upper may have the decimal points at different + // places. In this case upper is the longest, so we iterate from + // ui==0 and start li and mi at (possibly) -1. + mi := ui - upper.dp + d.dp + if mi >= d.nd { + break + } + li := ui - upper.dp + lower.dp + l := byte('0') // lower digit + if li >= 0 && li < lower.nd { + l = lower.d[li] + } + m := byte('0') // middle digit + if mi >= 0 { + m = d.d[mi] } - m := d.d[i] // middle digit u := byte('0') // upper digit - if i < upper.nd { - u = upper.d[i] + if ui < upper.nd { + u = upper.d[ui] } // Okay to round down (truncate) if lower has a different digit // or if lower is inclusive and is exactly the result of rounding // down (i.e., and we have reached the final digit of lower). - okdown := l != m || inclusive && i+1 == lower.nd + okdown := l != m || inclusive && li+1 == lower.nd + switch { + case upperdelta == 0 && m+1 < u: + // Example: + // m = 12345xxx + // u = 12347xxx + upperdelta = 2 + case upperdelta == 0 && m != u: + // Example: + // m = 12345xxx + // u = 12346xxx + upperdelta = 1 + case upperdelta == 1 && (m != '9' || u != '0'): + // Example: + // m = 1234598x + // u = 1234600x + upperdelta = 2 + } // Okay to round up if upper has a different digit and either upper // is inclusive or upper is bigger than the result of rounding up. - okup := m != u && (inclusive || m+1 < u || i+1 < upper.nd) + okup := upperdelta > 0 && (inclusive || upperdelta > 1 || ui+1 < upper.nd) // If it's okay to do either, then round to the nearest one. // If it's okay to do only one, do it. switch { case okdown && okup: - d.Round(i + 1) + d.Round(mi + 1) return case okdown: - d.RoundDown(i + 1) + d.RoundDown(mi + 1) return case okup: - d.RoundUp(i + 1) + d.RoundUp(mi + 1) return } } diff --git a/src/strconv/ftoa_test.go b/src/strconv/ftoa_test.go index 055fef99aa..755c986b86 100644 --- a/src/strconv/ftoa_test.go +++ b/src/strconv/ftoa_test.go @@ -137,6 +137,10 @@ var ftoatests = []ftoaTest{ {383260575764816448, 'f', 0, "383260575764816448"}, {383260575764816448, 'g', -1, "3.8326057576481645e+17"}, + // Issue 29491. + {498484681984085570, 'f', -1, "498484681984085570"}, + {-5.8339553793802237e+23, 'g', -1, "-5.8339553793802237e+23"}, + // rounding {2.275555555555555, 'x', -1, "0x1.23456789abcdep+01"}, {2.275555555555555, 'x', 0, "0x1p+01"}, diff --git a/src/sync/pool_test.go b/src/sync/pool_test.go index 796a5a0a73..ff1174cc15 100644 --- a/src/sync/pool_test.go +++ b/src/sync/pool_test.go @@ -105,6 +105,9 @@ func testPool(t *testing.T, drain bool) { const N = 100 loop: for try := 0; try < 3; try++ { + if try == 1 && testing.Short() { + break + } var fin, fin1 uint32 for i := 0; i < N; i++ { v := new(string) diff --git a/src/syscall/getdirentries_test.go b/src/syscall/getdirentries_test.go index b20ae1d1e3..8505a0bb89 100644 --- a/src/syscall/getdirentries_test.go +++ b/src/syscall/getdirentries_test.go @@ -26,6 +26,9 @@ func TestGetdirentries(t *testing.T) { } } func testGetdirentries(t *testing.T, count int) { + if count > 100 && testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { + t.Skip("skipping in -short mode") + } d, err := ioutil.TempDir("", "getdirentries-test") if err != nil { t.Fatalf("Tempdir: %v", err) diff --git a/src/testing/quick/quick_test.go b/src/testing/quick/quick_test.go index 4246cd1d3b..9df6dd4679 100644 --- a/src/testing/quick/quick_test.go +++ b/src/testing/quick/quick_test.go @@ -319,7 +319,7 @@ func TestInt64(t *testing.T) { } return true } - cfg := &Config{MaxCount: 100000} + cfg := &Config{MaxCount: 10000} Check(f, cfg) if uint64(lo)>>62 == 0 || uint64(hi)>>62 == 0 { t.Errorf("int64 returned range %#016x,%#016x; does not look like full range", lo, hi) diff --git a/src/testing/testing.go b/src/testing/testing.go index 753de9f27c..339df13f43 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -771,7 +771,7 @@ func (c *common) Helper() { // for the caller after skip frames (where 0 means the current function). func callerName(skip int) string { // Make room for the skip PC. - var pc [2]uintptr + var pc [1]uintptr n := runtime.Callers(skip+2, pc[:]) // skip + runtime.Callers + callerName if n == 0 { panic("testing: zero callers found") diff --git a/src/text/template/doc.go b/src/text/template/doc.go index 0179dec5c3..dbffaa4958 100644 --- a/src/text/template/doc.go +++ b/src/text/template/doc.go @@ -328,6 +328,11 @@ Predefined global functions are named as follows. Returns the result of indexing its first argument by the following arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each indexed item must be a map, slice, or array. + slice + slice returns the result of slicing its first argument by the + remaining arguments. Thus "slice x 1 2" is, in Go syntax, x[1:2], + while "slice x" is x[:], "slice x 1" is x[1:], and "slice x 1 2 3" + is x[1:2:3]. The first argument must be a string, slice, or array. js Returns the escaped JavaScript equivalent of the textual representation of its arguments. diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index c45df89d59..81f9e04476 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -23,7 +23,7 @@ type T struct { True bool I int U16 uint16 - X string + X, S string FloatZero float64 ComplexZero complex128 // Nested structs. @@ -36,8 +36,11 @@ type T struct { W1, W2 *W // Slices SI []int + SICap []int SIEmpty []int SB []bool + // Arrays + AI [3]int // Maps MSI map[string]int MSIone map[string]int // one element, for deterministic output @@ -122,12 +125,15 @@ var tVal = &T{ I: 17, U16: 16, X: "x", + S: "xyz", U: &U{"v"}, V0: V{6666}, V1: &V{7777}, // leave V2 as nil W0: W{888}, W1: &W{999}, // leave W2 as nil SI: []int{3, 4, 5}, + SICap: make([]int, 5, 10), + AI: [3]int{3, 4, 5}, SB: []bool{true, false}, MSI: map[string]int{"one": 1, "two": 2, "three": 3}, MSIone: map[string]int{"one": 1}, @@ -491,6 +497,31 @@ var execTests = []execTest{ {"map MI8S", "{{index .MI8S 3}}", "i83", tVal, true}, {"map MUI8S", "{{index .MUI8S 2}}", "u82", tVal, true}, + // Slicing. + {"slice[:]", "{{slice .SI}}", "[3 4 5]", tVal, true}, + {"slice[1:]", "{{slice .SI 1}}", "[4 5]", tVal, true}, + {"slice[1:2]", "{{slice .SI 1 2}}", "[4]", tVal, true}, + {"slice[-1:]", "{{slice .SI -1}}", "", tVal, false}, + {"slice[1:-2]", "{{slice .SI 1 -2}}", "", tVal, false}, + {"slice[1:2:-1]", "{{slice .SI 1 2 -1}}", "", tVal, false}, + {"slice[2:1]", "{{slice .SI 2 1}}", "", tVal, false}, + {"slice[2:2:1]", "{{slice .SI 2 2 1}}", "", tVal, false}, + {"out of range", "{{slice .SI 4 5}}", "", tVal, false}, + {"out of range", "{{slice .SI 2 2 5}}", "", tVal, false}, + {"len(s) < indexes < cap(s)", "{{slice .SICap 6 10}}", "[0 0 0 0]", tVal, true}, + {"len(s) < indexes < cap(s)", "{{slice .SICap 6 10 10}}", "[0 0 0 0]", tVal, true}, + {"indexes > cap(s)", "{{slice .SICap 10 11}}", "", tVal, false}, + {"indexes > cap(s)", "{{slice .SICap 6 10 11}}", "", tVal, false}, + {"array[:]", "{{slice .AI}}", "[3 4 5]", tVal, true}, + {"array[1:]", "{{slice .AI 1}}", "[4 5]", tVal, true}, + {"array[1:2]", "{{slice .AI 1 2}}", "[4]", tVal, true}, + {"string[:]", "{{slice .S}}", "xyz", tVal, true}, + {"string[0:1]", "{{slice .S 0 1}}", "x", tVal, true}, + {"string[1:]", "{{slice .S 1}}", "yz", tVal, true}, + {"string[1:2]", "{{slice .S 1 2}}", "y", tVal, true}, + {"out of range", "{{slice .S 1 5}}", "", tVal, false}, + {"3-index slice of string", "{{slice .S 1 2 2}}", "", tVal, false}, + // Len. {"slice", "{{len .SI}}", "3", tVal, true}, {"map", "{{len .MSI }}", "3", tVal, true}, @@ -1417,6 +1448,9 @@ func TestEvalFieldErrors(t *testing.T) { } func TestMaxExecDepth(t *testing.T) { + if testing.Short() { + t.Skip("skipping in -short mode") + } tmpl := Must(New("tmpl").Parse(`{{template "tmpl" .}}`)) err := tmpl.Execute(ioutil.Discard, nil) got := "" diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go index a626247c2c..248dbcf22e 100644 --- a/src/text/template/funcs.go +++ b/src/text/template/funcs.go @@ -34,6 +34,7 @@ var builtins = FuncMap{ "call": call, "html": HTMLEscaper, "index": index, + "slice": slice, "js": JSEscaper, "len": length, "not": not, @@ -159,17 +160,36 @@ func intLike(typ reflect.Kind) bool { return false } +// indexArg checks if a reflect.Value can be used as an index, and converts it to int if possible. +func indexArg(index reflect.Value, cap int) (int, error) { + var x int64 + switch index.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + x = index.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + x = int64(index.Uint()) + case reflect.Invalid: + return 0, fmt.Errorf("cannot index slice/array with nil") + default: + return 0, fmt.Errorf("cannot index slice/array with type %s", index.Type()) + } + if x < 0 || int(x) < 0 || int(x) > cap { + return 0, fmt.Errorf("index out of range: %d", x) + } + return int(x), nil +} + // Indexing. // index returns the result of indexing its first argument by the following // arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each // indexed item must be a map, slice, or array. -func index(item reflect.Value, indices ...reflect.Value) (reflect.Value, error) { +func index(item reflect.Value, indexes ...reflect.Value) (reflect.Value, error) { v := indirectInterface(item) if !v.IsValid() { return reflect.Value{}, fmt.Errorf("index of untyped nil") } - for _, i := range indices { + for _, i := range indexes { index := indirectInterface(i) var isNil bool if v, isNil = indirect(v); isNil { @@ -177,21 +197,11 @@ func index(item reflect.Value, indices ...reflect.Value) (reflect.Value, error) } switch v.Kind() { case reflect.Array, reflect.Slice, reflect.String: - var x int64 - switch index.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - x = index.Int() - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - x = int64(index.Uint()) - case reflect.Invalid: - return reflect.Value{}, fmt.Errorf("cannot index slice/array with nil") - default: - return reflect.Value{}, fmt.Errorf("cannot index slice/array with type %s", index.Type()) + x, err := indexArg(index, v.Len()) + if err != nil { + return reflect.Value{}, err } - if x < 0 || x >= int64(v.Len()) { - return reflect.Value{}, fmt.Errorf("index out of range: %d", x) - } - v = v.Index(int(x)) + v = v.Index(x) case reflect.Map: index, err := prepareArg(index, v.Type().Key()) if err != nil { @@ -212,6 +222,57 @@ func index(item reflect.Value, indices ...reflect.Value) (reflect.Value, error) return v, nil } +// Slicing. + +// slice returns the result of slicing its first argument by the remaining +// arguments. Thus "slice x 1 2" is, in Go syntax, x[1:2], while "slice x" +// is x[:], "slice x 1" is x[1:], and "slice x 1 2 3" is x[1:2:3]. The first +// argument must be a string, slice, or array. +func slice(item reflect.Value, indexes ...reflect.Value) (reflect.Value, error) { + var ( + cap int + v = indirectInterface(item) + ) + if !v.IsValid() { + return reflect.Value{}, fmt.Errorf("slice of untyped nil") + } + if len(indexes) > 3 { + return reflect.Value{}, fmt.Errorf("too many slice indexes: %d", len(indexes)) + } + switch v.Kind() { + case reflect.String: + if len(indexes) == 3 { + return reflect.Value{}, fmt.Errorf("cannot 3-index slice a string") + } + cap = v.Len() + case reflect.Array, reflect.Slice: + cap = v.Cap() + default: + return reflect.Value{}, fmt.Errorf("can't slice item of type %s", v.Type()) + } + // set default values for cases item[:], item[i:]. + idx := [3]int{0, v.Len()} + for i, index := range indexes { + x, err := indexArg(index, cap) + if err != nil { + return reflect.Value{}, err + } + idx[i] = x + } + // given item[i:j], make sure i <= j. + if idx[0] > idx[1] { + return reflect.Value{}, fmt.Errorf("invalid slice index: %d > %d", idx[0], idx[1]) + } + if len(indexes) < 3 { + return item.Slice(idx[0], idx[1]), nil + } + // given item[i:j:k], make sure i <= j <= k. + if idx[1] > idx[2] { + return reflect.Value{}, fmt.Errorf("invalid slice index: %d > %d", idx[1], idx[2]) + } + return item.Slice3(idx[0], idx[1], idx[2]), nil +} + // Length // length returns the length of the item, with an error if it has no defined length. diff --git a/test/fixedbugs/issue15071.dir/exp/exp.go b/test/fixedbugs/issue15071.dir/exp.go similarity index 100% rename from test/fixedbugs/issue15071.dir/exp/exp.go rename to test/fixedbugs/issue15071.dir/exp.go diff --git a/test/fixedbugs/issue15071.go b/test/fixedbugs/issue15071.go new file mode 100644 index 0000000000..af6f134172 --- /dev/null +++ b/test/fixedbugs/issue15071.go @@ -0,0 +1,7 @@ +// rundir + +// Copyright 2019 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. + +package ignored diff --git a/test/fixedbugs/issue15609.go b/test/fixedbugs/issue15609.go new file mode 100644 index 0000000000..87c96b480f --- /dev/null +++ b/test/fixedbugs/issue15609.go @@ -0,0 +1,7 @@ +// runindir + +// Copyright 2019 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. + +package ignored diff --git a/test/fixedbugs/issue29612.go b/test/fixedbugs/issue29612.go new file mode 100644 index 0000000000..87c96b480f --- /dev/null +++ b/test/fixedbugs/issue29612.go @@ -0,0 +1,7 @@ +// runindir + +// Copyright 2019 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. + +package ignored diff --git a/test/fixedbugs/issue31636.dir/a.go b/test/fixedbugs/issue31636.dir/a.go new file mode 100644 index 0000000000..e57e0d5fb7 --- /dev/null +++ b/test/fixedbugs/issue31636.dir/a.go @@ -0,0 +1,9 @@ +// Copyright 2019 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. + +package a + +func init() { + println("a") +} diff --git a/test/fixedbugs/issue31636.dir/b.go b/test/fixedbugs/issue31636.dir/b.go new file mode 100644 index 0000000000..990e68209b --- /dev/null +++ b/test/fixedbugs/issue31636.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2019 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. + +package b + +func init() { + println("b") +} diff --git a/test/fixedbugs/issue31636.dir/c.go b/test/fixedbugs/issue31636.dir/c.go new file mode 100644 index 0000000000..e53529aa59 --- /dev/null +++ b/test/fixedbugs/issue31636.dir/c.go @@ -0,0 +1,9 @@ +// Copyright 2019 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. + +package c + +func init() { + println("c") +} diff --git a/test/fixedbugs/issue31636.dir/main.go b/test/fixedbugs/issue31636.dir/main.go new file mode 100644 index 0000000000..d8ae902c64 --- /dev/null +++ b/test/fixedbugs/issue31636.dir/main.go @@ -0,0 +1,20 @@ +// Copyright 2019 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. + +package main + +// We want the initializers of these packages to occur in source code +// order. See issue 31636. This is the behavior up to and including +// 1.13. For 1.14, we will move to a variant of lexicographic ordering +// which will require a change to the test output of this test. +import ( + _ "c" + + _ "b" + + _ "a" +) + +func main() { +} diff --git a/test/fixedbugs/issue31636.go b/test/fixedbugs/issue31636.go new file mode 100644 index 0000000000..af6f134172 --- /dev/null +++ b/test/fixedbugs/issue31636.go @@ -0,0 +1,7 @@ +// rundir + +// Copyright 2019 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. + +package ignored diff --git a/test/fixedbugs/issue31636.out b/test/fixedbugs/issue31636.out new file mode 100644 index 0000000000..e274b2bb10 --- /dev/null +++ b/test/fixedbugs/issue31636.out @@ -0,0 +1,3 @@ +c +b +a diff --git a/test/fixedbugs/issue31959.dir/a.go b/test/fixedbugs/issue31959.dir/a.go new file mode 100644 index 0000000000..6c7ffa38c1 --- /dev/null +++ b/test/fixedbugs/issue31959.dir/a.go @@ -0,0 +1,12 @@ +// Copyright 2019 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. + +package a + +type T struct{} + +func F() { + type T = int + println(T(0)) +} diff --git a/test/fixedbugs/issue31959.dir/main.go b/test/fixedbugs/issue31959.dir/main.go new file mode 100644 index 0000000000..895c4e5345 --- /dev/null +++ b/test/fixedbugs/issue31959.dir/main.go @@ -0,0 +1,21 @@ +// run + +// Copyright 2019 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. + +// Check import package contains type alias in function +// with the same name with an export type not panic + +package main + +import ( + "fmt" + + "a" +) + +func main() { + fmt.Println(a.T{}) + a.F() +} diff --git a/test/fixedbugs/issue31959.go b/test/fixedbugs/issue31959.go new file mode 100644 index 0000000000..af6f134172 --- /dev/null +++ b/test/fixedbugs/issue31959.go @@ -0,0 +1,7 @@ +// rundir + +// Copyright 2019 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. + +package ignored diff --git a/test/fixedbugs/issue31959.out b/test/fixedbugs/issue31959.out new file mode 100644 index 0000000000..8ddcb67af1 --- /dev/null +++ b/test/fixedbugs/issue31959.out @@ -0,0 +1,2 @@ +{} +0 diff --git a/test/fixedbugs/issue32175.go b/test/fixedbugs/issue32175.go new file mode 100644 index 0000000000..a67735148e --- /dev/null +++ b/test/fixedbugs/issue32175.go @@ -0,0 +1,22 @@ +// run + +// Copyright 2019 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. + +package main + +// This used to print 0, because x was incorrectly captured by value. + +func f() (x int) { + defer func() func() { + return func() { + println(x) + } + }()() + return 42 +} + +func main() { + f() +} diff --git a/test/fixedbugs/issue32175.out b/test/fixedbugs/issue32175.out new file mode 100644 index 0000000000..d81cc0710e --- /dev/null +++ b/test/fixedbugs/issue32175.out @@ -0,0 +1 @@ +42 diff --git a/test/run.go b/test/run.go index f66db630c5..28ed865c50 100644 --- a/test/run.go +++ b/test/run.go @@ -34,6 +34,7 @@ var ( keep = flag.Bool("k", false, "keep. keep temporary directory.") numParallel = flag.Int("n", runtime.NumCPU(), "number of parallel tests to run") summary = flag.Bool("summary", false, "show summary of results") + allCodegen = flag.Bool("all_codegen", false, "run all goos/goarch for codegen") showSkips = flag.Bool("show_skips", false, "show skipped tests") runSkips = flag.Bool("run_skips", false, "run skipped tests (ignore skip and build tags)") linkshared = flag.Bool("linkshared", false, "") @@ -521,7 +522,7 @@ func (t *test) run() { // TODO: Clean up/simplify this switch statement. switch action { - case "compile", "compiledir", "build", "builddir", "buildrundir", "run", "buildrun", "runoutput", "rundir", "asmcheck": + case "compile", "compiledir", "build", "builddir", "buildrundir", "run", "buildrun", "runoutput", "rundir", "runindir", "asmcheck": // nothing to do case "errorcheckandrundir": wantError = false // should be no error if also will run @@ -602,16 +603,19 @@ func (t *test) run() { } useTmp := true + runInDir := false runcmd := func(args ...string) ([]byte, error) { cmd := exec.Command(args[0], args[1:]...) var buf bytes.Buffer cmd.Stdout = &buf cmd.Stderr = &buf + cmd.Env = os.Environ() if useTmp { cmd.Dir = t.tempDir cmd.Env = envForDir(cmd.Dir) - } else { - cmd.Env = os.Environ() + } + if runInDir { + cmd.Dir = t.goDirName() } var err error @@ -653,7 +657,13 @@ func (t *test) run() { // Compile Go file and match the generated assembly // against a set of regexps in comments. ops := t.wantedAsmOpcodes(long) + self := runtime.GOOS + "/" + runtime.GOARCH for _, env := range ops.Envs() { + // Only run checks relevant to the current GOOS/GOARCH, + // to avoid triggering a cross-compile of the runtime. + if string(env) != self && !strings.HasPrefix(string(env), self+"/") && !*allCodegen { + continue + } // -S=2 forces outermost line numbers when disassembling inlined code. cmdline := []string{"build", "-gcflags", "-S=2"} cmdline = append(cmdline, flags...) @@ -827,6 +837,28 @@ func (t *test) run() { } } + case "runindir": + // run "go run ." in t.goDirName() + // It's used when test requires go build and run the binary success. + // Example when long import path require (see issue29612.dir) or test + // contains assembly file (see issue15609.dir). + // Verify the expected output. + useTmp = false + runInDir = true + cmd := []string{goTool(), "run", goGcflags()} + if *linkshared { + cmd = append(cmd, "-linkshared") + } + cmd = append(cmd, ".") + out, err := runcmd(cmd...) + if err != nil { + t.err = err + return + } + if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() { + t.err = fmt.Errorf("incorrect output\n%s", out) + } + case "build": // Build Go file. _, err := runcmd(goTool(), "build", goGcflags(), "-o", "a.exe", long)