Skip to content

Commit 60c0500

Browse files
committed
Docs and race test
1 parent c6218da commit 60c0500

File tree

5 files changed

+61
-80
lines changed

5 files changed

+61
-80
lines changed

parrot/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Default test log level (can be overridden)
2-
TEST_LOG_LEVEL ?= ""
2+
PARROT_TEST_LOG_LEVEL ?= ""
33

44
# Pass TEST_LOG_LEVEL as a flag to go test
5-
TEST_ARGS ?= -testLogLevel=$(TEST_LOG_LEVEL)
5+
TEST_ARGS ?= -testLogLevel=$(PARROT_TEST_LOG_LEVEL)
66

77
.PHONY: lint
88
lint:

parrot/README.md

Lines changed: 6 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -2,83 +2,18 @@
22

33
A simple, high-performing mockserver that can dynamically build new routes with customized responses, parroting back whatever you tell it to.
44

5-
## Use
6-
7-
Call the `/register` endpoint to define a route.
8-
9-
### Curl
10-
11-
```sh
12-
curl -X POST http://localhost:8080/register -d '{
13-
"method": "GET",
14-
"path": "/hello",
15-
"response": "{\"message\": \"Hello, world!\"}",
16-
"status_code": 200,
17-
"content_type": "application/json"
18-
}' -H "Content-Type: application/json"
19-
```
20-
21-
### Go and [Resty](https://github.com/go-resty/resty)
22-
23-
```go
24-
client := resty.New()
25-
26-
route := map[string]any{
27-
"method": "GET",
28-
"path": "/hello",
29-
"response": "{\"message\":\"Hello, world!\"}",
30-
"status_code": 200,
31-
"content_type": "application/json",
32-
}
33-
34-
resp, _ := client.R().
35-
SetHeader("Content-Type", "application/json").
36-
SetBody(route).
37-
Post("http://localhost:8080/register")
38-
```
39-
40-
You can now call your endpoint and receive the JSON response back.
41-
42-
```sh
43-
curl -X GET http://localhost:8080/hello -H "Content-Type: application/json"
44-
# {"message":"Hello, world!"}
45-
```
46-
47-
## Configure
48-
49-
Config is through environment variables.
50-
51-
| **Environment Variable** | **Description** | **Default Value** |
52-
| ------------------------ | -------------------------------------------------------------- | ----------------- |
53-
| `LOG_LEVEL` | Controls the logging level (`debug`, `info`, `warn`, `error`). | `debug` |
54-
| `SAVE_FILE` | Path to the file where routes are saved and loaded. | `save.json` |
55-
565
## Run
576

587
```sh
59-
go run .
8+
go run ./cmd
9+
go run ./cmd -h # See all config options
6010
```
6111

6212
## Test
6313

6414
```sh
65-
go test -cover -race ./...
66-
```
67-
68-
## Benchmark
69-
70-
```sh
71-
LOG_LEVEL=disabled go test -bench=. -benchmem -run=^$
72-
```
73-
74-
Benchmark run on an Apple M3 Max.
75-
76-
```sh
77-
goos: darwin
78-
goarch: arm64
79-
pkg: github.com/smartcontractkit/chainlink-testing-framework/parrotserver
80-
BenchmarkRegisterRoute-14 604978 1967 ns/op 6263 B/op 29 allocs/op
81-
BenchmarkRouteResponse-14 16561670 70.62 ns/op 80 B/op 1 allocs/op
82-
BenchmarkSaveRoutes-14 1245 956784 ns/op 636042 B/op 2014 allocs/op
83-
BenchmarkLoadRoutes-14 1020 1185990 ns/op 348919 B/op 9020 allocs/op
15+
make test
16+
make test PARROT_TEST_LOG_LEVEL=trace # Set log level for tests
17+
make test_race # Test with -race flag enabled
18+
make bench # Benchmark
8419
```

parrot/cmd/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ func main() {
2222
)
2323

2424
rootCmd := &cobra.Command{
25-
Use: "parrotserver",
26-
Short: "a server that can set and parrrot back dynamic requests",
25+
Use: "parrot",
26+
Short: "A server that can register and parrot back dynamic requests",
2727
RunE: func(cmd *cobra.Command, args []string) error {
2828
options := []parrot.ServerOption{parrot.WithPort(port)}
2929
logLevel := zerolog.InfoLevel

parrot/parrot_examples_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"github.com/smartcontractkit/chainlink-testing-framework/parrot"
99
)
1010

11-
func ExampleServer_Register() {
11+
func ExampleServer() {
1212
p, err := parrot.Wake()
1313
if err != nil {
1414
panic(err)

parrot/parrot_test.go

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package parrot
22

33
import (
4+
"encoding/json"
45
"flag"
56
"fmt"
67
"io"
@@ -76,14 +77,20 @@ func TestRegisteredRoute(t *testing.T) {
7677
ResponseStatusCode: 201,
7778
ResponseContentType: "text/plain",
7879
},
80+
{
81+
Method: http.MethodGet,
82+
Path: "/json",
83+
ResponseBody: map[string]any{"message": "Squawk"},
84+
ResponseStatusCode: 200,
85+
ResponseContentType: "application/json",
86+
},
7987
}
8088

81-
for _, r := range routes {
82-
route := r
89+
for _, route := range routes {
8390
t.Run(route.Method+":"+route.Path, func(t *testing.T) {
8491
t.Parallel()
8592

86-
err = p.Register(route)
93+
err := p.Register(route)
8794
require.NoError(t, err, "error registering route")
8895

8996
resp, err := p.Call(route.Method, route.Path)
@@ -93,7 +100,13 @@ func TestRegisteredRoute(t *testing.T) {
93100
assert.Equal(t, resp.StatusCode, route.ResponseStatusCode)
94101
assert.Equal(t, resp.Header.Get("Content-Type"), route.ResponseContentType)
95102
body, _ := io.ReadAll(resp.Body)
96-
assert.Equal(t, route.RawResponseBody, string(body))
103+
if route.ResponseBody != nil {
104+
jsonBody, err := json.Marshal(route.ResponseBody)
105+
require.NoError(t, err)
106+
assert.JSONEq(t, string(jsonBody), string(body))
107+
} else {
108+
assert.Equal(t, route.RawResponseBody, string(body))
109+
}
97110
resp.Body.Close()
98111
})
99112
}
@@ -113,6 +126,39 @@ func TestUnregisteredRoute(t *testing.T) {
113126
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
114127
}
115128

129+
func TestUnregister(t *testing.T) {
130+
t.Parallel()
131+
132+
p, err := Wake(WithLogLevel(testLogLevel))
133+
require.NoError(t, err, "error waking parrot")
134+
135+
route := &Route{
136+
Method: http.MethodPost,
137+
Path: "/hello",
138+
RawResponseBody: "Squawk",
139+
ResponseStatusCode: 200,
140+
ResponseContentType: "text/plain",
141+
}
142+
143+
err = p.Register(route)
144+
require.NoError(t, err, "error registering route")
145+
146+
resp, err := p.Call(route.Method, route.Path)
147+
require.NoError(t, err, "error calling parrot")
148+
149+
assert.Equal(t, resp.StatusCode, route.ResponseStatusCode)
150+
assert.Equal(t, resp.Header.Get("Content-Type"), route.ResponseContentType)
151+
body, _ := io.ReadAll(resp.Body)
152+
assert.Equal(t, route.RawResponseBody, string(body))
153+
resp.Body.Close()
154+
155+
p.Unregister(route.Method, route.Path)
156+
157+
resp, err = p.Call(route.Method, route.Path)
158+
require.NoError(t, err, "error calling parrot")
159+
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
160+
}
161+
116162
func TestSaveLoad(t *testing.T) {
117163
t.Parallel()
118164

0 commit comments

Comments
 (0)