Atlas › Test

TestProcessDir

Exact test identity: go.temporal.io/server/tools/parallelize/TestProcessDir

Package
go.temporal.io/server/tools/parallelize
Suite / test hierarchy
TestProcessDir
Test
TestProcessDir
Introduced at
parallelize.go ×2 Frontier kind: Joint frontier
Covered ranges
33
Covered lines
83
Covered files
1

Covered source

Expand a file to inspect source; the > gutter marks covered lines.

go.temporal.io/server/tools/parallelize/parallelize.go 83 covered LOC · 33 ranges

Open complete file

31 }
32
33 > func processDir(dir string) error { parallelize.go
34 > return filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
35 > if err != nil {
36 return err
37 }
38 > if d.IsDir() || !strings.HasSuffix(path, "_test.go") { parallelize.go
39 > return nil
40 > }
41 > return processFile(path)
42 })
43 }
44
45 > func processFile(path string) error { parallelize.go
46 > fset := token.NewFileSet()
47 > f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
48 > if err != nil {
49 return fmt.Errorf("parse %s: %w", path, err)
50 }
52 // Collect line numbers where we need to insert t.Parallel().
53 // Each entry is the line of the opening '{' of the test function body.
54 > type insertion struct { parallelize.go
55 > line int // line number of the '{' opening the function body
56 > paramName string // name of the *testing.T parameter
57 > }
58 > var insertions []insertion
59 >
60 > for _, decl := range f.Decls {
61 > fn, ok := decl.(*ast.FuncDecl)
62 > if !ok {
63 > continue
64 }
65 > if !isTestFunc(fn) { parallelize.go
66 continue
67 }
68 > paramName := testingTParamName(fn) parallelize.go
69 > if paramName == "" {
70 continue
71 }
72 > if hasParallelCall(fn.Body, paramName) { parallelize.go
73 continue
74 }
75 > if hasNoLintComment(fn) { parallelize.go
76 continue
77 }
78 > bodyLine := fset.Position(fn.Body.Lbrace).Line parallelize.go
79 > insertions = append(insertions, insertion{line: bodyLine, paramName: paramName})
80 }
81
82 > if len(insertions) == 0 { parallelize.go
83 return nil
84 }
85
86 // Sort by line descending so insertions don't shift line numbers of subsequent insertions.
87 > sort.Slice(insertions, func(i, j int) bool { parallelize.go
88 return insertions[i].line > insertions[j].line
89 })
90
91 > fi, err := os.Stat(path) parallelize.go
92 > if err != nil {
93 return fmt.Errorf("stat %s: %w", path, err)
94 }
95
96 > src, err := os.ReadFile(path) parallelize.go
97 > if err != nil {
98 return fmt.Errorf("read %s: %w", path, err)
99 }
100
101 > lines := strings.Split(string(src), "\n") parallelize.go
102 > for _, ins := range insertions {
103 > // ins.line is 1-indexed, so it conveniently equals the 0-based index
104 > // of the line right after '{', which is where we want to insert.
105 > idx := ins.line
106 > newLine := "\t" + ins.paramName + ".Parallel()"
107 > lines = append(lines[:idx+1], lines[idx:]...)
108 > lines[idx] = newLine
109 > }
110
111 > if err := os.WriteFile(path, []byte(strings.Join(lines, "\n")), fi.Mode()); err != nil { parallelize.go
112 return fmt.Errorf("write %s: %w", path, err)
113 }
114
115 > fmt.Printf("parallelize: %s\n", path) parallelize.go
116 > return nil
117 }
118
119 // isTestFunc returns true for func TestXxx(t *testing.T).
120 > func isTestFunc(fn *ast.FuncDecl) bool { parallelize.go
121 > if fn.Recv != nil {
122 return false // method, not a function
123 }
124 > if !strings.HasPrefix(fn.Name.Name, "Test") { parallelize.go
125 return false
126 }
127 > if fn.Body == nil { parallelize.go
128 return false
129 }
130 > return testingTParamName(fn) != "" parallelize.go
131 }
132
133 // testingTParamName returns the name of the *testing.T parameter, or "" if not found.
134 > func testingTParamName(fn *ast.FuncDecl) string { parallelize.go
135 > if fn.Type.Params == nil || len(fn.Type.Params.List) == 0 {
136 return ""
137 }
138 > for _, field := range fn.Type.Params.List { parallelize.go
139 > starExpr, ok := field.Type.(*ast.StarExpr)
140 > if !ok {
141 continue
142 }
143 > selExpr, ok := starExpr.X.(*ast.SelectorExpr) parallelize.go
144 > if !ok {
145 continue
146 }
147 > pkg, ok := selExpr.X.(*ast.Ident) parallelize.go
148 > if !ok {
149 continue
150 }
151 > if pkg.Name == "testing" && selExpr.Sel.Name == "T" { parallelize.go
152 > if len(field.Names) > 0 {
153 > return field.Names[0].Name
154 > }
155 }
156 }
159
160 // hasNoLintComment checks for //parallelize:ignore in the function's doc comment.
161 > func hasNoLintComment(fn *ast.FuncDecl) bool { parallelize.go
162 > if fn.Doc == nil {
163 > return false parallelize.go
164 > }
165 for _, c := range fn.Doc.List {
166 if strings.Contains(c.Text, "parallelize:ignore") {
172
173 // hasParallelCall checks if the function body already contains <param>.Parallel().
174 > func hasParallelCall(body *ast.BlockStmt, paramName string) bool { parallelize.go
175 > found := false
176 > ast.Inspect(body, func(n ast.Node) bool {
177 > if found {
178 return false
179 }
180 > call, ok := n.(*ast.CallExpr) parallelize.go
181 > if !ok {
182 > return true
183 > }
184 > sel, ok := call.Fun.(*ast.SelectorExpr)
185 > if !ok {
186 return true
187 }
188 > ident, ok := sel.X.(*ast.Ident) parallelize.go
189 > if !ok {
190 return true
191 }
192 > if ident.Name == paramName && sel.Sel.Name == "Parallel" { parallelize.go
193 found = true
194 }
195 > return true parallelize.go
196 })
197 > return found parallelize.go
198 }