diff options
Diffstat (limited to 'SoraTests')
| -rw-r--r-- | SoraTests/SettingsManagerSyncTests.swift | 77 | ||||
| -rw-r--r-- | SoraTests/ViewDerivedDataTests.swift | 63 |
2 files changed, 140 insertions, 0 deletions
diff --git a/SoraTests/SettingsManagerSyncTests.swift b/SoraTests/SettingsManagerSyncTests.swift index 50106dc..8ed9d83 100644 --- a/SoraTests/SettingsManagerSyncTests.swift +++ b/SoraTests/SettingsManagerSyncTests.swift @@ -91,6 +91,83 @@ final class SettingsManagerSyncTests: XCTestCase { ) } + func testSearchHistoryMutationPathReusesSortedPayloadAndAvoidsInlineResort() throws { + let source = try loadSource(at: "Sora/Data/Settings/SettingsManager.swift") + let searchHistorySetterSection = try extractFunction( + named: "var searchHistory: [BooruSearchQuery]", + from: source + ) + let updateSearchHistorySection = try extractFunction( + named: "func updateSearchHistory(", + from: source + ) + let normalizedSetterSection = strippingCommentsAndStrings(from: searchHistorySetterSection) + let normalizedUpdateSection = strippingCommentsAndStrings(from: updateSearchHistorySection) + let setterSortedHistoryDeclarationCount = tokenCount( + matching: #"\blet\s+sortedSearchHistory\s*="#, + in: normalizedSetterSection + ) + let setterInlineSortClosureCount = tokenCount( + matching: #"syncableData\s*\([\s\S]*?\)\s*\{\s*\$0\s*\.\s*sorted"#, + in: normalizedSetterSection + ) + let setterPreEncodedForwardCount = tokenCount( + matching: #"syncableData\s*\([\s\S]*?\bencodedData\s*:"#, + in: normalizedSetterSection + ) + + let updateSortedHistoryDeclarationCount = tokenCount( + matching: #"\blet\s+sortedSearchHistory\s*="#, + in: normalizedUpdateSection + ) + let updateInlineSortClosureCount = tokenCount( + matching: #"syncableData\s*\([\s\S]*?\)\s*\{\s*\$0\s*\.\s*sorted"#, + in: normalizedUpdateSection + ) + let updatePreEncodedForwardCount = tokenCount( + matching: #"syncableData\s*\([\s\S]*?\bencodedData\s*:"#, + in: normalizedUpdateSection + ) + + // swiftlint:disable:next prefer_nimble + XCTAssertGreaterThan( + setterSortedHistoryDeclarationCount, + 0, + "searchHistory setter should precompute sorted values once." + ) + // swiftlint:disable:next prefer_nimble + XCTAssertEqual( + setterInlineSortClosureCount, + 0, + "searchHistory setter should avoid inline resorting inside syncableData." + ) + // swiftlint:disable:next prefer_nimble + XCTAssertGreaterThan( + setterPreEncodedForwardCount, + 0, + "searchHistory setter should forward a pre-encoded payload to syncableData." + ) + + // swiftlint:disable:next prefer_nimble + XCTAssertGreaterThan( + updateSortedHistoryDeclarationCount, + 0, + "updateSearchHistory should precompute sorted values once." + ) + // swiftlint:disable:next prefer_nimble + XCTAssertEqual( + updateInlineSortClosureCount, + 0, + "updateSearchHistory should avoid inline resorting inside syncableData." + ) + // swiftlint:disable:next prefer_nimble + XCTAssertGreaterThan( + updatePreEncodedForwardCount, + 0, + "updateSearchHistory should forward a pre-encoded payload to syncableData." + ) + } + func testBatchedSyncPathGuardsUnchangedPayloadWrites() throws { let source = try loadSource(at: "Sora/Data/Settings/SettingsManager.swift") let triggerSyncSection = try extractFunction( diff --git a/SoraTests/ViewDerivedDataTests.swift b/SoraTests/ViewDerivedDataTests.swift index 6a27667..d19b51a 100644 --- a/SoraTests/ViewDerivedDataTests.swift +++ b/SoraTests/ViewDerivedDataTests.swift @@ -872,6 +872,69 @@ final class ViewDerivedDataTests: XCTestCase { // swiftlint:disable:this type_b ) } + func testBooruManagerDanbooruPaginationCachesMinimumPostIDForCursorToken() throws { + let source = try loadSource(at: "Sora/Data/Booru/BooruManager.swift") + let pageTokenFunctionSection = try extractFunction( + named: "private func danbooruPageToken(for page: Int, tags: [String]) -> String", + from: source + ) + let updatePostsSection = try extractFunction( + named: "private func updatePosts(_ newPosts: [BooruPost], replace: Bool)", + from: source + ) + let cachedMinimumPostIDStorageCount = tokenCount( + matching: #"private\s+var\s+cachedMinimumPostID:\s*Int\?"#, + in: source + ) + let cachedTokenGuardCount = tokenCount( + matching: #"guard\s+let\s+minimumPostID\s*=\s*cachedMinimumPostID"#, + in: pageTokenFunctionSection + ) + let directPostsMinScanCount = tokenCount( + matching: #"posts\s*\.\s*lazy\s*\.\s*compactMap\s*\(\s*\{\s*Int\(\$0\.id\)\s*\}\s*\)\s*\.\s*min"#, + in: pageTokenFunctionSection + ) + let cacheInvalidationOnReplaceCount = tokenCount( + matching: #"cachedMinimumPostID\s*=\s*nil"#, + in: updatePostsSection + ) + let cacheRefreshCount = tokenCount( + matching: #"cachedMinimumPostID\s*=\s*min\("#, + in: updatePostsSection + ) + + // swiftlint:disable:next prefer_nimble + XCTAssertGreaterThan( + cachedMinimumPostIDStorageCount, + 0, + "BooruManager should store a cached minimum post ID for Danbooru pagination." + ) + // swiftlint:disable:next prefer_nimble + XCTAssertGreaterThan( + cachedTokenGuardCount, + 0, + "Danbooru page token generation should use cached minimum post ID." + ) + // swiftlint:disable:next prefer_nimble + XCTAssertEqual( + directPostsMinScanCount, + 0, + "Danbooru page token generation should avoid rescanning all posts for minimum ID." + ) + // swiftlint:disable:next prefer_nimble + XCTAssertGreaterThan( + cacheInvalidationOnReplaceCount, + 0, + "Replacing posts should invalidate cached Danbooru minimum post ID." + ) + // swiftlint:disable:next prefer_nimble + XCTAssertGreaterThan( + cacheRefreshCount, + 0, + "Appending posts should refresh cached Danbooru minimum post ID incrementally." + ) + } + func testBooruManagerDoesNotForceClientSidePostResort() throws { let source = try loadSource(at: "Sora/Data/Booru/BooruManager.swift") let retrySection = try extractFunction( |