package httpapi import ( "errors" "net/http" "net/http/httptest" "testing" "data-terminal-cloud/internal/deviceauth" ) type fakeDeviceVerifier struct { identity deviceauth.Identity err error } func (v fakeDeviceVerifier) Verify(*http.Request) (deviceauth.Identity, error) { return v.identity, v.err } func TestDeviceAuthAddsIdentityContext(t *testing.T) { expected := deviceauth.Identity{PublicID: "device-1", TenantID: "tenant-1"} handler := DeviceAuth(fakeDeviceVerifier{identity: expected}, http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { actual, ok := deviceauth.FromContext(request.Context()) if !ok || actual.PublicID != expected.PublicID { t.Fatalf("identity = %#v, ok = %v", actual, ok) } writer.WriteHeader(http.StatusNoContent) })) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/device/v2/config", nil)) if recorder.Code != http.StatusNoContent { t.Fatalf("status = %d", recorder.Code) } } func TestDeviceAuthDoesNotExposeCredentialFailure(t *testing.T) { for _, authError := range []error{ deviceauth.ErrCredentialsMissing, deviceauth.ErrCredentialInvalid, deviceauth.ErrDeviceInactive, deviceauth.ErrRequestExpired, deviceauth.ErrReplayDetected, } { handler := DeviceAuth(fakeDeviceVerifier{err: authError}, http.HandlerFunc(func(http.ResponseWriter, *http.Request) { t.Fatal("downstream must not be called") })) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/device/v2/config", nil)) if recorder.Code != http.StatusUnauthorized || !containsText(recorder.Body.String(), "DEVICE_AUTHENTICATION_FAILED") { t.Fatalf("error %v returned status %d and body %s", authError, recorder.Code, recorder.Body.String()) } } handler := DeviceAuth(fakeDeviceVerifier{err: errors.New("redis down")}, http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/device/v2/config", nil)) if recorder.Code != http.StatusServiceUnavailable || !containsText(recorder.Body.String(), `"retryable":true`) { t.Fatalf("unexpected unavailable response: %d %s", recorder.Code, recorder.Body.String()) } } func containsText(value, part string) bool { for index := 0; index+len(part) <= len(value); index++ { if value[index:index+len(part)] == part { return true } } return false }