Skip to content

Commit d44b362

Browse files
committed
Adds example for external recorder
1 parent 8a73802 commit d44b362

File tree

5 files changed

+314
-134
lines changed

5 files changed

+314
-134
lines changed

parrot/examples_test.go

Lines changed: 140 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ import (
55
"fmt"
66
"net/http"
77
"os"
8+
"time"
89

910
"github.com/go-resty/resty/v2"
1011
"github.com/rs/zerolog"
1112
"github.com/smartcontractkit/chainlink-testing-framework/parrot"
1213
)
1314

14-
func ExampleServer_Register() {
15+
func ExampleServer_Register_internal() {
1516
// Create a new parrot instance with no logging and a custom save file
1617
saveFile := "register_example.json"
1718
p, err := parrot.Wake(parrot.WithLogLevel(zerolog.NoLevel), parrot.WithSaveFile(saveFile))
@@ -48,30 +49,47 @@ func ExampleServer_Register() {
4849
}
4950
fmt.Println(resp.StatusCode())
5051
fmt.Println(string(resp.Body()))
52+
53+
// Get all routes from the parrot instance
54+
routes := p.Routes()
55+
fmt.Println(len(routes))
56+
57+
// Delete the route
58+
err = p.Delete(route.ID())
59+
if err != nil {
60+
panic(err)
61+
}
62+
63+
// Get all routes from the parrot instance
64+
routes = p.Routes()
65+
fmt.Println(len(routes))
5166
// Output:
5267
// 200
5368
// Squawk
69+
// 1
70+
// 0
5471
}
5572

56-
func ExampleRoute() {
57-
// Run the parrot server as a separate instance, like in a Docker container
58-
saveFile := "route_example.json"
59-
p, err := parrot.Wake(parrot.WithPort(9090), parrot.WithLogLevel(zerolog.NoLevel), parrot.WithSaveFile(saveFile))
60-
if err != nil {
61-
panic(err)
62-
}
63-
defer func() { // Cleanup the parrot instance
64-
err = p.Shutdown(context.Background()) // Gracefully shutdown the parrot instance
73+
func ExampleServer_Register_external() {
74+
var (
75+
saveFile = "route_example.json"
76+
port = 9090
77+
)
78+
defer os.Remove(saveFile) // Cleanup the save file for the example
79+
80+
go func() { // Run the parrot server as a separate instance, like in a Docker container
81+
_, err := parrot.Wake(parrot.WithPort(port), parrot.WithLogLevel(zerolog.NoLevel), parrot.WithSaveFile(saveFile))
6582
if err != nil {
6683
panic(err)
6784
}
68-
p.WaitShutdown() // Wait for the parrot instance to shutdown. Usually unnecessary, but we want to clean up the save file
69-
os.Remove(saveFile) // Cleanup the save file for the example
7085
}()
7186

7287
// Code that calls the parrot server from another service
7388
// Use resty to make HTTP calls to the parrot server
7489
client := resty.New()
90+
client.SetBaseURL(fmt.Sprintf("http://localhost:%d", port)) // The URL of the parrot server
91+
92+
waitForParrotServer(client, time.Second) // Wait for the parrot server to start
7593

7694
// Register a new route /test that will return a 200 status code with a text/plain response body of "Squawk"
7795
route := &parrot.Route{
@@ -80,7 +98,7 @@ func ExampleRoute() {
8098
RawResponseBody: "Squawk",
8199
ResponseStatusCode: http.StatusOK,
82100
}
83-
resp, err := client.R().SetBody(route).Post("http://localhost:9090/routes")
101+
resp, err := client.R().SetBody(route).Post("/routes")
84102
if err != nil {
85103
panic(err)
86104
}
@@ -89,7 +107,7 @@ func ExampleRoute() {
89107

90108
// Get all routes from the parrot server
91109
routes := make([]*parrot.Route, 0)
92-
resp, err = client.R().SetResult(&routes).Get("http://localhost:9090/routes")
110+
resp, err = client.R().SetResult(&routes).Get("/routes")
93111
if err != nil {
94112
panic(err)
95113
}
@@ -98,10 +116,7 @@ func ExampleRoute() {
98116
fmt.Println(len(routes))
99117

100118
// Delete the route
101-
req := &parrot.RouteRequest{
102-
ID: route.ID(),
103-
}
104-
resp, err = client.R().SetBody(req).Delete("http://localhost:9090/routes")
119+
resp, err = client.R().SetBody(route).Delete("/routes")
105120
if err != nil {
106121
panic(err)
107122
}
@@ -110,7 +125,7 @@ func ExampleRoute() {
110125

111126
// Get all routes from the parrot server
112127
routes = make([]*parrot.Route, 0)
113-
resp, err = client.R().SetResult(&routes).Get("http://localhost:9090/routes")
128+
resp, err = client.R().SetResult(&routes).Get("/routes")
114129
if err != nil {
115130
panic(err)
116131
}
@@ -125,7 +140,7 @@ func ExampleRoute() {
125140
// 0
126141
}
127142

128-
func ExampleRecorder() {
143+
func ExampleRecorder_internal() {
129144
saveFile := "recorder_example.json"
130145
p, err := parrot.Wake(parrot.WithLogLevel(zerolog.NoLevel), parrot.WithSaveFile(saveFile))
131146
if err != nil {
@@ -147,7 +162,7 @@ func ExampleRecorder() {
147162
}
148163

149164
// Register the recorder with the parrot instance
150-
err = p.Record(recorder.URL)
165+
err = p.Record(recorder.URL())
151166
if err != nil {
152167
panic(err)
153168
}
@@ -194,3 +209,107 @@ func ExampleRecorder() {
194209
// 200
195210
// Squawk
196211
}
212+
213+
// Example of how to use parrot recording when calling it from an external service
214+
func ExampleRecorder_external() {
215+
var (
216+
saveFile = "recorder_example.json"
217+
port = 9091
218+
)
219+
defer os.Remove(saveFile) // Cleanup the save file for the example
220+
221+
go func() { // Run the parrot server as a separate instance, like in a Docker container
222+
_, err := parrot.Wake(parrot.WithPort(port), parrot.WithLogLevel(zerolog.NoLevel), parrot.WithSaveFile(saveFile))
223+
if err != nil {
224+
panic(err)
225+
}
226+
}()
227+
228+
client := resty.New()
229+
client.SetBaseURL(fmt.Sprintf("http://localhost:%d", port)) // The URL of the parrot server
230+
231+
waitForParrotServer(client, time.Second) // Wait for the parrot server to start
232+
233+
// Register a new route /test that will return a 200 status code with a text/plain response body of "Squawk"
234+
route := &parrot.Route{
235+
Method: http.MethodGet,
236+
Path: "/test",
237+
RawResponseBody: "Squawk",
238+
ResponseStatusCode: http.StatusOK,
239+
}
240+
241+
// Register the route with the parrot instance
242+
resp, err := client.R().SetBody(route).Post("/routes")
243+
if err != nil {
244+
panic(err)
245+
}
246+
247+
// Use the host of the machine your recorder is running on
248+
// This should not be localhost if you are running the parrot server on a different machine
249+
// It should be the public IP address of the machine running your code, so that the parrot can call back to it
250+
host := "localhost"
251+
252+
// Create a new recorder with our host
253+
recorder, err := parrot.NewRecorder(parrot.WithHost(host))
254+
if err != nil {
255+
panic(err)
256+
}
257+
258+
// Register the recorder with the parrot instance
259+
resp, err = client.R().SetBody(recorder).Post("/record")
260+
if err != nil {
261+
panic(err)
262+
}
263+
if resp.StatusCode() != http.StatusCreated {
264+
panic(fmt.Sprintf("failed to register recorder, got %d status code", resp.StatusCode()))
265+
}
266+
267+
go func() { // Some other service calls the /test route
268+
_, err := client.R().Get("/test")
269+
if err != nil {
270+
panic(err)
271+
}
272+
}()
273+
274+
// You can now listen to the recorder for all route calls
275+
for {
276+
select {
277+
case recordedRouteCall := <-recorder.Record():
278+
if recordedRouteCall.RouteID == route.ID() {
279+
fmt.Println(recordedRouteCall.RouteID)
280+
fmt.Println(recordedRouteCall.Request.Method)
281+
fmt.Println(recordedRouteCall.Response.StatusCode)
282+
fmt.Println(string(recordedRouteCall.Response.Body))
283+
return
284+
}
285+
case err := <-recorder.Err():
286+
panic(err)
287+
}
288+
}
289+
// Output:
290+
// GET:/test
291+
// GET
292+
// 200
293+
// Squawk
294+
}
295+
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) {
298+
ticker := time.NewTicker(50 * time.Millisecond)
299+
defer ticker.Stop()
300+
timeout := time.NewTimer(timeoutDur)
301+
for { // Wait for the parrot server to start
302+
select {
303+
case <-ticker.C:
304+
resp, err := client.R().Get("/health")
305+
if err != nil {
306+
continue
307+
}
308+
if resp.StatusCode() == http.StatusOK {
309+
return
310+
}
311+
case <-timeout.C:
312+
panic("timeout waiting for parrot server to start")
313+
}
314+
}
315+
}

0 commit comments

Comments
 (0)