mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-08-29 12:17:00 +00:00
295 lines
7.0 KiB
Go
295 lines
7.0 KiB
Go
package pds
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"atcr.io/pkg/atproto"
|
|
)
|
|
|
|
func TestCreateLayerRecord(t *testing.T) {
|
|
// Setup test PDS
|
|
pds, ctx := setupTestPDS(t)
|
|
|
|
tests := []struct {
|
|
name string
|
|
record *atproto.HoldLayer
|
|
wantErr bool
|
|
errSubstr string
|
|
}{
|
|
{
|
|
name: "valid layer record",
|
|
record: atproto.NewLayerRecord(
|
|
"sha256:abc123def456",
|
|
1048576, // 1 MB
|
|
"application/vnd.oci.image.layer.v1.tar+gzip",
|
|
"myapp",
|
|
"did:plc:alice123",
|
|
"alice.bsky.social",
|
|
),
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid layer record with large size",
|
|
record: atproto.NewLayerRecord(
|
|
"sha256:fedcba987654",
|
|
1073741824, // 1 GB
|
|
"application/vnd.docker.image.rootfs.diff.tar.gzip",
|
|
"debian",
|
|
"did:plc:bob456",
|
|
"bob.example.com",
|
|
),
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "invalid record type",
|
|
record: &atproto.HoldLayer{
|
|
LexiconTypeID: "wrong.type",
|
|
Digest: "sha256:abc123",
|
|
Size: 1024,
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Repository: "test",
|
|
UserDid: "did:plc:test",
|
|
UserHandle: "test.example.com",
|
|
},
|
|
wantErr: true,
|
|
errSubstr: "invalid record type",
|
|
},
|
|
{
|
|
name: "missing digest",
|
|
record: &atproto.HoldLayer{
|
|
LexiconTypeID: atproto.LayerCollection,
|
|
Digest: "",
|
|
Size: 1024,
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Repository: "test",
|
|
UserDid: "did:plc:test",
|
|
UserHandle: "test.example.com",
|
|
},
|
|
wantErr: true,
|
|
errSubstr: "digest is required",
|
|
},
|
|
{
|
|
name: "zero size",
|
|
record: &atproto.HoldLayer{
|
|
LexiconTypeID: atproto.LayerCollection,
|
|
Digest: "sha256:abc123",
|
|
Size: 0,
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Repository: "test",
|
|
UserDid: "did:plc:test",
|
|
UserHandle: "test.example.com",
|
|
},
|
|
wantErr: true,
|
|
errSubstr: "size must be positive",
|
|
},
|
|
{
|
|
name: "negative size",
|
|
record: &atproto.HoldLayer{
|
|
LexiconTypeID: atproto.LayerCollection,
|
|
Digest: "sha256:abc123",
|
|
Size: -1,
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Repository: "test",
|
|
UserDid: "did:plc:test",
|
|
UserHandle: "test.example.com",
|
|
},
|
|
wantErr: true,
|
|
errSubstr: "size must be positive",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
rkey, cid, err := pds.CreateLayerRecord(ctx, tt.record)
|
|
|
|
if tt.wantErr {
|
|
if err == nil {
|
|
t.Errorf("CreateLayerRecord() expected error containing %q, got nil", tt.errSubstr)
|
|
return
|
|
}
|
|
if tt.errSubstr != "" && !contains(err.Error(), tt.errSubstr) {
|
|
t.Errorf("CreateLayerRecord() error = %v, want error containing %q", err, tt.errSubstr)
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Errorf("CreateLayerRecord() unexpected error: %v", err)
|
|
return
|
|
}
|
|
|
|
if rkey == "" {
|
|
t.Error("CreateLayerRecord() returned empty rkey")
|
|
}
|
|
|
|
if cid == "" {
|
|
t.Error("CreateLayerRecord() returned empty CID")
|
|
}
|
|
|
|
t.Logf("Created layer record: rkey=%s, cid=%s", rkey, cid)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCreateLayerRecord_MultipleRecords(t *testing.T) {
|
|
// Test creating multiple layer records for the same manifest
|
|
pds, ctx := setupTestPDS(t)
|
|
|
|
layers := []struct {
|
|
digest string
|
|
size int64
|
|
}{
|
|
{"sha256:layer1abc123", 1024},
|
|
{"sha256:layer2def456", 2048},
|
|
{"sha256:layer3ghi789", 4096},
|
|
}
|
|
|
|
createdRKeys := make(map[string]bool)
|
|
|
|
for i, layer := range layers {
|
|
record := atproto.NewLayerRecord(
|
|
layer.digest,
|
|
layer.size,
|
|
"application/vnd.oci.image.layer.v1.tar+gzip",
|
|
"multi-layer-app",
|
|
"did:plc:test123",
|
|
"test.example.com",
|
|
)
|
|
|
|
rkey, cid, err := pds.CreateLayerRecord(ctx, record)
|
|
if err != nil {
|
|
t.Fatalf("CreateLayerRecord() for layer %d failed: %v", i, err)
|
|
}
|
|
|
|
// Ensure unique rkeys
|
|
if createdRKeys[rkey] {
|
|
t.Errorf("CreateLayerRecord() returned duplicate rkey: %s", rkey)
|
|
}
|
|
createdRKeys[rkey] = true
|
|
|
|
t.Logf("Layer %d: rkey=%s, cid=%s", i, rkey, cid)
|
|
}
|
|
|
|
if len(createdRKeys) != len(layers) {
|
|
t.Errorf("Created %d unique rkeys, want %d", len(createdRKeys), len(layers))
|
|
}
|
|
}
|
|
|
|
func TestNewLayerRecord(t *testing.T) {
|
|
// Test the layer record constructor
|
|
digest := "sha256:abc123def456"
|
|
size := int64(1048576)
|
|
mediaType := "application/vnd.oci.image.layer.v1.tar+gzip"
|
|
repository := "myapp"
|
|
userDID := "did:plc:alice123"
|
|
userHandle := "alice.bsky.social"
|
|
|
|
record := atproto.NewLayerRecord(digest, size, mediaType, repository, userDID, userHandle)
|
|
|
|
if record == nil {
|
|
t.Fatal("NewLayerRecord() returned nil")
|
|
}
|
|
|
|
// Verify all fields are set correctly
|
|
if record.LexiconTypeID != atproto.LayerCollection {
|
|
t.Errorf("LexiconTypeID = %q, want %q", record.LexiconTypeID, atproto.LayerCollection)
|
|
}
|
|
|
|
if record.Digest != digest {
|
|
t.Errorf("Digest = %q, want %q", record.Digest, digest)
|
|
}
|
|
|
|
if record.Size != size {
|
|
t.Errorf("Size = %d, want %d", record.Size, size)
|
|
}
|
|
|
|
if record.MediaType != mediaType {
|
|
t.Errorf("MediaType = %q, want %q", record.MediaType, mediaType)
|
|
}
|
|
|
|
if record.Repository != repository {
|
|
t.Errorf("Repository = %q, want %q", record.Repository, repository)
|
|
}
|
|
|
|
if record.UserDid != userDID {
|
|
t.Errorf("UserDid = %q, want %q", record.UserDid, userDID)
|
|
}
|
|
|
|
if record.UserHandle != userHandle {
|
|
t.Errorf("UserHandle = %q, want %q", record.UserHandle, userHandle)
|
|
}
|
|
|
|
if record.CreatedAt == "" {
|
|
t.Error("CreatedAt is empty")
|
|
}
|
|
|
|
t.Logf("Created layer record: %+v", record)
|
|
}
|
|
|
|
func TestLayerRecord_FieldValidation(t *testing.T) {
|
|
// Test various field values
|
|
tests := []struct {
|
|
name string
|
|
digest string
|
|
size int64
|
|
mediaType string
|
|
repository string
|
|
userDID string
|
|
userHandle string
|
|
}{
|
|
{
|
|
name: "typical OCI layer",
|
|
digest: "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
|
|
size: 12582912, // 12 MB
|
|
mediaType: "application/vnd.oci.image.layer.v1.tar+gzip",
|
|
repository: "hsm-secrets-operator",
|
|
userDID: "did:plc:evan123",
|
|
userHandle: "evan.jarrett.net",
|
|
},
|
|
{
|
|
name: "Docker layer format",
|
|
digest: "sha256:abc123",
|
|
size: 1024,
|
|
mediaType: "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
|
repository: "nginx",
|
|
userDID: "did:plc:user456",
|
|
userHandle: "user.example.com",
|
|
},
|
|
{
|
|
name: "uncompressed layer",
|
|
digest: "sha256:def456",
|
|
size: 2048,
|
|
mediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
repository: "alpine",
|
|
userDID: "did:plc:user789",
|
|
userHandle: "user.bsky.social",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
record := atproto.NewLayerRecord(
|
|
tt.digest,
|
|
tt.size,
|
|
tt.mediaType,
|
|
tt.repository,
|
|
tt.userDID,
|
|
tt.userHandle,
|
|
)
|
|
|
|
if record == nil {
|
|
t.Fatal("NewLayerRecord() returned nil")
|
|
}
|
|
|
|
// Verify the record can be created
|
|
if record.LexiconTypeID != atproto.LayerCollection {
|
|
t.Errorf("Type = %q, want %q", record.LexiconTypeID, atproto.LayerCollection)
|
|
}
|
|
|
|
if record.Digest != tt.digest {
|
|
t.Errorf("Digest = %q, want %q", record.Digest, tt.digest)
|
|
}
|
|
})
|
|
}
|
|
}
|