package main import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "os" "testing" "spore-registry/internal/database" "spore-registry/internal/handlers" "spore-registry/internal/models" "spore-registry/internal/repository" "spore-registry/internal/service" "spore-registry/internal/storage" _ "github.com/mattn/go-sqlite3" ) // setupTestDB creates a temporary database for testing func setupTestDB(t *testing.T) (*database.DB, *storage.FileStorage, *handlers.FirmwareHandler) { // Create temporary directory for test registry tmpDir, err := os.MkdirTemp("", "registry_test") if err != nil { t.Fatalf("Failed to create temp dir: %v", err) } // Clean up temporary directory after test defer func() { os.RemoveAll(tmpDir) }() // Create test database db, err := database.NewDB(":memory:") if err != nil { t.Fatalf("Failed to open test database: %v", err) } // Create repository repo := repository.NewFirmwareRepository(db.GetConnection()) // Create storage fileStorage := storage.NewFileStorage(tmpDir) // Create service firmwareService := service.NewFirmwareService(repo, fileStorage) // Create handler handler := handlers.NewFirmwareHandler(firmwareService) return db, fileStorage, handler } func TestStoreFirmwareMetadata(t *testing.T) { db, _, _ := setupTestDB(t) defer db.Close() metadata := models.FirmwareMetadata{ Name: "test-firmware", Version: "1.0.0", Labels: map[string]string{ "app": "test", }, } // Create a test service to test the repository directly repo := repository.NewFirmwareRepository(db.GetConnection()) fileStorage := storage.NewFileStorage("/tmp") service := service.NewFirmwareService(repo, fileStorage) _, err := service.UploadFirmware(metadata, bytes.NewReader([]byte("test data"))) if err != nil { t.Fatalf("Failed to upload firmware: %v", err) } // Verify the record was stored by listing firmware grouped, err := service.ListFirmware("", "") if err != nil { t.Fatalf("Failed to retrieve firmware records: %v", err) } if len(grouped) != 1 { t.Fatalf("Expected 1 group, got %d", len(grouped)) } if len(grouped[0].Firmware) != 1 { t.Fatalf("Expected 1 firmware record, got %d", len(grouped[0].Firmware)) } record := grouped[0].Firmware[0] if record.Name != metadata.Name { t.Errorf("Expected name %s, got %s", metadata.Name, record.Name) } if record.Version != metadata.Version { t.Errorf("Expected version %s, got %s", metadata.Version, record.Version) } if record.Labels["app"] != "test" { t.Errorf("Expected label app=test, got %s", record.Labels["app"]) } } func TestGetFirmwareRecordsWithFilters(t *testing.T) { db, _, _ := setupTestDB(t) defer db.Close() // Create a test service to test the repository directly repo := repository.NewFirmwareRepository(db.GetConnection()) fileStorage := storage.NewFileStorage("/tmp") service := service.NewFirmwareService(repo, fileStorage) // Insert test data testRecords := []models.FirmwareMetadata{ {Name: "firmware1", Version: "1.0.0", Labels: map[string]string{"type": "app"}}, {Name: "firmware1", Version: "1.1.0", Labels: map[string]string{"type": "app"}}, {Name: "firmware2", Version: "1.0.0", Labels: map[string]string{"type": "sensor"}}, } for _, record := range testRecords { _, err := service.UploadFirmware(record, bytes.NewReader([]byte("test data"))) if err != nil { t.Fatalf("Failed to store test data: %v", err) } } // Test filtering by name grouped, err := service.ListFirmware("firmware1", "") if err != nil { t.Fatalf("Failed to get records by name: %v", err) } if len(grouped) != 1 || len(grouped[0].Firmware) != 2 { t.Errorf("Expected 1 group with 2 records for firmware1, got %d groups", len(grouped)) } // Test filtering by version grouped, err = service.ListFirmware("", "1.0.0") if err != nil { t.Fatalf("Failed to get records by version: %v", err) } if len(grouped) != 2 { t.Errorf("Expected 2 groups for version 1.0.0, got %d", len(grouped)) } // Test filtering by both name and version grouped, err = service.ListFirmware("firmware1", "1.0.0") if err != nil { t.Fatalf("Failed to get records by name and version: %v", err) } if len(grouped) != 1 || len(grouped[0].Firmware) != 1 { t.Errorf("Expected 1 group with 1 record for firmware1/1.0.0, got %d groups", len(grouped)) } } func TestStoreFirmwareBinary(t *testing.T) { db, fileStorage, _ := setupTestDB(t) defer db.Close() testData := []byte("test firmware binary data") reader := bytes.NewReader(testData) filePath, size, err := fileStorage.StoreFirmwareBinary("test", "1.0.0", reader) if err != nil { t.Fatalf("Failed to store firmware binary: %v", err) } if size != int64(len(testData)) { t.Errorf("Expected size %d, got %d", len(testData), size) } // Verify file was created if _, err := os.Stat(filePath); os.IsNotExist(err) { t.Errorf("Firmware file was not created at %s", filePath) } // Verify file contents storedData, err := os.ReadFile(filePath) if err != nil { t.Fatalf("Failed to read stored file: %v", err) } if !bytes.Equal(testData, storedData) { t.Error("Stored file contents don't match original data") } } func TestListFirmwareAPI(t *testing.T) { db, _, handler := setupTestDB(t) defer db.Close() // Create a test service to test the repository directly repo := repository.NewFirmwareRepository(db.GetConnection()) fileStorage := storage.NewFileStorage("/tmp") service := service.NewFirmwareService(repo, fileStorage) // Insert test data metadata := models.FirmwareMetadata{ Name: "test-firmware", Version: "1.0.0", Labels: map[string]string{"app": "test"}, } _, err := service.UploadFirmware(metadata, bytes.NewReader([]byte("test data"))) if err != nil { t.Fatalf("Failed to store test data: %v", err) } // Test GET /firmware req := httptest.NewRequest("GET", "/firmware", nil) w := httptest.NewRecorder() handler.ListFirmware(w, req) if w.Code != http.StatusOK { t.Errorf("Expected status 200, got %d", w.Code) } var grouped []models.GroupedFirmware err = json.Unmarshal(w.Body.Bytes(), &grouped) if err != nil { t.Fatalf("Failed to parse response: %v", err) } if len(grouped) != 1 { t.Errorf("Expected 1 group, got %d", len(grouped)) } } func TestHealthCheckAPI(t *testing.T) { db, _, handler := setupTestDB(t) defer db.Close() req := httptest.NewRequest("GET", "/health", nil) w := httptest.NewRecorder() handler.HealthCheck(w, req) if w.Code != http.StatusOK { t.Errorf("Expected status 200, got %d", w.Code) } var response models.HealthResponse err := json.Unmarshal(w.Body.Bytes(), &response) if err != nil { t.Fatalf("Failed to parse response: %v", err) } if response.Status != "healthy" { t.Errorf("Expected status 'healthy', got '%s'", response.Status) } } func TestInvalidFirmwarePath(t *testing.T) { db, _, handler := setupTestDB(t) defer db.Close() // Test invalid path (too many parts) req := httptest.NewRequest("GET", "/firmware/invalid/path/extra", nil) w := httptest.NewRecorder() handler.DownloadFirmware(w, req) if w.Code != http.StatusBadRequest { t.Errorf("Expected status 400, got %d", w.Code) } } func TestFirmwareNotFound(t *testing.T) { db, _, handler := setupTestDB(t) defer db.Close() // Test firmware not found req := httptest.NewRequest("GET", "/firmware/nonexistent/1.0.0", nil) w := httptest.NewRecorder() handler.DownloadFirmware(w, req) if w.Code != http.StatusNotFound { t.Errorf("Expected status 404, got %d", w.Code) } }