From a780e39094f7d1e3c15c7fa98d542137bc56519e Mon Sep 17 00:00:00 2001 From: Joseph Weigl Date: Mon, 19 Aug 2024 10:34:48 +0200 Subject: [PATCH 1/5] feat: replace variables in bodyFile path --- internal/server/http/handler.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/internal/server/http/handler.go b/internal/server/http/handler.go index cab0ae0..ab51b78 100644 --- a/internal/server/http/handler.go +++ b/internal/server/http/handler.go @@ -1,10 +1,12 @@ package http import ( + "github.com/gorilla/mux" "io" "log" "net/http" "os" + "strings" "time" ) @@ -15,9 +17,10 @@ func ImposterHandler(i Imposter) http.HandlerFunc { if res.Delay.Delay() > 0 { time.Sleep(res.Delay.Delay()) } + vars := mux.Vars(r) writeHeaders(res, w) w.WriteHeader(res.Status) - writeBody(i, res, w) + writeBody(i, res, w, vars) } } @@ -31,11 +34,14 @@ func writeHeaders(r Response, w http.ResponseWriter) { } } -func writeBody(i Imposter, r Response, w http.ResponseWriter) { +func writeBody(i Imposter, r Response, w http.ResponseWriter, vars map[string]string) { wb := []byte(r.Body) if r.BodyFile != nil { bodyFile := i.CalculateFilePath(*r.BodyFile) + for key, value := range vars { + bodyFile = strings.ReplaceAll(bodyFile, "{"+key+"}", value) + } wb = fetchBodyFromFile(bodyFile) } w.Write(wb) From ddbf72c7b05b2b8f60c9b71f10b0e5d99c67b6fe Mon Sep 17 00:00:00 2001 From: Joseph Weigl Date: Mon, 19 Aug 2024 10:35:01 +0200 Subject: [PATCH 2/5] build: add test as make goal --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b773558..99fafc8 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,7 @@ .PHONY: build build: - go build -ldflags "-s -w -X 'github.com/friendsofgo/killgrave/internal/app/cmd._version=`git rev-parse --abbrev-ref HEAD`-`git rev-parse --short HEAD`'" -o bin/killgrave cmd/killgrave/main.go \ No newline at end of file + go build -ldflags "-s -w -X 'github.com/friendsofgo/killgrave/internal/app/cmd._version=`git rev-parse --abbrev-ref HEAD`-`git rev-parse --short HEAD`'" -o bin/killgrave cmd/killgrave/main.go + +.PHONY: test +test: + go test -v -vet=off -race ./... \ No newline at end of file From d40eb82570c3a4358b7c3f8c948d302115ccc373 Mon Sep 17 00:00:00 2001 From: Joseph Weigl Date: Wed, 21 Aug 2024 11:44:20 +0200 Subject: [PATCH 3/5] test: add tests for variables in body file --- internal/server/http/handler_test.go | 56 +++++++++++++++++++ .../gopher_variables.imp.json | 34 +++++++++++ .../responses/gopher_1_1_response.json | 11 ++++ .../responses/gopher_1_2_response.json | 11 ++++ .../responses/gopher_1_response.json | 11 ++++ .../responses/gopher_2_response.json | 11 ++++ 6 files changed, 134 insertions(+) create mode 100644 internal/server/http/test/testdata/imposters_variables/gopher_variables.imp.json create mode 100644 internal/server/http/test/testdata/imposters_variables/responses/gopher_1_1_response.json create mode 100644 internal/server/http/test/testdata/imposters_variables/responses/gopher_1_2_response.json create mode 100644 internal/server/http/test/testdata/imposters_variables/responses/gopher_1_response.json create mode 100644 internal/server/http/test/testdata/imposters_variables/responses/gopher_2_response.json diff --git a/internal/server/http/handler_test.go b/internal/server/http/handler_test.go index ba87c9e..c18938c 100644 --- a/internal/server/http/handler_test.go +++ b/internal/server/http/handler_test.go @@ -2,6 +2,8 @@ package http import ( "bytes" + "encoding/json" + "github.com/gorilla/mux" "io" "net/http" "net/http/httptest" @@ -69,6 +71,60 @@ func TestImposterHandler(t *testing.T) { } } +func TestImposterHandler_Variables(t *testing.T) { + var headers = make(map[string]string) + headers["Content-Type"] = "application/json" + + responseId1 := "test/testdata/imposters_variables/responses/gopher_1_response.json" + responseId2 := "test/testdata/imposters_variables/responses/gopher_2_response.json" + responseId1Variable1 := "test/testdata/imposters_variables/responses/gopher_1_1_response.json" + responseId1Variable2 := "test/testdata/imposters_variables/responses/gopher_1_2_response.json" + + imposterFilePath := "test/testdata/imposters_variables/gopher_variables.imp.json" + imposterFile, _ := os.Open(imposterFilePath) + defer imposterFile.Close() + imposterBytes, _ := io.ReadAll(imposterFile) + + var imposters []Imposter + err := json.Unmarshal(imposterBytes, &imposters) + assert.NoError(t, err) + + var dataTest = []struct { + name string + imposter Imposter + url string + expectedBodyPath string + statusCode int + }{ + {"valid imposter with id 1 in path", imposters[0], "/gophers/1", responseId1, http.StatusOK}, + {"valid imposter with id 2 in path", imposters[0], "/gophers/2", responseId2, http.StatusOK}, + {"valid imposter with id 1 and second variable 1 in path", imposters[1], "/gophers/1/1", responseId1Variable1, http.StatusOK}, + {"valid imposter with id 1 and second variable 2 in path", imposters[1], "/gophers/1/2", responseId1Variable2, http.StatusOK}, + } + + for _, tt := range dataTest { + t.Run(tt.name, func(t *testing.T) { + req, err := http.NewRequest("GET", tt.url, nil) + assert.NoError(t, err) + rec := httptest.NewRecorder() + handler := ImposterHandler(tt.imposter) + + m := mux.NewRouter() + m.Handle(tt.imposter.Request.Endpoint, handler) + m.ServeHTTP(rec, req) + + expectedBodyPathFile, _ := os.Open(tt.expectedBodyPath) + defer expectedBodyPathFile.Close() + expectedBody, _ := io.ReadAll(expectedBodyPathFile) + + //handler.ServeHTTP(rec, req) + assert.Equal(t, rec.Code, tt.statusCode) + assert.Equal(t, string(expectedBody), rec.Body.String()) + + }) + } +} + func TestInvalidRequestWithSchema(t *testing.T) { validRequest := []byte(`{ "data": { diff --git a/internal/server/http/test/testdata/imposters_variables/gopher_variables.imp.json b/internal/server/http/test/testdata/imposters_variables/gopher_variables.imp.json new file mode 100644 index 0000000..8d785ba --- /dev/null +++ b/internal/server/http/test/testdata/imposters_variables/gopher_variables.imp.json @@ -0,0 +1,34 @@ +[ + { + "request": { + "method": "GET", + "endpoint": "/gophers/{id:.*}", + "headers": { + "Content-Type": "application/json" + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "bodyFile": "test/testdata/imposters_variables/responses/gopher_{id}_response.json" + } + }, + { + "request": { + "method": "GET", + "endpoint": "/gophers/{id:.*}/{second_id:.*}", + "headers": { + "Content-Type": "application/json" + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "bodyFile": "test/testdata/imposters_variables/responses/gopher_{id}_{second_id}_response.json" + } + } +] diff --git a/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_1_response.json b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_1_response.json new file mode 100644 index 0000000..f825bae --- /dev/null +++ b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_1_response.json @@ -0,0 +1,11 @@ +{ + "data": { + "type": "gophers", + "id": "1_1", + "attributes": { + "name": "Zebediah", + "color": "Purple", + "age": 54 + } + } +} diff --git a/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_2_response.json b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_2_response.json new file mode 100644 index 0000000..befb38e --- /dev/null +++ b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_2_response.json @@ -0,0 +1,11 @@ +{ + "data": { + "type": "gophers", + "id": "1_2", + "attributes": { + "name": "Zebediah", + "color": "Purple", + "age": 54 + } + } +} diff --git a/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_response.json b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_response.json new file mode 100644 index 0000000..410d54d --- /dev/null +++ b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_response.json @@ -0,0 +1,11 @@ +{ + "data": { + "type": "gophers", + "id": "1", + "attributes": { + "name": "Zebediah", + "color": "Purple", + "age": 54 + } + } +} diff --git a/internal/server/http/test/testdata/imposters_variables/responses/gopher_2_response.json b/internal/server/http/test/testdata/imposters_variables/responses/gopher_2_response.json new file mode 100644 index 0000000..1bbd76e --- /dev/null +++ b/internal/server/http/test/testdata/imposters_variables/responses/gopher_2_response.json @@ -0,0 +1,11 @@ +{ + "data": { + "type": "gophers", + "id": "2", + "attributes": { + "name": "Zebediah", + "color": "Purple", + "age": 54 + } + } +} From 18e28e7f7c16c2a4fc670f2aae6b744a82c1be51 Mon Sep 17 00:00:00 2001 From: Joseph Weigl Date: Wed, 21 Aug 2024 14:10:14 +0200 Subject: [PATCH 4/5] remove unused line --- internal/server/http/handler_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/server/http/handler_test.go b/internal/server/http/handler_test.go index c18938c..19e374b 100644 --- a/internal/server/http/handler_test.go +++ b/internal/server/http/handler_test.go @@ -117,7 +117,6 @@ func TestImposterHandler_Variables(t *testing.T) { defer expectedBodyPathFile.Close() expectedBody, _ := io.ReadAll(expectedBodyPathFile) - //handler.ServeHTTP(rec, req) assert.Equal(t, rec.Code, tt.statusCode) assert.Equal(t, string(expectedBody), rec.Body.String()) From c9dbb4b7afa8c138d678ba338d7f4be397297034 Mon Sep 17 00:00:00 2001 From: Joseph Weigl Date: Fri, 13 Sep 2024 12:03:29 +0200 Subject: [PATCH 5/5] fix: adjust test data and handle errors --- internal/server/http/handler_test.go | 19 +++++++++++++------ .../gopher_variables.imp.json | 16 ++++++++++++++++ .../responses/gopher_1_1_response.json | 6 +++--- .../responses/gopher_1_2_response.json | 6 +++--- .../gopher_1_without_variable_response.json | 0 .../responses/gopher_2_response.json | 6 +++--- 6 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 internal/server/http/test/testdata/imposters_variables/responses/gopher_1_without_variable_response.json diff --git a/internal/server/http/handler_test.go b/internal/server/http/handler_test.go index 19e374b..79df2fc 100644 --- a/internal/server/http/handler_test.go +++ b/internal/server/http/handler_test.go @@ -79,15 +79,19 @@ func TestImposterHandler_Variables(t *testing.T) { responseId2 := "test/testdata/imposters_variables/responses/gopher_2_response.json" responseId1Variable1 := "test/testdata/imposters_variables/responses/gopher_1_1_response.json" responseId1Variable2 := "test/testdata/imposters_variables/responses/gopher_1_2_response.json" + responseId1WithoutVariable := "test/testdata/imposters_variables/responses/gopher_1_without_variable_response.json" imposterFilePath := "test/testdata/imposters_variables/gopher_variables.imp.json" - imposterFile, _ := os.Open(imposterFilePath) + imposterFile, err := os.Open(imposterFilePath) + require.NoError(t, err) defer imposterFile.Close() - imposterBytes, _ := io.ReadAll(imposterFile) + + imposterBytes, err := io.ReadAll(imposterFile) + require.NoError(t, err) var imposters []Imposter - err := json.Unmarshal(imposterBytes, &imposters) - assert.NoError(t, err) + err = json.Unmarshal(imposterBytes, &imposters) + require.NoError(t, err) var dataTest = []struct { name string @@ -100,12 +104,14 @@ func TestImposterHandler_Variables(t *testing.T) { {"valid imposter with id 2 in path", imposters[0], "/gophers/2", responseId2, http.StatusOK}, {"valid imposter with id 1 and second variable 1 in path", imposters[1], "/gophers/1/1", responseId1Variable1, http.StatusOK}, {"valid imposter with id 1 and second variable 2 in path", imposters[1], "/gophers/1/2", responseId1Variable2, http.StatusOK}, + {"valid imposter without variable but body file has variable", imposters[2], "/gophers/1", responseId1WithoutVariable, http.StatusOK}, } for _, tt := range dataTest { + tt := tt t.Run(tt.name, func(t *testing.T) { req, err := http.NewRequest("GET", tt.url, nil) - assert.NoError(t, err) + require.NoError(t, err) rec := httptest.NewRecorder() handler := ImposterHandler(tt.imposter) @@ -115,7 +121,8 @@ func TestImposterHandler_Variables(t *testing.T) { expectedBodyPathFile, _ := os.Open(tt.expectedBodyPath) defer expectedBodyPathFile.Close() - expectedBody, _ := io.ReadAll(expectedBodyPathFile) + expectedBody, err := io.ReadAll(expectedBodyPathFile) + require.NoError(t, err) assert.Equal(t, rec.Code, tt.statusCode) assert.Equal(t, string(expectedBody), rec.Body.String()) diff --git a/internal/server/http/test/testdata/imposters_variables/gopher_variables.imp.json b/internal/server/http/test/testdata/imposters_variables/gopher_variables.imp.json index 8d785ba..47d783a 100644 --- a/internal/server/http/test/testdata/imposters_variables/gopher_variables.imp.json +++ b/internal/server/http/test/testdata/imposters_variables/gopher_variables.imp.json @@ -30,5 +30,21 @@ }, "bodyFile": "test/testdata/imposters_variables/responses/gopher_{id}_{second_id}_response.json" } + }, + { + "request": { + "method": "GET", + "endpoint": "/gophers/1", + "headers": { + "Content-Type": "application/json" + } + }, + "response": { + "status": 200, + "headers": { + "Content-Type": "application/json" + }, + "bodyFile": "test/testdata/imposters_variables/responses/gopher_{id}_response.json" + } } ] diff --git a/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_1_response.json b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_1_response.json index f825bae..42f60d7 100644 --- a/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_1_response.json +++ b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_1_response.json @@ -3,9 +3,9 @@ "type": "gophers", "id": "1_1", "attributes": { - "name": "Zebediah", - "color": "Purple", - "age": 54 + "name": "Hannes", + "color": "Yellow", + "age": 32 } } } diff --git a/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_2_response.json b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_2_response.json index befb38e..03d1499 100644 --- a/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_2_response.json +++ b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_2_response.json @@ -3,9 +3,9 @@ "type": "gophers", "id": "1_2", "attributes": { - "name": "Zebediah", - "color": "Purple", - "age": 54 + "name": "Manfred", + "color": "Blue", + "age": 31 } } } diff --git a/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_without_variable_response.json b/internal/server/http/test/testdata/imposters_variables/responses/gopher_1_without_variable_response.json new file mode 100644 index 0000000..e69de29 diff --git a/internal/server/http/test/testdata/imposters_variables/responses/gopher_2_response.json b/internal/server/http/test/testdata/imposters_variables/responses/gopher_2_response.json index 1bbd76e..7e95255 100644 --- a/internal/server/http/test/testdata/imposters_variables/responses/gopher_2_response.json +++ b/internal/server/http/test/testdata/imposters_variables/responses/gopher_2_response.json @@ -3,9 +3,9 @@ "type": "gophers", "id": "2", "attributes": { - "name": "Zebediah", - "color": "Purple", - "age": 54 + "name": "Brian", + "color": "Red", + "age": 35 } } }