2026-03-10 17:09:35 +08:00
import XCTest
@ testable import AtlasInfrastructure
import AtlasApplication
import AtlasDomain
import AtlasProtocol
final class AtlasInfrastructureTests : XCTestCase {
func testRepositoryPersistsWorkspaceState ( ) {
let fileURL = temporaryStateFileURL ( )
let repository = AtlasWorkspaceRepository ( stateFileURL : fileURL )
var state = AtlasScaffoldWorkspace . state ( )
state . settings . recoveryRetentionDays = 21
XCTAssertNoThrow ( try repository . saveState ( state ) )
let loaded = repository . loadState ( )
XCTAssertEqual ( loaded . settings . recoveryRetentionDays , 21 )
XCTAssertEqual ( loaded . snapshot . apps . count , state . snapshot . apps . count )
}
2026-03-23 17:35:05 +08:00
func testRepositoryPersistsVersionedWorkspaceEnvelope ( ) throws {
let fileURL = temporaryStateFileURL ( )
let repository = AtlasWorkspaceRepository ( stateFileURL : fileURL )
XCTAssertNoThrow ( try repository . saveState ( AtlasScaffoldWorkspace . state ( ) ) )
let data = try Data ( contentsOf : fileURL )
let persisted = try JSONDecoder ( ) . decode ( AtlasPersistedWorkspaceState . self , from : data )
XCTAssertEqual ( persisted . schemaVersion , AtlasWorkspaceStateSchemaVersion . current )
XCTAssertFalse ( persisted . snapshot . apps . isEmpty )
}
func testRepositoryLoadsLegacyWorkspaceStateAndRewritesEnvelope ( ) throws {
let fileURL = temporaryStateFileURL ( )
let legacyState = AtlasScaffoldWorkspace . state ( )
try FileManager . default . createDirectory ( at : fileURL . deletingLastPathComponent ( ) , withIntermediateDirectories : true )
try JSONEncoder ( ) . encode ( legacyState ) . write ( to : fileURL )
let repository = AtlasWorkspaceRepository ( stateFileURL : fileURL )
let loaded = repository . loadState ( )
XCTAssertEqual ( loaded . snapshot . apps . count , legacyState . snapshot . apps . count )
let migratedData = try Data ( contentsOf : fileURL )
let persisted = try JSONDecoder ( ) . decode ( AtlasPersistedWorkspaceState . self , from : migratedData )
XCTAssertEqual ( persisted . schemaVersion , AtlasWorkspaceStateSchemaVersion . current )
XCTAssertEqual ( persisted . snapshot . apps . count , legacyState . snapshot . apps . count )
}
2026-03-10 17:09:35 +08:00
func testRepositorySaveStateThrowsForInvalidParentURL ( ) {
let repository = AtlasWorkspaceRepository (
stateFileURL : URL ( fileURLWithPath : " /dev/null/workspace-state.json " )
)
XCTAssertThrowsError ( try repository . saveState ( AtlasScaffoldWorkspace . state ( ) ) )
}
2026-03-13 10:35:15 +08:00
func testRepositorySaveStatePrunesExpiredRecoveryItems ( ) throws {
let baseDate = Date ( timeIntervalSince1970 : 1_710_000_000 )
let clock = TestClock ( now : baseDate )
let repository = AtlasWorkspaceRepository (
stateFileURL : temporaryStateFileURL ( ) ,
nowProvider : { clock . now }
)
let activeItem = RecoveryItem (
id : UUID ( ) ,
title : " Active recovery " ,
detail : " Still valid " ,
originalPath : " ~/Library/Caches/Active " ,
bytes : 5 ,
deletedAt : baseDate . addingTimeInterval ( - 120 ) ,
expiresAt : baseDate . addingTimeInterval ( 3600 ) ,
payload : nil ,
restoreMappings : nil
)
let expiredItem = RecoveryItem (
id : UUID ( ) ,
title : " Expired recovery " ,
detail : " Expired " ,
originalPath : " ~/Library/Caches/Expired " ,
bytes : 7 ,
deletedAt : baseDate . addingTimeInterval ( - 7200 ) ,
expiresAt : baseDate . addingTimeInterval ( - 1 ) ,
payload : nil ,
restoreMappings : nil
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 0 ,
findings : [ ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ activeItem , expiredItem ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
let saved = try repository . saveState ( state )
XCTAssertEqual ( saved . snapshot . recoveryItems . map ( \ . id ) , [ activeItem . id ] )
XCTAssertEqual ( repository . loadState ( ) . snapshot . recoveryItems . map ( \ . id ) , [ activeItem . id ] )
}
2026-03-10 17:09:35 +08:00
func testExecutePlanMovesSupportedFindingsIntoRecoveryWhileKeepingInspectionOnlyItems ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " sample.cache " )
try Data ( " cache " . utf8 ) . write ( to : targetFile )
let supportedFinding = Finding (
id : UUID ( ) ,
title : " Sample cache " ,
detail : targetFile . path ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetFile . path ]
)
let unsupportedPath = home . appendingPathComponent ( " Documents/AtlasUnsupported/ " + UUID ( ) . uuidString ) . path
let unsupportedFinding = Finding (
id : UUID ( ) ,
title : " Unsupported cache " ,
detail : unsupportedPath ,
bytes : 7 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ unsupportedPath ]
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 12 ,
findings : [ supportedFinding , unsupportedFinding ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan (
title : " Review 2 selected findings " ,
items : [
ActionItem ( id : supportedFinding . id , title : " Move Sample cache to Trash " , detail : supportedFinding . detail , kind : . removeCache , recoverable : true ) ,
ActionItem ( id : unsupportedFinding . id , title : " Inspect Unsupported cache " , detail : unsupportedFinding . detail , kind : . inspectPermission , recoverable : false ) ,
] ,
estimatedBytes : 12
) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let executeResult = try await worker . submit (
AtlasRequestEnvelope ( command : . executePlan ( planID : state . currentPlan . id ) )
)
if case let . accepted ( task ) = executeResult . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertFalse ( FileManager . default . fileExists ( atPath : targetFile . path ) )
XCTAssertEqual ( executeResult . snapshot . findings . count , 1 )
XCTAssertEqual ( executeResult . snapshot . findings . first ? . id , unsupportedFinding . id )
XCTAssertEqual ( executeResult . snapshot . recoveryItems . count , 1 )
let restoredItemID = try XCTUnwrap ( executeResult . snapshot . recoveryItems . first ? . id )
let restoreTaskID = UUID ( )
let restoreResult = try await worker . submit (
AtlasRequestEnvelope ( command : . restoreItems ( taskID : restoreTaskID , itemIDs : [ restoredItemID ] ) )
)
XCTAssertTrue ( FileManager . default . fileExists ( atPath : targetFile . path ) )
XCTAssertEqual ( Set ( restoreResult . snapshot . findings . map ( \ . id ) ) , Set ( [ supportedFinding . id , unsupportedFinding . id ] ) )
XCTAssertEqual ( restoreResult . snapshot . recoveryItems . count , 0 )
}
2026-03-12 23:19:18 +08:00
func testExecutePlanPreservesCompletedRecoveryEntriesWhenLaterFindingFailsInStateOnlyMode ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let fileManager = FileManager . default
let home = fileManager . homeDirectoryForCurrentUser
let cacheDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try fileManager . createDirectory ( at : cacheDirectory , withIntermediateDirectories : true )
let cacheFile = cacheDirectory . appendingPathComponent ( " sample.cache " )
try Data ( " cache " . utf8 ) . write ( to : cacheFile )
let helperDirectory = home . appendingPathComponent ( " Applications/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try fileManager . createDirectory ( at : helperDirectory , withIntermediateDirectories : true )
let helperFile = helperDirectory . appendingPathComponent ( " HelperRequired.app " )
try Data ( " helper " . utf8 ) . write ( to : helperFile )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : helperDirectory )
}
let supportedFinding = Finding (
id : UUID ( ) ,
title : " Sample cache " ,
detail : cacheFile . path ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ cacheFile . path ]
)
let helperRequiredFinding = Finding (
id : UUID ( ) ,
title : " Helper required cleanup " ,
detail : helperFile . path ,
bytes : 7 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ helperFile . path ]
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 12 ,
findings : [ supportedFinding , helperRequiredFinding ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan (
title : " Review 2 selected findings " ,
items : [
ActionItem ( id : supportedFinding . id , title : " Move Sample cache to Trash " , detail : supportedFinding . detail , kind : . removeCache , recoverable : true ) ,
ActionItem ( id : helperRequiredFinding . id , title : " Move Helper required cleanup to Trash " , detail : helperRequiredFinding . detail , kind : . removeCache , recoverable : true ) ,
] ,
estimatedBytes : 12
) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : true )
let result = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : state . currentPlan . id ) ) )
if case let . accepted ( task ) = result . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertFalse ( fileManager . fileExists ( atPath : cacheFile . path ) )
XCTAssertTrue ( fileManager . fileExists ( atPath : helperFile . path ) )
XCTAssertEqual ( result . snapshot . recoveryItems . count , 1 )
XCTAssertEqual ( result . snapshot . recoveryItems . first ? . title , supportedFinding . title )
XCTAssertEqual ( result . snapshot . findings . map ( \ . id ) , [ helperRequiredFinding . id ] )
XCTAssertEqual ( result . snapshot . taskRuns . first ? . status , . failed )
XCTAssertEqual (
result . snapshot . taskRuns . first ? . summary ,
[
AtlasL10n . string ( " infrastructure.execute.summary.clean.one " , language : state . settings . language , 1 ) ,
AtlasL10n . string ( " infrastructure.execute.summary.clean.failed.one " , language : state . settings . language , 1 ) ,
] . joined ( separator : " " )
)
}
2026-03-10 17:09:35 +08:00
func testStartScanRejectsWhenProviderFailsWithoutFallback ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
smartCleanScanProvider : FailingSmartCleanProvider ( ) ,
allowProviderFailureFallback : false
)
let result = try await worker . submit (
AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) )
)
guard case let . rejected ( code , reason ) = result . response . response else {
return XCTFail ( " Expected rejected scan response " )
}
XCTAssertEqual ( code , . executionUnavailable )
XCTAssertTrue ( reason . contains ( " Smart Clean scan is unavailable " ) )
}
func testPermissionInspectorMarksFullDiskAccessGrantedWhenAnyProbeIsReadable ( ) async {
let probeURLs = [
URL ( fileURLWithPath : " /tmp/unreadable " ) ,
URL ( fileURLWithPath : " /tmp/readable " ) ,
]
let inspector = AtlasPermissionInspector (
homeDirectoryURL : URL ( fileURLWithPath : " /tmp " ) ,
fullDiskAccessProbeURLs : probeURLs ,
protectedLocationReader : { url in url . path = = " /tmp/readable " } ,
accessibilityStatusProvider : { false } ,
notificationsAuthorizationProvider : { false }
)
let permissions = await inspector . snapshot ( )
let fullDiskAccess = permissions . first ( where : { $0 . kind = = . fullDiskAccess } )
XCTAssertEqual ( fullDiskAccess ? . isGranted , true )
}
func testPermissionInspectorMarksFullDiskAccessMissingWhenAllProbesFail ( ) async {
let probeURLs = [
URL ( fileURLWithPath : " /tmp/probe-a " ) ,
URL ( fileURLWithPath : " /tmp/probe-b " ) ,
]
let inspector = AtlasPermissionInspector (
homeDirectoryURL : URL ( fileURLWithPath : " /tmp " ) ,
fullDiskAccessProbeURLs : probeURLs ,
protectedLocationReader : { _ in false } ,
accessibilityStatusProvider : { false } ,
notificationsAuthorizationProvider : { false }
)
let permissions = await inspector . snapshot ( )
let fullDiskAccess = permissions . first ( where : { $0 . kind = = . fullDiskAccess } )
XCTAssertEqual ( fullDiskAccess ? . isGranted , false )
XCTAssertTrue ( fullDiskAccess ? . rationale . contains ( " 重新打开 " ) = = true || fullDiskAccess ? . rationale . contains ( " reopen Atlas " ) = = true )
}
func testUnsupportedTargetIsDowngradedToInspectionAndDoesNotFailExecution ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let unsupportedPath = FileManager . default . homeDirectoryForCurrentUser . appendingPathComponent ( " Documents/AtlasUnsupported/ " + UUID ( ) . uuidString ) . path
let finding = Finding (
id : UUID ( ) ,
title : " Unsupported cache " ,
detail : unsupportedPath ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ unsupportedPath ]
)
XCTAssertFalse ( AtlasSmartCleanExecutionSupport . isFindingExecutionSupported ( finding ) )
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 5 ,
findings : [ finding ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan (
title : " Review 1 selected finding " ,
items : [ ActionItem ( id : finding . id , title : " Inspect Unsupported cache " , detail : finding . detail , kind : . inspectPermission , recoverable : false ) ] ,
estimatedBytes : 5
) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let result = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : state . currentPlan . id ) ) )
if case let . accepted ( task ) = result . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertEqual ( result . snapshot . findings . count , 1 )
XCTAssertEqual ( result . snapshot . recoveryItems . count , 0 )
}
func testInspectionOnlyPlanIsAcceptedWithoutMutatingState ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let initialState = repository . loadState ( )
let result = try await worker . submit (
AtlasRequestEnvelope ( command : . executePlan ( planID : initialState . currentPlan . id ) )
)
if case let . accepted ( task ) = result . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertEqual ( result . snapshot . findings . count , initialState . snapshot . findings . count )
XCTAssertEqual ( result . snapshot . recoveryItems . count , initialState . snapshot . recoveryItems . count )
}
2026-03-12 23:19:18 +08:00
func testExecutePlanRejectsWhenFailClosedExecutionFailsBeforeAnySideEffect ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let fileManager = FileManager . default
let helperDirectory = fileManager . homeDirectoryForCurrentUser . appendingPathComponent ( " Applications/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try fileManager . createDirectory ( at : helperDirectory , withIntermediateDirectories : true )
let helperFile = helperDirectory . appendingPathComponent ( " HelperRequired.app " )
try Data ( " helper " . utf8 ) . write ( to : helperFile )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : helperDirectory )
}
let finding = Finding (
id : UUID ( ) ,
title : " Helper required cleanup " ,
detail : helperFile . path ,
bytes : 7 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ helperFile . path ]
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 7 ,
findings : [ finding ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan (
title : " Review 1 selected finding " ,
items : [ ActionItem ( id : finding . id , title : " Move Helper required cleanup to Trash " , detail : finding . detail , kind : . removeCache , recoverable : true ) ] ,
estimatedBytes : 7
) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let result = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : state . currentPlan . id ) ) )
guard case let . rejected ( code , reason ) = result . response . response else {
return XCTFail ( " Expected rejected execute-plan response " )
}
XCTAssertEqual ( code , . executionUnavailable )
XCTAssertTrue ( reason . contains ( " Bundled helper unavailable " ) )
XCTAssertTrue ( fileManager . fileExists ( atPath : helperFile . path ) )
XCTAssertEqual ( result . snapshot . findings . map ( \ . id ) , [ finding . id ] )
XCTAssertEqual ( result . snapshot . recoveryItems . count , 0 )
}
2026-03-10 17:09:35 +08:00
func testZcompdumpTargetIsSupportedExecutionTarget ( ) {
let targetURL = FileManager . default . homeDirectoryForCurrentUser . appendingPathComponent ( " .zcompdump " )
let finding = Finding (
id : UUID ( ) ,
title : " Zsh completion cache " ,
detail : targetURL . path ,
bytes : 1 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetURL . path ]
)
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isSupportedExecutionTarget ( targetURL ) )
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isFindingExecutionSupported ( finding ) )
}
2026-03-12 23:19:18 +08:00
func testPnpmStoreTargetIsSupportedExecutionTarget ( ) {
let targetURL = FileManager . default . homeDirectoryForCurrentUser
. appendingPathComponent ( " Library/pnpm/store/v3/files/atlas-fixture/package.tgz " )
let finding = Finding (
id : UUID ( ) ,
title : " pnpm store " ,
detail : targetURL . path ,
bytes : 1 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetURL . path ]
)
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isSupportedExecutionTarget ( targetURL ) )
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isFindingExecutionSupported ( finding ) )
}
2026-03-23 17:35:05 +08:00
func testGradleCacheTargetIsSupportedExecutionTarget ( ) {
let targetURL = FileManager . default . homeDirectoryForCurrentUser
. appendingPathComponent ( " .gradle/caches/modules-2/files-2.1/atlas-fixture.bin " )
let finding = Finding (
id : UUID ( ) ,
title : " Gradle cache " ,
detail : targetURL . path ,
bytes : 1 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetURL . path ]
)
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isSupportedExecutionTarget ( targetURL ) )
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isFindingExecutionSupported ( finding ) )
}
func testCoreSimulatorCacheTargetIsSupportedExecutionTarget ( ) {
let targetURL = FileManager . default . homeDirectoryForCurrentUser
. appendingPathComponent ( " Library/Developer/CoreSimulator/Caches/atlas-fixture/device-cache.db " )
let finding = Finding (
id : UUID ( ) ,
title : " CoreSimulator cache " ,
detail : targetURL . path ,
bytes : 1 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetURL . path ]
)
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isSupportedExecutionTarget ( targetURL ) )
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isFindingExecutionSupported ( finding ) )
}
2026-03-23 16:48:59 +08:00
func testContainerCacheTargetIsSupportedExecutionTarget ( ) {
let targetURL = FileManager . default . homeDirectoryForCurrentUser
. appendingPathComponent ( " Library/Containers/com.example.preview/Data/Library/Caches/cache.db " )
let finding = Finding (
id : UUID ( ) ,
title : " Container cache " ,
detail : targetURL . path ,
bytes : 1 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetURL . path ]
)
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isSupportedExecutionTarget ( targetURL ) )
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isFindingExecutionSupported ( finding ) )
}
func testContainerLogsTargetIsSupportedExecutionTarget ( ) {
let targetURL = FileManager . default . homeDirectoryForCurrentUser
. appendingPathComponent ( " Library/Containers/com.example.preview/Data/Library/Logs/runtime.log " )
let finding = Finding (
id : UUID ( ) ,
title : " Container logs " ,
detail : targetURL . path ,
bytes : 1 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetURL . path ]
)
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isSupportedExecutionTarget ( targetURL ) )
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isFindingExecutionSupported ( finding ) )
}
func testContainerTempTargetIsSupportedExecutionTarget ( ) {
let targetURL = FileManager . default . homeDirectoryForCurrentUser
. appendingPathComponent ( " Library/Containers/com.example.preview/Data/tmp/runtime.tmp " )
let finding = Finding (
id : UUID ( ) ,
title : " Container temp " ,
detail : targetURL . path ,
bytes : 1 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetURL . path ]
)
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isSupportedExecutionTarget ( targetURL ) )
XCTAssertTrue ( AtlasSmartCleanExecutionSupport . isFindingExecutionSupported ( finding ) )
}
2026-03-10 17:09:35 +08:00
func testExecutePlanTrashesRealTargetsWhenAvailable ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " sample.cache " )
try Data ( " cache " . utf8 ) . write ( to : targetFile )
let finding = Finding (
id : UUID ( ) ,
title : " Sample cache " ,
detail : targetFile . path ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetFile . path ]
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 5 ,
findings : [ finding ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 1 selected finding " , items : [ ActionItem ( id : finding . id , title : " Move Sample cache to Trash " , detail : finding . detail , kind : . removeCache , recoverable : true ) ] , estimatedBytes : 5 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let result = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : state . currentPlan . id ) ) )
if case let . accepted ( task ) = result . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertFalse ( FileManager . default . fileExists ( atPath : targetFile . path ) )
XCTAssertEqual ( result . snapshot . findings . count , 0 )
}
2026-03-13 00:49:32 +08:00
func testExecutePlanUsesStructuredTargetPathsCarriedByCurrentPlan ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " plan-target.cache " )
try Data ( " cache " . utf8 ) . write ( to : targetFile )
let finding = Finding (
id : UUID ( ) ,
title : " Plan-backed cache " ,
detail : targetFile . path ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : nil
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 5 ,
findings : [ finding ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan (
title : " Review 1 selected finding " ,
items : [
ActionItem (
id : finding . id ,
title : " Move Plan-backed cache to Trash " ,
detail : finding . detail ,
kind : . removeCache ,
recoverable : true ,
targetPaths : [ targetFile . path ]
)
] ,
estimatedBytes : 5
) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let result = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : state . currentPlan . id ) ) )
if case let . accepted ( task ) = result . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertFalse ( FileManager . default . fileExists ( atPath : targetFile . path ) )
XCTAssertEqual ( result . snapshot . findings . count , 0 )
XCTAssertEqual ( result . snapshot . recoveryItems . first ? . originalPath , targetFile . path )
}
2026-03-10 17:09:35 +08:00
func testScanExecuteRescanRemovesExecutedTargetFromRealResults ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " sample.cache " )
try Data ( " cache " . utf8 ) . write ( to : targetFile )
let provider = FileBackedSmartCleanProvider ( targetFileURL : targetFile )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
smartCleanScanProvider : provider ,
allowProviderFailureFallback : false ,
allowStateOnlyCleanExecution : false
)
let firstScan = try await worker . submit ( AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) ) )
XCTAssertEqual ( firstScan . snapshot . findings . count , 1 )
let planID = try XCTUnwrap ( firstScan . previewPlan ? . id )
let execute = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : planID ) ) )
if case let . accepted ( task ) = execute . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertFalse ( FileManager . default . fileExists ( atPath : targetFile . path ) )
let secondScan = try await worker . submit ( AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) ) )
XCTAssertEqual ( secondScan . snapshot . findings . count , 0 )
XCTAssertEqual ( secondScan . snapshot . reclaimableSpaceBytes , 0 )
}
2026-03-12 23:19:18 +08:00
func testScanExecuteRescanRemovesExecutedPnpmStoreTargetFromRealResults ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/pnpm/store/v3/files/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " package.tgz " )
try Data ( " pnpm-cache " . utf8 ) . write ( to : targetFile )
let provider = FileBackedSmartCleanProvider ( targetFileURL : targetFile , title : " pnpm store " )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
smartCleanScanProvider : provider ,
allowProviderFailureFallback : false ,
allowStateOnlyCleanExecution : false
)
let firstScan = try await worker . submit ( AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) ) )
XCTAssertEqual ( firstScan . snapshot . findings . count , 1 )
let planID = try XCTUnwrap ( firstScan . previewPlan ? . id )
let initialRecoveryCount = firstScan . snapshot . recoveryItems . count
let execute = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : planID ) ) )
if case let . accepted ( task ) = execute . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertFalse ( FileManager . default . fileExists ( atPath : targetFile . path ) )
XCTAssertEqual ( execute . snapshot . recoveryItems . count , initialRecoveryCount + 1 )
XCTAssertTrue ( execute . snapshot . recoveryItems . contains ( where : { $0 . title = = " pnpm store " } ) )
let secondScan = try await worker . submit ( AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) ) )
XCTAssertEqual ( secondScan . snapshot . findings . count , 0 )
XCTAssertEqual ( secondScan . snapshot . reclaimableSpaceBytes , 0 )
}
2026-03-23 17:35:05 +08:00
func testScanExecuteRescanRemovesExecutedGradleCacheTargetFromRealResults ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " .gradle/caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " modules.bin " )
try Data ( " gradle-cache " . utf8 ) . write ( to : targetFile )
let provider = FileBackedSmartCleanProvider ( targetFileURL : targetFile , title : " Gradle cache " )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
smartCleanScanProvider : provider ,
allowProviderFailureFallback : false ,
allowStateOnlyCleanExecution : false
)
let firstScan = try await worker . submit ( AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) ) )
XCTAssertEqual ( firstScan . snapshot . findings . count , 1 )
let planID = try XCTUnwrap ( firstScan . previewPlan ? . id )
let execute = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : planID ) ) )
if case let . accepted ( task ) = execute . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertFalse ( FileManager . default . fileExists ( atPath : targetFile . path ) )
let secondScan = try await worker . submit ( AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) ) )
XCTAssertEqual ( secondScan . snapshot . findings . count , 0 )
XCTAssertEqual ( secondScan . snapshot . reclaimableSpaceBytes , 0 )
}
2026-03-23 16:48:59 +08:00
func testScanExecuteRescanRemovesExecutedContainerCacheTargetFromRealResults ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/Containers/com.example.atlas-fixture/Data/Library/Caches/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " cache.db " )
try Data ( " container-cache " . utf8 ) . write ( to : targetFile )
let provider = FileBackedSmartCleanProvider ( targetFileURL : targetFile , title : " com.example.atlas-fixture container cache " )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
smartCleanScanProvider : provider ,
allowProviderFailureFallback : false ,
allowStateOnlyCleanExecution : false
)
let firstScan = try await worker . submit ( AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) ) )
XCTAssertEqual ( firstScan . snapshot . findings . count , 1 )
let planID = try XCTUnwrap ( firstScan . previewPlan ? . id )
let execute = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : planID ) ) )
if case let . accepted ( task ) = execute . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertFalse ( FileManager . default . fileExists ( atPath : targetFile . path ) )
let secondScan = try await worker . submit ( AtlasRequestEnvelope ( command : . startScan ( taskID : UUID ( ) ) ) )
XCTAssertEqual ( secondScan . snapshot . findings . count , 0 )
XCTAssertEqual ( secondScan . snapshot . reclaimableSpaceBytes , 0 )
}
2026-03-12 23:19:18 +08:00
func testExecutePlanDoesNotCreateRecoveryEntryWhenTargetIsAlreadyGone ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " sample.cache " )
let finding = Finding (
id : UUID ( ) ,
title : " Stale cache " ,
detail : targetFile . path ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetFile . path ]
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 5 ,
findings : [ finding ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 1 selected finding " , items : [ ActionItem ( id : finding . id , title : " Move Stale cache to Trash " , detail : finding . detail , kind : . removeCache , recoverable : true ) ] , estimatedBytes : 5 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let result = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : state . currentPlan . id ) ) )
if case let . accepted ( task ) = result . response . response {
XCTAssertEqual ( task . kind , . executePlan )
} else {
XCTFail ( " Expected accepted execute-plan response " )
}
XCTAssertEqual ( result . snapshot . recoveryItems . count , 0 )
XCTAssertEqual ( result . snapshot . findings . count , 0 )
XCTAssertEqual (
result . snapshot . taskRuns . first ? . summary ,
AtlasL10n . string ( " infrastructure.execute.summary.clean.stale.one " , language : state . settings . language )
)
}
2026-03-10 17:09:35 +08:00
func testRestoreRecoveryItemPhysicallyRestoresRealTargets ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " sample.cache " )
try Data ( " cache " . utf8 ) . write ( to : targetFile )
let finding = Finding (
id : UUID ( ) ,
title : " Sample cache " ,
detail : targetFile . path ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetFile . path ]
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 5 ,
findings : [ finding ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 1 selected finding " , items : [ ActionItem ( id : finding . id , title : " Move Sample cache to Trash " , detail : finding . detail , kind : . removeCache , recoverable : true ) ] , estimatedBytes : 5 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let execute = try await worker . submit ( AtlasRequestEnvelope ( command : . executePlan ( planID : state . currentPlan . id ) ) )
let recoveryItemID = try XCTUnwrap ( execute . snapshot . recoveryItems . first ? . id )
XCTAssertFalse ( FileManager . default . fileExists ( atPath : targetFile . path ) )
let restore = try await worker . submit ( AtlasRequestEnvelope ( command : . restoreItems ( taskID : UUID ( ) , itemIDs : [ recoveryItemID ] ) ) )
if case let . accepted ( task ) = restore . response . response {
XCTAssertEqual ( task . kind , . restore )
} else {
XCTFail ( " Expected accepted restore response " )
}
XCTAssertTrue ( FileManager . default . fileExists ( atPath : targetFile . path ) )
2026-03-12 23:19:18 +08:00
XCTAssertEqual (
restore . snapshot . taskRuns . first ? . summary ,
AtlasL10n . string ( " infrastructure.restore.summary.disk.one " , language : state . settings . language )
)
}
func testRestoreItemsStateOnlySummaryDoesNotClaimOnDiskRestore ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let finding = Finding (
id : UUID ( ) ,
title : " Atlas-only fixture " ,
detail : " State-only recovery item " ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools "
)
let recoveryItem = RecoveryItem (
id : UUID ( ) ,
title : finding . title ,
detail : finding . detail ,
originalPath : " ~/Library/Caches/AtlasOnly " ,
bytes : 5 ,
deletedAt : Date ( ) ,
expiresAt : Date ( ) . addingTimeInterval ( 3600 ) ,
payload : . finding ( finding ) ,
restoreMappings : nil
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 0 ,
findings : [ ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ recoveryItem ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let restore = try await worker . submit ( AtlasRequestEnvelope ( command : . restoreItems ( taskID : UUID ( ) , itemIDs : [ recoveryItem . id ] ) ) )
if case let . accepted ( task ) = restore . response . response {
XCTAssertEqual ( task . kind , . restore )
} else {
XCTFail ( " Expected accepted restore response " )
}
XCTAssertEqual (
restore . snapshot . taskRuns . first ? . summary ,
AtlasL10n . string ( " infrastructure.restore.summary.state.one " , language : state . settings . language )
)
2026-03-10 17:09:35 +08:00
}
2026-03-13 10:35:15 +08:00
func testRestoreItemsRejectsExpiredRecoveryItemsAndPrunesThem ( ) async throws {
let baseDate = Date ( timeIntervalSince1970 : 1_710_000_000 )
let clock = TestClock ( now : baseDate )
let repository = AtlasWorkspaceRepository (
stateFileURL : temporaryStateFileURL ( ) ,
nowProvider : { clock . now }
)
let finding = Finding (
id : UUID ( ) ,
title : " Atlas-only fixture " ,
detail : " Expires soon " ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools "
)
let recoveryItem = RecoveryItem (
id : UUID ( ) ,
title : finding . title ,
detail : finding . detail ,
originalPath : " ~/Library/Caches/AtlasOnly " ,
bytes : 5 ,
deletedAt : baseDate ,
expiresAt : baseDate . addingTimeInterval ( 10 ) ,
payload : . finding ( finding ) ,
restoreMappings : nil
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 0 ,
findings : [ ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ recoveryItem ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
nowProvider : { clock . now } ,
allowStateOnlyCleanExecution : false
)
clock . now = baseDate . addingTimeInterval ( 60 )
let restore = try await worker . submit (
AtlasRequestEnvelope ( command : . restoreItems ( taskID : UUID ( ) , itemIDs : [ recoveryItem . id ] ) )
)
guard case let . rejected ( code , reason ) = restore . response . response else {
return XCTFail ( " Expected rejected restore response " )
}
XCTAssertEqual ( code , . restoreExpired )
XCTAssertTrue ( reason . contains ( " expired " ) )
XCTAssertFalse ( restore . snapshot . recoveryItems . contains ( where : { $0 . id = = recoveryItem . id } ) )
XCTAssertFalse ( repository . loadState ( ) . snapshot . recoveryItems . contains ( where : { $0 . id = = recoveryItem . id } ) )
}
func testRestoreItemsMixedSummaryIncludesDiskAndStateOnlyClauses ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let home = FileManager . default . homeDirectoryForCurrentUser
let targetDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try FileManager . default . createDirectory ( at : targetDirectory , withIntermediateDirectories : true )
let targetFile = targetDirectory . appendingPathComponent ( " sample.cache " )
try Data ( " cache " . utf8 ) . write ( to : targetFile )
var trashedURL : NSURL ?
try FileManager . default . trashItem ( at : targetFile , resultingItemURL : & trashedURL )
let trashedPath = try XCTUnwrap ( ( trashedURL as URL ? ) ? . path )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : targetDirectory )
if let trashedURL {
try ? FileManager . default . removeItem ( at : trashedURL as URL )
}
}
let fileBackedFinding = Finding (
id : UUID ( ) ,
title : " Disk-backed fixture " ,
detail : targetFile . path ,
bytes : 5 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ targetFile . path ]
)
let stateOnlyFinding = Finding (
id : UUID ( ) ,
title : " Atlas-only fixture " ,
detail : " State-only recovery item " ,
bytes : 7 ,
risk : . safe ,
category : " Developer tools "
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 0 ,
findings : [ ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [
RecoveryItem (
id : UUID ( ) ,
title : fileBackedFinding . title ,
detail : fileBackedFinding . detail ,
originalPath : targetFile . path ,
bytes : fileBackedFinding . bytes ,
deletedAt : Date ( ) ,
expiresAt : Date ( ) . addingTimeInterval ( 3600 ) ,
payload : . finding ( fileBackedFinding ) ,
restoreMappings : [ RecoveryPathMapping ( originalPath : targetFile . path , trashedPath : trashedPath ) ]
) ,
RecoveryItem (
id : UUID ( ) ,
title : stateOnlyFinding . title ,
detail : stateOnlyFinding . detail ,
originalPath : " ~/Library/Caches/AtlasOnly " ,
bytes : stateOnlyFinding . bytes ,
deletedAt : Date ( ) ,
expiresAt : Date ( ) . addingTimeInterval ( 3600 ) ,
payload : . finding ( stateOnlyFinding ) ,
restoreMappings : nil
) ,
] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let restoreItemIDs = state . snapshot . recoveryItems . map ( \ . id )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let restore = try await worker . submit ( AtlasRequestEnvelope ( command : . restoreItems ( taskID : UUID ( ) , itemIDs : restoreItemIDs ) ) )
if case let . accepted ( task ) = restore . response . response {
XCTAssertEqual ( task . kind , . restore )
} else {
XCTFail ( " Expected accepted restore response " )
}
XCTAssertTrue ( FileManager . default . fileExists ( atPath : targetFile . path ) )
XCTAssertTrue ( restore . snapshot . findings . contains ( where : { $0 . id = = fileBackedFinding . id } ) )
XCTAssertTrue ( restore . snapshot . findings . contains ( where : { $0 . id = = stateOnlyFinding . id } ) )
XCTAssertEqual (
restore . snapshot . taskRuns . first ? . summary ,
[
AtlasL10n . string ( " infrastructure.restore.summary.disk.one " , language : state . settings . language ) ,
AtlasL10n . string ( " infrastructure.restore.summary.state.one " , language : state . settings . language ) ,
] . joined ( separator : " " )
)
}
func testRestoreItemsRejectsWhenDestinationAlreadyExists ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let fileManager = FileManager . default
let home = fileManager . homeDirectoryForCurrentUser
let sourceDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
let destinationDirectory = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try fileManager . createDirectory ( at : sourceDirectory , withIntermediateDirectories : true )
try fileManager . createDirectory ( at : destinationDirectory , withIntermediateDirectories : true )
let trashedCandidate = sourceDirectory . appendingPathComponent ( " trashed.cache " )
try Data ( " trashed " . utf8 ) . write ( to : trashedCandidate )
var trashedURL : NSURL ?
try fileManager . trashItem ( at : trashedCandidate , resultingItemURL : & trashedURL )
let trashedPath = try XCTUnwrap ( ( trashedURL as URL ? ) ? . path )
let destinationURL = destinationDirectory . appendingPathComponent ( " trashed.cache " )
try Data ( " existing " . utf8 ) . write ( to : destinationURL )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : sourceDirectory )
try ? FileManager . default . removeItem ( at : destinationDirectory )
if let trashedURL {
try ? FileManager . default . removeItem ( at : trashedURL as URL )
}
}
let finding = Finding (
id : UUID ( ) ,
title : " Conflicting restore " ,
detail : destinationURL . path ,
bytes : 7 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ destinationURL . path ]
)
let recoveryItem = RecoveryItem (
id : UUID ( ) ,
title : finding . title ,
detail : finding . detail ,
originalPath : destinationURL . path ,
bytes : 7 ,
deletedAt : Date ( ) ,
expiresAt : Date ( ) . addingTimeInterval ( 3600 ) ,
payload : . finding ( finding ) ,
restoreMappings : [ RecoveryPathMapping ( originalPath : destinationURL . path , trashedPath : trashedPath ) ]
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 0 ,
findings : [ ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ recoveryItem ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : false )
let restore = try await worker . submit (
AtlasRequestEnvelope ( command : . restoreItems ( taskID : UUID ( ) , itemIDs : [ recoveryItem . id ] ) )
)
guard case let . rejected ( code , reason ) = restore . response . response else {
return XCTFail ( " Expected rejected restore response " )
}
XCTAssertEqual ( code , . restoreConflict )
XCTAssertTrue ( reason . contains ( destinationURL . path ) )
XCTAssertTrue ( fileManager . fileExists ( atPath : destinationURL . path ) )
XCTAssertTrue ( fileManager . fileExists ( atPath : trashedPath ) )
}
2026-03-13 16:40:31 +08:00
func testRestoreItemsKeepsStateUnchangedWhenLaterHelperRestoreFails ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let fileManager = FileManager . default
let home = fileManager . homeDirectoryForCurrentUser
let directRoot = home . appendingPathComponent ( " Library/Caches/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
try fileManager . createDirectory ( at : directRoot , withIntermediateDirectories : true )
let directTargetURL = directRoot . appendingPathComponent ( " restored.cache " )
try Data ( " restored " . utf8 ) . write ( to : directTargetURL )
var directTrashedURL : NSURL ?
try fileManager . trashItem ( at : directTargetURL , resultingItemURL : & directTrashedURL )
let directTrashedPath = try XCTUnwrap ( ( directTrashedURL as URL ? ) ? . path )
let appRoot = home . appendingPathComponent ( " Applications/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
let appBundleURL = appRoot . appendingPathComponent ( " Atlas Restore Conflict.app " , isDirectory : true )
try fileManager . createDirectory ( at : appBundleURL . appendingPathComponent ( " Contents/MacOS " ) , withIntermediateDirectories : true )
try Data ( " #!/bin/sh \n exit 0 \n " . utf8 ) . write ( to : appBundleURL . appendingPathComponent ( " Contents/MacOS/AtlasRestoreConflict " ) )
var appTrashedURL : NSURL ?
try fileManager . trashItem ( at : appBundleURL , resultingItemURL : & appTrashedURL )
let appTrashedPath = try XCTUnwrap ( ( appTrashedURL as URL ? ) ? . path )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : directRoot )
try ? FileManager . default . removeItem ( at : appRoot )
if let directTrashedURL {
try ? FileManager . default . removeItem ( at : directTrashedURL as URL )
}
if let appTrashedURL {
try ? FileManager . default . removeItem ( at : appTrashedURL as URL )
}
}
let directFinding = Finding (
id : UUID ( ) ,
title : " Direct restore fixture " ,
detail : directTargetURL . path ,
bytes : 11 ,
risk : . safe ,
category : " Developer tools " ,
targetPaths : [ directTargetURL . path ]
)
let helperApp = AppFootprint (
id : UUID ( ) ,
name : " Atlas Restore Conflict " ,
bundleIdentifier : " com.atlas.restore-conflict " ,
bundlePath : appBundleURL . path ,
bytes : 17 ,
leftoverItems : 1
)
let directRecoveryItem = RecoveryItem (
id : UUID ( ) ,
title : directFinding . title ,
detail : directFinding . detail ,
originalPath : directTargetURL . path ,
bytes : directFinding . bytes ,
deletedAt : Date ( ) ,
expiresAt : Date ( ) . addingTimeInterval ( 3600 ) ,
payload : . finding ( directFinding ) ,
restoreMappings : [ RecoveryPathMapping ( originalPath : directTargetURL . path , trashedPath : directTrashedPath ) ]
)
let helperRecoveryItem = RecoveryItem (
id : UUID ( ) ,
title : helperApp . name ,
detail : helperApp . bundlePath ,
originalPath : helperApp . bundlePath ,
bytes : helperApp . bytes ,
deletedAt : Date ( ) ,
expiresAt : Date ( ) . addingTimeInterval ( 3600 ) ,
2026-03-23 16:48:59 +08:00
payload : . app (
AtlasAppRecoveryPayload (
app : helperApp ,
uninstallEvidence : AtlasAppUninstallEvidence (
bundlePath : helperApp . bundlePath ,
bundleBytes : helperApp . bytes ,
reviewOnlyGroups : [ ]
)
)
) ,
2026-03-13 16:40:31 +08:00
restoreMappings : [ RecoveryPathMapping ( originalPath : helperApp . bundlePath , trashedPath : appTrashedPath ) ]
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 0 ,
findings : [ ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ directRecoveryItem , helperRecoveryItem ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
helperExecutor : RestoreConflictPrivilegedHelperExecutor ( ) ,
allowStateOnlyCleanExecution : false
)
let restore = try await worker . submit (
AtlasRequestEnvelope ( command : . restoreItems ( taskID : UUID ( ) , itemIDs : [ directRecoveryItem . id , helperRecoveryItem . id ] ) )
)
guard case let . rejected ( code , reason ) = restore . response . response else {
return XCTFail ( " Expected rejected restore response " )
}
XCTAssertEqual ( code , . restoreConflict )
XCTAssertTrue ( reason . contains ( helperApp . bundlePath ) )
XCTAssertTrue ( fileManager . fileExists ( atPath : directTargetURL . path ) )
XCTAssertFalse ( fileManager . fileExists ( atPath : directTrashedPath ) )
XCTAssertFalse ( fileManager . fileExists ( atPath : helperApp . bundlePath ) )
XCTAssertTrue ( fileManager . fileExists ( atPath : appTrashedPath ) )
XCTAssertFalse ( restore . snapshot . findings . contains ( where : { $0 . id = = directFinding . id } ) )
XCTAssertFalse ( restore . snapshot . apps . contains ( where : { $0 . id = = helperApp . id } ) )
XCTAssertEqual ( restore . snapshot . recoveryItems . map ( \ . id ) , [ directRecoveryItem . id , helperRecoveryItem . id ] )
let persisted = repository . loadState ( )
XCTAssertFalse ( persisted . snapshot . findings . contains ( where : { $0 . id = = directFinding . id } ) )
XCTAssertFalse ( persisted . snapshot . apps . contains ( where : { $0 . id = = helperApp . id } ) )
XCTAssertEqual ( persisted . snapshot . recoveryItems . map ( \ . id ) , [ directRecoveryItem . id , helperRecoveryItem . id ] )
}
2026-03-10 17:09:35 +08:00
func testExecuteAppUninstallRemovesAppAndCreatesRecoveryEntry ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let worker = AtlasScaffoldWorkerService ( repository : repository , allowStateOnlyCleanExecution : true )
let initialState = repository . loadState ( )
let app = try XCTUnwrap ( initialState . snapshot . apps . first )
let result = try await worker . submit (
AtlasRequestEnvelope ( command : . executeAppUninstall ( appID : app . id ) )
)
XCTAssertFalse ( result . snapshot . apps . contains ( where : { $0 . id = = app . id } ) )
XCTAssertTrue ( result . snapshot . recoveryItems . contains ( where : { $0 . title = = app . name } ) )
XCTAssertEqual ( result . snapshot . taskRuns . first ? . kind , . uninstallApp )
2026-03-23 16:48:59 +08:00
XCTAssertEqual (
result . snapshot . taskRuns . first ? . summary ,
AtlasL10n . string ( " infrastructure.apps.uninstall.summary " , language : initialState . settings . language , app . name )
)
}
func testExecuteAppUninstallSummaryMentionsReviewOnlyEvidenceGroupsWhenPresent ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let fileManager = FileManager . default
let sandboxRoot = fileManager . temporaryDirectory . appendingPathComponent ( UUID ( ) . uuidString , isDirectory : true )
let homeRoot = sandboxRoot . appendingPathComponent ( " Home " , isDirectory : true )
let cacheURL = homeRoot . appendingPathComponent ( " Library/Caches/com.example.execute " , isDirectory : true )
let logsURL = homeRoot . appendingPathComponent ( " Library/Logs/Execute Preview " , isDirectory : true )
try fileManager . createDirectory ( at : cacheURL , withIntermediateDirectories : true )
try fileManager . createDirectory ( at : logsURL , withIntermediateDirectories : true )
try Data ( repeating : 0x1 , count : 64 ) . write ( to : cacheURL . appendingPathComponent ( " cache.bin " ) )
try Data ( repeating : 0x2 , count : 64 ) . write ( to : logsURL . appendingPathComponent ( " run.log " ) )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : sandboxRoot )
}
let appRoot = fileManager . homeDirectoryForCurrentUser . appendingPathComponent ( " Applications/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
let appBundleURL = appRoot . appendingPathComponent ( " Execute Preview.app " , isDirectory : true )
try fileManager . createDirectory ( at : appBundleURL , withIntermediateDirectories : true )
let executableURL = appBundleURL . appendingPathComponent ( " Contents/MacOS/ExecutePreview " )
try fileManager . createDirectory ( at : executableURL . deletingLastPathComponent ( ) , withIntermediateDirectories : true )
try Data ( " #!/bin/sh \n exit 0 \n " . utf8 ) . write ( to : executableURL )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : appRoot )
}
let app = AppFootprint (
id : UUID ( ) ,
name : " Execute Preview " ,
bundleIdentifier : " com.example.execute " ,
bundlePath : appBundleURL . path ,
bytes : 17 ,
leftoverItems : 2
)
var settings = AtlasScaffoldWorkspace . state ( ) . settings
settings . language = . en
settings . acknowledgementText = AtlasL10n . acknowledgement ( language : . en )
settings . thirdPartyNoticesText = AtlasL10n . thirdPartyNotices ( language : . en )
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : app . bytes ,
findings : [ ] ,
apps : [ app ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
helperExecutor : StubPrivilegedHelperExecutor ( ) ,
appUninstallEvidenceAnalyzer : AtlasAppUninstallEvidenceAnalyzer ( homeDirectoryURL : homeRoot ) ,
allowStateOnlyCleanExecution : false
)
let result = try await worker . submit (
AtlasRequestEnvelope ( command : . executeAppUninstall ( appID : app . id ) )
)
XCTAssertEqual (
result . snapshot . taskRuns . first ? . summary ,
AtlasL10n . string ( " infrastructure.apps.uninstall.summary.review.other " , language : . en , app . name , 2 )
+ " "
+ AtlasL10n . string ( " infrastructure.apps.uninstall.reviewCategories " , language : . en , " caches, logs " )
)
XCTAssertEqual (
result . snapshot . recoveryItems . first ? . detail ,
AtlasL10n . string ( " infrastructure.recovery.app.detail.other " , language : . en , 2 )
+ " "
+ AtlasL10n . string ( " infrastructure.apps.uninstall.reviewCategories " , language : . en , " caches, logs " )
)
}
func testPreviewAppUninstallBuildsReviewOnlyEvidenceItems ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let fileManager = FileManager . default
let sandboxRoot = fileManager . temporaryDirectory . appendingPathComponent ( UUID ( ) . uuidString , isDirectory : true )
let homeRoot = sandboxRoot . appendingPathComponent ( " Home " , isDirectory : true )
let appSupportURL = homeRoot . appendingPathComponent ( " Library/Application Support/Atlas Preview " , isDirectory : true )
let cacheURL = homeRoot . appendingPathComponent ( " Library/Caches/com.example.preview " , isDirectory : true )
let launchAgentURL = homeRoot . appendingPathComponent ( " Library/LaunchAgents/com.example.preview.plist " )
try fileManager . createDirectory ( at : appSupportURL , withIntermediateDirectories : true )
try fileManager . createDirectory ( at : cacheURL , withIntermediateDirectories : true )
try fileManager . createDirectory ( at : launchAgentURL . deletingLastPathComponent ( ) , withIntermediateDirectories : true )
try Data ( repeating : 0x1 , count : 256 ) . write ( to : appSupportURL . appendingPathComponent ( " state.db " ) )
try Data ( repeating : 0x2 , count : 128 ) . write ( to : cacheURL . appendingPathComponent ( " cache.bin " ) )
try Data ( " <?xml version= \" 1.0 \" ?><plist></plist> " . utf8 ) . write ( to : launchAgentURL )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : sandboxRoot )
}
let app = AppFootprint (
id : UUID ( ) ,
name : " Atlas Preview " ,
bundleIdentifier : " com.example.preview " ,
bundlePath : " /Applications/Atlas Preview.app " ,
bytes : 2_048 ,
leftoverItems : 3
)
var settings = AtlasScaffoldWorkspace . state ( ) . settings
settings . language = . en
settings . acknowledgementText = AtlasL10n . acknowledgement ( language : . en )
settings . thirdPartyNoticesText = AtlasL10n . thirdPartyNotices ( language : . en )
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : app . bytes ,
findings : [ ] ,
apps : [ app ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
appUninstallEvidenceAnalyzer : AtlasAppUninstallEvidenceAnalyzer ( homeDirectoryURL : homeRoot ) ,
allowStateOnlyCleanExecution : true
)
let result = try await worker . submit (
AtlasRequestEnvelope ( command : . previewAppUninstall ( appID : app . id ) )
)
guard case let . preview ( plan ) = result . response . response else {
return XCTFail ( " Expected preview response " )
}
XCTAssertEqual ( plan . estimatedBytes , app . bytes )
XCTAssertEqual ( plan . items . first ? . kind , . removeApp )
XCTAssertEqual ( plan . items . first ? . targetPaths , [ app . bundlePath ] )
XCTAssertEqual ( plan . items . count , 4 )
let supportFilesItem = try XCTUnwrap ( plan . items . first ( where : { $0 . title = = " Review support files (1) " && ! $0 . recoverable } ) )
let cachesItem = try XCTUnwrap ( plan . items . first ( where : { $0 . title = = " Review caches (1) " && ! $0 . recoverable } ) )
let launchItemsItem = try XCTUnwrap ( plan . items . first ( where : { $0 . title = = " Review launch items (1) " && ! $0 . recoverable } ) )
XCTAssertEqual ( supportFilesItem . evidencePaths , [ appSupportURL . path ] )
XCTAssertEqual ( cachesItem . evidencePaths , [ cacheURL . path ] )
XCTAssertEqual ( launchItemsItem . evidencePaths , [ launchAgentURL . path ] )
2026-03-10 17:09:35 +08:00
}
2026-03-13 10:35:15 +08:00
func testExecuteAppUninstallRestorePhysicallyRestoresAppBundle ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let fileManager = FileManager . default
let appRoot = fileManager . homeDirectoryForCurrentUser . appendingPathComponent ( " Applications/AtlasExecutionTests/ " + UUID ( ) . uuidString , isDirectory : true )
let appBundleURL = appRoot . appendingPathComponent ( " Atlas Restore Test.app " , isDirectory : true )
try fileManager . createDirectory ( at : appBundleURL , withIntermediateDirectories : true )
let executableURL = appBundleURL . appendingPathComponent ( " Contents/MacOS/AtlasRestoreTest " )
try fileManager . createDirectory ( at : executableURL . deletingLastPathComponent ( ) , withIntermediateDirectories : true )
try Data ( " #!/bin/sh \n exit 0 \n " . utf8 ) . write ( to : executableURL )
addTeardownBlock {
try ? FileManager . default . removeItem ( at : appRoot )
}
let app = AppFootprint (
id : UUID ( ) ,
name : " Atlas Restore Test " ,
bundleIdentifier : " com.atlas.restore-test " ,
bundlePath : appBundleURL . path ,
bytes : 17 ,
leftoverItems : 1
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : app . bytes ,
findings : [ ] ,
apps : [ app ] ,
taskRuns : [ ] ,
recoveryItems : [ ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
helperExecutor : StubPrivilegedHelperExecutor ( ) ,
allowStateOnlyCleanExecution : false
)
let execute = try await worker . submit (
AtlasRequestEnvelope ( command : . executeAppUninstall ( appID : app . id ) )
)
if case let . accepted ( task ) = execute . response . response {
XCTAssertEqual ( task . kind , . uninstallApp )
} else {
XCTFail ( " Expected accepted uninstall response " )
}
XCTAssertFalse ( fileManager . fileExists ( atPath : appBundleURL . path ) )
XCTAssertFalse ( execute . snapshot . apps . contains ( where : { $0 . id = = app . id } ) )
let recoveryItem = try XCTUnwrap ( execute . snapshot . recoveryItems . first )
XCTAssertEqual ( recoveryItem . restoreMappings ? . first ? . originalPath , appBundleURL . path )
XCTAssertNotNil ( recoveryItem . restoreMappings ? . first ? . trashedPath )
let restore = try await worker . submit (
AtlasRequestEnvelope ( command : . restoreItems ( taskID : UUID ( ) , itemIDs : [ recoveryItem . id ] ) )
)
if case let . accepted ( task ) = restore . response . response {
XCTAssertEqual ( task . kind , . restore )
} else {
XCTFail ( " Expected accepted restore response " )
}
XCTAssertTrue ( fileManager . fileExists ( atPath : appBundleURL . path ) )
XCTAssertTrue ( restore . snapshot . apps . contains ( where : { $0 . id = = app . id } ) )
XCTAssertEqual (
restore . snapshot . taskRuns . first ? . summary ,
AtlasL10n . string ( " infrastructure.restore.summary.disk.one " , language : state . settings . language )
)
}
2026-03-23 16:48:59 +08:00
func testRestoreAppUsesPersistedUninstallEvidenceCountWhenAvailable ( ) async throws {
let repository = AtlasWorkspaceRepository ( stateFileURL : temporaryStateFileURL ( ) )
let app = AppFootprint (
id : UUID ( ) ,
name : " Atlas Restore Evidence " ,
bundleIdentifier : " com.example.restore-evidence " ,
bundlePath : " /Applications/Atlas Restore Evidence.app " ,
bytes : 42 ,
leftoverItems : 1
)
let recoveryItem = RecoveryItem (
id : UUID ( ) ,
title : app . name ,
detail : app . bundlePath ,
originalPath : app . bundlePath ,
bytes : app . bytes ,
deletedAt : Date ( ) ,
expiresAt : Date ( ) . addingTimeInterval ( 3600 ) ,
payload : . app (
AtlasAppRecoveryPayload (
app : app ,
uninstallEvidence : AtlasAppUninstallEvidence (
bundlePath : app . bundlePath ,
bundleBytes : app . bytes ,
reviewOnlyGroups : [
AtlasAppFootprintEvidenceGroup (
category : . caches ,
items : [
AtlasAppFootprintEvidenceItem ( path : " /Users/test/Library/Caches/com.example.restore-evidence " , bytes : 12 ) ,
AtlasAppFootprintEvidenceItem ( path : " /Users/test/Library/Caches/com.example.restore-evidence-2 " , bytes : 12 ) ,
]
) ,
AtlasAppFootprintEvidenceGroup (
category : . logs ,
items : [
AtlasAppFootprintEvidenceItem ( path : " /Users/test/Library/Logs/Atlas Restore Evidence " , bytes : 8 )
]
)
]
)
)
) ,
restoreMappings : nil
)
let state = AtlasWorkspaceState (
snapshot : AtlasWorkspaceSnapshot (
reclaimableSpaceBytes : 0 ,
findings : [ ] ,
apps : [ ] ,
taskRuns : [ ] ,
recoveryItems : [ recoveryItem ] ,
permissions : [ ] ,
healthSnapshot : nil
) ,
currentPlan : ActionPlan ( title : " Review 0 selected findings " , items : [ ] , estimatedBytes : 0 ) ,
settings : AtlasScaffoldWorkspace . state ( ) . settings
)
_ = try repository . saveState ( state )
let worker = AtlasScaffoldWorkerService (
repository : repository ,
allowStateOnlyCleanExecution : true
)
let restore = try await worker . submit (
AtlasRequestEnvelope ( command : . restoreItems ( taskID : UUID ( ) , itemIDs : [ recoveryItem . id ] ) )
)
let restoredApp = try XCTUnwrap ( restore . snapshot . apps . first ( where : { $0 . id = = app . id } ) )
XCTAssertEqual ( restoredApp . leftoverItems , 3 )
}
2026-03-10 17:09:35 +08:00
private func temporaryStateFileURL ( ) -> URL {
FileManager . default . temporaryDirectory
. appendingPathComponent ( UUID ( ) . uuidString , isDirectory : true )
. appendingPathComponent ( " workspace-state.json " )
}
}
private struct FailingSmartCleanProvider : AtlasSmartCleanScanProviding {
func collectSmartCleanScan ( ) async throws -> AtlasSmartCleanScanResult {
struct SampleError : LocalizedError { var errorDescription : String ? { " simulated scan failure " } }
throw SampleError ( )
}
}
private struct FileBackedSmartCleanProvider : AtlasSmartCleanScanProviding {
let targetFileURL : URL
2026-03-12 23:19:18 +08:00
var title : String = " Sample cache "
var category : String = " Developer tools "
2026-03-10 17:09:35 +08:00
func collectSmartCleanScan ( ) async throws -> AtlasSmartCleanScanResult {
guard FileManager . default . fileExists ( atPath : targetFileURL . path ) else {
return AtlasSmartCleanScanResult ( findings : [ ] , summary : " No reclaimable items remain. " )
}
let size = Int64 ( ( try ? FileManager . default . attributesOfItem ( atPath : targetFileURL . path ) [ . size ] as ? NSNumber ) ? . int64Value ? ? 0 )
let finding = Finding (
id : UUID ( uuidString : " 30000000-0000-0000-0000-000000000001 " ) ? ? UUID ( ) ,
2026-03-12 23:19:18 +08:00
title : title ,
2026-03-10 17:09:35 +08:00
detail : targetFileURL . path ,
bytes : size ,
risk : . safe ,
2026-03-12 23:19:18 +08:00
category : category ,
2026-03-10 17:09:35 +08:00
targetPaths : [ targetFileURL . path ]
)
return AtlasSmartCleanScanResult ( findings : [ finding ] , summary : " Found 1 reclaimable item. " )
}
}
2026-03-13 10:35:15 +08:00
private actor StubPrivilegedHelperExecutor : AtlasPrivilegedActionExecuting {
func perform ( _ action : AtlasHelperAction ) async throws -> AtlasHelperActionResult {
let fileManager = FileManager . default
let targetURL = URL ( fileURLWithPath : action . targetPath )
switch action . kind {
case . trashItems :
var trashedURL : NSURL ?
try fileManager . trashItem ( at : targetURL , resultingItemURL : & trashedURL )
return AtlasHelperActionResult (
action : action ,
success : true ,
message : " Moved item to Trash. " ,
resolvedPath : ( trashedURL as URL ? ) ? . path
)
case . restoreItem :
let destinationPath = try XCTUnwrap ( action . destinationPath )
let destinationURL = URL ( fileURLWithPath : destinationPath )
try fileManager . createDirectory ( at : destinationURL . deletingLastPathComponent ( ) , withIntermediateDirectories : true )
try fileManager . moveItem ( at : targetURL , to : destinationURL )
return AtlasHelperActionResult (
action : action ,
success : true ,
message : " Restored item from Trash. " ,
resolvedPath : destinationURL . path
)
case . removeLaunchService , . repairOwnership :
throw NSError ( domain : " StubPrivilegedHelperExecutor " , code : 1 , userInfo : [ NSLocalizedDescriptionKey : " Unsupported test helper action: \( action . kind ) " ] )
}
}
}
2026-03-13 16:40:31 +08:00
private actor RestoreConflictPrivilegedHelperExecutor : AtlasPrivilegedActionExecuting {
func perform ( _ action : AtlasHelperAction ) async throws -> AtlasHelperActionResult {
AtlasHelperActionResult (
action : action ,
success : false ,
message : " Restore destination already exists: \( action . destinationPath ? ? " <missing> " ) "
)
}
}
2026-03-13 10:35:15 +08:00
private final class TestClock : @ unchecked Sendable {
var now : Date
init ( now : Date ) {
self . now = now
}
}