package spool import ( "bytes" "os" "strings" "testing" "browser.local/run/protocol" ) func TestArtifactQueueRetainsPendingAndRemovesAcknowledgedChunk(t *testing.T) { queue, err := NewArtifactQueue(t.TempDir()) if err != nil { t.Fatalf("new artifact queue: %v", err) } first := validQueuedArtifactChunk(0) second := validQueuedArtifactChunk(1) if err := queue.Enqueue(first); err != nil { t.Fatalf("enqueue first: %v", err) } metadata, err := os.ReadFile(queue.chunkPath(first)) if err != nil { t.Fatalf("read queued metadata: %v", err) } if strings.Contains(string(metadata), "payload") { t.Fatalf("queued artifact metadata must not JSON encode payload: %s", string(metadata)) } storedPayload, err := os.ReadFile(artifactChunkPayloadPath(queue.chunkPath(first))) if err != nil || !bytes.Equal(storedPayload, first.Payload) { t.Fatalf("queued raw payload mismatch payload=%q err=%v", storedPayload, err) } if err := queue.Enqueue(second); err != nil { t.Fatalf("enqueue second: %v", err) } pending, err := queue.Pending() if err != nil { t.Fatalf("pending before ack: %v", err) } if len(pending) != 2 { t.Fatalf("expected two pending chunks, got %+v", pending) } if err := queue.Ack(protocol.ArtifactChunkUploadResponse{Accepted: true, TransferID: "transfer-1", ArtifactID: "artifact-1", ChunkIndex: 0}); err != nil { t.Fatalf("ack first: %v", err) } pending, err = queue.Pending() if err != nil { t.Fatalf("pending after ack: %v", err) } if len(pending) != 1 || pending[0].ChunkIndex != 1 { t.Fatalf("expected second chunk pending, got %+v", pending) } } func TestArtifactQueueRetainsChunkWhenAckDoesNotMatch(t *testing.T) { queue, err := NewArtifactQueue(t.TempDir()) if err != nil { t.Fatalf("new artifact queue: %v", err) } if err := queue.Enqueue(validQueuedArtifactChunk(0)); err != nil { t.Fatalf("enqueue: %v", err) } if err := queue.Ack(protocol.ArtifactChunkUploadResponse{Accepted: true, TransferID: "transfer-1", ArtifactID: "artifact-1", ChunkIndex: 1}); err != nil { t.Fatalf("ack mismatch: %v", err) } pending, err := queue.Pending() if err != nil { t.Fatalf("pending: %v", err) } if len(pending) != 1 || pending[0].ChunkIndex != 0 { t.Fatalf("expected original chunk pending, got %+v", pending) } } func validQueuedArtifactChunk(index int) protocol.ArtifactChunkUploadRequest { payload := []byte{byte(index), byte(index + 1)} return protocol.ArtifactChunkUploadRequest{ RunEndpointID: "run-local", SessionToken: "session-token", TransferID: "transfer-1", ArtifactID: "artifact-1", ChunkIndex: index, Offset: int64(index * len(payload)), SizeBytes: len(payload), Checksum: "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", Payload: payload, } }