1
2
3
4
5
6
7 package errorstest
8
9 import (
10 "bytes"
11 "fmt"
12 "go/ast"
13 "go/parser"
14 "go/token"
15 "internal/testenv"
16 "os"
17 "os/exec"
18 "path/filepath"
19 "strings"
20 "testing"
21 )
22
23 type ShortPosition struct {
24 Line int
25 Column int
26 Visited bool
27 }
28
29 type IdentPositionInfo map[string][]ShortPosition
30
31 type Visitor struct {
32 identPosInfo IdentPositionInfo
33 fset *token.FileSet
34 t *testing.T
35 }
36
37 func (v *Visitor) Visit(node ast.Node) ast.Visitor {
38 if ident, ok := node.(*ast.Ident); ok {
39 if expectedPositions, ok := v.identPosInfo[ident.Name]; ok {
40 gotMatch := false
41 var errorMessage strings.Builder
42 for caseIndex, expectedPos := range expectedPositions {
43 actualPosition := v.fset.PositionFor(ident.Pos(), true)
44 errorOccurred := false
45 if expectedPos.Line != actualPosition.Line {
46 fmt.Fprintf(&errorMessage, "wrong line number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Line, actualPosition.Line)
47 errorOccurred = true
48 }
49 if expectedPos.Column != actualPosition.Column {
50 fmt.Fprintf(&errorMessage, "wrong column number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Column, actualPosition.Column)
51 errorOccurred = true
52 }
53 if errorOccurred {
54 continue
55 }
56 gotMatch = true
57 expectedPositions[caseIndex].Visited = true
58 }
59
60 if !gotMatch {
61 v.t.Error(errorMessage.String())
62 }
63 }
64 }
65 return v
66 }
67
68 func TestArgumentsPositions(t *testing.T) {
69 testenv.MustHaveCGO(t)
70 testenv.MustHaveExec(t)
71
72 testdata, err := filepath.Abs("testdata")
73 if err != nil {
74 t.Fatal(err)
75 }
76
77 tmpPath := t.TempDir()
78
79 dir := filepath.Join(tmpPath, "src", "testpositions")
80 if err := os.MkdirAll(dir, 0755); err != nil {
81 t.Fatal(err)
82 }
83
84 cmd := exec.Command("go", "tool", "cgo",
85 "-srcdir", testdata,
86 "-objdir", dir,
87 "issue42580.go")
88 cmd.Stderr = new(bytes.Buffer)
89
90 err = cmd.Run()
91 if err != nil {
92 t.Fatalf("%s: %v\n%s", cmd, err, cmd.Stderr)
93 }
94 mainProcessed, err := os.ReadFile(filepath.Join(dir, "issue42580.cgo1.go"))
95 if err != nil {
96 t.Fatal(err)
97 }
98 fset := token.NewFileSet()
99 f, err := parser.ParseFile(fset, "", mainProcessed, parser.AllErrors)
100 if err != nil {
101 fmt.Println(err)
102 return
103 }
104
105 expectation := IdentPositionInfo{
106 "checkedPointer": []ShortPosition{
107 ShortPosition{
108 Line: 32,
109 Column: 56,
110 },
111 },
112 "singleInnerPointerChecked": []ShortPosition{
113 ShortPosition{
114 Line: 37,
115 Column: 91,
116 },
117 },
118 "doublePointerChecked": []ShortPosition{
119 ShortPosition{
120 Line: 42,
121 Column: 91,
122 },
123 },
124 }
125 for _, decl := range f.Decls {
126 if fdecl, ok := decl.(*ast.FuncDecl); ok {
127 ast.Walk(&Visitor{expectation, fset, t}, fdecl.Body)
128 }
129 }
130 for ident, positions := range expectation {
131 for _, position := range positions {
132 if !position.Visited {
133 t.Errorf("Position %d:%d missed for %s ident", position.Line, position.Column, ident)
134 }
135 }
136 }
137 }
138
View as plain text