Something went wrong. Try again.
A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
Something went wrong. Try again.
12 kB · 361 lines
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362package db
import ( "database/sql" "testing")
func TestAnnotations_Placeholder(t *testing.T) { // Placeholder test for annotations package // GetRepositoryAnnotations returns map[string]string annotations := make(map[string]string) annotations["test"] = "value"
if annotations["test"] != "value" { t.Error("Expected annotation value to be stored") }}
// Integration tests
func setupAnnotationsTestDB(t *testing.T) *sql.DB { t.Helper() // Use file::memory: with cache=shared to ensure all connections share the same in-memory DB db, err := InitDB("file::memory:?cache=shared", true) if err != nil { t.Fatalf("Failed to initialize test database: %v", err) } // Limit to single connection to avoid race conditions in tests db.SetMaxOpenConns(1) t.Cleanup(func() { db.Close() }) return db}
func createAnnotationTestUser(t *testing.T, db *sql.DB, did, handle string) { t.Helper() _, err := db.Exec(` INSERT OR IGNORE INTO users (did, handle, pds_endpoint, last_seen) VALUES (?, ?, ?, datetime('now')) `, did, handle, "https://pds.example.com") if err != nil { t.Fatalf("Failed to create test user: %v", err) }}
// TestGetRepositoryAnnotations_Empty tests retrieving from empty repositoryfunc TestGetRepositoryAnnotations_Empty(t *testing.T) { db := setupAnnotationsTestDB(t)
annotations, err := GetRepositoryAnnotations(db, "did:plc:alice123", "myapp") if err != nil { t.Fatalf("GetRepositoryAnnotations() error = %v", err) }
if len(annotations) != 0 { t.Errorf("Expected empty annotations, got %d entries", len(annotations)) }}
// TestGetRepositoryAnnotations_WithData tests retrieving existing annotationsfunc TestGetRepositoryAnnotations_WithData(t *testing.T) { db := setupAnnotationsTestDB(t) createAnnotationTestUser(t, db, "did:plc:alice123", "alice.bsky.social")
// Insert test annotations testAnnotations := map[string]string{ "org.opencontainers.image.title": "My App", "org.opencontainers.image.description": "A test application", "org.opencontainers.image.version": "1.0.0", }
err := UpsertRepositoryAnnotations(db, "did:plc:alice123", "myapp", testAnnotations) if err != nil { t.Fatalf("UpsertRepositoryAnnotations() error = %v", err) }
// Retrieve annotations annotations, err := GetRepositoryAnnotations(db, "did:plc:alice123", "myapp") if err != nil { t.Fatalf("GetRepositoryAnnotations() error = %v", err) }
if len(annotations) != len(testAnnotations) { t.Errorf("Expected %d annotations, got %d", len(testAnnotations), len(annotations)) }
for key, expectedValue := range testAnnotations { if actualValue, ok := annotations[key]; !ok { t.Errorf("Missing annotation key: %s", key) } else if actualValue != expectedValue { t.Errorf("Annotation[%s] = %v, want %v", key, actualValue, expectedValue) } }}
// TestUpsertRepositoryAnnotations_Insert tests inserting new annotationsfunc TestUpsertRepositoryAnnotations_Insert(t *testing.T) { db := setupAnnotationsTestDB(t) createAnnotationTestUser(t, db, "did:plc:bob456", "bob.bsky.social")
annotations := map[string]string{ "key1": "value1", "key2": "value2", }
err := UpsertRepositoryAnnotations(db, "did:plc:bob456", "testapp", annotations) if err != nil { t.Fatalf("UpsertRepositoryAnnotations() error = %v", err) }
// Verify annotations were inserted retrieved, err := GetRepositoryAnnotations(db, "did:plc:bob456", "testapp") if err != nil { t.Fatalf("GetRepositoryAnnotations() error = %v", err) }
if len(retrieved) != len(annotations) { t.Errorf("Expected %d annotations, got %d", len(annotations), len(retrieved)) }
for key, expectedValue := range annotations { if actualValue := retrieved[key]; actualValue != expectedValue { t.Errorf("Annotation[%s] = %v, want %v", key, actualValue, expectedValue) } }}
// TestUpsertRepositoryAnnotations_Update tests updating existing annotationsfunc TestUpsertRepositoryAnnotations_Update(t *testing.T) { db := setupAnnotationsTestDB(t) createAnnotationTestUser(t, db, "did:plc:charlie789", "charlie.bsky.social")
// Insert initial annotations initial := map[string]string{ "key1": "oldvalue1", "key2": "oldvalue2", "key3": "oldvalue3", }
err := UpsertRepositoryAnnotations(db, "did:plc:charlie789", "updateapp", initial) if err != nil { t.Fatalf("Initial UpsertRepositoryAnnotations() error = %v", err) }
// Update with new annotations (completely replaces old ones) updated := map[string]string{ "key1": "newvalue1", // Updated "key4": "newvalue4", // New key (key2 and key3 removed) }
err = UpsertRepositoryAnnotations(db, "did:plc:charlie789", "updateapp", updated) if err != nil { t.Fatalf("Update UpsertRepositoryAnnotations() error = %v", err) }
// Verify annotations were replaced retrieved, err := GetRepositoryAnnotations(db, "did:plc:charlie789", "updateapp") if err != nil { t.Fatalf("GetRepositoryAnnotations() error = %v", err) }
if len(retrieved) != len(updated) { t.Errorf("Expected %d annotations, got %d", len(updated), len(retrieved)) }
// Verify new values if retrieved["key1"] != "newvalue1" { t.Errorf("key1 = %v, want newvalue1", retrieved["key1"]) } if retrieved["key4"] != "newvalue4" { t.Errorf("key4 = %v, want newvalue4", retrieved["key4"]) }
// Verify old keys were removed if _, exists := retrieved["key2"]; exists { t.Error("key2 should have been removed") } if _, exists := retrieved["key3"]; exists { t.Error("key3 should have been removed") }}
// TestUpsertRepositoryAnnotations_EmptyMap tests upserting with empty mapfunc TestUpsertRepositoryAnnotations_EmptyMap(t *testing.T) { db := setupAnnotationsTestDB(t) createAnnotationTestUser(t, db, "did:plc:dave111", "dave.bsky.social")
// Insert initial annotations initial := map[string]string{ "key1": "value1", "key2": "value2", }
err := UpsertRepositoryAnnotations(db, "did:plc:dave111", "emptyapp", initial) if err != nil { t.Fatalf("Initial UpsertRepositoryAnnotations() error = %v", err) }
// Upsert with empty map (should delete all) empty := make(map[string]string)
err = UpsertRepositoryAnnotations(db, "did:plc:dave111", "emptyapp", empty) if err != nil { t.Fatalf("Empty UpsertRepositoryAnnotations() error = %v", err) }
// Verify all annotations were deleted retrieved, err := GetRepositoryAnnotations(db, "did:plc:dave111", "emptyapp") if err != nil { t.Fatalf("GetRepositoryAnnotations() error = %v", err) }
if len(retrieved) != 0 { t.Errorf("Expected 0 annotations after empty upsert, got %d", len(retrieved)) }}
// TestUpsertRepositoryAnnotations_MultipleRepos tests isolation between repositoriesfunc TestUpsertRepositoryAnnotations_MultipleRepos(t *testing.T) { db := setupAnnotationsTestDB(t) createAnnotationTestUser(t, db, "did:plc:eve222", "eve.bsky.social")
// Insert annotations for repo1 repo1Annotations := map[string]string{ "repo": "repo1", "key1": "value1", } err := UpsertRepositoryAnnotations(db, "did:plc:eve222", "repo1", repo1Annotations) if err != nil { t.Fatalf("UpsertRepositoryAnnotations(repo1) error = %v", err) }
// Insert annotations for repo2 (same DID, different repo) repo2Annotations := map[string]string{ "repo": "repo2", "key2": "value2", } err = UpsertRepositoryAnnotations(db, "did:plc:eve222", "repo2", repo2Annotations) if err != nil { t.Fatalf("UpsertRepositoryAnnotations(repo2) error = %v", err) }
// Verify repo1 annotations unchanged retrieved1, err := GetRepositoryAnnotations(db, "did:plc:eve222", "repo1") if err != nil { t.Fatalf("GetRepositoryAnnotations(repo1) error = %v", err) } if len(retrieved1) != len(repo1Annotations) { t.Errorf("repo1: Expected %d annotations, got %d", len(repo1Annotations), len(retrieved1)) } if retrieved1["repo"] != "repo1" { t.Errorf("repo1: Expected repo=repo1, got %v", retrieved1["repo"]) }
// Verify repo2 annotations retrieved2, err := GetRepositoryAnnotations(db, "did:plc:eve222", "repo2") if err != nil { t.Fatalf("GetRepositoryAnnotations(repo2) error = %v", err) } if len(retrieved2) != len(repo2Annotations) { t.Errorf("repo2: Expected %d annotations, got %d", len(repo2Annotations), len(retrieved2)) } if retrieved2["repo"] != "repo2" { t.Errorf("repo2: Expected repo=repo2, got %v", retrieved2["repo"]) }}
// TestDeleteRepositoryAnnotations tests deleting annotationsfunc TestDeleteRepositoryAnnotations(t *testing.T) { db := setupAnnotationsTestDB(t) createAnnotationTestUser(t, db, "did:plc:frank333", "frank.bsky.social")
// Insert annotations annotations := map[string]string{ "key1": "value1", "key2": "value2", } err := UpsertRepositoryAnnotations(db, "did:plc:frank333", "deleteapp", annotations) if err != nil { t.Fatalf("UpsertRepositoryAnnotations() error = %v", err) }
// Verify annotations exist retrieved, err := GetRepositoryAnnotations(db, "did:plc:frank333", "deleteapp") if err != nil { t.Fatalf("GetRepositoryAnnotations() error = %v", err) } if len(retrieved) != 2 { t.Fatalf("Expected 2 annotations before delete, got %d", len(retrieved)) }
// Delete annotations err = DeleteRepositoryAnnotations(db, "did:plc:frank333", "deleteapp") if err != nil { t.Fatalf("DeleteRepositoryAnnotations() error = %v", err) }
// Verify annotations were deleted retrieved, err = GetRepositoryAnnotations(db, "did:plc:frank333", "deleteapp") if err != nil { t.Fatalf("GetRepositoryAnnotations() after delete error = %v", err) } if len(retrieved) != 0 { t.Errorf("Expected 0 annotations after delete, got %d", len(retrieved)) }}
// TestDeleteRepositoryAnnotations_NonExistent tests deleting non-existent annotationsfunc TestDeleteRepositoryAnnotations_NonExistent(t *testing.T) { db := setupAnnotationsTestDB(t)
// Delete from non-existent repository (should not error) err := DeleteRepositoryAnnotations(db, "did:plc:ghost999", "nonexistent") if err != nil { t.Errorf("DeleteRepositoryAnnotations() for non-existent repo should not error, got: %v", err) }}
// TestAnnotations_DifferentDIDs tests isolation between different DIDsfunc TestAnnotations_DifferentDIDs(t *testing.T) { db := setupAnnotationsTestDB(t) createAnnotationTestUser(t, db, "did:plc:alice123", "alice.bsky.social") createAnnotationTestUser(t, db, "did:plc:bob456", "bob.bsky.social")
// Insert annotations for alice aliceAnnotations := map[string]string{ "owner": "alice", "key1": "alice-value1", } err := UpsertRepositoryAnnotations(db, "did:plc:alice123", "sharedname", aliceAnnotations) if err != nil { t.Fatalf("UpsertRepositoryAnnotations(alice) error = %v", err) }
// Insert annotations for bob (same repo name, different DID) bobAnnotations := map[string]string{ "owner": "bob", "key1": "bob-value1", } err = UpsertRepositoryAnnotations(db, "did:plc:bob456", "sharedname", bobAnnotations) if err != nil { t.Fatalf("UpsertRepositoryAnnotations(bob) error = %v", err) }
// Verify alice's annotations unchanged aliceRetrieved, err := GetRepositoryAnnotations(db, "did:plc:alice123", "sharedname") if err != nil { t.Fatalf("GetRepositoryAnnotations(alice) error = %v", err) } if aliceRetrieved["owner"] != "alice" { t.Errorf("alice: Expected owner=alice, got %v", aliceRetrieved["owner"]) }
// Verify bob's annotations bobRetrieved, err := GetRepositoryAnnotations(db, "did:plc:bob456", "sharedname") if err != nil { t.Fatalf("GetRepositoryAnnotations(bob) error = %v", err) } if bobRetrieved["owner"] != "bob" { t.Errorf("bob: Expected owner=bob, got %v", bobRetrieved["owner"]) }}