github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/constraints/constraints_test.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package constraints 6 7 import ( 8 "bytes" 9 "fmt" 10 "internal/testenv" 11 "os" 12 "os/exec" 13 "path/filepath" 14 "testing" 15 ) 16 17 type ( 18 testSigned[T Signed] struct{ f T } 19 testUnsigned[T Unsigned] struct{ f T } 20 testInteger[T Integer] struct{ f T } 21 testFloat[T Float] struct{ f T } 22 testComplex[T Complex] struct{ f T } 23 testOrdered[T Ordered] struct{ f T } 24 ) 25 26 // TestTypes passes if it compiles. 27 type TestTypes struct { 28 _ testSigned[int] 29 _ testSigned[int64] 30 _ testUnsigned[uint] 31 _ testUnsigned[uintptr] 32 _ testInteger[int8] 33 _ testInteger[uint8] 34 _ testInteger[uintptr] 35 _ testFloat[float32] 36 _ testComplex[complex64] 37 _ testOrdered[int] 38 _ testOrdered[float64] 39 _ testOrdered[string] 40 } 41 42 var prolog = []byte(` 43 package constrainttest 44 45 import "constraints" 46 47 type ( 48 testSigned[T constraints.Signed] struct{ f T } 49 testUnsigned[T constraints.Unsigned] struct{ f T } 50 testInteger[T constraints.Integer] struct{ f T } 51 testFloat[T constraints.Float] struct{ f T } 52 testComplex[T constraints.Complex] struct{ f T } 53 testOrdered[T constraints.Ordered] struct{ f T } 54 ) 55 `) 56 57 func TestFailure(t *testing.T) { 58 testenv.MustHaveGoBuild(t) 59 gocmd := testenv.GoToolPath(t) 60 tmpdir := t.TempDir() 61 62 if err := os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module constraintest"), 0666); err != nil { 63 t.Fatal(err) 64 } 65 66 // Test for types that should not satisfy a constraint. 67 // For each pair of constraint and type, write a Go file 68 // var V constraint[type] 69 // For example, 70 // var V testSigned[uint] 71 // This should not compile, as testSigned (above) uses 72 // constraints.Signed, and uint does not satisfy that constraint. 73 // Therefore, the build of that code should fail. 74 for i, test := range []struct { 75 constraint, typ string 76 }{ 77 {"testSigned", "uint"}, 78 {"testUnsigned", "int"}, 79 {"testInteger", "float32"}, 80 {"testFloat", "int8"}, 81 {"testComplex", "float64"}, 82 {"testOrdered", "bool"}, 83 } { 84 i := i 85 test := test 86 t.Run(fmt.Sprintf("%s %d", test.constraint, i), func(t *testing.T) { 87 t.Parallel() 88 name := fmt.Sprintf("go%d.go", i) 89 f, err := os.Create(filepath.Join(tmpdir, name)) 90 if err != nil { 91 t.Fatal(err) 92 } 93 if _, err := f.Write(prolog); err != nil { 94 t.Fatal(err) 95 } 96 if _, err := fmt.Fprintf(f, "var V %s[%s]\n", test.constraint, test.typ); err != nil { 97 t.Fatal(err) 98 } 99 if err := f.Close(); err != nil { 100 t.Fatal(err) 101 } 102 cmd := exec.Command(gocmd, "build", name) 103 cmd.Dir = tmpdir 104 if out, err := cmd.CombinedOutput(); err == nil { 105 t.Error("build succeeded, but expected to fail") 106 } else if len(out) > 0 { 107 t.Logf("%s", out) 108 const want = "does not implement" 109 if !bytes.Contains(out, []byte(want)) { 110 t.Errorf("output does not include %q", want) 111 } 112 } else { 113 t.Error("no error output, expected something") 114 } 115 }) 116 } 117 }