Skip to content

Commit 42e3fb5

Browse files
committed
Basic test skips
1 parent ee8bccc commit 42e3fb5

File tree

3 files changed

+122
-10
lines changed

3 files changed

+122
-10
lines changed

tools/flakeguard/cmd/make_pr.go

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/go-git/go-git/v5"
1010
"github.com/go-git/go-git/v5/plumbing"
1111
"github.com/google/go-github/v72/github"
12+
"github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard/golang"
1213
"github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard/localdb"
1314
"github.com/spf13/cobra"
1415
"golang.org/x/oauth2"
@@ -36,34 +37,39 @@ func makePR(cmd *cobra.Command, args []string) error {
3637
return err
3738
}
3839

39-
entries := db.GetAllEntries()
40+
currentlyFlakyEntries := db.GetAllCurrentlyFlakyEntries()
4041

4142
branchName := fmt.Sprintf("flakeguard-skip-%s", time.Now().Format("20060102150405"))
42-
w, err := repo.Worktree()
43+
targetRepoWorktree, err := repo.Worktree()
4344
if err != nil {
4445
return err
4546
}
46-
err = w.Checkout(&git.CheckoutOptions{
47+
err = targetRepoWorktree.Checkout(&git.CheckoutOptions{
4748
Branch: plumbing.NewBranchReferenceName(branchName),
4849
Create: true,
4950
})
5051
if err != nil {
5152
return err
5253
}
5354

54-
for _, entry := range entries {
55-
// Find the test function in the codebase and skip it
56-
57-
entry.SkippedAt = time.Now()
58-
db.UpsertEntry(entry.TestPackage, entry.TestName, entry.JiraTicket, entry.SkippedAt, entry.AssigneeID)
55+
testsToSkip := []golang.SkipTest{}
56+
for _, entry := range currentlyFlakyEntries {
57+
testsToSkip = append(testsToSkip, golang.SkipTest{
58+
Package: entry.TestPackage,
59+
Name: entry.TestName,
60+
})
61+
}
5962

63+
err = golang.SkipTests(repoPath, testsToSkip)
64+
if err != nil {
65+
return err
6066
}
6167

62-
_, err = w.Add(".")
68+
_, err = targetRepoWorktree.Add(".")
6369
if err != nil {
6470
return err
6571
}
66-
_, err = w.Commit("Skips flaky tests", &git.CommitOptions{})
72+
_, err = targetRepoWorktree.Commit("Skips flaky tests", &git.CommitOptions{})
6773
if err != nil {
6874
return err
6975
}

tools/flakeguard/golang/golang.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ import (
55
"bytes"
66
"encoding/json"
77
"fmt"
8+
"go/ast"
9+
"go/parser"
10+
"go/printer"
11+
"go/token"
12+
"os"
813
"os/exec"
14+
"path/filepath"
915
"strings"
1016

1117
"github.com/rs/zerolog/log"
@@ -197,3 +203,89 @@ func FilterPackagesWithTests(pkgs []string) []string {
197203
}
198204
return testPkgs
199205
}
206+
207+
// SkipTest is a struct that contains the package and name of the test to skip
208+
type SkipTest struct {
209+
Package string
210+
Name string
211+
}
212+
213+
// SkipTests finds all package/test pairs provided and skips them
214+
func SkipTests(repoPath string, testsToSkip []SkipTest) error {
215+
for _, testToSkip := range testsToSkip {
216+
cmd := exec.Command("go", "list", "-json", testToSkip.Package)
217+
out, err := cmd.CombinedOutput()
218+
if err != nil {
219+
return fmt.Errorf("error getting package path for %s: %w", testToSkip.Package, err)
220+
}
221+
packagePath := strings.TrimSpace(string(out))
222+
log.Debug().Str("package", testToSkip.Package).Str("test", testToSkip.Name).Str("packagePath", packagePath).Msg("Skipping test")
223+
224+
err = filepath.Walk(filepath.Join(repoPath, packagePath), func(path string, info os.FileInfo, err error) error {
225+
if err != nil {
226+
return err
227+
}
228+
if info.IsDir() || !strings.HasSuffix(info.Name(), "_test.go") {
229+
return nil
230+
}
231+
232+
fset := token.NewFileSet()
233+
fileAst, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
234+
if err != nil {
235+
return err
236+
}
237+
238+
found := false
239+
ast.Inspect(fileAst, func(n ast.Node) bool {
240+
fn, ok := n.(*ast.FuncDecl)
241+
if !ok || fn.Name.Name != testToSkip.Name {
242+
return true
243+
}
244+
// Check if first parameter is *testing.T
245+
if fn.Type.Params != nil && len(fn.Type.Params.List) > 0 {
246+
param := fn.Type.Params.List[0]
247+
if starExpr, ok := param.Type.(*ast.StarExpr); ok {
248+
if sel, ok := starExpr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == "T" {
249+
// Insert t.Skip as first statement
250+
skipStmt := &ast.ExprStmt{
251+
X: &ast.CallExpr{
252+
Fun: &ast.SelectorExpr{
253+
X: ast.NewIdent(param.Names[0].Name),
254+
Sel: ast.NewIdent("Skip"),
255+
},
256+
Args: []ast.Expr{
257+
&ast.BasicLit{
258+
Kind: token.STRING,
259+
Value: "\"skipped by flakeguard\"",
260+
},
261+
},
262+
},
263+
}
264+
fn.Body.List = append([]ast.Stmt{skipStmt}, fn.Body.List...)
265+
found = true
266+
return false // stop
267+
}
268+
}
269+
}
270+
return true
271+
})
272+
273+
if found {
274+
// Write back the file
275+
var out strings.Builder
276+
if err := printer.Fprint(&out, fset, fileAst); err != nil {
277+
return err
278+
}
279+
if err := os.WriteFile(path, []byte(out.String()), info.Mode()); err != nil {
280+
return err
281+
}
282+
return filepath.SkipDir // stop walking
283+
}
284+
return fmt.Errorf("test function %s not found in package %s", testToSkip.Name, testToSkip.Package)
285+
})
286+
if err != nil {
287+
return err
288+
}
289+
}
290+
return nil
291+
}

tools/flakeguard/localdb/localdb.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,20 @@ func (db *DB) GetAllEntries() []Entry {
202202
return entries
203203
}
204204

205+
// GetAllCurrentlyFlakyEntries returns all entries that currently have an open Jira ticket
206+
// for being a flaky test.
207+
func (db *DB) GetAllCurrentlyFlakyEntries() []Entry {
208+
db.mu.RLock()
209+
defer db.mu.RUnlock()
210+
entries := make([]Entry, 0, len(db.data))
211+
for _, entry := range db.data {
212+
if entry.JiraTicket != "" {
213+
entries = append(entries, entry)
214+
}
215+
}
216+
return entries
217+
}
218+
205219
// DefaultDBPath returns the default DB file path in the user's home directory.
206220
// Renamed from getDefaultDBPath to be exported.
207221
// If the user's home directory cannot be determined, it falls back to the current directory.

0 commit comments

Comments
 (0)