72 lines
3.1 KiB
Go
72 lines
3.1 KiB
Go
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)
|
|
}
|
|
}
|