mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-08-29 04:06:58 +00:00
215 lines
6.2 KiB
Go
215 lines
6.2 KiB
Go
package db
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
const testLabelerSrc = "did:plc:labeler"
|
|
|
|
// TestSetTakedown_RepoLevel verifies that an exact-repo row blocks only that
|
|
// repo and leaves siblings untouched.
|
|
func TestSetTakedown_RepoLevel(t *testing.T) {
|
|
db, err := InitDB("file:TestSetTakedown_RepoLevel?mode=memory&cache=shared", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("init db: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
if err := SetTakedown(db, testLabelerSrc, "did:plc:user", "myrepo", time.Now().UTC()); err != nil {
|
|
t.Fatalf("set takedown: %v", err)
|
|
}
|
|
|
|
hit, err := IsTakenDown(db, "did:plc:user", "myrepo")
|
|
if err != nil {
|
|
t.Fatalf("is taken down (target): %v", err)
|
|
}
|
|
if !hit {
|
|
t.Fatal("expected target repo to be taken down")
|
|
}
|
|
|
|
hit, err = IsTakenDown(db, "did:plc:user", "otherrepo")
|
|
if err != nil {
|
|
t.Fatalf("is taken down (sibling): %v", err)
|
|
}
|
|
if hit {
|
|
t.Fatal("sibling repo should not be taken down")
|
|
}
|
|
|
|
hit, err = IsTakenDown(db, "did:plc:other", "myrepo")
|
|
if err != nil {
|
|
t.Fatalf("is taken down (other did): %v", err)
|
|
}
|
|
if hit {
|
|
t.Fatal("repo on different did should not be taken down")
|
|
}
|
|
}
|
|
|
|
// TestSetTakedown_UserLevel verifies that a user-level row (repo=”) matches
|
|
// any repo lookup for that DID.
|
|
func TestSetTakedown_UserLevel(t *testing.T) {
|
|
db, err := InitDB("file:TestSetTakedown_UserLevel?mode=memory&cache=shared", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("init db: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
if err := SetTakedown(db, testLabelerSrc, "did:plc:user", "", time.Now().UTC()); err != nil {
|
|
t.Fatalf("set user-level takedown: %v", err)
|
|
}
|
|
|
|
for _, repo := range []string{"alpha", "beta", "anything"} {
|
|
hit, err := IsTakenDown(db, "did:plc:user", repo)
|
|
if err != nil {
|
|
t.Fatalf("is taken down %q: %v", repo, err)
|
|
}
|
|
if !hit {
|
|
t.Fatalf("user-level takedown should cover repo %q", repo)
|
|
}
|
|
}
|
|
|
|
hit, err := IsTakenDown(db, "did:plc:bystander", "alpha")
|
|
if err != nil {
|
|
t.Fatalf("is taken down (bystander): %v", err)
|
|
}
|
|
if hit {
|
|
t.Fatal("user-level takedown should not affect a different did")
|
|
}
|
|
}
|
|
|
|
// TestRemoveTakedown_Idempotent verifies that removing a missing row is a
|
|
// no-op and removing an existing row flips IsTakenDown back to false.
|
|
func TestRemoveTakedown_Idempotent(t *testing.T) {
|
|
db, err := InitDB("file:TestRemoveTakedown_Idempotent?mode=memory&cache=shared", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("init db: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
if err := RemoveTakedown(db, testLabelerSrc, "did:plc:ghost", "ghost"); err != nil {
|
|
t.Fatalf("remove missing row: %v", err)
|
|
}
|
|
|
|
if err := SetTakedown(db, testLabelerSrc, "did:plc:user", "myrepo", time.Now().UTC()); err != nil {
|
|
t.Fatalf("set takedown: %v", err)
|
|
}
|
|
if err := RemoveTakedown(db, testLabelerSrc, "did:plc:user", "myrepo"); err != nil {
|
|
t.Fatalf("remove existing row: %v", err)
|
|
}
|
|
|
|
hit, err := IsTakenDown(db, "did:plc:user", "myrepo")
|
|
if err != nil {
|
|
t.Fatalf("is taken down after remove: %v", err)
|
|
}
|
|
if hit {
|
|
t.Fatal("expected takedown to be cleared after remove")
|
|
}
|
|
}
|
|
|
|
// TestSetTakedown_OnConflictUpdatesCts verifies that re-applying with a later
|
|
// cts updates the row's timestamp instead of inserting a duplicate.
|
|
func TestSetTakedown_OnConflictUpdatesCts(t *testing.T) {
|
|
db, err := InitDB("file:TestSetTakedown_OnConflictUpdatesCts?mode=memory&cache=shared", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("init db: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
earlier := time.Now().Add(-2 * time.Hour).UTC().Truncate(time.Second)
|
|
later := time.Now().UTC().Truncate(time.Second)
|
|
|
|
if err := SetTakedown(db, testLabelerSrc, "did:plc:user", "repo", earlier); err != nil {
|
|
t.Fatalf("set initial: %v", err)
|
|
}
|
|
if err := SetTakedown(db, testLabelerSrc, "did:plc:user", "repo", later); err != nil {
|
|
t.Fatalf("set update: %v", err)
|
|
}
|
|
|
|
var stored string
|
|
err = db.QueryRow(
|
|
`SELECT cts FROM taken_down_subjects WHERE src=? AND did=? AND repo=?`,
|
|
testLabelerSrc, "did:plc:user", "repo",
|
|
).Scan(&stored)
|
|
if err != nil {
|
|
t.Fatalf("query cts: %v", err)
|
|
}
|
|
got, err := time.Parse(time.RFC3339, stored)
|
|
if err != nil {
|
|
t.Fatalf("parse stored cts %q: %v", stored, err)
|
|
}
|
|
if !got.Equal(later) {
|
|
t.Fatalf("expected cts to be updated to %s, got %s", later, got)
|
|
}
|
|
}
|
|
|
|
// TestCursor_GetSetRoundtrip verifies that an unknown src returns 0 and
|
|
// SetCursor/GetCursor round-trip and overwrite.
|
|
func TestCursor_GetSetRoundtrip(t *testing.T) {
|
|
db, err := InitDB("file:TestCursor_GetSetRoundtrip?mode=memory&cache=shared", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("init db: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
got, err := GetCursor(db, "did:plc:nobody")
|
|
if err != nil {
|
|
t.Fatalf("get cursor unknown: %v", err)
|
|
}
|
|
if got != 0 {
|
|
t.Fatalf("expected 0 for unknown src, got %d", got)
|
|
}
|
|
|
|
if err := SetCursor(db, testLabelerSrc, 42); err != nil {
|
|
t.Fatalf("set cursor: %v", err)
|
|
}
|
|
got, err = GetCursor(db, testLabelerSrc)
|
|
if err != nil {
|
|
t.Fatalf("get cursor after set: %v", err)
|
|
}
|
|
if got != 42 {
|
|
t.Fatalf("expected 42, got %d", got)
|
|
}
|
|
|
|
if err := SetCursor(db, testLabelerSrc, 7); err != nil {
|
|
t.Fatalf("set cursor (overwrite): %v", err)
|
|
}
|
|
got, err = GetCursor(db, testLabelerSrc)
|
|
if err != nil {
|
|
t.Fatalf("get cursor after overwrite: %v", err)
|
|
}
|
|
if got != 7 {
|
|
t.Fatalf("expected 7 after overwrite, got %d", got)
|
|
}
|
|
}
|
|
|
|
// TestSetTakedown_PerSrcIsolation verifies that two labeler srcs can each
|
|
// own a row for the same (did, repo) and removing one src's row leaves the
|
|
// other intact.
|
|
func TestSetTakedown_PerSrcIsolation(t *testing.T) {
|
|
db, err := InitDB("file:TestSetTakedown_PerSrcIsolation?mode=memory&cache=shared", LibsqlConfig{})
|
|
if err != nil {
|
|
t.Fatalf("init db: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
now := time.Now().UTC()
|
|
if err := SetTakedown(db, "did:plc:labeler-a", "did:plc:user", "repo", now); err != nil {
|
|
t.Fatalf("set src a: %v", err)
|
|
}
|
|
if err := SetTakedown(db, "did:plc:labeler-b", "did:plc:user", "repo", now); err != nil {
|
|
t.Fatalf("set src b: %v", err)
|
|
}
|
|
|
|
if err := RemoveTakedown(db, "did:plc:labeler-a", "did:plc:user", "repo"); err != nil {
|
|
t.Fatalf("remove src a: %v", err)
|
|
}
|
|
|
|
hit, err := IsTakenDown(db, "did:plc:user", "repo")
|
|
if err != nil {
|
|
t.Fatalf("is taken down: %v", err)
|
|
}
|
|
if !hit {
|
|
t.Fatal("repo should still be taken down by src b after src a row removed")
|
|
}
|
|
}
|