Skip to content

Commit 530a75d

Browse files
committed
Merge branch 'main' into havoc-examples
2 parents 85380a9 + 99204e1 commit 530a75d

File tree

17 files changed

+779
-565
lines changed

17 files changed

+779
-565
lines changed

lib/.changeset/v1.51.0.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Allows for EVMClient to Poll for headers when not using WS
2+
- Adds InitializeHeaderSubscription method

parrot/.changeset/v0.3.0.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
- Changed underlying parrot router to use chi: https://github.com/go-chi/chi
2+
- Enables usage of wildcards and more stable routing with less code
3+
4+
### Before Bench
5+
6+
```sh
7+
goos: darwin
8+
goarch: arm64
9+
pkg: github.com/smartcontractkit/chainlink-testing-framework/parrot
10+
cpu: Apple M3 Max
11+
BenchmarkRegisterRoute-14 3014044 432.6 ns/op
12+
BenchmarkRouteResponse-14 16904 66540 ns/op
13+
BenchmarkSave-14 6507 177113 ns/op
14+
BenchmarkLoad-14 1258 937961 ns/op
15+
```
16+
17+
### After Bench
18+
19+
```sh
20+
goos: darwin
21+
goarch: arm64
22+
pkg: github.com/smartcontractkit/chainlink-testing-framework/parrot
23+
cpu: Apple M3 Max
24+
BenchmarkRegisterRoute-14 2144967 605.9 ns/op
25+
BenchmarkRouteResponse-14 18518 63014 ns/op
26+
BenchmarkGetRoutes-14 14031 262574 ns/op
27+
BenchmarkSave-14 6404 185332 ns/op
28+
BenchmarkLoad-14 1012 1170008 ns/op
29+
```

parrot/Makefile

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# Default test log level (can be overridden)
1+
# Default test log level is none
22
PARROT_TEST_LOG_LEVEL ?= ""
3-
4-
# Pass TEST_LOG_LEVEL as a flag to go test
53
TEST_ARGS ?= -testLogLevel=$(PARROT_TEST_LOG_LEVEL)
64

5+
TEST_TIMEOUT ?= 30s
6+
77
.PHONY: lint
88
lint:
99
golangci-lint --color=always run ./... --fix -v
@@ -12,26 +12,28 @@ lint:
1212
test:
1313
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
1414
set -euo pipefail
15-
go test $(TEST_ARGS) -json -cover -coverprofile cover.out -v ./... 2>&1 | tee /tmp/gotest.log | gotestfmt
15+
go test $(TEST_ARGS) -json -timeout $(TEST_TIMEOUT) -cover -coverprofile cover.out -v ./... 2>&1 | tee /tmp/gotest.log | gotestfmt
1616

1717
.PHONY: test_race
1818
test_race:
1919
go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
2020
set -euo pipefail
21-
go test $(TEST_ARGS) -json -cover -count=1 -race -coverprofile cover.out -v ./... 2>&1 | tee /tmp/gotest.log | gotestfmt
21+
go test $(TEST_ARGS) -json -timeout $(TEST_TIMEOUT) -cover -count=1 -race -coverprofile cover.out -v ./... 2>&1 | tee /tmp/gotest.log | gotestfmt
22+
2223

2324
.PHONY: test_unit
2425
test_unit:
25-
go test $(TEST_ARGS) -coverprofile cover.out ./...
26+
go test $(TEST_ARGS) -timeout $(TEST_TIMEOUT) -coverprofile cover.out ./...
2627

2728
.PHONY: bench
2829
bench:
2930
go test $(TEST_ARGS) -bench=. -run=^$$ ./...
3031

32+
.PHONY: fuzz_tests
33+
fuzz:
34+
go test -list="Fuzz" ./...
35+
3136
.PHONY: build
3237
build:
33-
go build -o ./parrot ./cmd
34-
35-
.PHONY: goreleaser
36-
goreleaser:
37-
cd .. && goreleaser release --snapshot --clean -f ./parrot/.goreleaser.yaml
38+
cd .. && goreleaser release --snapshot --clean -f ./parrot/.goreleaser.yaml
39+

parrot/cmd/main.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func main() {
4242
if json {
4343
options = append(options, parrot.WithJSONLogs())
4444
}
45+
options = append(options, parrot.WithRecorders(recorders...))
4546

4647
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
4748
defer cancel()
@@ -51,13 +52,6 @@ func main() {
5152
return err
5253
}
5354

54-
for _, r := range recorders {
55-
err = p.Record(r)
56-
if err != nil {
57-
return err
58-
}
59-
}
60-
6155
c := make(chan os.Signal, 1)
6256
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
6357
<-c

parrot/errors.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,20 @@ import (
77

88
var (
99
ErrNilRoute = errors.New("route is nil")
10-
ErrNoMethod = errors.New("no method specified")
1110
ErrInvalidPath = errors.New("invalid path")
11+
ErrInvalidMethod = errors.New("invalid method")
1212
ErrNoResponse = errors.New("route must have a handler or some response")
1313
ErrOnlyOneResponse = errors.New("route can only have one response type")
1414
ErrResponseMarshal = errors.New("unable to marshal response body to JSON")
1515
ErrRouteNotFound = errors.New("route not found")
16+
ErrWildcardPath = fmt.Errorf("path can only contain one wildcard '*' and it must be the final value")
1617

1718
ErrNoRecorderURL = errors.New("no recorder URL specified")
1819
ErrInvalidRecorderURL = errors.New("invalid recorder URL")
1920
ErrRecorderNotFound = errors.New("recorder not found")
2021

21-
ErrServerShutdown = errors.New("parrot is already asleep")
22+
ErrServerShutdown = errors.New("parrot is already asleep")
23+
ErrServerUnhealthy = errors.New("parrot is unhealthy")
2224
)
2325

2426
// Custom error type to help add more detail to base errors

parrot/examples_test.go

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/smartcontractkit/chainlink-testing-framework/parrot"
1313
)
1414

15-
func ExampleServer_Register_internal() {
15+
func ExampleServer_internal() {
1616
// Create a new parrot instance with no logging and a custom save file
1717
saveFile := "register_example.json"
1818
p, err := parrot.Wake(parrot.WithLogLevel(zerolog.NoLevel), parrot.WithSaveFile(saveFile))
@@ -36,6 +36,8 @@ func ExampleServer_Register_internal() {
3636
ResponseStatusCode: http.StatusOK,
3737
}
3838

39+
waitForParrotServerInternal(p, time.Second) // Wait for the parrot server to start
40+
3941
// Register the route with the parrot instance
4042
err = p.Register(route)
4143
if err != nil {
@@ -55,10 +57,7 @@ func ExampleServer_Register_internal() {
5557
fmt.Println(len(routes))
5658

5759
// Delete the route
58-
err = p.Delete(route.ID())
59-
if err != nil {
60-
panic(err)
61-
}
60+
p.Delete(route)
6261

6362
// Get all routes from the parrot instance
6463
routes = p.Routes()
@@ -70,7 +69,7 @@ func ExampleServer_Register_internal() {
7069
// 0
7170
}
7271

73-
func ExampleServer_Register_external() {
72+
func ExampleServer_external() {
7473
var (
7574
saveFile = "route_example.json"
7675
port = 9090
@@ -89,7 +88,7 @@ func ExampleServer_Register_external() {
8988
client := resty.New()
9089
client.SetBaseURL(fmt.Sprintf("http://localhost:%d", port)) // The URL of the parrot server
9190

92-
waitForParrotServer(client, time.Second) // Wait for the parrot server to start
91+
waitForParrotServerExternal(client, time.Second) // Wait for the parrot server to start
9392

9493
// Register a new route /test that will return a 200 status code with a text/plain response body of "Squawk"
9594
route := &parrot.Route{
@@ -98,7 +97,7 @@ func ExampleServer_Register_external() {
9897
RawResponseBody: "Squawk",
9998
ResponseStatusCode: http.StatusOK,
10099
}
101-
resp, err := client.R().SetBody(route).Post("/routes")
100+
resp, err := client.R().SetBody(route).Post(parrot.RoutesRoute)
102101
if err != nil {
103102
panic(err)
104103
}
@@ -107,7 +106,7 @@ func ExampleServer_Register_external() {
107106

108107
// Get all routes from the parrot server
109108
routes := make([]*parrot.Route, 0)
110-
resp, err = client.R().SetResult(&routes).Get("/routes")
109+
resp, err = client.R().SetResult(&routes).Get(parrot.RoutesRoute)
111110
if err != nil {
112111
panic(err)
113112
}
@@ -116,7 +115,7 @@ func ExampleServer_Register_external() {
116115
fmt.Println(len(routes))
117116

118117
// Delete the route
119-
resp, err = client.R().SetBody(route).Delete("/routes")
118+
resp, err = client.R().SetBody(route).Delete(parrot.RoutesRoute)
120119
if err != nil {
121120
panic(err)
122121
}
@@ -125,7 +124,7 @@ func ExampleServer_Register_external() {
125124

126125
// Get all routes from the parrot server
127126
routes = make([]*parrot.Route, 0)
128-
resp, err = client.R().SetResult(&routes).Get("/routes")
127+
resp, err = client.R().SetResult(&routes).Get(parrot.RoutesRoute)
129128
if err != nil {
130129
panic(err)
131130
}
@@ -161,6 +160,8 @@ func ExampleRecorder_internal() {
161160
panic(err)
162161
}
163162

163+
waitForParrotServerInternal(p, time.Second) // Wait for the parrot server to start
164+
164165
// Register the recorder with the parrot instance
165166
err = p.Record(recorder.URL())
166167
if err != nil {
@@ -228,7 +229,7 @@ func ExampleRecorder_external() {
228229
client := resty.New()
229230
client.SetBaseURL(fmt.Sprintf("http://localhost:%d", port)) // The URL of the parrot server
230231

231-
waitForParrotServer(client, time.Second) // Wait for the parrot server to start
232+
waitForParrotServerExternal(client, time.Second) // Wait for the parrot server to start
232233

233234
// Register a new route /test that will return a 200 status code with a text/plain response body of "Squawk"
234235
route := &parrot.Route{
@@ -239,7 +240,7 @@ func ExampleRecorder_external() {
239240
}
240241

241242
// Register the route with the parrot instance
242-
resp, err := client.R().SetBody(route).Post("/routes")
243+
resp, err := client.R().SetBody(route).Post(parrot.RoutesRoute)
243244
if err != nil {
244245
panic(err)
245246
}
@@ -256,7 +257,7 @@ func ExampleRecorder_external() {
256257
}
257258

258259
// Register the recorder with the parrot instance
259-
resp, err = client.R().SetBody(recorder).Post("/record")
260+
resp, err = client.R().SetBody(recorder).Post(parrot.RecorderRoute)
260261
if err != nil {
261262
panic(err)
262263
}
@@ -293,15 +294,15 @@ func ExampleRecorder_external() {
293294
// Squawk
294295
}
295296

296-
// waitForParrotServer checks the parrot server health endpoint until it returns a 200 status code or the timeout is reached
297-
func waitForParrotServer(client *resty.Client, timeoutDur time.Duration) {
297+
// waitForParrotServerExternal checks the parrot server health endpoint until it returns a 200 status code or the timeout is reached
298+
func waitForParrotServerExternal(client *resty.Client, timeoutDur time.Duration) {
298299
ticker := time.NewTicker(50 * time.Millisecond)
299300
defer ticker.Stop()
300301
timeout := time.NewTimer(timeoutDur)
301302
for { // Wait for the parrot server to start
302303
select {
303304
case <-ticker.C:
304-
resp, err := client.R().Get("/health")
305+
resp, err := client.R().Get(parrot.HealthRoute)
305306
if err != nil {
306307
continue
307308
}
@@ -313,3 +314,19 @@ func waitForParrotServer(client *resty.Client, timeoutDur time.Duration) {
313314
}
314315
}
315316
}
317+
318+
func waitForParrotServerInternal(p *parrot.Server, timeoutDur time.Duration) {
319+
ticker := time.NewTicker(50 * time.Millisecond)
320+
defer ticker.Stop()
321+
timeout := time.NewTimer(timeoutDur)
322+
for { // Wait for the parrot server to start
323+
select {
324+
case <-ticker.C:
325+
if err := p.Healthy(); err == nil {
326+
return
327+
}
328+
case <-timeout.C:
329+
panic("timeout waiting for parrot server to start")
330+
}
331+
}
332+
}

parrot/go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@ module github.com/smartcontractkit/chainlink-testing-framework/parrot
33
go 1.23.4
44

55
require (
6+
github.com/go-chi/chi v1.5.5
67
github.com/go-resty/resty/v2 v2.16.3
78
github.com/google/uuid v1.6.0
89
github.com/rs/zerolog v1.33.0
910
github.com/spf13/cobra v1.8.1
1011
github.com/stretchr/testify v1.9.0
12+
golang.org/x/sync v0.10.0
1113
)
1214

1315
require (
1416
github.com/davecgh/go-spew v1.1.1 // indirect
1517
github.com/inconshreveable/mousetrap v1.1.0 // indirect
1618
github.com/mattn/go-colorable v0.1.13 // indirect
17-
github.com/mattn/go-isatty v0.0.19 // indirect
19+
github.com/mattn/go-isatty v0.0.20 // indirect
1820
github.com/pmezard/go-difflib v1.0.0 // indirect
1921
github.com/rs/xid v1.5.0 // indirect
2022
github.com/spf13/pflag v1.0.5 // indirect

parrot/go.sum

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV
22
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
33
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
44
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
6+
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
57
github.com/go-resty/resty/v2 v2.16.3 h1:zacNT7lt4b8M/io2Ahj6yPypL7bqx9n1iprfQuodV+E=
68
github.com/go-resty/resty/v2 v2.16.3/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
79
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -12,8 +14,9 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
1214
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
1315
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
1416
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
15-
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
1617
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
18+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
19+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
1720
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
1821
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1922
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -30,6 +33,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
3033
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
3134
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
3235
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
36+
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
37+
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
3338
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3439
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
3540
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

0 commit comments

Comments
 (0)