first commit
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
"browser.local/platform/dto"
|
||||
)
|
||||
|
||||
func TestRunControlAPIHelloHeartbeatWorkflow(t *testing.T) {
|
||||
router := newTestRouter()
|
||||
|
||||
helloRecorder := performJSON(t, router, http.MethodPost, "/api/v1/run/control/hello", validRunControlHelloRequest())
|
||||
assertStatus(t, helloRecorder, http.StatusOK)
|
||||
hello := decodeBody[dto.RunControlHelloResponse](t, helloRecorder)
|
||||
if !hello.Accepted || hello.SessionToken == "" || hello.RunEndpointID != "run-local" {
|
||||
t.Fatalf("expected accepted hello response, got %+v", hello)
|
||||
}
|
||||
|
||||
endpoint := getJSON[dto.RunEndpointResponse](t, router, "/api/v1/run/endpoints/run-local")
|
||||
if endpoint.Status != domain.RunEndpointStatusOnline || len(endpoint.Capabilities) != 2 {
|
||||
t.Fatalf("expected registered endpoint metadata, got %+v", endpoint)
|
||||
}
|
||||
|
||||
heartbeatRecorder := performJSON(t, router, http.MethodPost, "/api/v1/run/control/heartbeat", dto.RunControlHeartbeatRequest{
|
||||
RunEndpointID: "run-local",
|
||||
SessionToken: hello.SessionToken,
|
||||
Version: "0.1.1",
|
||||
Status: domain.RunEndpointStatusOnline,
|
||||
CapabilityFingerprint: "cap-v2",
|
||||
Capacity: dto.RunCapacityResponse{
|
||||
MaxJobs: 4,
|
||||
RunningJobs: 1,
|
||||
},
|
||||
})
|
||||
assertStatus(t, heartbeatRecorder, http.StatusOK)
|
||||
heartbeat := decodeBody[dto.RunControlHeartbeatResponse](t, heartbeatRecorder)
|
||||
if !heartbeat.Accepted || !heartbeat.RefreshCapabilities || heartbeat.NextHeartbeatSeconds <= 0 {
|
||||
t.Fatalf("expected accepted heartbeat with refresh, got %+v", heartbeat)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunControlAPIReRegistrationRotatesToken(t *testing.T) {
|
||||
router := newTestRouter()
|
||||
first := decodeBody[dto.RunControlHelloResponse](t, performRunControlHello(t, router, validRunControlHelloRequest()))
|
||||
|
||||
request := validRunControlHelloRequest()
|
||||
request.Version = "0.2.0"
|
||||
second := decodeBody[dto.RunControlHelloResponse](t, performRunControlHello(t, router, request))
|
||||
if second.SessionToken == first.SessionToken {
|
||||
t.Fatalf("expected new session token after re-registration, got %q", second.SessionToken)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunControlAPIErrors(t *testing.T) {
|
||||
router := newTestRouter()
|
||||
|
||||
invalid := validRunControlHelloRequest()
|
||||
invalid.RegistrationToken = ""
|
||||
invalid.Capacity.RunningJobs = 8
|
||||
invalid.Capacity.MaxJobs = 4
|
||||
invalidHello := performJSON(t, router, http.MethodPost, "/api/v1/run/control/hello", invalid)
|
||||
assertErrorResponse(t, invalidHello, http.StatusBadRequest, errorCodeValidation)
|
||||
|
||||
hello := decodeBody[dto.RunControlHelloResponse](t, performRunControlHello(t, router, validRunControlHelloRequest()))
|
||||
invalidHeartbeat := performJSON(t, router, http.MethodPost, "/api/v1/run/control/heartbeat", dto.RunControlHeartbeatRequest{
|
||||
RunEndpointID: "run-local",
|
||||
SessionToken: "stale-token",
|
||||
Version: "0.1.1",
|
||||
Status: domain.RunEndpointStatusOnline,
|
||||
CapabilityFingerprint: "cap-v1",
|
||||
Capacity: dto.RunCapacityResponse{MaxJobs: 4},
|
||||
})
|
||||
assertErrorResponse(t, invalidHeartbeat, http.StatusBadRequest, errorCodeValidation)
|
||||
|
||||
validHeartbeat := performJSON(t, router, http.MethodPost, "/api/v1/run/control/heartbeat", dto.RunControlHeartbeatRequest{
|
||||
RunEndpointID: "run-local",
|
||||
SessionToken: hello.SessionToken,
|
||||
Version: "0.1.1",
|
||||
Status: domain.RunEndpointStatusOnline,
|
||||
CapabilityFingerprint: "cap-v1",
|
||||
Capacity: dto.RunCapacityResponse{MaxJobs: 4},
|
||||
})
|
||||
assertStatus(t, validHeartbeat, http.StatusOK)
|
||||
|
||||
methodFailure := performRaw(t, router, http.MethodGet, "/api/v1/run/control/hello", "")
|
||||
assertErrorResponse(t, methodFailure, http.StatusMethodNotAllowed, errorCodeMethodNotAllowed)
|
||||
}
|
||||
|
||||
func performRunControlHello(t *testing.T, router http.Handler, request dto.RunControlHelloRequest) *httptest.ResponseRecorder {
|
||||
t.Helper()
|
||||
recorder := performJSON(t, router, http.MethodPost, "/api/v1/run/control/hello", request)
|
||||
assertStatus(t, recorder, http.StatusOK)
|
||||
return recorder
|
||||
}
|
||||
|
||||
func validRunControlHelloRequest() dto.RunControlHelloRequest {
|
||||
return dto.RunControlHelloRequest{
|
||||
RegistrationToken: "registration-token",
|
||||
RunEndpointID: "run-local",
|
||||
DisplayName: "Local Run",
|
||||
Version: "0.1.0",
|
||||
Status: domain.RunEndpointStatusOnline,
|
||||
Platform: "darwin/arm64",
|
||||
CapabilityReport: dto.RunCapabilityReport{
|
||||
Capabilities: []string{"control.hello", "control.heartbeat"},
|
||||
Fingerprint: "cap-v1",
|
||||
},
|
||||
Capacity: dto.RunCapacityResponse{MaxJobs: 4},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user