golang.org/x/tools@v0.21.1-0.20240520172518-788d39e776b1/go/ssa/interp/interp_go122_test.go (about) 1 // Copyright 2023 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 //go:build go1.22 6 // +build go1.22 7 8 package interp_test 9 10 import ( 11 "bytes" 12 "log" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "reflect" 17 "testing" 18 19 "golang.org/x/tools/internal/testenv" 20 ) 21 22 func init() { 23 testdataTests = append(testdataTests, 24 "rangevarlifetime_go122.go", 25 "forvarlifetime_go122.go", 26 ) 27 } 28 29 // TestExperimentRange tests files in testdata with GOEXPERIMENT=range set. 30 func TestExperimentRange(t *testing.T) { 31 testenv.NeedsGoExperiment(t, "range") 32 33 // TODO: Is cwd actually needed here? 34 goroot := makeGoroot(t) 35 cwd, err := os.Getwd() 36 if err != nil { 37 log.Fatal(err) 38 } 39 run(t, filepath.Join(cwd, "testdata", "rangeoverint.go"), goroot) 40 } 41 42 // TestRangeFunc tests range-over-func in a subprocess. 43 func TestRangeFunc(t *testing.T) { 44 testenv.NeedsGo1Point(t, 23) 45 46 // TODO(taking): Remove subprocess from the test and capture output another way. 47 if os.Getenv("INTERPTEST_CHILD") == "1" { 48 testRangeFunc(t) 49 return 50 } 51 52 testenv.NeedsExec(t) 53 testenv.NeedsTool(t, "go") 54 55 cmd := exec.Command(os.Args[0], "-test.run=TestRangeFunc") 56 cmd.Env = append(os.Environ(), "INTERPTEST_CHILD=1") 57 out, err := cmd.CombinedOutput() 58 if len(out) > 0 { 59 t.Logf("out=<<%s>>", out) 60 } 61 62 // Check the output of the tests. 63 const ( 64 RERR_DONE = "Saw expected panic: yield function called after range loop exit" 65 RERR_MISSING = "Saw expected panic: iterator call did not preserve panic" 66 RERR_EXHAUSTED = RERR_DONE // ssa does not distinguish. Same message as RERR_DONE. 67 68 CERR_DONE = "Saw expected panic: checked rangefunc error: loop iteration after body done" 69 CERR_EXHAUSTED = "Saw expected panic: checked rangefunc error: loop iteration after iterator exit" 70 CERR_MISSING = "Saw expected panic: checked rangefunc error: loop iterator swallowed panic" 71 72 panickyIterMsg = "Saw expected panic: Panicky iterator panicking" 73 ) 74 expected := map[string][]string{ 75 // rangefunc.go 76 "TestCheck": []string{"i = 45", CERR_DONE}, 77 "TestCooperativeBadOfSliceIndex": []string{RERR_EXHAUSTED, "i = 36"}, 78 "TestCooperativeBadOfSliceIndexCheck": []string{CERR_EXHAUSTED, "i = 36"}, 79 "TestTrickyIterAll": []string{"i = 36", RERR_EXHAUSTED}, 80 "TestTrickyIterOne": []string{"i = 1", RERR_EXHAUSTED}, 81 "TestTrickyIterZero": []string{"i = 0", RERR_EXHAUSTED}, 82 "TestTrickyIterZeroCheck": []string{"i = 0", CERR_EXHAUSTED}, 83 "TestTrickyIterEcho": []string{ 84 "first loop i=0", 85 "first loop i=1", 86 "first loop i=3", 87 "first loop i=6", 88 "i = 10", 89 "second loop i=0", 90 RERR_EXHAUSTED, 91 "end i=0", 92 }, 93 "TestTrickyIterEcho2": []string{ 94 "k=0,x=1,i=0", 95 "k=0,x=2,i=1", 96 "k=0,x=3,i=3", 97 "k=0,x=4,i=6", 98 "i = 10", 99 "k=1,x=1,i=0", 100 RERR_EXHAUSTED, 101 "end i=1", 102 }, 103 "TestBreak1": []string{"[1 2 -1 1 2 -2 1 2 -3]"}, 104 "TestBreak2": []string{"[1 2 -1 1 2 -2 1 2 -3]"}, 105 "TestContinue": []string{"[-1 1 2 -2 1 2 -3 1 2 -4]"}, 106 "TestBreak3": []string{"[100 10 2 4 200 10 2 4 20 2 4 300 10 2 4 20 2 4 30]"}, 107 "TestBreak1BadA": []string{"[1 2 -1 1 2 -2 1 2 -3]", RERR_DONE}, 108 "TestBreak1BadB": []string{"[1 2]", RERR_DONE}, 109 "TestMultiCont0": []string{"[1000 10 2 4 2000]"}, 110 "TestMultiCont1": []string{"[1000 10 2 4]", RERR_DONE}, 111 "TestMultiCont2": []string{"[1000 10 2 4]", RERR_DONE}, 112 "TestMultiCont3": []string{"[1000 10 2 4]", RERR_DONE}, 113 "TestMultiBreak0": []string{"[1000 10 2 4]", RERR_DONE}, 114 "TestMultiBreak1": []string{"[1000 10 2 4]", RERR_DONE}, 115 "TestMultiBreak2": []string{"[1000 10 2 4]", RERR_DONE}, 116 "TestMultiBreak3": []string{"[1000 10 2 4]", RERR_DONE}, 117 "TestPanickyIterator1": []string{panickyIterMsg}, 118 "TestPanickyIterator1Check": []string{panickyIterMsg}, 119 "TestPanickyIterator2": []string{RERR_MISSING}, 120 "TestPanickyIterator2Check": []string{CERR_MISSING}, 121 "TestPanickyIterator3": []string{"[100 10 1 2 200 10 1 2]"}, 122 "TestPanickyIterator3Check": []string{"[100 10 1 2 200 10 1 2]"}, 123 "TestPanickyIterator4": []string{RERR_MISSING}, 124 "TestPanickyIterator4Check": []string{CERR_MISSING}, 125 "TestVeryBad1": []string{"[1 10]"}, 126 "TestVeryBad2": []string{"[1 10]"}, 127 "TestVeryBadCheck": []string{"[1 10]"}, 128 "TestOk": []string{"[1 10]"}, 129 "TestBreak1BadDefer": []string{RERR_DONE, "[1 2 -1 1 2 -2 1 2 -3 -30 -20 -10]"}, 130 "TestReturns": []string{"[-1 1 2 -10]", "[-1 1 2 -10]", RERR_DONE, "[-1 1 2 -10]", RERR_DONE}, 131 "TestGotoA": []string{"testGotoA1[-1 1 2 -2 1 2 -3 1 2 -4 -30 -20 -10]", "testGotoA2[-1 1 2 -2 1 2 -3 1 2 -4 -30 -20 -10]", RERR_DONE, "testGotoA3[-1 1 2 -10]", RERR_DONE}, 132 "TestGotoB": []string{"testGotoB1[-1 1 2 999 -10]", "testGotoB2[-1 1 2 -10]", RERR_DONE, "testGotoB3[-1 1 2 -10]", RERR_DONE}, 133 "TestPanicReturns": []string{ 134 "Got expected 'f return'", 135 "Got expected 'g return'", 136 "Got expected 'h return'", 137 "Got expected 'k return'", 138 "Got expected 'j return'", 139 "Got expected 'm return'", 140 "Got expected 'n return and n closure return'", 141 }, 142 } 143 got := make(map[string][]string) 144 for _, ln := range bytes.Split(out, []byte("\n")) { 145 if ind := bytes.Index(ln, []byte(" \t ")); ind >= 0 { 146 n, m := string(ln[:ind]), string(ln[ind+3:]) 147 got[n] = append(got[n], m) 148 } 149 } 150 for n, es := range expected { 151 if gs := got[n]; !reflect.DeepEqual(es, gs) { 152 t.Errorf("Output of test %s did not match expected output %v. got %v", n, es, gs) 153 } 154 } 155 for n, gs := range got { 156 if expected[n] == nil { 157 t.Errorf("No expected output for test %s. got %v", n, gs) 158 } 159 } 160 161 var exitcode int 162 if err, ok := err.(*exec.ExitError); ok { 163 exitcode = err.ExitCode() 164 } 165 const want = 0 166 if exitcode != want { 167 t.Errorf("exited %d, want %d", exitcode, want) 168 } 169 } 170 171 func testRangeFunc(t *testing.T) { 172 goroot := makeGoroot(t) 173 cwd, err := os.Getwd() 174 if err != nil { 175 log.Fatal(err) 176 } 177 178 input := "rangefunc.go" 179 run(t, filepath.Join(cwd, "testdata", input), goroot) 180 }