summaryrefslogtreecommitdiff
path: root/internal/operations/operations_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/operations/operations_test.go')
-rw-r--r--internal/operations/operations_test.go89
1 files changed, 89 insertions, 0 deletions
diff --git a/internal/operations/operations_test.go b/internal/operations/operations_test.go
new file mode 100644
index 0000000..6936b1a
--- /dev/null
+++ b/internal/operations/operations_test.go
@@ -0,0 +1,89 @@
+package operations
+
+import (
+ "context"
+ "encoding/json"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+ "time"
+
+ "aigw/internal/billing"
+ "aigw/internal/controlplane"
+)
+
+type healthyStore struct{}
+
+func (healthyStore) Ping(context.Context) error { return nil }
+func (healthyStore) MailQueueStatus(context.Context) (controlplane.MailQueueStatus, error) {
+ return controlplane.MailQueueStatus{}, nil
+}
+
+type slowBilling struct{}
+
+func (slowBilling) Ping(context.Context) error { return nil }
+func (slowBilling) SettlementQueueStatus(context.Context) (billing.SettlementQueueStatus, error) {
+ return billing.SettlementQueueStatus{}, nil
+}
+func (slowBilling) OperationalStatus(ctx context.Context) (billing.OperationalStatus, error) {
+ <-ctx.Done()
+ return billing.OperationalStatus{}, ctx.Err()
+}
+
+func TestReadinessTimeoutDoesNotMislabelCompletedChecks(t *testing.T) {
+ handler := Handler{Store: healthyStore{}, Billing: slowBilling{}, ReadinessTimeout: 20 * time.Millisecond}
+ request := httptest.NewRequest(http.MethodGet, "/readyz", nil)
+ recorder := httptest.NewRecorder()
+ handler.ServeHTTP(recorder, request)
+ if recorder.Code != http.StatusServiceUnavailable {
+ t.Fatalf("status = %d, want 503", recorder.Code)
+ }
+ var payload struct {
+ Checks map[string]struct {
+ Status string `json:"status"`
+ Error string `json:"error"`
+ } `json:"checks"`
+ }
+ if err := json.NewDecoder(recorder.Body).Decode(&payload); err != nil {
+ t.Fatal(err)
+ }
+ for _, name := range []string{"postgres", "mail_queue", "billing_postgres", "settlement_queue"} {
+ if payload.Checks[name].Status != "ok" {
+ t.Fatalf("%s status = %q, want ok; payload=%s", name, payload.Checks[name].Status, recorder.Body.String())
+ }
+ }
+ if payload.Checks["billing_operations"].Status != "failed" || payload.Checks["billing_operations"].Error != "check timed out" {
+ t.Fatalf("billing operations = %+v", payload.Checks["billing_operations"])
+ }
+}
+
+func TestMailQueueIsCheckedWithoutBilling(t *testing.T) {
+ handler := Handler{Store: healthyStore{}, ReadinessTimeout: time.Second}
+ recorder := httptest.NewRecorder()
+ handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/readyz", nil))
+ if recorder.Code != http.StatusOK {
+ t.Fatalf("status = %d, body=%s", recorder.Code, recorder.Body.String())
+ }
+ var payload struct {
+ Checks map[string]any `json:"checks"`
+ }
+ if err := json.NewDecoder(recorder.Body).Decode(&payload); err != nil {
+ t.Fatal(err)
+ }
+ if _, ok := payload.Checks["mail_queue"]; !ok {
+ t.Fatal("mail_queue check missing when billing is disabled")
+ }
+}
+
+func TestReadinessChecksDoNotInheritCanceledClientContext(t *testing.T) {
+ handler := Handler{Store: healthyStore{}, ReadinessTimeout: time.Second}
+ request := httptest.NewRequest(http.MethodGet, "/readyz", nil)
+ ctx, cancel := context.WithCancel(request.Context())
+ cancel()
+ request = request.WithContext(ctx)
+ recorder := httptest.NewRecorder()
+ handler.ServeHTTP(recorder, request)
+ if recorder.Code != http.StatusOK {
+ t.Fatalf("status = %d, body=%s", recorder.Code, recorder.Body.String())
+ }
+}