-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmain.go
148 lines (122 loc) · 4.14 KB
/
main.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package main
import (
"errors"
"flag"
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"time"
"gopkg.in/yaml.v3"
)
const (
timeLayout = "Jan 2, 2006 at 3:04pm (UTC)"
readmeMarkdownFilename = "README.md"
resultsMarkdownFilename = "RESULTS.md"
)
var (
waitRunDur = flag.Duration("wait-run", 3*time.Second, "wait time between tests")
testsFile = flag.String("i", "./tests.yml", "yaml file path contains the tests to run")
outputDir = flag.String("o", "./", "directory to save generaged Markdown and CSV files")
enableREADMEOutput = flag.Bool("readme", false, "to generate a README.md file near the RESULTS.md")
spreadsheetID = flag.String("g-spreadsheet", "", "Google Spreadsheet ID to send results")
// Note: we can support user credentials and token generated by user's input
// and saved on disk at first ran (kataras/sheets already supports it)
// but let's accept only a service account unless otherwise requested.
googleSecretFile = flag.String("g-secret", "client_secret.json", "if g-spreadsheet is set, service account credentials file should be provided")
)
// server-benchmarks --wait-run=3s -i ./tests.dev.yml -o ./dev -g-spreadsheet $GoogleSpreadsheetID -g-secret client_secret.json
func main() {
var specificTests stringSlice
flag.Var(&specificTests, "t", "run only specific tests by their names") // support multiple -t flags.
flag.Parse()
if _, err := os.Stat("/.dockerenv"); err == nil || os.IsExist(err) {
fmt.Fprintf(os.Stdout, "Running through docker container...")
}
tests, err := readTests(*testsFile)
catch(err)
tests = filterTests(specificTests, tests...)
// TESTS
for _, t := range tests {
err = benchmark(t)
catch(err)
}
cleanup()
err = os.MkdirAll(*outputDir, 0777)
catch(err)
filename := filepath.Join(*outputDir, resultsMarkdownFilename)
err = writeResults(filename, *spreadsheetID, *googleSecretFile, tests)
catch(err)
fmt.Fprintf(os.Stdout, "Generate: %s\n", filename)
if *enableREADMEOutput {
filename = filepath.Join(*outputDir, readmeMarkdownFilename)
err = writeReadme(filename, tests)
catch(err)
fmt.Fprintf(os.Stdout, "Generate: %s\n", filename)
}
}
func readTests(filename string) ([]*Test, error) {
testsFile, err := os.OpenFile(filename, os.O_RDONLY, 0644)
if err != nil {
return nil, err
}
var tests []*Test
if err = yaml.NewDecoder(testsFile).Decode(&tests); err != nil {
return nil, err
}
if err = testsFile.Close(); err != nil {
return nil, err
}
if len(tests) == 0 {
return nil, fmt.Errorf("no tests to run")
}
return tests, nil
}
func filterTests(specificTests stringSlice, tests ...*Test) []*Test {
if len(specificTests) == 0 {
return tests
}
testsAndEnvsToKeep := make(map[string][]string, len(specificTests))
for _, specificTest := range specificTests {
if specificTestName := strings.ToLower(specificTest); specificTestName != "" {
specificTestEnvName := ""
if dotParts := strings.Split(specificTestName, "."); len(dotParts) > 1 {
specificTestName = strings.Join(dotParts[0:len(dotParts)-1], ".") // name all except last dot.
specificTestEnvName = dotParts[len(dotParts)-1]
}
testsAndEnvsToKeep[specificTestName] = append(testsAndEnvsToKeep[specificTestName], specificTestEnvName)
}
}
// Delete all tests and envs that are not in the specificTests list.
return slices.DeleteFunc(tests, func(t *Test) bool {
// keep only the specific test.
testName := strings.ToLower(t.Name)
if specificTestEnvNames, ok := testsAndEnvsToKeep[testName]; ok {
// keep only the specific test's environment.
// E.g. -t rest.iris -t rest.iris-private
if len(specificTestEnvNames) > 0 {
t.Envs = slices.DeleteFunc(t.Envs, func(e *TestEnv) bool {
return !slices.Contains(specificTestEnvNames, strings.ToLower(e.GetName()))
})
}
return false
}
return true
})
}
func cleanup() {
for i, f := range downloadedFiles {
if err := os.Remove(f); err != nil && !errors.Is(err, os.ErrNotExist) {
fmt.Fprintf(os.Stdout, "remove: %v\n", err)
}
// delete slice element.
downloadedFiles = append(downloadedFiles[:i], downloadedFiles[i+1:]...)
}
}
func catch(err error) {
if err != nil {
cleanup()
panic(err)
}
}