cmd/stringer: add a few tests using instantiated generic types
The added tests are in a subdirectory of testdir that is looked
at only if typeparams.Enabled is true, but some test helper routines
needed to be modified to cope with files in a subdirectory.
Change-Id: I82c22a8ba74a1e4a1a2c8669c2271449d5fcaf3a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/355313
Run-TryBot: Peter Weinberger <pjw@google.com>
Trust: Peter Weinberger <pjw@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/cmd/stringer/endtoend_test.go b/cmd/stringer/endtoend_test.go
index 3b0b39d..5b969a5 100644
--- a/cmd/stringer/endtoend_test.go
+++ b/cmd/stringer/endtoend_test.go
@@ -17,11 +17,13 @@
"io/ioutil"
"os"
"os/exec"
+ "path"
"path/filepath"
"strings"
"testing"
"golang.org/x/tools/internal/testenv"
+ "golang.org/x/tools/internal/typeparams"
)
// This file contains a test that compiles and runs each program in testdata
@@ -42,8 +44,15 @@
if err != nil {
t.Fatalf("Readdirnames: %s", err)
}
+ if typeparams.Enabled {
+ names = append(names, moreTests(t, "testdata/typeparams", "typeparams")...)
+ }
// Generate, compile, and run the test programs.
for _, name := range names {
+ if name == "typeparams" {
+ // ignore the directory containing the tests with type params
+ continue
+ }
if !strings.HasSuffix(name, ".go") {
t.Errorf("%s is not a Go file", name)
continue
@@ -56,12 +65,31 @@
t.Logf("cgo is not enabled for %s", name)
continue
}
- // Names are known to be ASCII and long enough.
- typeName := fmt.Sprintf("%c%s", name[0]+'A'-'a', name[1:len(name)-len(".go")])
- stringerCompileAndRun(t, dir, stringer, typeName, name)
+ stringerCompileAndRun(t, dir, stringer, typeName(name), name)
}
}
+// a type name for stringer. use the last component of the file name with the .go
+func typeName(fname string) string {
+ // file names are known to be ascii and end .go
+ base := path.Base(fname)
+ return fmt.Sprintf("%c%s", base[0]+'A'-'a', base[1:len(base)-len(".go")])
+}
+
+func moreTests(t *testing.T, dirname, prefix string) []string {
+ x, err := os.ReadDir(dirname)
+ if err != nil {
+ // error, but try the rest of the tests
+ t.Errorf("can't read type param tess from %s: %v", dirname, err)
+ return nil
+ }
+ names := make([]string, len(x))
+ for i, f := range x {
+ names[i] = prefix + "/" + f.Name()
+ }
+ return names
+}
+
// TestTags verifies that the -tags flag works as advertised.
func TestTags(t *testing.T) {
dir, stringer := buildStringer(t)
@@ -173,7 +201,7 @@
func stringerCompileAndRun(t *testing.T, dir, stringer, typeName, fileName string) {
t.Helper()
t.Logf("run: %s %s\n", fileName, typeName)
- source := filepath.Join(dir, fileName)
+ source := filepath.Join(dir, path.Base(fileName))
err := copy(source, filepath.Join("testdata", fileName))
if err != nil {
t.Fatalf("copying file to temporary directory: %s", err)
diff --git a/cmd/stringer/testdata/typeparams/conv2.go b/cmd/stringer/testdata/typeparams/conv2.go
new file mode 100644
index 0000000..1563fe8
--- /dev/null
+++ b/cmd/stringer/testdata/typeparams/conv2.go
@@ -0,0 +1,43 @@
+// Copyright 2021 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 is a version of ../conv.go with type params
+
+// Check that constants defined as a conversion are accepted.
+
+package main
+
+import "fmt"
+
+type Other[T interface{ ~int | ~uint }] T // Imagine this is in another package.
+
+const (
+ alpha Other[int] = iota
+ beta
+ gamma
+ delta
+)
+
+type Conv2 Other[int]
+
+const (
+ Alpha = Conv2(alpha)
+ Beta = Conv2(beta)
+ Gamma = Conv2(gamma)
+ Delta = Conv2(delta)
+)
+
+func main() {
+ ck(Alpha, "Alpha")
+ ck(Beta, "Beta")
+ ck(Gamma, "Gamma")
+ ck(Delta, "Delta")
+ ck(42, "Conv2(42)")
+}
+
+func ck(c Conv2, str string) {
+ if fmt.Sprint(c) != str {
+ panic("conv2.go: " + str)
+ }
+}
diff --git a/cmd/stringer/testdata/typeparams/prime2.go b/cmd/stringer/testdata/typeparams/prime2.go
new file mode 100644
index 0000000..376c9e2
--- /dev/null
+++ b/cmd/stringer/testdata/typeparams/prime2.go
@@ -0,0 +1,60 @@
+// Copyright 2021 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 is a version of ../prime.go with type params
+
+// Enough gaps to trigger a map implementation of the method.
+// Also includes a duplicate to test that it doesn't cause problems
+
+package main
+
+import "fmt"
+
+type Likeint[T interface{ ~int | ~uint8 }] T
+
+type Prime2 Likeint[int]
+
+const (
+ p2 Prime2 = 2
+ p3 Prime2 = 3
+ p5 Prime2 = 5
+ p7 Prime2 = 7
+ p77 Prime2 = 7 // Duplicate; note that p77 doesn't appear below.
+ p11 Prime2 = 11
+ p13 Prime2 = 13
+ p17 Prime2 = 17
+ p19 Prime2 = 19
+ p23 Prime2 = 23
+ p29 Prime2 = 29
+ p37 Prime2 = 31
+ p41 Prime2 = 41
+ p43 Prime2 = 43
+)
+
+func main() {
+ ck(0, "Prime2(0)")
+ ck(1, "Prime2(1)")
+ ck(p2, "p2")
+ ck(p3, "p3")
+ ck(4, "Prime2(4)")
+ ck(p5, "p5")
+ ck(p7, "p7")
+ ck(p77, "p7")
+ ck(p11, "p11")
+ ck(p13, "p13")
+ ck(p17, "p17")
+ ck(p19, "p19")
+ ck(p23, "p23")
+ ck(p29, "p29")
+ ck(p37, "p37")
+ ck(p41, "p41")
+ ck(p43, "p43")
+ ck(44, "Prime2(44)")
+}
+
+func ck(prime Prime2, str string) {
+ if fmt.Sprint(prime) != str {
+ panic("prime2.go: " + str)
+ }
+}