Skip to content

Commit

Permalink
add configurable stub server
Browse files Browse the repository at this point in the history
  • Loading branch information
wimspaargaren committed Nov 21, 2024
1 parent 2c1879d commit b671c89
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 1 deletion.
93 changes: 93 additions & 0 deletions cmd/mcvs-stub-server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package main

import (
"encoding/json"
"fmt"
"log"
"net/http"
"sync"
)

func main() {
h := newHandler()
http.HandleFunc("/reset", h.reset)
http.HandleFunc("/configure", h.configure)
http.HandleFunc("/", h.catchAll)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err)
}
}

type handler struct {
mu sync.RWMutex
endpoints map[string]any
}

func newHandler() *handler {
return &handler{
endpoints: map[string]any{},
}
}

func (h *handler) reset(w http.ResponseWriter, r *http.Request) {
h.endpoints = map[string]any{}
w.WriteHeader(http.StatusOK)
}

// EndpointConfigurationRequest is the request body for the /configure endpoint.
type EndpointConfigurationRequest struct {
Path string `json:"path"`
Response any `json:"response"`
}

func (h *handler) configure(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}

request := EndpointConfigurationRequest{}
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}

if request.Path == "" {
http.Error(w, "Path is required", http.StatusBadRequest)
return
}

if request.Response == nil {
http.Error(w, "Response is required", http.StatusBadRequest)
return
}
fmt.Println("HIIII", request.Response)
h.mu.Lock()
h.endpoints[request.Path] = request.Response
h.mu.Unlock()

w.WriteHeader(http.StatusOK)
}

func (h *handler) catchAll(w http.ResponseWriter, r *http.Request) {
h.mu.RLock()
response, exists := h.endpoints[r.URL.Path]
h.mu.RUnlock()

if !exists {
http.NotFound(w, r)
return
}

b, err := json.Marshal(response)
if err != nil {
http.Error(w, "Internal server error", http.StatusInternalServerError)
return
}

_, err = w.Write(b)
if err != nil {
log.Default().Println("Failed to write response:", err)
}
}
93 changes: 93 additions & 0 deletions cmd/mcvs-stub-server/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package main

import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

"github.com/stretchr/testify/assert"
)

func TestResetHandler(t *testing.T) {
// given
handler := newHandler()
handler.endpoints["/test"] = "test"
assert.Len(t, handler.endpoints, 1)

// when
httptestRecorder := httptest.NewRecorder()
httptestRequest := httptest.NewRequest("GET", "/reset", nil)

// then
handler.reset(httptestRecorder, httptestRequest)
assert.Len(t, handler.endpoints, 0)
assert.Equal(t, http.StatusOK, httptestRecorder.Code)
}

func TestConfigureHandler(t *testing.T) {
// given
handler := newHandler()
assert.Len(t, handler.endpoints, 0)

// when
httptestRecorder := httptest.NewRecorder()
httptestRequest := httptest.NewRequest("POST", "/configure", bytes.NewBuffer([]byte(`{"path": "/test", "response": {"foo": "bar"}}`)))

// then
handler.configure(httptestRecorder, httptestRequest)
assert.Len(t, handler.endpoints, 1)
b, err := json.Marshal(handler.endpoints["/test"])
assert.NoError(t, err)
assert.Equal(t, []byte(`{"foo":"bar"}`), b)
assert.Equal(t, http.StatusOK, httptestRecorder.Code)
}

func TestConfigureHandlerInvalidMethod(t *testing.T) {
// given
handler := newHandler()

// when
httptestRecorder := httptest.NewRecorder()
httptestRequest := httptest.NewRequest("GET", "/configure", nil)

// then
handler.configure(httptestRecorder, httptestRequest)
assert.Equal(t, http.StatusMethodNotAllowed, httptestRecorder.Code)
}

func TestCatchAllHandler(t *testing.T) {
// given
handler := newHandler()

response := struct {
Foo string `json:"foo"`
}{
Foo: "bar",
}

handler.endpoints["/test"] = response

// when
httptestRecorder := httptest.NewRecorder()
httptestRequest := httptest.NewRequest("GET", "/test", nil)

// then
handler.catchAll(httptestRecorder, httptestRequest)
assert.Equal(t, []byte(`{"foo":"bar"}`), httptestRecorder.Body.Bytes())
assert.Equal(t, http.StatusOK, httptestRecorder.Code)
}

func TestCatchAllHandlerNotFound(t *testing.T) {
// given
handler := newHandler()

// when
httptestRecorder := httptest.NewRecorder()
httptestRequest := httptest.NewRequest("GET", "/test", nil)

// then
handler.catchAll(httptestRecorder, httptestRequest)
assert.Equal(t, http.StatusNotFound, httptestRecorder.Code)
}
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ module schubergphilis/mcvs-integrationtest-services

go 1.23.3

require github.com/labstack/echo/v4 v4.12.0
require (
github.com/labstack/echo/v4 v4.12.0
github.com/stretchr/testify v1.8.4
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,7 @@ golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 comments on commit b671c89

Please sign in to comment.