Commit cb80c289 authored by Yury Smolsky's avatar Yury Smolsky Committed by Brad Fitzpatrick

test: eliminate use of Perl in test/fixedbugs/bug248.go

This change enables bug248 to be tested with Go code.
For that, it adds a flag -1 to error check and run directory
with one package failing compilation prior the last package
which should be run.

Specifically, the "p" package in bug1.go file was renamed into "q"
to compile them in separate steps,
bug2.go and bug3.go files were reordered,
bug2.go was changed into non-main package.

Updates #25586.

Change-Id: Ie47aacd56ebb2ce4eac66c792d1a53e1e30e637c
Reviewed-on: https://go-review.googlesource.com/114818
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
parent f7b625e4
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file // license that can be found in the LICENSE file
package p package q
type T struct { type T struct {
X, Y int X, Y int
......
...@@ -2,19 +2,20 @@ ...@@ -2,19 +2,20 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file // license that can be found in the LICENSE file
package main package s
import ( import (
p0 "./bug0" p0 "./bug0"
p1 "./bug1" p1 "./bug1"
"reflect"
"strings"
) )
// both p0.T and p1.T are struct { X, Y int }.
var v0 p0.T var v0 p0.T
var v1 p1.T var v1 p1.T
// interfaces involving the two
type I0 interface { type I0 interface {
M(p0.T) M(p0.T)
} }
...@@ -23,83 +24,50 @@ type I1 interface { ...@@ -23,83 +24,50 @@ type I1 interface {
M(p1.T) M(p1.T)
} }
// t0 satisfies I0 and p0.I
type t0 int type t0 int
func (t0) M(p0.T) {} func (t0) M(p0.T) {}
// t1 satisfies I1 and p1.I
type t1 float64 type t1 float64
func (t1) M(p1.T) {} func (t1) M(p1.T) {}
// check static interface assignments
var i0 I0 = t0(0) // ok var i0 I0 = t0(0) // ok
var i1 I1 = t1(0) // ok var i1 I1 = t1(0) // ok
var i2 I0 = t1(0) // ERROR "does not implement|incompatible"
var i3 I1 = t0(0) // ERROR "does not implement|incompatible"
var p0i p0.I = t0(0) // ok var p0i p0.I = t0(0) // ok
var p1i p1.I = t1(0) // ok var p1i p1.I = t1(0) // ok
func main() { var p0i1 p0.I = t1(0) // ERROR "does not implement|incompatible"
// check that reflect paths are correct, var p0i2 p1.I = t0(0) // ERROR "does not implement|incompatible"
// meaning that reflect data for v0, v1 didn't get confused.
func foobar() {
// path is full (rooted) path name. check suffix for gc, prefix for gccgo // check that cannot assign one to the other,
if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") { // but can convert.
println("bad v0 path", len(s), s) v0 = v1 // ERROR "assign"
panic("fail") v1 = v0 // ERROR "assign"
}
if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") { v0 = p0.T(v1)
println("bad v1 path", s) v1 = p1.T(v0)
panic("fail")
} i0 = i1 // ERROR "cannot use|incompatible"
i1 = i0 // ERROR "cannot use|incompatible"
// check that dynamic interface check doesn't get confused p0i = i1 // ERROR "cannot use|incompatible"
var i interface{} = t0(0) p1i = i0 // ERROR "cannot use|incompatible"
if _, ok := i.(I1); ok { i0 = p1i // ERROR "cannot use|incompatible"
println("used t0 as i1") i1 = p0i // ERROR "cannot use|incompatible"
panic("fail") p0i = p1i // ERROR "cannot use|incompatible"
} p1i = p0i // ERROR "cannot use|incompatible"
if _, ok := i.(p1.I); ok {
println("used t0 as p1.I") i0 = p0i
panic("fail") p0i = i0
}
i1 = p1i
i = t1(1) p1i = i1
if _, ok := i.(I0); ok {
println("used t1 as i0")
panic("fail")
}
if _, ok := i.(p0.I); ok {
println("used t1 as p0.I")
panic("fail")
}
// check that type switch works.
// the worry is that if p0.T and p1.T have the same hash,
// the binary search will handle one of them incorrectly.
for j := 0; j < 3; j++ {
switch j {
case 0:
i = p0.T{}
case 1:
i = p1.T{}
case 2:
i = 3.14
}
switch i.(type) {
case p0.T:
if j != 0 {
println("type switch p0.T")
panic("fail")
}
case p1.T:
if j != 1 {
println("type switch p1.T")
panic("fail")
}
default:
if j != 2 {
println("type switch default", j)
panic("fail")
}
}
}
} }
...@@ -7,15 +7,14 @@ package main ...@@ -7,15 +7,14 @@ package main
import ( import (
p0 "./bug0" p0 "./bug0"
p1 "./bug1" p1 "./bug1"
)
// both p0.T and p1.T are struct { X, Y int }. "reflect"
"strings"
)
var v0 p0.T var v0 p0.T
var v1 p1.T var v1 p1.T
// interfaces involving the two
type I0 interface { type I0 interface {
M(p0.T) M(p0.T)
} }
...@@ -24,50 +23,83 @@ type I1 interface { ...@@ -24,50 +23,83 @@ type I1 interface {
M(p1.T) M(p1.T)
} }
// t0 satisfies I0 and p0.I
type t0 int type t0 int
func (t0) M(p0.T) {} func (t0) M(p0.T) {}
// t1 satisfies I1 and p1.I
type t1 float64 type t1 float64
func (t1) M(p1.T) {} func (t1) M(p1.T) {}
// check static interface assignments
var i0 I0 = t0(0) // ok var i0 I0 = t0(0) // ok
var i1 I1 = t1(0) // ok var i1 I1 = t1(0) // ok
var i2 I0 = t1(0) // ERROR "does not implement|incompatible"
var i3 I1 = t0(0) // ERROR "does not implement|incompatible"
var p0i p0.I = t0(0) // ok var p0i p0.I = t0(0) // ok
var p1i p1.I = t1(0) // ok var p1i p1.I = t1(0) // ok
var p0i1 p0.I = t1(0) // ERROR "does not implement|incompatible"
var p0i2 p1.I = t0(0) // ERROR "does not implement|incompatible"
func main() { func main() {
// check that cannot assign one to the other, // check that reflect paths are correct,
// but can convert. // meaning that reflect data for v0, v1 didn't get confused.
v0 = v1 // ERROR "assign"
v1 = v0 // ERROR "assign" // path is full (rooted) path name. check suffix for gc, prefix for gccgo
if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
v0 = p0.T(v1) println("bad v0 path", len(s), s)
v1 = p1.T(v0) panic("fail")
}
i0 = i1 // ERROR "cannot use|incompatible" if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
i1 = i0 // ERROR "cannot use|incompatible" println("bad v1 path", s)
p0i = i1 // ERROR "cannot use|incompatible" panic("fail")
p1i = i0 // ERROR "cannot use|incompatible" }
i0 = p1i // ERROR "cannot use|incompatible"
i1 = p0i // ERROR "cannot use|incompatible" // check that dynamic interface check doesn't get confused
p0i = p1i // ERROR "cannot use|incompatible" var i interface{} = t0(0)
p1i = p0i // ERROR "cannot use|incompatible" if _, ok := i.(I1); ok {
println("used t0 as i1")
i0 = p0i panic("fail")
p0i = i0 }
if _, ok := i.(p1.I); ok {
i1 = p1i println("used t0 as p1.I")
p1i = i1 panic("fail")
}
i = t1(1)
if _, ok := i.(I0); ok {
println("used t1 as i0")
panic("fail")
}
if _, ok := i.(p0.I); ok {
println("used t1 as p0.I")
panic("fail")
}
// check that type switch works.
// the worry is that if p0.T and p1.T have the same hash,
// the binary search will handle one of them incorrectly.
for j := 0; j < 3; j++ {
switch j {
case 0:
i = p0.T{}
case 1:
i = p1.T{}
case 2:
i = 3.14
}
switch i.(type) {
case p0.T:
if j != 0 {
println("type switch p0.T")
panic("fail")
}
case p1.T:
if j != 1 {
println("type switch p1.T")
panic("fail")
}
default:
if j != 2 {
println("type switch default", j)
panic("fail")
}
}
}
} }
// +build !nacl,!js,!plan9,!windows // +build !nacl,!js,!plan9
// run // errorcheckandrundir -1
// Copyright 2009 The Go Authors. All rights reserved. // Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package main package ignored
import ( // Compile: bug0.go, bug1.go
"fmt" // Compile and errorCheck: bug2.go
"os" // Link and run: bug3.go
"os/exec"
"path/filepath"
"regexp"
)
func main() {
// TODO: If we get rid of errchk, re-enable this test on Windows.
errchk, err := filepath.Abs("errchk")
check(err)
bugDir := filepath.Join(".", "fixedbugs", "bug248.dir")
run("go", "tool", "compile", filepath.Join(bugDir, "bug0.go"))
run("go", "tool", "compile", filepath.Join(bugDir, "bug1.go"))
run("go", "tool", "compile", filepath.Join(bugDir, "bug2.go"))
run(errchk, "go", "tool", "compile", "-e", filepath.Join(bugDir, "bug3.go"))
run("go", "tool", "link", "bug2.o")
run(fmt.Sprintf(".%ca.out", filepath.Separator))
os.Remove("bug0.o")
os.Remove("bug1.o")
os.Remove("bug2.o")
os.Remove("a.out")
}
var bugRE = regexp.MustCompile(`(?m)^BUG`)
func run(name string, args ...string) {
cmd := exec.Command(name, args...)
out, err := cmd.CombinedOutput()
if bugRE.Match(out) || err != nil {
fmt.Println(string(out))
fmt.Println(err)
os.Exit(1)
}
}
func check(err error) {
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
...@@ -524,6 +524,8 @@ func (t *test) run() { ...@@ -524,6 +524,8 @@ func (t *test) run() {
// collect flags // collect flags
for len(args) > 0 && strings.HasPrefix(args[0], "-") { for len(args) > 0 && strings.HasPrefix(args[0], "-") {
switch args[0] { switch args[0] {
case "-1":
wantError = true
case "-0": case "-0":
wantError = false wantError = false
case "-s": case "-s":
...@@ -681,9 +683,15 @@ func (t *test) run() { ...@@ -681,9 +683,15 @@ func (t *test) run() {
t.err = err t.err = err
return return
} }
errPkg := len(pkgs) - 1
if wantError && action == "errorcheckandrundir" {
// The last pkg should compiled successfully and will be run in next case.
// Preceding pkg must return an error from compileInDir.
errPkg--
}
for i, gofiles := range pkgs { for i, gofiles := range pkgs {
out, err := compileInDir(runcmd, longdir, flags, gofiles...) out, err := compileInDir(runcmd, longdir, flags, gofiles...)
if i == len(pkgs)-1 { if i == errPkg {
if wantError && err == nil { if wantError && err == nil {
t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out) t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
return return
...@@ -720,7 +728,9 @@ func (t *test) run() { ...@@ -720,7 +728,9 @@ func (t *test) run() {
} }
for i, gofiles := range pkgs { for i, gofiles := range pkgs {
_, err := compileInDir(runcmd, longdir, flags, gofiles...) _, err := compileInDir(runcmd, longdir, flags, gofiles...)
if err != nil { // Allow this package compilation fail based on conditions below;
// its errors were checked in previous case.
if err != nil && !(wantError && action == "errorcheckandrundir" && i == len(pkgs)-2) {
t.err = err t.err = err
return return
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment