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