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  }