package storage import ( "context" "errors" "fmt" "testing" "time" ) func newUploadRepo(t *testing.T) *UploadRepo { t.Helper() db, err := Open(":memory:") if err != nil { t.Fatalf("Open in-memory db: %v", err) } t.Cleanup(func() { _ = db.Close() }) return db.Uploads() } func assertUploadEqual(t *testing.T, got, want UploadMeta) { t.Helper() if got.FileID != want.FileID { t.Errorf("FileID: got %q, want %q", got.FileID, want.FileID) } if got.Name != want.Name { t.Errorf("Name: got %q, want %q", got.Name, want.Name) } if got.Size != want.Size { t.Errorf("Size: got %d, want %d", got.Size, want.Size) } if got.SHA256 != want.SHA256 { t.Errorf("SHA256: got %q, want %q", got.SHA256, want.SHA256) } if !got.UploadedAt.Equal(want.UploadedAt) { t.Errorf("UploadedAt: got %v, want %v", got.UploadedAt, want.UploadedAt) } } func TestUploadRepo_CreateGetListDelete(t *testing.T) { repo := newUploadRepo(t) ctx := context.Background() uploadedAt := time.Unix(0, time.Now().UnixNano()) want := UploadMeta{ FileID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Name: "report.csv", Size: 42, SHA256: "deadbeef", UploadedAt: uploadedAt, } if err := repo.Create(ctx, want.FileID, want.Name, want.Size, want.SHA256, want.UploadedAt); err != nil { t.Fatalf("Create: %v", err) } got, err := repo.Get(ctx, want.FileID) if err != nil { t.Fatalf("Get: %v", err) } assertUploadEqual(t, got, want) if err := repo.Create(ctx, want.FileID, "other", 1, "abcd", time.Now()); err == nil { t.Errorf("duplicate Create succeeded, want error") } list, err := repo.List(ctx, "", 100) if err != nil { t.Fatalf("List: %v", err) } if len(list) != 1 { t.Fatalf("List len: got %d, want 1", len(list)) } assertUploadEqual(t, list[0], want) if err := repo.Delete(ctx, want.FileID); err != nil { t.Fatalf("Delete: %v", err) } if _, err := repo.Get(ctx, want.FileID); !errors.Is(err, ErrNotFound) { t.Fatalf("Get after Delete: got %v, want ErrNotFound", err) } if err := repo.Delete(ctx, want.FileID); !errors.Is(err, ErrNotFound) { t.Fatalf("Delete again: got %v, want ErrNotFound", err) } } func TestUploadRepo_ListOrderAndSearch(t *testing.T) { repo := newUploadRepo(t) ctx := context.Background() base := time.Unix(0, time.Now().UnixNano()) records := []UploadMeta{ {FileID: "00000000000000000000000000000001", Name: "alpha.csv", Size: 1, SHA256: "a", UploadedAt: base.Add(-2 * time.Hour)}, {FileID: "00000000000000000000000000000002", Name: "beta.log", Size: 2, SHA256: "b", UploadedAt: base.Add(-1 * time.Hour)}, {FileID: "00000000000000000000000000000003", Name: "gamma.csv", Size: 3, SHA256: "c", UploadedAt: base}, } for _, r := range records { if err := repo.Create(ctx, r.FileID, r.Name, r.Size, r.SHA256, r.UploadedAt); err != nil { t.Fatalf("Create %s: %v", r.FileID, err) } } all, err := repo.List(ctx, "", 100) if err != nil { t.Fatalf("List: %v", err) } if len(all) != 3 { t.Fatalf("List len: got %d, want 3", len(all)) } wantOrder := []string{"00000000000000000000000000000003", "00000000000000000000000000000002", "00000000000000000000000000000001"} for i, id := range wantOrder { if all[i].FileID != id { t.Errorf("List order[%d]: got %q, want %q", i, all[i].FileID, id) } } csv, err := repo.List(ctx, "csv", 100) if err != nil { t.Fatalf("List search: %v", err) } if len(csv) != 2 { t.Fatalf("search csv len: got %d, want 2", len(csv)) } if csv[0].Name != "gamma.csv" || csv[1].Name != "alpha.csv" { t.Errorf("search csv order: got %v", []string{csv[0].Name, csv[1].Name}) } beta, err := repo.List(ctx, "beta", 100) if err != nil { t.Fatalf("List search beta: %v", err) } if len(beta) != 1 || beta[0].Name != "beta.log" { t.Errorf("search beta: got %+v", beta) } } func TestUploadRepo_ListLimitCap(t *testing.T) { repo := newUploadRepo(t) ctx := context.Background() base := time.Unix(0, time.Now().UnixNano()) for i := 0; i < 10; i++ { id := fmt.Sprintf("%032d", i) if err := repo.Create(ctx, id, "x", int64(i), "h", base.Add(time.Duration(i)*time.Second)); err != nil { t.Fatalf("Create %d: %v", i, err) } } list, err := repo.List(ctx, "", 0) if err != nil { t.Fatalf("List default limit: %v", err) } // Default limit is 100 but only 10 rows exist. if len(list) != 10 { t.Errorf("default limit: got %d, want 10", len(list)) } list, err = repo.List(ctx, "", 501) if err != nil { t.Fatalf("List cap: %v", err) } if len(list) != 10 { t.Errorf("cap limit: got %d, want 10", len(list)) } // Explicit small limit is respected. list, err = repo.List(ctx, "", 3) if err != nil { t.Fatalf("List small limit: %v", err) } if len(list) != 3 { t.Errorf("small limit: got %d, want 3", len(list)) } }