package barrier import ( "context" "path/filepath" "testing" "git.wntrmute.dev/kyle/metacrypt/internal/crypto" "git.wntrmute.dev/kyle/metacrypt/internal/db" ) func setupBarrier(t *testing.T) (*AESGCMBarrier, func()) { t.Helper() dir := t.TempDir() database, err := db.Open(filepath.Join(dir, "test.db")) if err != nil { t.Fatalf("open db: %v", err) } if err := db.Migrate(database); err != nil { t.Fatalf("migrate: %v", err) } b := NewAESGCMBarrier(database) return b, func() { database.Close() } } func TestBarrierSealUnseal(t *testing.T) { b, cleanup := setupBarrier(t) defer cleanup() if !b.IsSealed() { t.Fatal("new barrier should be sealed") } mek, _ := crypto.GenerateKey() if err := b.Unseal(mek); err != nil { t.Fatalf("Unseal: %v", err) } if b.IsSealed() { t.Fatal("barrier should be unsealed") } if err := b.Seal(); err != nil { t.Fatalf("Seal: %v", err) } if !b.IsSealed() { t.Fatal("barrier should be sealed after Seal()") } } func TestBarrierPutGet(t *testing.T) { b, cleanup := setupBarrier(t) defer cleanup() ctx := context.Background() mek, _ := crypto.GenerateKey() b.Unseal(mek) data := []byte("test value") if err := b.Put(ctx, "test/path", data); err != nil { t.Fatalf("Put: %v", err) } got, err := b.Get(ctx, "test/path") if err != nil { t.Fatalf("Get: %v", err) } if string(got) != string(data) { t.Fatalf("Get: got %q, want %q", got, data) } } func TestBarrierGetNotFound(t *testing.T) { b, cleanup := setupBarrier(t) defer cleanup() ctx := context.Background() mek, _ := crypto.GenerateKey() b.Unseal(mek) _, err := b.Get(ctx, "nonexistent") if err != ErrNotFound { t.Fatalf("expected ErrNotFound, got: %v", err) } } func TestBarrierDelete(t *testing.T) { b, cleanup := setupBarrier(t) defer cleanup() ctx := context.Background() mek, _ := crypto.GenerateKey() b.Unseal(mek) b.Put(ctx, "test/delete-me", []byte("data")) if err := b.Delete(ctx, "test/delete-me"); err != nil { t.Fatalf("Delete: %v", err) } _, err := b.Get(ctx, "test/delete-me") if err != ErrNotFound { t.Fatalf("expected ErrNotFound after delete, got: %v", err) } } func TestBarrierList(t *testing.T) { b, cleanup := setupBarrier(t) defer cleanup() ctx := context.Background() mek, _ := crypto.GenerateKey() b.Unseal(mek) b.Put(ctx, "engine/ca/default/config", []byte("cfg")) b.Put(ctx, "engine/ca/default/dek", []byte("key")) b.Put(ctx, "engine/transit/main/config", []byte("cfg")) paths, err := b.List(ctx, "engine/ca/") if err != nil { t.Fatalf("List: %v", err) } if len(paths) != 2 { t.Fatalf("List: got %d paths, want 2", len(paths)) } } func TestBarrierSealedOperations(t *testing.T) { b, cleanup := setupBarrier(t) defer cleanup() ctx := context.Background() if _, err := b.Get(ctx, "test"); err != ErrSealed { t.Fatalf("Get when sealed: expected ErrSealed, got: %v", err) } if err := b.Put(ctx, "test", []byte("data")); err != ErrSealed { t.Fatalf("Put when sealed: expected ErrSealed, got: %v", err) } if err := b.Delete(ctx, "test"); err != ErrSealed { t.Fatalf("Delete when sealed: expected ErrSealed, got: %v", err) } if _, err := b.List(ctx, "test"); err != ErrSealed { t.Fatalf("List when sealed: expected ErrSealed, got: %v", err) } } func TestBarrierOverwrite(t *testing.T) { b, cleanup := setupBarrier(t) defer cleanup() ctx := context.Background() mek, _ := crypto.GenerateKey() b.Unseal(mek) b.Put(ctx, "test/overwrite", []byte("v1")) b.Put(ctx, "test/overwrite", []byte("v2")) got, _ := b.Get(ctx, "test/overwrite") if string(got) != "v2" { t.Fatalf("overwrite: got %q, want %q", got, "v2") } }