package service import ( "bytes" "context" "net/http" "net/http/httptest" "testing" "time" "git.apinb.com/heqiapp/platforms/backend/iot-gateway/internal/config" ) func TestDispatchForwardsCommandMetadata(t *testing.T) { calls := 0 upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls++ w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusAccepted) _, _ = w.Write([]byte(`{"status":"dispatched","packet_number":9}`)) })) defer upstream.Close() srv := New(config.Config{HTTP: config.HTTP{InternalToken: "token"}, Upstream: config.Upstream{IoTServerURL: upstream.URL, Token: "token"}}) cmd := Command{Identity: "one", IdempotencyKey: "same", DeviceID: "1234567890123456", Action: "close_valve", ExpiresAt: time.Now().Add(time.Minute)} status, packet, err := srv.dispatch(context.Background(), cmd) if err != nil || status != "dispatched" || packet != 9 || calls != 1 { t.Fatalf("status=%s packet=%d calls=%d err=%v", status, packet, calls, err) } } func TestDeviceMessageForwardsToPlatformAPI(t *testing.T) { var received bool platform := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { received = r.URL.Path == "/heqi/internal/v1/iot/device-messages" && r.Header.Get("X-Heqi-Iot-Token") == "token" w.WriteHeader(http.StatusAccepted) })) defer platform.Close() srv := New(config.Config{HTTP: config.HTTP{InternalToken: "token"}, Upstream: config.Upstream{PlatformAPIURL: platform.URL, Token: "token"}}) request := httptest.NewRequest(http.MethodPost, "/internal/v1/device-messages", bytes.NewBufferString(`{"type":"device_message","receivedAt":"2026-08-03T12:00:00Z"}`)) request.Header.Set("X-Heqi-Iot-Token", "token") response := httptest.NewRecorder() srv.deviceMessage(response, request) if response.Code != http.StatusAccepted || !received { t.Fatalf("status=%d received=%v body=%s", response.Code, received, response.Body.String()) } } func TestCommandsForwardsEveryRequestWithoutLocalState(t *testing.T) { calls := 0 upstream := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { calls++ w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusAccepted) _, _ = w.Write([]byte(`{"status":"dispatched","packet_number":9}`)) })) defer upstream.Close() srv := New(config.Config{HTTP: config.HTTP{InternalToken: "token"}, Upstream: config.Upstream{IoTServerURL: upstream.URL, Token: "token"}}) body := []byte(`{"identity":"one","idempotency_key":"same","device_id":"1234567890123456","action":"close_valve","expires_at":"2099-01-01T00:00:00Z"}`) for range 2 { request := httptest.NewRequest(http.MethodPost, "/v1/device-commands", bytes.NewReader(body)) request.Header.Set("X-Heqi-Iot-Token", "token") response := httptest.NewRecorder() srv.commands(response, request) if response.Code != http.StatusAccepted && response.Code != http.StatusOK { t.Fatalf("unexpected status %d: %s", response.Code, response.Body.String()) } } if calls != 2 { t.Fatalf("stateless gateway forwarded %d requests, want 2", calls) } }