-
Notifications
You must be signed in to change notification settings - Fork 0
/
listtests.go
127 lines (109 loc) · 2.69 KB
/
listtests.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"sort"
"strings"
"log"
)
var reLine = regexp.MustCompile("^\\s*(\\w+)\\s+(\\w+)\\s+(.+)$")
func main() {
log.SetFlags(0)
dir := flag.String("dir", "", "the directory that contains the binary; if empty, the same as the first argument")
prefix := flag.String("prefix", "", "the function prefix to scan for; if not specified will use *<dirBasename>.Test*")
help := flag.Bool("help", false, "display help")
flag.Parse()
if *help {
flag.PrintDefaults()
return
}
args := flag.Args()
if len(args) == 0 {
log.Fatalf("Must specify the name of a single directory, e.g. ./test/integration")
}
path := args[0]
_ = args[1:]
base := filepath.Base(path)
execDir := path
if len(*dir) > 0 {
execDir = *dir
}
pkg := filepath.Join(execDir, fmt.Sprintf("%s.test", base))
test, err := filepath.Abs(pkg)
if err != nil {
log.Fatalf("Unable to make path %q absolute: %v", execDir, err)
}
if _, err := os.Stat(test); err != nil {
log.Fatalf("No test executable %q exits, did you run `go test -c` on the named package?", test)
}
cmd := exec.Command("go", "tool", "nm", "-sort", "name", "-n", test)
out, err := cmd.CombinedOutput()
if err != nil {
log.Fatalf("Can't get `go tool nm` output from %q: %v", test, err)
}
names := []string{}
scanner := bufio.NewScanner(bytes.NewReader(out))
for scanner.Scan() {
line := scanner.Text()
match := reLine.FindStringSubmatch(line)
if len(match) == 0 {
//log.Printf("mismatch: %s", line)
continue
}
// ignore non code segments
if match[2] != "t" && match[2] != "T" {
// log.Printf("non-code line: %s",line)
continue
}
name := match[3]
// there are always two segments per function, ignore the extra one
if strings.HasSuffix(name, ".f") {
continue
}
segments := strings.SplitAfter(name, "/")
// expect a package and name
if len(segments) < 2 {
//log.Printf("root_package: %s", name)
continue
}
last := segments[len(segments)-1]
_ = segments[len(segments)-2]
// two parts
parts := strings.Split(last, ".")
if len(parts) != 2 {
//log.Printf("bad_name: %s", last)
continue
}
if parts[0] != base {
//log.Printf("ignore: %s", last)
continue
}
test := parts[1]
if len(*prefix) == 0 {
if !strings.HasPrefix(test, "Test") {
continue
}
} else {
if !strings.HasPrefix(name, *prefix) {
continue
}
}
names = append(names, test)
}
if len(names) == 0 {
log.Fatalf("No tests found!")
}
sort.Sort(sort.StringSlice(names))
for _, test := range names {
fmt.Printf("%s\n", test)
}
if err := scanner.Err(); err != nil {
log.Fatalf("Unable to scan the symbol output: %v", err)
}
}