first commit
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"browser.local/run/protocol"
|
||||
)
|
||||
|
||||
func TestPlatformClientArtifactMethodsPostJSONAndDecodeResponses(t *testing.T) {
|
||||
seen := map[string]bool{}
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
seen[r.URL.Path] = true
|
||||
switch r.URL.Path {
|
||||
case "/api/v1/run/artifacts/open":
|
||||
var request protocol.ArtifactTransferOpenRequest
|
||||
decodeTestRequest(t, r, &request)
|
||||
if request.ArtifactID != "artifact-1" || request.ChunkSizeBytes != 8 {
|
||||
t.Fatalf("unexpected artifact open request: %+v", request)
|
||||
}
|
||||
writeTestJSON(t, w, validArtifactOpenResponse())
|
||||
case "/api/v1/run/artifacts/chunks":
|
||||
var request protocol.ArtifactChunkUploadRequest
|
||||
decodeTestRequest(t, r, &request)
|
||||
if request.TransferID != "transfer-1" || request.ChunkIndex != 0 || string(request.Payload) != "payload" {
|
||||
t.Fatalf("unexpected artifact chunk request: %+v", request)
|
||||
}
|
||||
writeTestJSON(t, w, protocol.ArtifactChunkUploadResponse{Accepted: true, TransferID: "transfer-1", ArtifactID: "artifact-1", ChunkIndex: 0, ReceivedChunkIndexes: []int{0}, NextMissingChunkIndex: 1, ServerTime: fixedClientTestTime()})
|
||||
case "/api/v1/run/artifacts/status":
|
||||
var request protocol.ArtifactTransferStatusRequest
|
||||
decodeTestRequest(t, r, &request)
|
||||
if request.TransferID != "transfer-1" {
|
||||
t.Fatalf("unexpected artifact status request: %+v", request)
|
||||
}
|
||||
writeTestJSON(t, w, protocol.ArtifactTransferStatusResponse{Accepted: true, TransferID: "transfer-1", ArtifactID: "artifact-1", Direction: "upload", TotalChunks: 2, ChunkSizeBytes: 8, ReceivedChunkIndexes: []int{0}, NextMissingChunkIndex: 1, ServerTime: fixedClientTestTime()})
|
||||
case "/api/v1/run/artifacts/complete":
|
||||
var request protocol.ArtifactTransferCompleteRequest
|
||||
decodeTestRequest(t, r, &request)
|
||||
if request.Checksum == "" || request.SizeBytes != 7 {
|
||||
t.Fatalf("unexpected artifact complete request: %+v", request)
|
||||
}
|
||||
response := protocol.ArtifactTransferCompleteResponse{Accepted: true, TransferID: "transfer-1", Artifact: validArtifactMetadata("available"), Completed: true, ServerTime: fixedClientTestTime()}
|
||||
writeTestJSON(t, w, response)
|
||||
default:
|
||||
t.Fatalf("unexpected request path %s", r.URL.Path)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewPlatformClient(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("new client: %v", err)
|
||||
}
|
||||
ctx := context.Background()
|
||||
open, err := client.OpenArtifactTransfer(ctx, validClientArtifactOpen())
|
||||
if err != nil || !open.Accepted || open.TransferID != "transfer-1" {
|
||||
t.Fatalf("open artifact response=%+v err=%v", open, err)
|
||||
}
|
||||
chunk, err := client.UploadArtifactChunk(ctx, validClientArtifactChunk())
|
||||
if err != nil || chunk.NextMissingChunkIndex != 1 {
|
||||
t.Fatalf("upload artifact chunk response=%+v err=%v", chunk, err)
|
||||
}
|
||||
status, err := client.QueryArtifactTransferStatus(ctx, validClientArtifactStatus())
|
||||
if err != nil || len(status.ReceivedChunkIndexes) != 1 {
|
||||
t.Fatalf("artifact status response=%+v err=%v", status, err)
|
||||
}
|
||||
complete, err := client.CompleteArtifactTransfer(ctx, validClientArtifactComplete())
|
||||
if err != nil || !complete.Completed || complete.Artifact.State != "available" {
|
||||
t.Fatalf("complete artifact response=%+v err=%v", complete, err)
|
||||
}
|
||||
|
||||
for _, path := range []string{"/api/v1/run/artifacts/open", "/api/v1/run/artifacts/chunks", "/api/v1/run/artifacts/status", "/api/v1/run/artifacts/complete"} {
|
||||
if !seen[path] {
|
||||
t.Fatalf("expected request to %s", path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlatformClientArtifactMethodReturnsErrorForPlatformFailure(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = w.Write([]byte(`{"code":"validation_failed"}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client, err := NewPlatformClient(server.URL)
|
||||
if err != nil {
|
||||
t.Fatalf("new client: %v", err)
|
||||
}
|
||||
if _, err := client.OpenArtifactTransfer(context.Background(), validClientArtifactOpen()); err == nil {
|
||||
t.Fatal("expected platform error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactChunkPayloadUsesJSONBase64Encoding(t *testing.T) {
|
||||
encoded, err := json.Marshal(validClientArtifactChunk())
|
||||
if err != nil {
|
||||
t.Fatalf("marshal artifact chunk: %v", err)
|
||||
}
|
||||
if !json.Valid(encoded) || !containsJSONPayloadField(encoded) {
|
||||
t.Fatalf("expected JSON encoded payload field, got %s", string(encoded))
|
||||
}
|
||||
}
|
||||
|
||||
func validClientArtifactOpen() protocol.ArtifactTransferOpenRequest {
|
||||
return protocol.ArtifactTransferOpenRequest{
|
||||
RunEndpointID: "run-local",
|
||||
SessionToken: "session-token",
|
||||
ArtifactID: "artifact-1",
|
||||
Direction: "upload",
|
||||
OwnerKind: "job",
|
||||
OwnerID: "job-1",
|
||||
SizeBytes: 7,
|
||||
ChunkSizeBytes: 8,
|
||||
Checksum: validSHA256Checksum(),
|
||||
IdempotencyKey: "artifact-upload-1",
|
||||
}
|
||||
}
|
||||
|
||||
func validClientArtifactChunk() protocol.ArtifactChunkUploadRequest {
|
||||
return protocol.ArtifactChunkUploadRequest{RunEndpointID: "run-local", SessionToken: "session-token", TransferID: "transfer-1", ArtifactID: "artifact-1", ChunkIndex: 0, Offset: 0, SizeBytes: 7, Checksum: validSHA256Checksum(), Payload: []byte("payload")}
|
||||
}
|
||||
|
||||
func validClientArtifactStatus() protocol.ArtifactTransferStatusRequest {
|
||||
return protocol.ArtifactTransferStatusRequest{RunEndpointID: "run-local", SessionToken: "session-token", TransferID: "transfer-1", ArtifactID: "artifact-1"}
|
||||
}
|
||||
|
||||
func validClientArtifactComplete() protocol.ArtifactTransferCompleteRequest {
|
||||
return protocol.ArtifactTransferCompleteRequest{RunEndpointID: "run-local", SessionToken: "session-token", TransferID: "transfer-1", ArtifactID: "artifact-1", Checksum: validSHA256Checksum(), SizeBytes: 7}
|
||||
}
|
||||
|
||||
func validArtifactOpenResponse() protocol.ArtifactTransferOpenResponse {
|
||||
return protocol.ArtifactTransferOpenResponse{Accepted: true, TransferID: "transfer-1", Direction: "upload", Artifact: validArtifactMetadata("uploading"), TotalChunks: 2, ChunkSizeBytes: 8, NextMissingChunkIndex: 0, ServerTime: fixedClientTestTime()}
|
||||
}
|
||||
|
||||
func validArtifactMetadata(state string) protocol.ArtifactMetadata {
|
||||
return protocol.ArtifactMetadata{ID: "artifact-1", OwnerKind: "job", OwnerID: "job-1", SizeBytes: 7, Checksum: validSHA256Checksum(), State: state, CreatedAt: fixedClientTestTime(), UpdatedAt: fixedClientTestTime()}
|
||||
}
|
||||
|
||||
func validSHA256Checksum() string {
|
||||
return "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
}
|
||||
|
||||
func containsJSONPayloadField(encoded []byte) bool {
|
||||
var body map[string]any
|
||||
if err := json.Unmarshal(encoded, &body); err != nil {
|
||||
return false
|
||||
}
|
||||
_, exists := body["payload"]
|
||||
return exists
|
||||
}
|
||||
Reference in New Issue
Block a user