github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/expect/expect_test.go (about) 1 // Copyright 2018 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 expect_test 6 7 import ( 8 "bytes" 9 "go/token" 10 "io/ioutil" 11 "testing" 12 13 "golang.org/x/tools/go/expect" 14 ) 15 16 func TestMarker(t *testing.T) { 17 for _, tt := range []struct { 18 filename string 19 expectNotes int 20 expectMarkers map[string]string 21 expectChecks map[string][]interface{} 22 }{ 23 { 24 filename: "testdata/test.go", 25 expectNotes: 13, 26 expectMarkers: map[string]string{ 27 "αSimpleMarker": "α", 28 "OffsetMarker": "β", 29 "RegexMarker": "γ", 30 "εMultiple": "ε", 31 "ζMarkers": "ζ", 32 "ηBlockMarker": "η", 33 "Declared": "η", 34 "Comment": "ι", 35 "LineComment": "someFunc", 36 "NonIdentifier": "+", 37 "StringMarker": "\"hello\"", 38 }, 39 expectChecks: map[string][]interface{}{ 40 "αSimpleMarker": nil, 41 "StringAndInt": {"Number %d", int64(12)}, 42 "Bool": {true}, 43 }, 44 }, 45 { 46 filename: "testdata/go.fake.mod", 47 expectNotes: 2, 48 expectMarkers: map[string]string{ 49 "αMarker": "αfake1α", 50 "βMarker": "require golang.org/modfile v0.0.0", 51 }, 52 }, 53 } { 54 t.Run(tt.filename, func(t *testing.T) { 55 content, err := ioutil.ReadFile(tt.filename) 56 if err != nil { 57 t.Fatal(err) 58 } 59 readFile := func(string) ([]byte, error) { return content, nil } 60 61 markers := make(map[string]token.Pos) 62 for name, tok := range tt.expectMarkers { 63 offset := bytes.Index(content, []byte(tok)) 64 markers[name] = token.Pos(offset + 1) 65 end := bytes.Index(content[offset:], []byte(tok)) 66 if end > 0 { 67 markers[name+"@"] = token.Pos(offset + end + 2) 68 } 69 } 70 71 fset := token.NewFileSet() 72 notes, err := expect.Parse(fset, tt.filename, content) 73 if err != nil { 74 t.Fatalf("Failed to extract notes: %v", err) 75 } 76 if len(notes) != tt.expectNotes { 77 t.Errorf("Expected %v notes, got %v", tt.expectNotes, len(notes)) 78 } 79 for _, n := range notes { 80 switch { 81 case n.Args == nil: 82 // A //@foo note associates the name foo with the position of the 83 // first match of "foo" on the current line. 84 checkMarker(t, fset, readFile, markers, n.Pos, n.Name, n.Name) 85 case n.Name == "mark": 86 // A //@mark(name, "pattern") note associates the specified name 87 // with the position on the first match of pattern on the current line. 88 if len(n.Args) != 2 { 89 t.Errorf("%v: expected 2 args to mark, got %v", fset.Position(n.Pos), len(n.Args)) 90 continue 91 } 92 ident, ok := n.Args[0].(expect.Identifier) 93 if !ok { 94 t.Errorf("%v: identifier, got %T", fset.Position(n.Pos), n.Args[0]) 95 continue 96 } 97 checkMarker(t, fset, readFile, markers, n.Pos, string(ident), n.Args[1]) 98 99 case n.Name == "check": 100 // A //@check(args, ...) note specifies some hypothetical action to 101 // be taken by the test driver and its expected outcome. 102 // In this test, the action is to compare the arguments 103 // against expectChecks. 104 if len(n.Args) < 1 { 105 t.Errorf("%v: expected 1 args to check, got %v", fset.Position(n.Pos), len(n.Args)) 106 continue 107 } 108 ident, ok := n.Args[0].(expect.Identifier) 109 if !ok { 110 t.Errorf("%v: identifier, got %T", fset.Position(n.Pos), n.Args[0]) 111 continue 112 } 113 args, ok := tt.expectChecks[string(ident)] 114 if !ok { 115 t.Errorf("%v: unexpected check %v", fset.Position(n.Pos), ident) 116 continue 117 } 118 if len(n.Args) != len(args)+1 { 119 t.Errorf("%v: expected %v args to check, got %v", fset.Position(n.Pos), len(args)+1, len(n.Args)) 120 continue 121 } 122 for i, got := range n.Args[1:] { 123 if args[i] != got { 124 t.Errorf("%v: arg %d expected %v, got %v", fset.Position(n.Pos), i, args[i], got) 125 } 126 } 127 default: 128 t.Errorf("Unexpected note %v at %v", n.Name, fset.Position(n.Pos)) 129 } 130 } 131 }) 132 } 133 } 134 135 func checkMarker(t *testing.T, fset *token.FileSet, readFile expect.ReadFile, markers map[string]token.Pos, pos token.Pos, name string, pattern interface{}) { 136 start, end, err := expect.MatchBefore(fset, readFile, pos, pattern) 137 if err != nil { 138 t.Errorf("%v: MatchBefore failed: %v", fset.Position(pos), err) 139 return 140 } 141 if start == token.NoPos { 142 t.Errorf("%v: Pattern %v did not match", fset.Position(pos), pattern) 143 return 144 } 145 expectStart, ok := markers[name] 146 if !ok { 147 t.Errorf("%v: unexpected marker %v", fset.Position(pos), name) 148 return 149 } 150 if start != expectStart { 151 t.Errorf("%v: Expected %v got %v", fset.Position(pos), fset.Position(expectStart), fset.Position(start)) 152 } 153 if expectEnd, ok := markers[name+"@"]; ok && end != expectEnd { 154 t.Errorf("%v: Expected end %v got %v", fset.Position(pos), fset.Position(expectEnd), fset.Position(end)) 155 } 156 }