A container registry that uses the AT Protocol for manifest storage and S3 for blob storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 235 lines 5.6 kB view raw
1package s3 2 3import ( 4 "testing" 5 6 "atcr.io/pkg/logging" 7) 8 9func TestNewS3Service_MissingBucket(t *testing.T) { 10 t.Cleanup(logging.SetupTestLogger()) 11 12 params := map[string]any{ 13 "region": "us-east-1", 14 "accesskey": "test-key", 15 "secretkey": "test-secret", 16 // Missing bucket 17 } 18 19 _, err := NewS3Service(params) 20 if err == nil { 21 t.Error("Expected error when bucket is missing") 22 } 23} 24 25func TestNewS3Service_Success(t *testing.T) { 26 t.Cleanup(logging.SetupTestLogger()) 27 28 params := map[string]any{ 29 "bucket": "test-bucket", 30 "region": "us-west-2", 31 "accesskey": "test-access-key", 32 "secretkey": "test-secret-key", 33 } 34 35 service, err := NewS3Service(params) 36 if err != nil { 37 t.Fatalf("Expected success, got error: %v", err) 38 } 39 40 if service.Client == nil { 41 t.Error("Expected Client to be initialized") 42 } 43 if service.Bucket != "test-bucket" { 44 t.Errorf("Expected Bucket=test-bucket, got %s", service.Bucket) 45 } 46 if service.PathPrefix != "" { 47 t.Errorf("Expected empty PathPrefix, got %s", service.PathPrefix) 48 } 49} 50 51func TestNewS3Service_WithEndpoint(t *testing.T) { 52 t.Cleanup(logging.SetupTestLogger()) 53 54 params := map[string]any{ 55 "bucket": "test-bucket", 56 "region": "us-east-1", 57 "accesskey": "test-key", 58 "secretkey": "test-secret", 59 "regionendpoint": "https://s3.storj.io", 60 } 61 62 service, err := NewS3Service(params) 63 if err != nil { 64 t.Fatalf("Expected success with custom endpoint, got error: %v", err) 65 } 66 67 if service.Client == nil { 68 t.Error("Expected Client to be initialized") 69 } 70 if service.Bucket != "test-bucket" { 71 t.Errorf("Expected Bucket=test-bucket, got %s", service.Bucket) 72 } 73} 74 75func TestNewS3Service_DefaultRegion(t *testing.T) { 76 t.Cleanup(logging.SetupTestLogger()) 77 78 params := map[string]any{ 79 "bucket": "test-bucket", 80 "accesskey": "test-key", 81 "secretkey": "test-secret", 82 // No region specified - should use default 83 } 84 85 service, err := NewS3Service(params) 86 if err != nil { 87 t.Fatalf("Expected success with default region, got error: %v", err) 88 } 89 90 if service.Client == nil { 91 t.Error("Expected Client to be initialized") 92 } 93 94 // Note: We can't easily verify the region without accessing private fields 95 // but the fact that it didn't error means it used the default 96} 97 98func TestNewS3Service_WithPathPrefix(t *testing.T) { 99 t.Cleanup(logging.SetupTestLogger()) 100 101 params := map[string]any{ 102 "bucket": "test-bucket", 103 "region": "us-east-1", 104 "accesskey": "test-key", 105 "secretkey": "test-secret", 106 "rootdirectory": "/my/prefix/path", 107 } 108 109 service, err := NewS3Service(params) 110 if err != nil { 111 t.Fatalf("Expected success, got error: %v", err) 112 } 113 114 if service.PathPrefix != "my/prefix/path" { 115 t.Errorf("Expected PathPrefix=my/prefix/path (leading slash stripped), got %s", service.PathPrefix) 116 } 117} 118 119func TestNewS3Service_NoCredentials(t *testing.T) { 120 t.Cleanup(logging.SetupTestLogger()) 121 122 params := map[string]any{ 123 "bucket": "test-bucket", 124 "region": "us-east-1", 125 // No credentials - should allow IAM role auth 126 } 127 128 service, err := NewS3Service(params) 129 if err != nil { 130 t.Fatalf("Expected success without credentials (IAM role), got error: %v", err) 131 } 132 133 if service.Client == nil { 134 t.Error("Expected Client to be initialized") 135 } 136} 137 138func TestBlobPath_SHA256(t *testing.T) { 139 tests := []struct { 140 name string 141 digest string 142 expected string 143 }{ 144 { 145 name: "standard sha256 digest", 146 digest: "sha256:abc123def456", 147 expected: "/docker/registry/v2/blobs/sha256/ab/abc123def456/data", 148 }, 149 { 150 name: "short hash (less than 2 chars)", 151 digest: "sha256:a", 152 expected: "/docker/registry/v2/blobs/sha256/a/data", 153 }, 154 { 155 name: "exactly 2 char hash", 156 digest: "sha256:ab", 157 expected: "/docker/registry/v2/blobs/sha256/ab/ab/data", 158 }, 159 { 160 name: "long sha256", 161 digest: "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 162 expected: "/docker/registry/v2/blobs/sha256/e3/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855/data", 163 }, 164 } 165 166 for _, tt := range tests { 167 t.Run(tt.name, func(t *testing.T) { 168 result := BlobPath(tt.digest) 169 if result != tt.expected { 170 t.Errorf("Expected %s, got %s", tt.expected, result) 171 } 172 }) 173 } 174} 175 176func TestBlobPath_TempUpload(t *testing.T) { 177 tests := []struct { 178 name string 179 digest string 180 expected string 181 }{ 182 { 183 name: "temp upload path", 184 digest: "uploads/temp-uuid-123", 185 expected: "/docker/registry/v2/uploads/temp-uuid-123/data", 186 }, 187 { 188 name: "temp upload with different uuid", 189 digest: "uploads/temp-abc-def-456", 190 expected: "/docker/registry/v2/uploads/temp-abc-def-456/data", 191 }, 192 } 193 194 for _, tt := range tests { 195 t.Run(tt.name, func(t *testing.T) { 196 result := BlobPath(tt.digest) 197 if result != tt.expected { 198 t.Errorf("Expected %s, got %s", tt.expected, result) 199 } 200 }) 201 } 202} 203 204func TestBlobPath_MalformedDigest(t *testing.T) { 205 tests := []struct { 206 name string 207 digest string 208 expected string 209 }{ 210 { 211 name: "no colon in digest", 212 digest: "malformed-digest", 213 expected: "/docker/registry/v2/blobs/malformed-digest/data", 214 }, 215 { 216 name: "empty digest", 217 digest: "", 218 expected: "/docker/registry/v2/blobs//data", 219 }, 220 { 221 name: "only algorithm", 222 digest: "sha256:", 223 expected: "/docker/registry/v2/blobs/sha256//data", 224 }, 225 } 226 227 for _, tt := range tests { 228 t.Run(tt.name, func(t *testing.T) { 229 result := BlobPath(tt.digest) 230 if result != tt.expected { 231 t.Errorf("Expected %s, got %s", tt.expected, result) 232 } 233 }) 234 } 235}