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 codeberg-source 363 lines 9.7 kB view raw
1package hold 2 3import ( 4 "os" 5 "path/filepath" 6 "testing" 7 "time" 8) 9 10// setupEnv sets environment variables for testing and returns a cleanup function 11func setupEnv(t *testing.T, vars map[string]string) func() { 12 // Save original env 13 original := make(map[string]string) 14 for k := range vars { 15 original[k] = os.Getenv(k) 16 } 17 18 // Set test env vars 19 for k, v := range vars { 20 if err := os.Setenv(k, v); err != nil { 21 t.Fatalf("Failed to set env %s: %v", k, err) 22 } 23 } 24 25 // Return cleanup function 26 return func() { 27 for k, v := range original { 28 if v == "" { 29 os.Unsetenv(k) 30 } else { 31 os.Setenv(k, v) 32 } 33 } 34 } 35} 36 37func TestLoadConfigFromEnv_Success(t *testing.T) { 38 cleanup := setupEnv(t, map[string]string{ 39 "HOLD_PUBLIC_URL": "https://hold.example.com", 40 "HOLD_SERVER_ADDR": ":9000", 41 "HOLD_PUBLIC": "true", 42 "TEST_MODE": "true", 43 "HOLD_OWNER": "did:plc:owner123", 44 "HOLD_ALLOW_ALL_CREW": "true", 45 "STORAGE_DRIVER": "filesystem", 46 "STORAGE_ROOT_DIR": "/tmp/test-storage", 47 "HOLD_DATABASE_DIR": "/tmp/test-db", 48 "HOLD_KEY_PATH": "/tmp/test-key.pem", 49 }) 50 defer cleanup() 51 52 cfg, err := LoadConfigFromEnv() 53 if err != nil { 54 t.Fatalf("Expected success, got error: %v", err) 55 } 56 57 // Verify server config 58 if cfg.Server.PublicURL != "https://hold.example.com" { 59 t.Errorf("Expected PublicURL=https://hold.example.com, got %s", cfg.Server.PublicURL) 60 } 61 if cfg.Server.Addr != ":9000" { 62 t.Errorf("Expected Addr=:9000, got %s", cfg.Server.Addr) 63 } 64 if !cfg.Server.Public { 65 t.Error("Expected Public=true") 66 } 67 if !cfg.Server.TestMode { 68 t.Error("Expected TestMode=true") 69 } 70 if cfg.Server.ReadTimeout != 5*time.Minute { 71 t.Errorf("Expected ReadTimeout=5m, got %v", cfg.Server.ReadTimeout) 72 } 73 74 // Verify registration config 75 if cfg.Registration.OwnerDID != "did:plc:owner123" { 76 t.Errorf("Expected OwnerDID=did:plc:owner123, got %s", cfg.Registration.OwnerDID) 77 } 78 if !cfg.Registration.AllowAllCrew { 79 t.Error("Expected AllowAllCrew=true") 80 } 81 82 // Verify database config 83 if cfg.Database.Path != "/tmp/test-db" { 84 t.Errorf("Expected Database.Path=/tmp/test-db, got %s", cfg.Database.Path) 85 } 86 if cfg.Database.KeyPath != "/tmp/test-key.pem" { 87 t.Errorf("Expected Database.KeyPath=/tmp/test-key.pem, got %s", cfg.Database.KeyPath) 88 } 89} 90 91func TestLoadConfigFromEnv_MissingPublicURL(t *testing.T) { 92 cleanup := setupEnv(t, map[string]string{ 93 "HOLD_PUBLIC_URL": "", // Missing required field 94 "STORAGE_DRIVER": "filesystem", 95 }) 96 defer cleanup() 97 98 _, err := LoadConfigFromEnv() 99 if err == nil { 100 t.Error("Expected error for missing HOLD_PUBLIC_URL") 101 } 102} 103 104func TestLoadConfigFromEnv_Defaults(t *testing.T) { 105 cleanup := setupEnv(t, map[string]string{ 106 "HOLD_PUBLIC_URL": "https://hold.example.com", 107 "STORAGE_DRIVER": "filesystem", 108 // Don't set optional vars - test defaults 109 "HOLD_SERVER_ADDR": "", 110 "HOLD_PUBLIC": "", 111 "TEST_MODE": "", 112 "HOLD_OWNER": "", 113 "HOLD_ALLOW_ALL_CREW": "", 114 "AWS_REGION": "", 115 "STORAGE_ROOT_DIR": "", 116 "HOLD_DATABASE_DIR": "", 117 }) 118 defer cleanup() 119 120 cfg, err := LoadConfigFromEnv() 121 if err != nil { 122 t.Fatalf("Expected success, got error: %v", err) 123 } 124 125 // Verify defaults 126 if cfg.Server.Addr != ":8080" { 127 t.Errorf("Expected default Addr=:8080, got %s", cfg.Server.Addr) 128 } 129 if cfg.Server.Public { 130 t.Error("Expected default Public=false") 131 } 132 if cfg.Server.TestMode { 133 t.Error("Expected default TestMode=false") 134 } 135 if cfg.Server.DisablePresignedURLs { 136 t.Error("Expected default DisablePresignedURLs=false") 137 } 138 if cfg.Registration.OwnerDID != "" { 139 t.Error("Expected default OwnerDID to be empty") 140 } 141 if cfg.Registration.AllowAllCrew { 142 t.Error("Expected default AllowAllCrew=false") 143 } 144 if cfg.Database.Path != "/var/lib/atcr-hold" { 145 t.Errorf("Expected default Database.Path=/var/lib/atcr-hold, got %s", cfg.Database.Path) 146 } 147} 148 149func TestLoadConfigFromEnv_KeyPathDefault(t *testing.T) { 150 cleanup := setupEnv(t, map[string]string{ 151 "HOLD_PUBLIC_URL": "https://hold.example.com", 152 "STORAGE_DRIVER": "filesystem", 153 "HOLD_DATABASE_DIR": "/custom/db/path", 154 "HOLD_KEY_PATH": "", // Should default to {Database.Path}/signing.key 155 }) 156 defer cleanup() 157 158 cfg, err := LoadConfigFromEnv() 159 if err != nil { 160 t.Fatalf("Expected success, got error: %v", err) 161 } 162 163 expectedKeyPath := filepath.Join("/custom/db/path", "signing.key") 164 if cfg.Database.KeyPath != expectedKeyPath { 165 t.Errorf("Expected KeyPath=%s, got %s", expectedKeyPath, cfg.Database.KeyPath) 166 } 167} 168 169func TestLoadConfigFromEnv_DisablePresignedURLs(t *testing.T) { 170 cleanup := setupEnv(t, map[string]string{ 171 "HOLD_PUBLIC_URL": "https://hold.example.com", 172 "STORAGE_DRIVER": "filesystem", 173 "DISABLE_PRESIGNED_URLS": "true", 174 }) 175 defer cleanup() 176 177 cfg, err := LoadConfigFromEnv() 178 if err != nil { 179 t.Fatalf("Expected success, got error: %v", err) 180 } 181 182 if !cfg.Server.DisablePresignedURLs { 183 t.Error("Expected DisablePresignedURLs=true") 184 } 185} 186 187func TestBuildStorageConfig_S3_Complete(t *testing.T) { 188 cleanup := setupEnv(t, map[string]string{ 189 "AWS_ACCESS_KEY_ID": "test-access-key", 190 "AWS_SECRET_ACCESS_KEY": "test-secret-key", 191 "AWS_REGION": "us-west-2", 192 "S3_BUCKET": "test-bucket", 193 "S3_ENDPOINT": "https://s3.example.com", 194 }) 195 defer cleanup() 196 197 cfg, err := buildStorageConfig("s3") 198 if err != nil { 199 t.Fatalf("Expected success, got error: %v", err) 200 } 201 202 s3Params, ok := cfg.Storage["s3"] 203 if !ok { 204 t.Fatal("Expected s3 storage config") 205 } 206 207 params := map[string]any(s3Params) 208 209 if params["accesskey"] != "test-access-key" { 210 t.Errorf("Expected accesskey=test-access-key, got %v", params["accesskey"]) 211 } 212 if params["secretkey"] != "test-secret-key" { 213 t.Errorf("Expected secretkey=test-secret-key, got %v", params["secretkey"]) 214 } 215 if params["region"] != "us-west-2" { 216 t.Errorf("Expected region=us-west-2, got %v", params["region"]) 217 } 218 if params["bucket"] != "test-bucket" { 219 t.Errorf("Expected bucket=test-bucket, got %v", params["bucket"]) 220 } 221 if params["regionendpoint"] != "https://s3.example.com" { 222 t.Errorf("Expected regionendpoint=https://s3.example.com, got %v", params["regionendpoint"]) 223 } 224} 225 226func TestBuildStorageConfig_S3_NoEndpoint(t *testing.T) { 227 cleanup := setupEnv(t, map[string]string{ 228 "AWS_ACCESS_KEY_ID": "test-key", 229 "AWS_SECRET_ACCESS_KEY": "test-secret", 230 "S3_BUCKET": "test-bucket", 231 "S3_ENDPOINT": "", // No custom endpoint 232 "AWS_REGION": "", // Test default region 233 }) 234 defer cleanup() 235 236 cfg, err := buildStorageConfig("s3") 237 if err != nil { 238 t.Fatalf("Expected success, got error: %v", err) 239 } 240 241 s3Params, ok := cfg.Storage["s3"] 242 if !ok { 243 t.Fatal("Expected s3 storage config") 244 } 245 246 params := map[string]any(s3Params) 247 248 // Should have default region 249 if params["region"] != "us-east-1" { 250 t.Errorf("Expected default region=us-east-1, got %v", params["region"]) 251 } 252 253 // Should not have regionendpoint 254 if _, exists := params["regionendpoint"]; exists { 255 t.Error("Expected no regionendpoint when S3_ENDPOINT not set") 256 } 257} 258 259func TestBuildStorageConfig_S3_MissingBucket(t *testing.T) { 260 cleanup := setupEnv(t, map[string]string{ 261 "AWS_ACCESS_KEY_ID": "test-key", 262 "AWS_SECRET_ACCESS_KEY": "test-secret", 263 "S3_BUCKET": "", // Missing required field 264 }) 265 defer cleanup() 266 267 _, err := buildStorageConfig("s3") 268 if err == nil { 269 t.Error("Expected error for missing S3_BUCKET") 270 } 271} 272 273func TestBuildStorageConfig_Filesystem(t *testing.T) { 274 cleanup := setupEnv(t, map[string]string{ 275 "STORAGE_ROOT_DIR": "/custom/storage/path", 276 }) 277 defer cleanup() 278 279 cfg, err := buildStorageConfig("filesystem") 280 if err != nil { 281 t.Fatalf("Expected success, got error: %v", err) 282 } 283 284 fsParams, ok := cfg.Storage["filesystem"] 285 if !ok { 286 t.Fatal("Expected filesystem storage config") 287 } 288 289 params := map[string]any(fsParams) 290 291 if params["rootdirectory"] != "/custom/storage/path" { 292 t.Errorf("Expected rootdirectory=/custom/storage/path, got %v", params["rootdirectory"]) 293 } 294} 295 296func TestBuildStorageConfig_Filesystem_Default(t *testing.T) { 297 cleanup := setupEnv(t, map[string]string{ 298 "STORAGE_ROOT_DIR": "", // Test default 299 }) 300 defer cleanup() 301 302 cfg, err := buildStorageConfig("filesystem") 303 if err != nil { 304 t.Fatalf("Expected success, got error: %v", err) 305 } 306 307 fsParams, ok := cfg.Storage["filesystem"] 308 if !ok { 309 t.Fatal("Expected filesystem storage config") 310 } 311 312 params := map[string]any(fsParams) 313 314 if params["rootdirectory"] != "/var/lib/atcr/hold" { 315 t.Errorf("Expected default rootdirectory=/var/lib/atcr/hold, got %v", params["rootdirectory"]) 316 } 317} 318 319func TestBuildStorageConfig_UnsupportedDriver(t *testing.T) { 320 cleanup := setupEnv(t, map[string]string{}) 321 defer cleanup() 322 323 _, err := buildStorageConfig("azure") 324 if err == nil { 325 t.Error("Expected error for unsupported driver") 326 } 327} 328 329func TestGetEnvOrDefault_Set(t *testing.T) { 330 cleanup := setupEnv(t, map[string]string{ 331 "TEST_VAR": "custom-value", 332 }) 333 defer cleanup() 334 335 result := getEnvOrDefault("TEST_VAR", "default-value") 336 if result != "custom-value" { 337 t.Errorf("Expected custom-value, got %s", result) 338 } 339} 340 341func TestGetEnvOrDefault_NotSet(t *testing.T) { 342 cleanup := setupEnv(t, map[string]string{ 343 "TEST_VAR": "", 344 }) 345 defer cleanup() 346 347 result := getEnvOrDefault("TEST_VAR", "default-value") 348 if result != "default-value" { 349 t.Errorf("Expected default-value, got %s", result) 350 } 351} 352 353func TestGetEnvOrDefault_EmptyString(t *testing.T) { 354 cleanup := setupEnv(t, map[string]string{ 355 "TEST_VAR": "", 356 }) 357 defer cleanup() 358 359 result := getEnvOrDefault("TEST_VAR", "") 360 if result != "" { 361 t.Errorf("Expected empty string, got %s", result) 362 } 363}