mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-08-29 04:06:58 +00:00
413 lines
9.4 KiB
Go
413 lines
9.4 KiB
Go
package labeler
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestOpenDB(t *testing.T) {
|
|
dir := t.TempDir()
|
|
dbPath := filepath.Join(dir, "subdir", "test.db")
|
|
|
|
db, err := OpenDB(dbPath)
|
|
if err != nil {
|
|
t.Fatalf("OpenDB failed: %v", err)
|
|
}
|
|
defer db.Close()
|
|
|
|
// Verify directory was created
|
|
if _, err := os.Stat(filepath.Dir(dbPath)); os.IsNotExist(err) {
|
|
t.Error("expected directory to be created")
|
|
}
|
|
|
|
// Verify tables exist
|
|
var count int
|
|
err = db.QueryRow("SELECT COUNT(*) FROM labels").Scan(&count)
|
|
if err != nil {
|
|
t.Fatalf("failed to query labels table: %v", err)
|
|
}
|
|
if count != 0 {
|
|
t.Errorf("expected 0 labels, got %d", count)
|
|
}
|
|
}
|
|
|
|
func TestCreateLabel(t *testing.T) {
|
|
dir := t.TempDir()
|
|
db, err := OpenDB(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
now := time.Now().UTC().Truncate(time.Second)
|
|
label := &Label{
|
|
Src: "did:web:labeler.atcr.io",
|
|
URI: "at://did:plc:abc/io.atcr.manifest/sha256-123",
|
|
Val: "!takedown",
|
|
Cts: now,
|
|
SubjectDID: "did:plc:abc",
|
|
SubjectRepo: "myimage",
|
|
}
|
|
|
|
id, err := CreateLabel(db, label)
|
|
if err != nil {
|
|
t.Fatalf("CreateLabel failed: %v", err)
|
|
}
|
|
if id <= 0 {
|
|
t.Errorf("expected positive id, got %d", id)
|
|
}
|
|
|
|
// Verify it was stored
|
|
labels, err := GetLabelsSince(db, 0, 10)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(labels) != 1 {
|
|
t.Fatalf("expected 1 label, got %d", len(labels))
|
|
}
|
|
if labels[0].Src != "did:web:labeler.atcr.io" {
|
|
t.Errorf("expected src did:web:labeler.atcr.io, got %s", labels[0].Src)
|
|
}
|
|
if labels[0].Val != "!takedown" {
|
|
t.Errorf("expected val !takedown, got %s", labels[0].Val)
|
|
}
|
|
if labels[0].SubjectDID != "did:plc:abc" {
|
|
t.Errorf("expected subject_did did:plc:abc, got %s", labels[0].SubjectDID)
|
|
}
|
|
if labels[0].SubjectRepo != "myimage" {
|
|
t.Errorf("expected subject_repo myimage, got %s", labels[0].SubjectRepo)
|
|
}
|
|
}
|
|
|
|
func TestCreateLabel_Upsert(t *testing.T) {
|
|
dir := t.TempDir()
|
|
db, err := OpenDB(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
now := time.Now().UTC()
|
|
label := &Label{
|
|
Src: "did:web:labeler.atcr.io",
|
|
URI: "at://did:plc:abc/io.atcr.manifest/sha256-123",
|
|
Val: "!takedown",
|
|
Cts: now,
|
|
SubjectDID: "did:plc:abc",
|
|
SubjectRepo: "myimage",
|
|
}
|
|
|
|
// First insert
|
|
_, err = CreateLabel(db, label)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Same (src, uri, val) - should upsert, not error
|
|
label.Cts = now.Add(time.Hour)
|
|
_, err = CreateLabel(db, label)
|
|
if err != nil {
|
|
t.Fatalf("upsert should not fail: %v", err)
|
|
}
|
|
|
|
// Should still be 1 label
|
|
labels, err := GetLabelsSince(db, 0, 10)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(labels) != 1 {
|
|
t.Errorf("expected 1 label after upsert, got %d", len(labels))
|
|
}
|
|
}
|
|
|
|
func TestNegateLabel(t *testing.T) {
|
|
dir := t.TempDir()
|
|
db, err := OpenDB(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
src := "did:web:labeler.atcr.io"
|
|
now := time.Now().UTC()
|
|
|
|
// Create a label
|
|
_, err = CreateLabel(db, &Label{
|
|
Src: src, URI: "at://did:plc:abc/io.atcr.manifest/sha256-123",
|
|
Val: "!takedown", Cts: now,
|
|
SubjectDID: "did:plc:abc", SubjectRepo: "myimage",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Negate it
|
|
err = NegateLabel(db, src, "at://did:plc:abc/io.atcr.manifest/sha256-123", "!takedown", "did:plc:abc", "myimage")
|
|
if err != nil {
|
|
t.Fatalf("NegateLabel failed: %v", err)
|
|
}
|
|
|
|
// Should have 2 labels now (original + negation)
|
|
labels, err := GetLabelsSince(db, 0, 10)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(labels) != 2 {
|
|
t.Fatalf("expected 2 labels, got %d", len(labels))
|
|
}
|
|
|
|
// The negation label should have neg=true
|
|
negLabel := labels[1]
|
|
if !negLabel.Neg {
|
|
t.Error("expected negation label to have neg=true")
|
|
}
|
|
}
|
|
|
|
func TestListActiveTakedowns(t *testing.T) {
|
|
dir := t.TempDir()
|
|
db, err := OpenDB(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
src := "did:web:labeler.atcr.io"
|
|
now := time.Now().UTC()
|
|
|
|
// Create 3 labels
|
|
for i, repo := range []string{"repo1", "repo2", "repo3"} {
|
|
_, err = CreateLabel(db, &Label{
|
|
Src: src, URI: "at://did:plc:abc/io.atcr.repo/" + repo,
|
|
Val: "!takedown", Cts: now.Add(time.Duration(i) * time.Minute),
|
|
SubjectDID: "did:plc:abc", SubjectRepo: repo,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// All 3 should be active
|
|
labels, total, err := ListActiveTakedowns(db, 10, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if total != 3 {
|
|
t.Errorf("expected 3 active takedowns, got %d", total)
|
|
}
|
|
if len(labels) != 3 {
|
|
t.Errorf("expected 3 labels returned, got %d", len(labels))
|
|
}
|
|
|
|
// Negate one
|
|
err = NegateLabel(db, src, "at://did:plc:abc/io.atcr.repo/repo2", "!takedown", "did:plc:abc", "repo2")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Should be 2 active
|
|
_, total, err = ListActiveTakedowns(db, 10, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if total != 2 {
|
|
t.Errorf("expected 2 active takedowns after negation, got %d", total)
|
|
}
|
|
}
|
|
|
|
func TestNegateRepoLabels(t *testing.T) {
|
|
dir := t.TempDir()
|
|
db, err := OpenDB(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
src := "did:web:labeler.atcr.io"
|
|
now := time.Now().UTC()
|
|
did := "did:plc:abc"
|
|
|
|
// Create multiple labels for same repo
|
|
uris := []string{
|
|
"at://did:plc:abc/io.atcr.manifest/sha256-111",
|
|
"at://did:plc:abc/io.atcr.manifest/sha256-222",
|
|
"at://did:plc:abc/io.atcr.tag/myimage-latest",
|
|
}
|
|
for _, uri := range uris {
|
|
_, err = CreateLabel(db, &Label{
|
|
Src: src, URI: uri, Val: "!takedown", Cts: now,
|
|
SubjectDID: did, SubjectRepo: "myimage",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Negate all labels for the repo
|
|
err = NegateRepoLabels(db, src, did, "myimage")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Should have 0 active takedowns
|
|
_, total, err := ListActiveTakedowns(db, 10, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if total != 0 {
|
|
t.Errorf("expected 0 active takedowns after repo negation, got %d", total)
|
|
}
|
|
}
|
|
|
|
func TestNegateUserLabels(t *testing.T) {
|
|
dir := t.TempDir()
|
|
db, err := OpenDB(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
src := "did:web:labeler.atcr.io"
|
|
now := time.Now().UTC()
|
|
did := "did:plc:abc"
|
|
|
|
// Create labels for different repos + a user-level label
|
|
_, err = CreateLabel(db, &Label{
|
|
Src: src, URI: "at://did:plc:abc", Val: "!takedown", Cts: now,
|
|
SubjectDID: did, SubjectRepo: "",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = CreateLabel(db, &Label{
|
|
Src: src, URI: "at://did:plc:abc/io.atcr.repo/repo1", Val: "!takedown", Cts: now,
|
|
SubjectDID: did, SubjectRepo: "repo1",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Negate all labels for the user
|
|
err = NegateUserLabels(db, src, did)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// Should have 0 active
|
|
_, total, err := ListActiveTakedowns(db, 10, 0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if total != 0 {
|
|
t.Errorf("expected 0 active takedowns after user negation, got %d", total)
|
|
}
|
|
}
|
|
|
|
func TestGetLabelsSince(t *testing.T) {
|
|
dir := t.TempDir()
|
|
db, err := OpenDB(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
src := "did:web:labeler.atcr.io"
|
|
now := time.Now().UTC()
|
|
|
|
// Create 5 labels
|
|
for i := 0; i < 5; i++ {
|
|
_, err = CreateLabel(db, &Label{
|
|
Src: src, URI: "at://did:plc:abc/io.atcr.manifest/" + string(rune('a'+i)),
|
|
Val: "!takedown", Cts: now.Add(time.Duration(i) * time.Minute),
|
|
SubjectDID: "did:plc:abc", SubjectRepo: "repo",
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Get all since 0
|
|
labels, err := GetLabelsSince(db, 0, 10)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(labels) != 5 {
|
|
t.Errorf("expected 5 labels, got %d", len(labels))
|
|
}
|
|
|
|
// Get since cursor (skip first 3)
|
|
if len(labels) >= 3 {
|
|
cursor := labels[2].ID
|
|
after, err := GetLabelsSince(db, cursor, 10)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(after) != 2 {
|
|
t.Errorf("expected 2 labels after cursor %d, got %d", cursor, len(after))
|
|
}
|
|
}
|
|
|
|
// Get with limit
|
|
limited, err := GetLabelsSince(db, 0, 2)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(limited) != 2 {
|
|
t.Errorf("expected 2 labels with limit, got %d", len(limited))
|
|
}
|
|
}
|
|
|
|
func TestGetLabelsForRepo(t *testing.T) {
|
|
dir := t.TempDir()
|
|
db, err := OpenDB(filepath.Join(dir, "test.db"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer db.Close()
|
|
|
|
src := "did:web:labeler.atcr.io"
|
|
now := time.Now().UTC()
|
|
|
|
// Labels for different repos
|
|
_, _ = CreateLabel(db, &Label{
|
|
Src: src, URI: "at://did:plc:abc/io.atcr.repo/repo1",
|
|
Val: "!takedown", Cts: now, SubjectDID: "did:plc:abc", SubjectRepo: "repo1",
|
|
})
|
|
_, _ = CreateLabel(db, &Label{
|
|
Src: src, URI: "at://did:plc:abc/io.atcr.repo/repo2",
|
|
Val: "!takedown", Cts: now, SubjectDID: "did:plc:abc", SubjectRepo: "repo2",
|
|
})
|
|
_, _ = CreateLabel(db, &Label{
|
|
Src: src, URI: "at://did:plc:def/io.atcr.repo/repo1",
|
|
Val: "!takedown", Cts: now, SubjectDID: "did:plc:def", SubjectRepo: "repo1",
|
|
})
|
|
|
|
// Get labels for specific did+repo
|
|
labels, err := GetLabelsForRepo(db, "did:plc:abc", "repo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(labels) != 1 {
|
|
t.Errorf("expected 1 label for did:plc:abc/repo1, got %d", len(labels))
|
|
}
|
|
|
|
// Different user same repo
|
|
labels, err = GetLabelsForRepo(db, "did:plc:def", "repo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(labels) != 1 {
|
|
t.Errorf("expected 1 label for did:plc:def/repo1, got %d", len(labels))
|
|
}
|
|
|
|
// No labels
|
|
labels, err = GetLabelsForRepo(db, "did:plc:xyz", "repo1")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(labels) != 0 {
|
|
t.Errorf("expected 0 labels for unknown did, got %d", len(labels))
|
|
}
|
|
}
|