diff --git a/internal/application/devnet/export.go b/internal/application/devnet/export.go index a0544ba5..500e56ce 100644 --- a/internal/application/devnet/export.go +++ b/internal/application/devnet/export.go @@ -270,16 +270,11 @@ func (uc *ExportUseCase) Execute(ctx context.Context, input dto.ExportInput) (*d // List returns all exports for a devnet. func (uc *ExportUseCase) List(ctx context.Context, homeDir string) (*dto.ExportListOutput, error) { // Load all exports - exportsInterface, err := uc.exportRepo.ListForDevnet(ctx, homeDir) + exports, err := uc.exportRepo.ListForDevnet(ctx, homeDir) if err != nil { return nil, fmt.Errorf("failed to list exports: %w", err) } - exports, ok := exportsInterface.([]*domainExport.Export) - if !ok { - return nil, fmt.Errorf("invalid export list type") - } - // Build summaries summaries := make([]*dto.ExportSummary, 0, len(exports)) var totalSize int64 @@ -314,16 +309,11 @@ func (uc *ExportUseCase) List(ctx context.Context, homeDir string) (*dto.ExportL // Inspect returns detailed information about a specific export. func (uc *ExportUseCase) Inspect(ctx context.Context, exportPath string) (*dto.ExportInspectOutput, error) { // Validate export - resultInterface, err := uc.exportRepo.Validate(ctx, exportPath) + result, err := uc.exportRepo.Validate(ctx, exportPath) if err != nil && err != domainExport.ErrExportIncomplete { return nil, fmt.Errorf("failed to validate export: %w", err) } - result, ok := resultInterface.(*infraExport.ValidationResult) - if !ok { - return nil, fmt.Errorf("invalid validation result type") - } - // Calculate directory size size, _ := calculateDirectorySize(exportPath) diff --git a/internal/application/devnet/export_test.go b/internal/application/devnet/export_test.go index 965bae24..f041b2b9 100644 --- a/internal/application/devnet/export_test.go +++ b/internal/application/devnet/export_test.go @@ -11,7 +11,6 @@ import ( "github.com/altuslabsxyz/devnet-builder/internal/application/dto" "github.com/altuslabsxyz/devnet-builder/internal/application/ports" domainExport "github.com/altuslabsxyz/devnet-builder/internal/domain/export" - infraExport "github.com/altuslabsxyz/devnet-builder/internal/infrastructure/export" "github.com/altuslabsxyz/devnet-builder/types" ) @@ -83,23 +82,23 @@ func (m *mockNodeRepository) Delete(ctx context.Context, homeDir string, index i } type mockExportRepository struct { - saveFunc func(ctx context.Context, export interface{}) error - listForDevnetFunc func(ctx context.Context, homeDir string) (interface{}, error) - validateFunc func(ctx context.Context, exportPath string) (interface{}, error) + saveFunc func(ctx context.Context, export *domainExport.Export) error + listForDevnetFunc func(ctx context.Context, homeDir string) ([]*domainExport.Export, error) + validateFunc func(ctx context.Context, exportPath string) (*ports.ExportValidationResult, error) } -func (m *mockExportRepository) Save(ctx context.Context, export interface{}) error { +func (m *mockExportRepository) Save(ctx context.Context, export *domainExport.Export) error { if m.saveFunc != nil { return m.saveFunc(ctx, export) } return nil } -func (m *mockExportRepository) Load(ctx context.Context, exportPath string) (interface{}, error) { +func (m *mockExportRepository) Load(ctx context.Context, exportPath string) (*domainExport.Export, error) { return nil, nil } -func (m *mockExportRepository) ListForDevnet(ctx context.Context, homeDir string) (interface{}, error) { +func (m *mockExportRepository) ListForDevnet(ctx context.Context, homeDir string) ([]*domainExport.Export, error) { if m.listForDevnetFunc != nil { return m.listForDevnetFunc(ctx, homeDir) } @@ -110,11 +109,11 @@ func (m *mockExportRepository) Delete(ctx context.Context, exportPath string) er return nil } -func (m *mockExportRepository) Validate(ctx context.Context, exportPath string) (interface{}, error) { +func (m *mockExportRepository) Validate(ctx context.Context, exportPath string) (*ports.ExportValidationResult, error) { if m.validateFunc != nil { return m.validateFunc(ctx, exportPath) } - return &infraExport.ValidationResult{ + return &ports.ExportValidationResult{ IsComplete: true, }, nil } @@ -280,7 +279,7 @@ func TestExportUseCase_Execute_DevnetNotRunning(t *testing.T) { func TestExportUseCase_List_Success(t *testing.T) { exportRepo := &mockExportRepository{ - listForDevnetFunc: func(ctx context.Context, homeDir string) (interface{}, error) { + listForDevnetFunc: func(ctx context.Context, homeDir string) ([]*domainExport.Export, error) { return []*domainExport.Export{}, nil }, } @@ -304,7 +303,7 @@ func TestExportUseCase_List_Success(t *testing.T) { func TestExportUseCase_List_RepositoryFailure(t *testing.T) { exportRepo := &mockExportRepository{ - listForDevnetFunc: func(ctx context.Context, homeDir string) (interface{}, error) { + listForDevnetFunc: func(ctx context.Context, homeDir string) ([]*domainExport.Export, error) { return nil, errors.New("repository error") }, } @@ -318,23 +317,6 @@ func TestExportUseCase_List_RepositoryFailure(t *testing.T) { } } -func TestExportUseCase_List_InvalidType(t *testing.T) { - exportRepo := &mockExportRepository{ - listForDevnetFunc: func(ctx context.Context, homeDir string) (interface{}, error) { - // Return wrong type - return "invalid", nil - }, - } - - uc := NewExportUseCase(context.Background(), &mockDevnetRepository{}, &mockNodeRepository{}, exportRepo, &mockNodeLifecycleManager{}, &mockLogger{}) - - _, err := uc.List(context.Background(), "/tmp/test-devnet") - - if err == nil { - t.Fatal("expected error for invalid type") - } -} - func TestExportUseCase_Inspect_Success(t *testing.T) { // Create valid test export hash := "a1b2c3d4e5f67890123456789012345678901234567890123456789012345678" @@ -365,8 +347,8 @@ func TestExportUseCase_Inspect_Success(t *testing.T) { ) exportRepo := &mockExportRepository{ - validateFunc: func(ctx context.Context, exportPath string) (interface{}, error) { - return &infraExport.ValidationResult{ + validateFunc: func(ctx context.Context, exportPath string) (*ports.ExportValidationResult, error) { + return &ports.ExportValidationResult{ Export: export, IsComplete: true, MissingFiles: []string{}, @@ -393,7 +375,7 @@ func TestExportUseCase_Inspect_Success(t *testing.T) { func TestExportUseCase_Inspect_ValidationFailure(t *testing.T) { exportRepo := &mockExportRepository{ - validateFunc: func(ctx context.Context, exportPath string) (interface{}, error) { + validateFunc: func(ctx context.Context, exportPath string) (*ports.ExportValidationResult, error) { return nil, errors.New("validation error") }, } @@ -436,8 +418,8 @@ func TestExportUseCase_Inspect_IncompleteExport(t *testing.T) { ) exportRepo := &mockExportRepository{ - validateFunc: func(ctx context.Context, exportPath string) (interface{}, error) { - return &infraExport.ValidationResult{ + validateFunc: func(ctx context.Context, exportPath string) (*ports.ExportValidationResult, error) { + return &ports.ExportValidationResult{ Export: export, IsComplete: false, MissingFiles: []string{"genesis.json"}, @@ -463,23 +445,6 @@ func TestExportUseCase_Inspect_IncompleteExport(t *testing.T) { } } -func TestExportUseCase_Inspect_InvalidType(t *testing.T) { - exportRepo := &mockExportRepository{ - validateFunc: func(ctx context.Context, exportPath string) (interface{}, error) { - // Return wrong type - return "invalid", nil - }, - } - - uc := NewExportUseCase(context.Background(), &mockDevnetRepository{}, &mockNodeRepository{}, exportRepo, &mockNodeLifecycleManager{}, &mockLogger{}) - - _, err := uc.Inspect(context.Background(), "/tmp/exports/invalid") - - if err == nil { - t.Fatal("expected error for invalid type") - } -} - // Helper functions func testTimestamp() time.Time { diff --git a/internal/application/ports/repositories.go b/internal/application/ports/repositories.go index 2c4c168d..1f20debf 100644 --- a/internal/application/ports/repositories.go +++ b/internal/application/ports/repositories.go @@ -4,6 +4,7 @@ import ( "context" "time" + domainExport "github.com/altuslabsxyz/devnet-builder/internal/domain/export" "github.com/altuslabsxyz/devnet-builder/types" ) @@ -190,17 +191,24 @@ type NodeConfigOptions struct { // ExportRepository manages export persistence and querying type ExportRepository interface { // Save saves export metadata to disk - Save(ctx context.Context, exp interface{}) error + Save(ctx context.Context, exp *domainExport.Export) error // Load loads export from directory - Load(ctx context.Context, exportPath string) (interface{}, error) + Load(ctx context.Context, exportPath string) (*domainExport.Export, error) // ListForDevnet lists all exports for a devnet - ListForDevnet(ctx context.Context, devnetHomeDir string) (interface{}, error) + ListForDevnet(ctx context.Context, devnetHomeDir string) ([]*domainExport.Export, error) // Delete removes an export directory Delete(ctx context.Context, exportPath string) error // Validate checks export completeness - Validate(ctx context.Context, exportPath string) (interface{}, error) + Validate(ctx context.Context, exportPath string) (*ExportValidationResult, error) +} + +// ExportValidationResult is the typed validation result returned by ExportRepository. +type ExportValidationResult struct { + Export *domainExport.Export + IsComplete bool + MissingFiles []string } diff --git a/internal/application/ports/services.go b/internal/application/ports/services.go index 4d636ba9..dc5143aa 100644 --- a/internal/application/ports/services.go +++ b/internal/application/ports/services.go @@ -228,12 +228,26 @@ const ( StageFailed UpgradeStage = "failed" ) +// ExportExecuteInput is the boundary DTO for export requests. +type ExportExecuteInput struct { + HomeDir string + OutputDir string + Force bool +} + +// ExportExecuteOutput is the boundary DTO for export responses. +type ExportExecuteOutput struct { + ExportPath string + BlockHeight int64 + GenesisPath string + MetadataPath string + WasRunning bool + Warnings []string +} + // ExportUseCase defines the interface for exporting blockchain state. -// Note: Uses dto.ExportInput and dto.ExportOutput from internal/application/dto type ExportUseCase interface { - // Execute performs a state export - // Returns export result with paths and metadata - Execute(ctx context.Context, input interface{}) (interface{}, error) + Execute(ctx context.Context, input ExportExecuteInput) (*ExportExecuteOutput, error) } // NodeLifecycleManager defines operations for managing node lifecycle. diff --git a/internal/application/upgrade/execute.go b/internal/application/upgrade/execute.go index de562427..396a59d1 100644 --- a/internal/application/upgrade/execute.go +++ b/internal/application/upgrade/execute.go @@ -115,23 +115,18 @@ func (uc *ExecuteUpgradeUseCase) executeWithGov(ctx context.Context, input dto.E // Pre-upgrade export (if enabled) if input.WithExport { uc.logger.Info("Pre-upgrade: Exporting state before upgrade...") - exportInput := dto.ExportInput{ + exportInput := ports.ExportExecuteInput{ HomeDir: input.HomeDir, OutputDir: input.GenesisDir, Force: false, } - preExportResultRaw, err := uc.exportUC.Execute(ctx, exportInput) + preExportResult, err := uc.exportUC.Execute(ctx, exportInput) if err != nil { uc.logger.Error("Pre-upgrade export failed: %v", err) output.Error = fmt.Errorf("pre-upgrade export failed: %w", err) return output, output.Error } - preExportResult, ok := preExportResultRaw.(*dto.ExportOutput) - if !ok { - output.Error = fmt.Errorf("invalid export result type") - return output, output.Error - } output.PreGenesisPath = preExportResult.ExportPath uc.logger.Success("Pre-upgrade export complete: %s", preExportResult.ExportPath) } @@ -214,25 +209,20 @@ func (uc *ExecuteUpgradeUseCase) executeWithGov(ctx context.Context, input dto.E // Post-upgrade export (if enabled) if input.WithExport { uc.logger.Info("Post-upgrade: Exporting state after upgrade...") - exportInput := dto.ExportInput{ + exportInput := ports.ExportExecuteInput{ HomeDir: input.HomeDir, OutputDir: input.GenesisDir, Force: false, } - postExportResultRaw, err := uc.exportUC.Execute(ctx, exportInput) + postExportResult, err := uc.exportUC.Execute(ctx, exportInput) if err != nil { // Post-upgrade export failure is non-fatal (upgrade already complete) uc.logger.Warn("Post-upgrade export failed: %v", err) uc.logger.Warn("Upgrade completed successfully, but post-upgrade state export failed") } else { - postExportResult, ok := postExportResultRaw.(*dto.ExportOutput) - if ok { - output.PostGenesisPath = postExportResult.ExportPath - uc.logger.Success("Post-upgrade export complete: %s", postExportResult.ExportPath) - } else { - uc.logger.Warn("Invalid export result type for post-upgrade export") - } + output.PostGenesisPath = postExportResult.ExportPath + uc.logger.Success("Post-upgrade export complete: %s", postExportResult.ExportPath) } } diff --git a/internal/application/upgrade/resumable_execute.go b/internal/application/upgrade/resumable_execute.go index 9e1afad7..c15a0555 100644 --- a/internal/application/upgrade/resumable_execute.go +++ b/internal/application/upgrade/resumable_execute.go @@ -178,22 +178,20 @@ func (uc *ResumableExecuteUpgradeUseCase) executeWithGovResumable( // Pre-upgrade export (only if starting fresh and enabled) if state.Stage == ports.ResumableStageInitialized && input.WithExport { uc.logger.Info("Pre-upgrade: Exporting state before upgrade...") - exportInput := dto.ExportInput{ + exportInput := ports.ExportExecuteInput{ HomeDir: input.HomeDir, OutputDir: input.GenesisDir, Force: false, } - preExportResultRaw, err := uc.exportUC.Execute(ctx, exportInput) + preExportResult, err := uc.exportUC.Execute(ctx, exportInput) if err != nil { uc.logger.Error("Pre-upgrade export failed: %v", err) output.Error = fmt.Errorf("pre-upgrade export failed: %w", err) return output, output.Error } - if preExportResult, ok := preExportResultRaw.(*dto.ExportOutput); ok { - output.PreGenesisPath = preExportResult.ExportPath - uc.logger.Success("Pre-upgrade export complete: %s", preExportResult.ExportPath) - } + output.PreGenesisPath = preExportResult.ExportPath + uc.logger.Success("Pre-upgrade export complete: %s", preExportResult.ExportPath) } // Resume from current stage @@ -345,16 +343,16 @@ func (uc *ResumableExecuteUpgradeUseCase) executeWithGovResumable( // Post-upgrade export (if enabled) if input.WithExport { uc.logger.Info("Post-upgrade: Exporting state after upgrade...") - exportInput := dto.ExportInput{ + exportInput := ports.ExportExecuteInput{ HomeDir: input.HomeDir, OutputDir: input.GenesisDir, Force: false, } - postExportResultRaw, err := uc.exportUC.Execute(ctx, exportInput) + postExportResult, err := uc.exportUC.Execute(ctx, exportInput) if err != nil { uc.logger.Warn("Post-upgrade export failed: %v", err) - } else if postExportResult, ok := postExportResultRaw.(*dto.ExportOutput); ok { + } else { output.PostGenesisPath = postExportResult.ExportPath uc.logger.Success("Post-upgrade export complete: %s", postExportResult.ExportPath) } diff --git a/internal/di/container.go b/internal/di/container.go index 7647352e..0c2cd11e 100644 --- a/internal/di/container.go +++ b/internal/di/container.go @@ -5,7 +5,6 @@ package di import ( "context" - "fmt" "io" "sync" "time" @@ -30,12 +29,24 @@ type exportUseCaseAdapter struct { } } -func (a *exportUseCaseAdapter) Execute(ctx context.Context, input interface{}) (interface{}, error) { - exportInput, ok := input.(dto.ExportInput) - if !ok { - return nil, fmt.Errorf("invalid input type for export: expected dto.ExportInput, got %T", input) +func (a *exportUseCaseAdapter) Execute(ctx context.Context, input ports.ExportExecuteInput) (*ports.ExportExecuteOutput, error) { + result, err := a.concrete.Execute(ctx, dto.ExportInput{ + HomeDir: input.HomeDir, + OutputDir: input.OutputDir, + Force: input.Force, + }) + if err != nil { + return nil, err } - return a.concrete.Execute(ctx, exportInput) + + return &ports.ExportExecuteOutput{ + ExportPath: result.ExportPath, + BlockHeight: result.BlockHeight, + GenesisPath: result.GenesisPath, + MetadataPath: result.MetadataPath, + WasRunning: result.WasRunning, + Warnings: result.Warnings, + }, nil } // Container holds all application dependencies. diff --git a/internal/di/providers/upgrade.go b/internal/di/providers/upgrade.go index bb1c34af..3455dcd2 100644 --- a/internal/di/providers/upgrade.go +++ b/internal/di/providers/upgrade.go @@ -2,7 +2,6 @@ package providers import ( "context" - "fmt" "sync" "github.com/altuslabsxyz/devnet-builder/internal/application/dto" @@ -160,12 +159,23 @@ type exportUseCaseAdapter struct { } } -func (a *exportUseCaseAdapter) Execute(ctx context.Context, input interface{}) (interface{}, error) { - exportInput, ok := input.(dto.ExportInput) - if !ok { - return nil, fmt.Errorf("invalid input type for export: expected dto.ExportInput, got %T", input) +func (a *exportUseCaseAdapter) Execute(ctx context.Context, input ports.ExportExecuteInput) (*ports.ExportExecuteOutput, error) { + result, err := a.concrete.Execute(ctx, dto.ExportInput{ + HomeDir: input.HomeDir, + OutputDir: input.OutputDir, + Force: input.Force, + }) + if err != nil { + return nil, err } - return a.concrete.Execute(ctx, exportInput) + return &ports.ExportExecuteOutput{ + ExportPath: result.ExportPath, + BlockHeight: result.BlockHeight, + GenesisPath: result.GenesisPath, + MetadataPath: result.MetadataPath, + WasRunning: result.WasRunning, + Warnings: result.Warnings, + }, nil } // StateManager returns the upgrade state manager (lazy init). diff --git a/internal/infrastructure/export/repository.go b/internal/infrastructure/export/repository.go index 289c8624..c124aafd 100644 --- a/internal/infrastructure/export/repository.go +++ b/internal/infrastructure/export/repository.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/altuslabsxyz/devnet-builder/internal/application/ports" domainExport "github.com/altuslabsxyz/devnet-builder/internal/domain/export" "github.com/altuslabsxyz/devnet-builder/internal/paths" "github.com/altuslabsxyz/devnet-builder/types" @@ -27,18 +28,17 @@ func NewRepository(baseDir string) *Repository { } // Save persists export metadata to disk. -func (r *Repository) Save(ctx context.Context, exp interface{}) error { - export, ok := exp.(*domainExport.Export) - if !ok { - return fmt.Errorf("expected *export.Export, got %T", exp) - } - +func (r *Repository) Save(ctx context.Context, export *domainExport.Export) error { select { case <-ctx.Done(): return ctx.Err() default: } + if export == nil { + return fmt.Errorf("export cannot be nil") + } + // Validate export before saving if err := export.Validate(); err != nil { return fmt.Errorf("export validation failed: %w", err) @@ -65,7 +65,7 @@ func (r *Repository) Save(ctx context.Context, exp interface{}) error { } // Load retrieves export metadata from a directory. -func (r *Repository) Load(ctx context.Context, exportPath string) (interface{}, error) { +func (r *Repository) Load(ctx context.Context, exportPath string) (*domainExport.Export, error) { select { case <-ctx.Done(): return nil, ctx.Err() @@ -126,7 +126,7 @@ func (r *Repository) Load(ctx context.Context, exportPath string) (interface{}, } // ListForDevnet lists all exports for a given devnet home directory. -func (r *Repository) ListForDevnet(ctx context.Context, devnetHomeDir string) (interface{}, error) { +func (r *Repository) ListForDevnet(ctx context.Context, devnetHomeDir string) ([]*domainExport.Export, error) { select { case <-ctx.Done(): return nil, ctx.Err() @@ -163,13 +163,7 @@ func (r *Repository) ListForDevnet(ctx context.Context, devnetHomeDir string) (i // Skip invalid exports continue } - - export, ok := exp.(*domainExport.Export) - if !ok { - continue - } - - exports = append(exports, export) + exports = append(exports, exp) } // Sort by timestamp (newest first) @@ -209,7 +203,7 @@ func (r *Repository) Delete(ctx context.Context, exportPath string) error { } // Validate checks if an export is complete and valid. -func (r *Repository) Validate(ctx context.Context, exportPath string) (interface{}, error) { +func (r *Repository) Validate(ctx context.Context, exportPath string) (*ports.ExportValidationResult, error) { select { case <-ctx.Done(): return nil, ctx.Err() @@ -221,11 +215,7 @@ func (r *Repository) Validate(ctx context.Context, exportPath string) (interface if err != nil { return nil, err } - - export, ok := exp.(*domainExport.Export) - if !ok { - return nil, fmt.Errorf("invalid export type") - } + export := exp // Check completeness var missingFiles []string @@ -241,7 +231,7 @@ func (r *Repository) Validate(ctx context.Context, exportPath string) (interface missingFiles = append(missingFiles, filepath.Base(export.GenesisFilePath)) } - result := &ValidationResult{ + result := &ports.ExportValidationResult{ Export: export, IsComplete: len(missingFiles) == 0, MissingFiles: missingFiles, @@ -254,13 +244,6 @@ func (r *Repository) Validate(ctx context.Context, exportPath string) (interface return result, nil } -// ValidationResult contains the result of export validation. -type ValidationResult struct { - Export *domainExport.Export - IsComplete bool - MissingFiles []string -} - // GetExportsDirectory returns the exports directory path for a devnet. func (r *Repository) GetExportsDirectory(devnetHomeDir string) string { return paths.ExportsPath(devnetHomeDir) diff --git a/internal/infrastructure/export/repository_test.go b/internal/infrastructure/export/repository_test.go index 93804739..8b0ffa0a 100644 --- a/internal/infrastructure/export/repository_test.go +++ b/internal/infrastructure/export/repository_test.go @@ -112,14 +112,14 @@ func TestRepository_Save(t *testing.T) { } } -func TestRepository_Save_InvalidType(t *testing.T) { +func TestRepository_Save_NilExport(t *testing.T) { ctx := context.Background() repo := NewRepository(t.TempDir()) - err := repo.Save(ctx, "invalid type") + err := repo.Save(ctx, nil) - if err == nil { - t.Fatal("expected error for invalid type") + if err == nil || err.Error() != "export cannot be nil" { + t.Fatalf("expected nil export error, got %v", err) } } @@ -153,16 +153,11 @@ func TestRepository_Load(t *testing.T) { } // Load back - loadedInterface, err := repo.Load(ctx, exportDir) + loadedExport, err := repo.Load(ctx, exportDir) if err != nil { t.Fatalf("failed to load export: %v", err) } - loadedExport, ok := loadedInterface.(*domainExport.Export) - if !ok { - t.Fatalf("expected *domainExport.Export, got %T", loadedInterface) - } - // Verify loaded data matches original if loadedExport.BlockHeight != originalExport.BlockHeight { t.Errorf("block height mismatch: expected %d, got %d", originalExport.BlockHeight, loadedExport.BlockHeight) @@ -272,16 +267,11 @@ func TestRepository_ListForDevnet(t *testing.T) { } // List exports - listInterface, err := repo.ListForDevnet(ctx, tmpDir) + exports, err := repo.ListForDevnet(ctx, tmpDir) if err != nil { t.Fatalf("failed to list exports: %v", err) } - exports, ok := listInterface.([]*domainExport.Export) - if !ok { - t.Fatalf("expected []*domainExport.Export, got %T", listInterface) - } - if len(exports) != 2 { t.Fatalf("expected 2 exports, got %d", len(exports)) } @@ -300,16 +290,11 @@ func TestRepository_ListForDevnet_NoExportsDir(t *testing.T) { repo := NewRepository(filepath.Join(tmpDir, "exports")) // List when exports directory doesn't exist - listInterface, err := repo.ListForDevnet(ctx, tmpDir) + exports, err := repo.ListForDevnet(ctx, tmpDir) if err != nil { t.Fatalf("unexpected error: %v", err) } - exports, ok := listInterface.([]*domainExport.Export) - if !ok { - t.Fatalf("expected []*domainExport.Export, got %T", listInterface) - } - if len(exports) != 0 { t.Errorf("expected empty list, got %d exports", len(exports)) } @@ -414,16 +399,11 @@ func TestRepository_Validate(t *testing.T) { } // Validate - resultInterface, err := repo.Validate(ctx, exportDir) + result, err := repo.Validate(ctx, exportDir) if err != nil { t.Fatalf("failed to validate export: %v", err) } - result, ok := resultInterface.(*ValidationResult) - if !ok { - t.Fatalf("expected *ValidationResult, got %T", resultInterface) - } - if !result.IsComplete { t.Error("expected export to be complete") } @@ -447,18 +427,13 @@ func TestRepository_Validate_Incomplete(t *testing.T) { } // Validate - resultInterface, err := repo.Validate(ctx, exportDir) + result, err := repo.Validate(ctx, exportDir) // Should return ErrExportIncomplete if err != domainExport.ErrExportIncomplete { t.Errorf("expected ErrExportIncomplete, got %v", err) } - result, ok := resultInterface.(*ValidationResult) - if !ok { - t.Fatalf("expected *ValidationResult, got %T", resultInterface) - } - if result.IsComplete { t.Error("expected export to be incomplete") }