Files

295 lines
6.9 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.LayerRecord
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.LayerRecord{
Type: "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.LayerRecord{
Type: 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.LayerRecord{
Type: 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.LayerRecord{
Type: 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.Type != atproto.LayerCollection {
t.Errorf("Type = %q, want %q", record.Type, 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.Type != atproto.LayerCollection {
t.Errorf("Type = %q, want %q", record.Type, atproto.LayerCollection)
}
if record.Digest != tt.digest {
t.Errorf("Digest = %q, want %q", record.Digest, tt.digest)
}
})
}
}