61 lines
1.4 KiB
Go
61 lines
1.4 KiB
Go
package integration
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/any-hub/any-hub/internal/cache"
|
|
)
|
|
|
|
func TestCacheWriteCleanupOnInterruptedStream(t *testing.T) {
|
|
tmpDir := t.TempDir()
|
|
store, err := cache.NewStore(tmpDir)
|
|
if err != nil {
|
|
t.Fatalf("store init error: %v", err)
|
|
}
|
|
|
|
loc := cache.Locator{HubName: "docker", Path: "/interrupt/blob.tar"}
|
|
|
|
reader := &flakyReader{
|
|
payload: []byte("partial_data"),
|
|
failAfter: 5,
|
|
}
|
|
|
|
if _, err := store.Put(context.Background(), loc, reader, cache.PutOptions{}); err == nil {
|
|
t.Fatalf("expected error from interrupted reader")
|
|
}
|
|
|
|
target := filepath.Join(tmpDir, "docker", "interrupt", "blob.tar")
|
|
if _, err := os.Stat(target); !errors.Is(err, os.ErrNotExist) {
|
|
t.Fatalf("expected no final file, got err=%v", err)
|
|
}
|
|
pattern := filepath.Join(tmpDir, "docker", "interrupt", ".cache-*")
|
|
matches, _ := filepath.Glob(pattern)
|
|
if len(matches) != 0 {
|
|
t.Fatalf("temporary files should be cleaned up, found %v", matches)
|
|
}
|
|
}
|
|
|
|
type flakyReader struct {
|
|
payload []byte
|
|
failAfter int
|
|
readBytes int
|
|
}
|
|
|
|
func (f *flakyReader) Read(p []byte) (int, error) {
|
|
if f.readBytes >= f.failAfter {
|
|
return 0, io.ErrUnexpectedEOF
|
|
}
|
|
remaining := f.failAfter - f.readBytes
|
|
if remaining > len(p) {
|
|
remaining = len(p)
|
|
}
|
|
copy(p[:remaining], f.payload[f.readBytes:f.readBytes+remaining])
|
|
f.readBytes += remaining
|
|
return remaining, nil
|
|
}
|