From 234323c7666bfcf2a11f0c7da70cdf54926e733e Mon Sep 17 00:00:00 2001 From: Tianyu Liu Date: Wed, 23 Oct 2024 13:53:29 +0200 Subject: [PATCH] Add more tests for ha --- .github/workflows/short-tests.yml | 2 +- src/components/homeassistant/homeassistant.go | 38 ++++--- .../homeassistant/homeassistant_test.go | 106 +++++++++++++++++- src/go.mod | 1 - src/go.sum | 1 - src/util/ticktickutil/ticktickutil.go | 2 +- 6 files changed, 128 insertions(+), 22 deletions(-) diff --git a/.github/workflows/short-tests.yml b/.github/workflows/short-tests.yml index b48fb6c..ae0042f 100644 --- a/.github/workflows/short-tests.yml +++ b/.github/workflows/short-tests.yml @@ -2,7 +2,7 @@ name: Run short tests on: push: - branches: [ "master" ] + pull_request: jobs: run-tests: diff --git a/src/components/homeassistant/homeassistant.go b/src/components/homeassistant/homeassistant.go index b66bf56..b041478 100644 --- a/src/components/homeassistant/homeassistant.go +++ b/src/components/homeassistant/homeassistant.go @@ -37,16 +37,22 @@ func HandleHaMessage(w http.ResponseWriter, r *http.Request) { decoder.DisallowUnknownFields() err := decoder.Decode(&message) if err != nil { - slog.Warn(fmt.Sprintln("HandleHaMessage Error decoding request body", err)) + slog.Warn(fmt.Sprintln("HandleHaMessage: Error decoding request body", err)) http.Error(w, err.Error(), http.StatusBadRequest) return } switch message.Target { case "poo_recorder": - handlePooRecorderMsg(message) + res := handlePooRecorderMsg(message) + if !res { + http.Error(w, "Error handling poo recorder message", http.StatusInternalServerError) + } case "location_recorder": - handleLocationRecorderMsg(message) + res := handleLocationRecorderMsg(message) + if !res { + http.Error(w, "Error handling location recorder message", http.StatusInternalServerError) + } case "ticktick": handleTicktickMsg(message) default: @@ -55,32 +61,32 @@ func HandleHaMessage(w http.ResponseWriter, r *http.Request) { } } -func handlePooRecorderMsg(message haMessage) { +func handlePooRecorderMsg(message haMessage) bool { switch message.Action { case "get_latest": - handleGetLatestPoo() + return handleGetLatestPoo() + default: + slog.Warn(fmt.Sprintln("handlePooRecorderMsg: Unknown action", message.Action)) + return false } } -func handleLocationRecorderMsg(message haMessage) { +func handleLocationRecorderMsg(message haMessage) bool { if message.Action == "record" { port := viper.GetString("port") - req, err := http.NewRequest("POST", "http://localhost:"+port+"/location/record", strings.NewReader(strings.ReplaceAll(message.Content, "'", "\""))) - if err != nil { - slog.Warn(fmt.Sprintln("handleLocationRecorderMsg Error creating request to location recorder", err)) - return - } - req.Header.Set("Content-Type", "application/json") client := &http.Client{ Timeout: time.Second * 1, } - _, err = client.Do(req) + _, err := client.Post("http://localhost:"+port+"/location/record", "application/json", strings.NewReader(strings.ReplaceAll(message.Content, "'", "\""))) if err != nil { - slog.Warn(fmt.Sprintln("handleLocationRecorderMsg Error sending request to location recorder", err)) + slog.Warn(fmt.Sprintln("handleLocationRecorderMsg: Error sending request to location recorder", err)) + return false } } else { - slog.Warn(fmt.Sprintln("handleLocationRecorderMsg Unknown action", message.Action)) + slog.Warn(fmt.Sprintln("handleLocationRecorderMsg: Unknown action", message.Action)) + return false } + return true } func handleTicktickMsg(message haMessage) { @@ -97,7 +103,7 @@ func handleGetLatestPoo() bool { port := viper.GetString("port") _, err := client.Get("http://localhost:" + port + "/poo/latest") if err != nil { - slog.Warn(fmt.Sprintln("handleGetLatestPoo Error sending request to poo recorder", err)) + slog.Warn(fmt.Sprintln("handleGetLatestPoo: Error sending request to poo recorder", err)) return false } diff --git a/src/components/homeassistant/homeassistant_test.go b/src/components/homeassistant/homeassistant_test.go index fcb3750..f9c5513 100644 --- a/src/components/homeassistant/homeassistant_test.go +++ b/src/components/homeassistant/homeassistant_test.go @@ -16,7 +16,15 @@ var ( loggerText = new(bytes.Buffer) ) -func LoggerSetupTeardown(t *testing.T) func() { +func SetupTearDown(t *testing.T) func() { + loggertearDown := loggerSetupTeardown() + + return func() { + loggertearDown() + } +} + +func loggerSetupTeardown() func() { logger := slog.New(slog.NewTextHandler(loggerText, nil)) defaultLogger := slog.Default() slog.SetDefault(logger) @@ -27,13 +35,27 @@ func LoggerSetupTeardown(t *testing.T) func() { } } +func TestHandleHaMessageJsonDecodeError(t *testing.T) { + teardown := SetupTearDown(t) + defer teardown() + + invalidRequestBody := ` { "target": "poo_recorder", "action": "get_latest", "content": " }` + req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(invalidRequestBody)) + w := httptest.NewRecorder() + + HandleHaMessage(w, req) + assert.Equal(t, http.StatusBadRequest, w.Code) + assert.Contains(t, loggerText.String(), "HandleHaMessage: Error decoding request body") +} + func TestHandlePooRecorderMsgGetLatest(t *testing.T) { - teardown := LoggerSetupTeardown(t) + teardown := SetupTearDown(t) defer teardown() requestBody := `{"target": "poo_recorder", "action": "get_latest", "content": ""}` req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(requestBody)) w := httptest.NewRecorder() server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method) assert.Equal(t, "/poo/latest", r.URL.Path) })) defer server.Close() @@ -44,3 +66,83 @@ func TestHandlePooRecorderMsgGetLatest(t *testing.T) { assert.Equal(t, http.StatusOK, w.Code) assert.Empty(t, loggerText.String()) } + +func TestHandlePooRecorderMsgUnknownAction(t *testing.T) { + teardown := SetupTearDown(t) + defer teardown() + + requestBody := `{"target": "poo_recorder", "action": "unknown_action", "content": ""}` + req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(requestBody)) + w := httptest.NewRecorder() + + HandleHaMessage(w, req) + assert.Equal(t, http.StatusInternalServerError, w.Code) + assert.Contains(t, loggerText.String(), "handlePooRecorderMsg: Unknown action") +} + +func TestHandlePooRecorderMsgGetLatestError(t *testing.T) { + teardown := SetupTearDown(t) + defer teardown() + + requestBody := `{"target": "poo_recorder", "action": "get_latest", "content": ""}` + req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(requestBody)) + w := httptest.NewRecorder() + + port := "invalid port" + viper.Set("port", port) + + HandleHaMessage(w, req) + assert.Equal(t, http.StatusInternalServerError, w.Code) + assert.Contains(t, loggerText.String(), "handleGetLatestPoo: Error sending request to poo recorder") +} + +func TestHandleLocationRecorderMsg(t *testing.T) { + teardown := SetupTearDown(t) + defer teardown() + + requestBody := `{"target": "location_recorder", "action": "record", "content": "{'person': 'test', 'latitude': '1.0', 'longitude': '2.0', 'altitude': '3.0'}"}` + req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(requestBody)) + w := httptest.NewRecorder() + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method) + assert.Equal(t, "/location/record", r.URL.Path) + assert.Equal(t, "application/json", r.Header.Get("Content-Type")) + })) + defer server.Close() + + port := strings.Split(server.URL, ":")[2] + viper.Set("port", port) + + HandleHaMessage(w, req) + assert.Equal(t, http.StatusOK, w.Code) + assert.Empty(t, loggerText.String()) +} + +func TestHandleLocationRecorderMsgUnknownAction(t *testing.T) { + teardown := SetupTearDown(t) + defer teardown() + + requestBody := `{"target": "location_recorder", "action": "unknown_action", "content": ""}` + req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(requestBody)) + w := httptest.NewRecorder() + + HandleHaMessage(w, req) + assert.Equal(t, http.StatusInternalServerError, w.Code) + assert.Contains(t, loggerText.String(), "handleLocationRecorderMsg: Unknown action") +} + +func TestHandleLocationRecorderMsgRequestErr(t *testing.T) { + teardown := SetupTearDown(t) + defer teardown() + + requestBody := `{"target": "location_recorder", "action": "record", "content": "{'person': 'test', 'latitude': '1.0', 'longitude': '2.0', 'altitude': '3.0'}"}` + req := httptest.NewRequest(http.MethodPost, "/homeassistant/publish", strings.NewReader(requestBody)) + w := httptest.NewRecorder() + + port := "invalid port" + viper.Set("port", port) + + HandleHaMessage(w, req) + assert.Equal(t, http.StatusInternalServerError, w.Code) + assert.Contains(t, loggerText.String(), "handleLocationRecorderMsg: Error sending request to location recorder") +} diff --git a/src/go.mod b/src/go.mod index 7ec9e03..a85caf1 100644 --- a/src/go.mod +++ b/src/go.mod @@ -36,7 +36,6 @@ require ( github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect diff --git a/src/go.sum b/src/go.sum index a1676a1..31842a7 100644 --- a/src/go.sum +++ b/src/go.sum @@ -72,7 +72,6 @@ github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= diff --git a/src/util/ticktickutil/ticktickutil.go b/src/util/ticktickutil/ticktickutil.go index 3edc317..c1e57e8 100644 --- a/src/util/ticktickutil/ticktickutil.go +++ b/src/util/ticktickutil/ticktickutil.go @@ -78,7 +78,7 @@ type ( } ) -func Init() *TicktickUtilImpl { +func Init() *TicktickUtilImpl { // TODO: Will modify Init to a proper behavior ticktickUtilImpl := &TicktickUtilImpl{} if !viper.InConfig("ticktick.clientId") { slog.Error("TickTick clientId not found in config file, exiting..")