Skip to content

Commit d21605e

Browse files
committed
Fixes splunk tests
1 parent 341c92c commit d21605e

File tree

6 files changed

+160
-44
lines changed

6 files changed

+160
-44
lines changed

tools/flakeguard/Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ test:
88
set -euo pipefail
99
go list ./... | grep -v 'example_test_package' | xargs go test -json -cover -coverprofile unit-test-coverage.out -v 2>&1 | tee /tmp/gotest.log | gotestfmt
1010

11+
.PHONY: test-race
12+
test-race:
13+
go list ./... | grep -v 'example_test_package' | xargs go test -count=1 -race
14+
15+
.PHONY: bench
16+
bench:
17+
go test -run=^$$ -bench=. -benchmem ./...
18+
1119
.PHONY: example
1220
example:
1321
rm -rf example_results

tools/flakeguard/cmd/aggregate_results.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ var AggregateResultsCmd = &cobra.Command{
6969
return fmt.Errorf("error aggregating test reports: %w", err)
7070
}
7171
s.Stop()
72-
log.Info().Msg("Successfully loaded and aggregated test reports")
72+
log.Debug().Msg("Successfully loaded and aggregated test reports")
7373

7474
// Start spinner for mapping test results to paths
7575
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
@@ -83,7 +83,7 @@ var AggregateResultsCmd = &cobra.Command{
8383
return fmt.Errorf("error mapping test results to paths: %w", err)
8484
}
8585
s.Stop()
86-
log.Info().Msg("Successfully mapped paths to test results")
86+
log.Debug().Msg("Successfully mapped paths to test results")
8787

8888
// Map test results to code owners if codeOwnersPath is provided
8989
if codeOwnersPath != "" {
@@ -97,7 +97,7 @@ var AggregateResultsCmd = &cobra.Command{
9797
return fmt.Errorf("error mapping test results to code owners: %w", err)
9898
}
9999
s.Stop()
100-
log.Info().Msg("Successfully mapped code owners to test results")
100+
log.Debug().Msg("Successfully mapped code owners to test results")
101101
}
102102

103103
failedTests := reports.FilterTests(aggregatedReport.Results, func(tr reports.TestResult) bool {
@@ -141,7 +141,7 @@ var AggregateResultsCmd = &cobra.Command{
141141
if err := reports.SaveReport(fs, failedTestsReportNoLogsPath, *failedReportWithLogs); err != nil {
142142
return fmt.Errorf("error saving failed tests report without logs: %w", err)
143143
}
144-
log.Info().Str("path", failedTestsReportNoLogsPath).Msg("Failed tests report without logs saved")
144+
log.Debug().Str("path", failedTestsReportNoLogsPath).Msg("Failed tests report without logs saved")
145145
} else {
146146
log.Debug().Msg("No failed tests found. Skipping generation of failed tests reports")
147147
}
@@ -158,25 +158,26 @@ var AggregateResultsCmd = &cobra.Command{
158158
if err := reports.SaveReport(fs, aggregatedReportPath, *aggregatedReport); err != nil {
159159
return fmt.Errorf("error saving aggregated test report: %w", err)
160160
}
161-
log.Info().Str("path", aggregatedReportPath).Msg("Aggregated test report saved")
161+
log.Debug().Str("path", aggregatedReportPath).Msg("Aggregated test report saved")
162162

163163
// Generate all-tests-summary.json
164+
var summaryFilePath string
164165
if summaryFileName != "" {
165166
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
166167
s.Suffix = " Generating summary json..."
167168
s.Start()
168169

169-
summaryFilePath := filepath.Join(outputDir, summaryFileName)
170+
summaryFilePath = filepath.Join(outputDir, summaryFileName)
170171
err = generateAllTestsSummaryJSON(aggregatedReport, summaryFilePath, maxPassRatio)
171172
if err != nil {
172173
s.Stop()
173174
return fmt.Errorf("error generating summary json: %w", err)
174175
}
175176
s.Stop()
176-
log.Info().Str("path", summaryFilePath).Msg("Summary generated")
177+
log.Debug().Str("path", summaryFilePath).Msg("Summary generated")
177178
}
178179

179-
log.Info().Msg("Aggregation complete")
180+
log.Info().Str("summary", summaryFilePath).Str("report", aggregatedReportPath).Msg("Aggregation complete")
180181
return nil
181182
},
182183
}

tools/flakeguard/cmd/run.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"os"
88
"os/exec"
99

10-
"github.com/rs/zerolog"
1110
"github.com/rs/zerolog/log"
1211
"github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard/reports"
1312
"github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard/runner"
@@ -106,8 +105,6 @@ var RunTestsCmd = &cobra.Command{
106105
}
107106

108107
func init() {
109-
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
110-
111108
RunTestsCmd.Flags().StringP("project-path", "r", ".", "The path to the Go project. Default is the current directory. Useful for subprojects")
112109
RunTestsCmd.Flags().String("test-packages-json", "", "JSON-encoded string of test packages")
113110
RunTestsCmd.Flags().StringSlice("test-packages", nil, "Comma-separated list of test packages to run")

tools/flakeguard/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package main
22

33
import (
44
"os"
5+
"time"
56

7+
"github.com/rs/zerolog"
8+
"github.com/rs/zerolog/log"
69
"github.com/spf13/cobra"
710

811
"github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard/cmd"
@@ -24,6 +27,11 @@ func Execute() {
2427
}
2528

2629
func init() {
30+
zerolog.TimeFieldFormat = time.RFC3339Nano
31+
log.Logger = log.Output(zerolog.ConsoleWriter{
32+
Out: os.Stderr,
33+
TimeFormat: "15:04:05.00", // hh:mm:ss.ss format
34+
})
2735
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
2836

2937
rootCmd.AddCommand(cmd.FindTestsCmd)

tools/flakeguard/reports/data.go

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,11 @@ type SummaryData struct {
6969
}
7070

7171
// SplunkEvent represents a customized splunk event string that helps us distinguish what
72-
// triggered the test to run
72+
// triggered the test to run. This is a custom field, different from the Splunk event field.
7373
type SplunkEvent string
7474

75-
// SplunkType represents what type of data is being sent to Splunk, e.g. a report or a result
75+
// SplunkType represents what type of data is being sent to Splunk, e.g. a report or a result.
76+
// This is a custom field to help us distinguish what kind of data we're sending.
7677
type SplunkType string
7778

7879
const (
@@ -82,6 +83,9 @@ const (
8283

8384
Report SplunkType = "report"
8485
Result SplunkType = "result"
86+
87+
// https://docs.splunk.com/Splexicon:Sourcetype
88+
SplunkSourceType = "flakeguard_json"
8589
)
8690

8791
// SplunkTestReport is the full wrapper structure sent to Splunk for the full test report (sans results)
@@ -182,10 +186,13 @@ func FilterTests(results []TestResult, predicate func(TestResult) bool) []TestRe
182186
}
183187

184188
func aggregate(reportChan <-chan *TestReport, errChan <-chan error, opts *aggregateOptions) (*TestReport, error) {
185-
testMap := make(map[string]TestResult)
186-
fullReport := &TestReport{}
187-
excludedTests := map[string]struct{}{}
188-
selectedTests := map[string]struct{}{}
189+
var (
190+
testMap = make(map[string]TestResult)
191+
fullReport = &TestReport{}
192+
excludedTests = map[string]struct{}{}
193+
selectedTests = map[string]struct{}{}
194+
sendToSplunk = opts.splunkURL != ""
195+
)
189196

190197
fullReport.ID = opts.reportID
191198
for report := range reportChan {
@@ -227,12 +234,12 @@ func aggregate(reportChan <-chan *TestReport, errChan <-chan error, opts *aggreg
227234
}
228235

229236
// Send report to Splunk before adding test results
230-
if opts.splunkURL != "" {
237+
if sendToSplunk {
231238
err := sendReportToSplunk(opts.splunkURL, opts.splunkToken, opts.splunkEvent, fullReport)
232239
if err != nil {
233240
log.Error().Err(err).Msg("Error sending report to Splunk")
234241
} else {
235-
log.Debug().Str("event", string(opts.splunkEvent)).Msg("Report sent to Splunk")
242+
log.Debug().Str("event", string(opts.splunkEvent)).Msg("Successfully sent report sent to Splunk")
236243
}
237244
}
238245

@@ -242,7 +249,7 @@ func aggregate(reportChan <-chan *TestReport, errChan <-chan error, opts *aggreg
242249
for _, r := range testMap {
243250
result := r
244251
aggregatedResults = append(aggregatedResults, result)
245-
if opts.splunkURL != "" {
252+
if sendToSplunk {
246253
eg.Go(func() error {
247254
return sendResultsToSplunk(opts.splunkURL, opts.splunkToken, opts.splunkEvent, result)
248255
})
@@ -252,10 +259,12 @@ func aggregate(reportChan <-chan *TestReport, errChan <-chan error, opts *aggreg
252259
sortTestResults(aggregatedResults)
253260
fullReport.Results = aggregatedResults
254261

255-
if splunkErr := eg.Wait(); splunkErr != nil {
256-
log.Error().Err(splunkErr).Msg("Error sending results to Splunk")
257-
} else {
258-
log.Debug().Str("event", string(opts.splunkEvent)).Msg("All results sent to Splunk")
262+
if sendToSplunk {
263+
if splunkErr := eg.Wait(); splunkErr != nil {
264+
log.Error().Err(splunkErr).Msg("Error sending results to Splunk")
265+
} else {
266+
log.Debug().Str("event", string(opts.splunkEvent)).Msg("Successfully sent results to Splunk")
267+
}
259268
}
260269
return fullReport, nil
261270
}
@@ -273,7 +282,7 @@ func sendReportToSplunk(url, token string, event SplunkEvent, report *TestReport
273282
Type: Report,
274283
Data: *report,
275284
},
276-
SourceType: "flakeguard_json",
285+
SourceType: SplunkSourceType,
277286
}).
278287
Post(url)
279288
if err != nil {
@@ -301,7 +310,7 @@ func sendResultsToSplunk(url, token string, event SplunkEvent, results ...TestRe
301310
Type: Result,
302311
Data: result,
303312
},
304-
SourceType: "flakeguard_json",
313+
SourceType: SplunkSourceType,
305314
}).
306315
Post(url)
307316
if err != nil {

tools/flakeguard/reports/io_test.go

Lines changed: 111 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,45 @@ import (
88
"net/http/httptest"
99
"testing"
1010

11+
"github.com/rs/zerolog"
1112
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
1314
)
1415

1516
const (
16-
splunkToken = "test-token"
17-
numberReports = 3
18-
reportID = "123"
19-
testsRun = 15
17+
splunkToken = "test-token"
18+
splunkEvent SplunkEvent = "test"
19+
numberReports = 3
20+
reportID = "123"
21+
testRunCount = 15
22+
uniqueTests = 18
2023
)
2124

2225
func TestAggregateResultsSplunk(t *testing.T) {
26+
t.Parallel()
27+
2328
srv := splunkServer(t)
2429
t.Cleanup(srv.Close)
2530

26-
report, err := LoadAndAggregate("./testdata", WithReportID(reportID), WithSplunk(srv.URL, splunkToken, "test"))
31+
report, err := LoadAndAggregate("./testdata", WithReportID(reportID), WithSplunk(srv.URL, splunkToken, splunkEvent))
2732
require.NoError(t, err, "LoadAndAggregate failed")
28-
require.NotNil(t, report, "report is nil")
33+
verifyAggregatedReport(t, report)
2934
}
3035

3136
func TestAggregateResults(t *testing.T) {
37+
t.Parallel()
38+
3239
report, err := LoadAndAggregate("./testdata", WithReportID(reportID))
3340
require.NoError(t, err, "LoadAndAggregate failed")
34-
require.NotNil(t, report, "report is nil")
35-
assert.Equal(t, reportID, report.ID, "report ID mismatch")
36-
assert.Equal(t, testsRun, len(report.Results), "report results count mismatch")
37-
assert.Equal(t, testsRun, report.TestRunCount, "report test run count mismatch")
41+
verifyAggregatedReport(t, report)
3842
}
3943

4044
func splunkServer(t *testing.T) *httptest.Server {
4145
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
42-
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
43-
assert.Equal(t, fmt.Sprintf("Splunk %s", splunkToken), r.Header.Get("Authorization"))
46+
require.Equal(t, "application/json", r.Header.Get("Content-Type"), "unexpected content type")
47+
require.Equal(t, fmt.Sprintf("Splunk %s", splunkToken), r.Header.Get("Authorization"), "unexpected authorization header")
4448

45-
// Figure out what the payload is
49+
// Figure out what kind of splunk data the payload is
4650
bodyBytes, err := io.ReadAll(r.Body)
4751
require.NoError(t, err)
4852
defer r.Body.Close()
@@ -59,22 +63,111 @@ func splunkServer(t *testing.T) *httptest.Server {
5963
require.NotNil(t, eventType, "error parsing splunk event type")
6064

6165
if eventType == string(Report) {
62-
var report TestReport
66+
var report SplunkTestReport
6367
err := json.Unmarshal(bodyBytes, &report)
6468
require.NoError(t, err, "error parsing report data")
6569
require.NotNil(t, report, "error parsing report data")
66-
assert.Equal(t, reportID, report.ID, "report ID mismatch")
67-
assert.Equal(t, testsRun, len(report.Results), "report results count mismatch")
68-
assert.Equal(t, testsRun, report.TestRunCount, "report test run count mismatch")
70+
assert.Equal(t, SplunkSourceType, report.SourceType, "source type mismatch")
71+
assert.Equal(t, splunkEvent, report.Event.Event, "event mismatch")
72+
assert.Equal(t, reportID, report.Event.Data.ID, "ID mismatch")
6973
} else if eventType == string(Result) {
7074
var result SplunkTestResult
7175
err := json.Unmarshal(bodyBytes, &result)
7276
require.NoError(t, err, "error parsing results data")
7377
require.NotNil(t, result, "error parsing results data")
78+
assert.Equal(t, SplunkSourceType, result.SourceType, "source type mismatch")
79+
assert.Equal(t, splunkEvent, result.Event.Event, "event mismatch")
7480
} else {
75-
t.Errorf("unexpected event type: %s", eventType)
81+
t.Errorf("unexpected splunk event type: %s", eventType)
82+
}
83+
84+
w.WriteHeader(http.StatusOK)
85+
}))
86+
}
87+
88+
func verifyAggregatedReport(t *testing.T, report *TestReport) {
89+
require.NotNil(t, report, "report is nil")
90+
assert.Equal(t, reportID, report.ID, "report ID mismatch")
91+
assert.Equal(t, uniqueTests, len(report.Results), "report results count mismatch")
92+
assert.Equal(t, testRunCount, report.TestRunCount, "report test run count mismatch")
93+
assert.Equal(t, false, report.RaceDetection, "race detection should be false")
94+
95+
var (
96+
testFail, testSkipped, testPass TestResult
97+
testFailName = "TestFail"
98+
testSkippedName = "TestSkipped"
99+
testPassName = "TestPass"
100+
)
101+
for _, result := range report.Results {
102+
if result.TestName == testFailName {
103+
testFail = result
76104
}
105+
if result.TestName == testSkippedName {
106+
testSkipped = result
107+
}
108+
if result.TestName == testPassName {
109+
testPass = result
110+
}
111+
}
112+
113+
t.Run("verify TestFail", func(t *testing.T) {
114+
t.Parallel()
115+
116+
require.Equal(t, testFailName, testFail.TestName, "TestFail not found")
117+
assert.False(t, testFail.Panic, "TestFail should not panic")
118+
assert.False(t, testFail.Skipped, "TestFail should not be skipped")
119+
assert.Equal(t, testRunCount, testFail.Runs, "TestFail should run every time")
120+
assert.Zero(t, testFail.Skips, "TestFail should not be skipped")
121+
assert.Equal(t, testRunCount, testFail.Failures, "TestFail should fail every time")
122+
assert.Len(t, testFail.Durations, testRunCount, "TestFail should have durations")
123+
})
124+
125+
t.Run("verify TestSkipped", func(t *testing.T) {
126+
t.Parallel()
127+
128+
require.Equal(t, testSkippedName, testSkipped.TestName, "TestSkip not found")
129+
assert.False(t, testSkipped.Panic, "TestSkipped should not panic")
130+
assert.Zero(t, testSkipped.Runs, "TestSkipped should not pass")
131+
assert.True(t, testSkipped.Skipped, "TestSkipped should be skipped")
132+
assert.Equal(t, testRunCount, testSkipped.Skips, "TestSkipped should be skipped entirely")
133+
assert.Empty(t, testSkipped.Durations, "TestSkipped should not have durations")
134+
})
135+
136+
t.Run("verify TestPass", func(t *testing.T) {
137+
t.Parallel()
77138

139+
require.Equal(t, testPassName, testPass.TestName, "TestPass not found")
140+
assert.False(t, testPass.Panic, "TestPass should not panic")
141+
assert.Equal(t, testRunCount, testPass.Runs, "TestPass should run every time")
142+
assert.False(t, testPass.Skipped, "TestPass should not be skipped")
143+
assert.Zero(t, testPass.Skips, "TestPass should not be skipped")
144+
assert.Equal(t, testRunCount, testPass.Successes, "TestPass should pass every time")
145+
assert.Len(t, testPass.Durations, testRunCount, "TestPass should have durations")
146+
})
147+
}
148+
149+
func BenchmarkTestAggregateResults(b *testing.B) {
150+
zerolog.SetGlobalLevel(zerolog.Disabled)
151+
for i := 0; i < b.N; i++ {
152+
_, err := LoadAndAggregate("./testdata", WithReportID(reportID))
153+
if err != nil {
154+
b.Fatalf("LoadAndAggregate failed: %v", err)
155+
}
156+
}
157+
}
158+
159+
func BenchmarkTestAggregateResultsSplunk(b *testing.B) {
160+
zerolog.SetGlobalLevel(zerolog.Disabled)
161+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
78162
w.WriteHeader(http.StatusOK)
79163
}))
164+
defer srv.Close()
165+
166+
b.ResetTimer()
167+
for i := 0; i < b.N; i++ {
168+
_, err := LoadAndAggregate("./testdata", WithReportID(reportID), WithSplunk(srv.URL, splunkToken, "test"))
169+
if err != nil {
170+
b.Fatalf("LoadAndAggregate failed: %v", err)
171+
}
172+
}
80173
}

0 commit comments

Comments
 (0)