diff --git a/Firestore/CHANGELOG.md b/Firestore/CHANGELOG.md index 37b5bbd9cd3..e1926f1fe07 100644 --- a/Firestore/CHANGELOG.md +++ b/Firestore/CHANGELOG.md @@ -1,3 +1,7 @@ +# Unreleased +- [feature] Add the option to allow the SDK to create cache indexes automatically to + improve query execution locally. (#11596) + # 10.12.0 - [feature] Implemented an optimization in the local cache synchronization logic that reduces the number of billed document reads when documents were deleted diff --git a/Firestore/Example/Firestore.xcodeproj/project.pbxproj b/Firestore/Example/Firestore.xcodeproj/project.pbxproj index d31d4893c53..ac9c117034c 100644 --- a/Firestore/Example/Firestore.xcodeproj/project.pbxproj +++ b/Firestore/Example/Firestore.xcodeproj/project.pbxproj @@ -233,6 +233,7 @@ 21836C4D9D48F962E7A3A244 /* ordered_code_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380D03201BC6E400D97691 /* ordered_code_test.cc */; }; 21A2A881F71CB825299DF06E /* hard_assert_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */; }; 21C17F15579341289AD01051 /* persistence_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 9113B6F513D0473AEABBAF1F /* persistence_testing.cc */; }; + 21E588CF29C72813D8A7A0A1 /* FSTExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */; }; 21E66B6A4A00786C3E934EB1 /* query_engine_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B8A853940305237AFDA8050B /* query_engine_test.cc */; }; 224496E752E42E220F809FAC /* resource.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1C3F7302BF4AE6CBC00ECDD0 /* resource.pb.cc */; }; 226574601C3F6D14DF14C16B /* recovery_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 9C1AFCC9E616EC33D6E169CF /* recovery_spec_test.json */; }; @@ -364,6 +365,7 @@ 380E543B7BC6F648BBB250B4 /* md5_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3D050936A2D52257FD17FB6E /* md5_test.cc */; }; 38208AC761FF994BA69822BE /* async_queue_std_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6FB4681208EA0BE00554BA2 /* async_queue_std_test.cc */; }; 3887E1635B31DCD7BC0922BD /* existence_filter_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA129D1F315EE100DD57A1 /* existence_filter_spec_test.json */; }; + 38C37F0CE0AB18F1AAE6E67C /* FSTExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */; }; 392966346DA5EB3165E16A22 /* bundle_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F7FC06E0A47D393DE1759AE1 /* bundle_cache_test.cc */; }; 392F527F144BADDAC69C5485 /* string_format_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54131E9620ADE678001DF3FF /* string_format_test.cc */; }; 394259BB091E1DB5994B91A2 /* bundle.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = A366F6AE1A5A77548485C091 /* bundle.pb.cc */; }; @@ -488,6 +490,7 @@ 4E7981690432CDFA2058E3EC /* FSTTestingHooks.mm in Sources */ = {isa = PBXBuildFile; fileRef = D85AC18C55650ED230A71B82 /* FSTTestingHooks.mm */; }; 4EC642DFC4AE98DBFFB37B17 /* fields_array_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = BA4CBA48204C9E25B56993BC /* fields_array_test.cc */; }; 4EE1ABA574FBFDC95165624C /* delayed_constructor_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D0A6E9136804A41CEC9D55D4 /* delayed_constructor_test.cc */; }; + 4F55A97F725D86E5CC6BE2DC /* FSTExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */; }; 4F5714D37B6D119CB07ED8AE /* orderby_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA12A21F315EE100DD57A1 /* orderby_spec_test.json */; }; 4F65FD71B7960944C708A962 /* leveldb_lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B629525F7A1AAC1AB765C74F /* leveldb_lru_garbage_collector_test.cc */; }; 4F857404731D45F02C5EE4C3 /* async_queue_libdispatch_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = B6FB4680208EA0BE00554BA2 /* async_queue_libdispatch_test.mm */; }; @@ -732,6 +735,9 @@ 627253FDEC6BB5549FE77F4E /* tree_sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA4D20A36DBB00BCEB75 /* tree_sorted_map_test.cc */; }; 62B1C1100A8C68D94565916C /* document_overlay_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = FFCA39825D9678A03D1845D0 /* document_overlay_cache_test.cc */; }; 62DA31B79FE97A90EEF28B0B /* delayed_constructor_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D0A6E9136804A41CEC9D55D4 /* delayed_constructor_test.cc */; }; + 62E54B842A9E910B003347C8 /* IndexingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E54B832A9E910A003347C8 /* IndexingTests.swift */; }; + 62E54B852A9E910B003347C8 /* IndexingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E54B832A9E910A003347C8 /* IndexingTests.swift */; }; + 62E54B862A9E910B003347C8 /* IndexingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E54B832A9E910A003347C8 /* IndexingTests.swift */; }; 62EC5F7FB416BA124A2B4604 /* byte_stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 432C71959255C5DBDF522F52 /* byte_stream_test.cc */; }; 62F86BBE7DDA5B295B57C8DA /* string_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0EE5300F8233D14025EF0456 /* string_apple_test.mm */; }; 6300709ECDE8E0B5A8645F8D /* time_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5497CB76229DECDE000FB92F /* time_testing.cc */; }; @@ -1170,6 +1176,7 @@ B491EF0E70DC0542644F623E /* Validation_BloomFilterTest_MD5_500_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 8AB49283E544497A9C5A0E59 /* Validation_BloomFilterTest_MD5_500_1_membership_test_result.json */; }; B4C675BE9030D5C7D19C4D19 /* ordered_code_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB380D03201BC6E400D97691 /* ordered_code_test.cc */; }; B4F544C50B4472268A2E633B /* bloom_filter.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1E0C7C0DCD2790019E66D8CC /* bloom_filter.pb.cc */; }; + B510921E4CD441289F6B2B78 /* FSTExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */; }; B513F723728E923DFF34F60F /* leveldb_key_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54995F6E205B6E12004EFFA0 /* leveldb_key_test.cc */; }; B54BA1E76636C0C93334271B /* settings_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = DD12BC1DB2480886D2FB0005 /* settings_test.cc */; }; B576823475FBCA5EFA583F9C /* leveldb_migrations_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EF83ACD5E1E9F25845A9ACED /* leveldb_migrations_test.cc */; }; @@ -1329,6 +1336,7 @@ D00B06FD0F20D09C813547F4 /* Validation_BloomFilterTest_MD5_1_01_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 5C68EE4CB94C0DD6E333F546 /* Validation_BloomFilterTest_MD5_1_01_membership_test_result.json */; }; D00E69F7FDF2BE674115AD3F /* field_path_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B686F2AD2023DDB20028D6BE /* field_path_test.cc */; }; D04CBBEDB8DC16D8C201AC49 /* leveldb_target_cache_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = E76F0CDF28E5FA62D21DE648 /* leveldb_target_cache_test.cc */; }; + D0CD302D79FF5CE4F418FF0E /* FSTExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */; }; D0DA42DC66C4FE508A63B269 /* testing_hooks_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = A002425BC4FC4E805F4175B6 /* testing_hooks_test.cc */; }; D143FBD057481C1A59B27E5E /* persistence_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA12A31F315EE100DD57A1 /* persistence_spec_test.json */; }; D156B9F19B5B29E77664FDFC /* logic_utils_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 28B45B2104E2DAFBBF86DBB7 /* logic_utils_test.cc */; }; @@ -1341,6 +1349,7 @@ D2A96D452AF6426C491AF931 /* DatabaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3355BE9391CC4857AF0BDAE3 /* DatabaseTests.swift */; }; D2C486D904E08CC41E409695 /* Validation_BloomFilterTest_MD5_5000_1_membership_test_result.json in Resources */ = {isa = PBXBuildFile; fileRef = 1A7D48A017ECB54FD381D126 /* Validation_BloomFilterTest_MD5_5000_1_membership_test_result.json */; }; D3180BF788CA5EBA9FCB58FB /* Validation_BloomFilterTest_MD5_50000_01_bloom_filter_proto.json in Resources */ = {isa = PBXBuildFile; fileRef = 7B44DD11682C4803B73DCC34 /* Validation_BloomFilterTest_MD5_50000_01_bloom_filter_proto.json */; }; + D34E3F7FC4DC5210E671EF4D /* FSTExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */; }; D377FA653FB976FB474D748C /* remote_event_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */; }; D39F0216BF1EA8CD54C76CF8 /* FIRQueryUnitTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = FF73B39D04D1760190E6B84A /* FIRQueryUnitTests.mm */; }; D3B470C98ACFAB7307FB3800 /* datastore_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 3167BD972EFF8EC636530E59 /* datastore_test.cc */; }; @@ -1871,6 +1880,7 @@ 620C1427763BA5D3CCFB5A1F /* BridgingHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = ""; }; 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryIntegrationTests.swift; sourceTree = ""; }; 62E103B28B48A81D682A0DE9 /* Pods_Firestore_Example_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Example_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 62E54B832A9E910A003347C8 /* IndexingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexingTests.swift; sourceTree = ""; }; 63136A2371C0C013EC7A540C /* target_index_matcher_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = target_index_matcher_test.cc; sourceTree = ""; }; 64AA92CFA356A2360F3C5646 /* filesystem_testing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = filesystem_testing.h; sourceTree = ""; }; 67786C62C76A740AEDBD8CD3 /* FSTTestingHooks.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FSTTestingHooks.h; sourceTree = ""; }; @@ -1910,6 +1920,7 @@ 7B44DD11682C4803B73DCC34 /* Validation_BloomFilterTest_MD5_50000_01_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_50000_01_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_01_bloom_filter_proto.json; sourceTree = ""; }; 7B65C996438B84DBC7616640 /* CodableTimestampTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CodableTimestampTests.swift; sourceTree = ""; }; 7C3F995E040E9E9C5E8514BB /* query_listener_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = query_listener_test.cc; sourceTree = ""; }; + 7C5C40C7BFBB86032F1DC632 /* FSTExceptionCatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = FSTExceptionCatcher.h; sourceTree = ""; }; 7EB299CF85034F09CFD6F3FD /* remote_document_cache_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = remote_document_cache_test.cc; sourceTree = ""; }; 84076EADF6872C78CDAC7291 /* bundle_builder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = bundle_builder.h; sourceTree = ""; }; 84434E57CA72951015FC71BC /* Pods-Firestore_FuzzTests_iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_FuzzTests_iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_FuzzTests_iOS/Pods-Firestore_FuzzTests_iOS.debug.xcconfig"; sourceTree = ""; }; @@ -1992,6 +2003,7 @@ B6FB468A208F9B9100554BA2 /* executor_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = executor_test.h; sourceTree = ""; }; B79CA87A1A01FC5329031C9B /* Pods_Firestore_FuzzTests_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_FuzzTests_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B8A853940305237AFDA8050B /* query_engine_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = query_engine_test.cc; sourceTree = ""; }; + B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = FSTExceptionCatcher.m; sourceTree = ""; }; B953604968FBF5483BD20F5A /* Pods-Firestore_IntegrationTests_macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_IntegrationTests_macOS/Pods-Firestore_IntegrationTests_macOS.release.xcconfig"; sourceTree = ""; }; B9C261C26C5D311E1E3C0CB9 /* query_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = query_test.cc; sourceTree = ""; }; B9ED38DA914BDCD2E3A0714D /* aggregation_result.pb.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = aggregation_result.pb.h; sourceTree = ""; }; @@ -2020,7 +2032,7 @@ D5B2593BCB52957D62F1C9D3 /* perf_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = perf_spec_test.json; sourceTree = ""; }; D5B25E7E7D6873CBA4571841 /* FIRNumericTransformTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FIRNumericTransformTests.mm; sourceTree = ""; }; D7DF4A6F740086A2D8C0E28E /* Pods_Firestore_Tests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Firestore_Tests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D85AC18C55650ED230A71B82 /* FSTTestingHooks.mm */ = {isa = PBXFileReference; includeInIndex = 1; path = FSTTestingHooks.mm; sourceTree = ""; }; + D85AC18C55650ED230A71B82 /* FSTTestingHooks.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTTestingHooks.mm; sourceTree = ""; }; D872D754B8AD88E28AF28B28 /* aggregation_result.pb.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = aggregation_result.pb.cc; sourceTree = ""; }; D8A6D52723B1BABE1B7B8D8F /* leveldb_overlay_migration_manager_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_overlay_migration_manager_test.cc; sourceTree = ""; }; D8E530B27D5641B9C26A452C /* Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.json; name = Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json; path = bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_500_1_bloom_filter_proto.json; sourceTree = ""; }; @@ -2196,6 +2208,7 @@ 062072B62773A055001655D7 /* AsyncAwaitIntegrationTests.swift */, 124C932B22C1642C00CA8C2D /* CodableIntegrationTests.swift */, 3355BE9391CC4857AF0BDAE3 /* DatabaseTests.swift */, + 62E54B832A9E910A003347C8 /* IndexingTests.swift */, 621D620928F9CE7400D2FA26 /* QueryIntegrationTests.swift */, ); path = Integration; @@ -2902,6 +2915,8 @@ B69CF05A219B9105004C434D /* FIRFirestore+Testing.h */, 54E9281C1F33950B00C1953E /* FSTEventAccumulator.h */, 5492E0392021401F00B64F25 /* FSTEventAccumulator.mm */, + 7C5C40C7BFBB86032F1DC632 /* FSTExceptionCatcher.h */, + B8BFD9B37D1029D238BDD71E /* FSTExceptionCatcher.m */, DE51B1881F0D48AC0013853F /* FSTHelpers.h */, 5492E03A2021401F00B64F25 /* FSTHelpers.mm */, 54E9281E1F33950B00C1953E /* FSTIntegrationTestCase.h */, @@ -4075,6 +4090,7 @@ 16FF9073CA381CA43CA9BF29 /* FIRTransactionOptionsTests.mm in Sources */, 9D71628E38D9F64C965DF29E /* FSTAPIHelpers.mm in Sources */, F4F00BF4E87D7F0F0F8831DB /* FSTEventAccumulator.mm in Sources */, + 4F55A97F725D86E5CC6BE2DC /* FSTExceptionCatcher.m in Sources */, 0A6FBE65A7FE048BAD562A15 /* FSTGoogleTestTests.mm in Sources */, 939C898FE9D129F6A2EA259C /* FSTHelpers.mm in Sources */, C4055D868A38221B332CD03D /* FSTIntegrationTestCase.mm in Sources */, @@ -4291,6 +4307,7 @@ DBFE8B2E803C1D0DECB71FF6 /* FIRTransactionOptionsTests.mm in Sources */, 6E4854B19B120C6F0F8192CC /* FSTAPIHelpers.mm in Sources */, 73E42D984FB36173A2BDA57C /* FSTEventAccumulator.mm in Sources */, + 21E588CF29C72813D8A7A0A1 /* FSTExceptionCatcher.m in Sources */, E375FBA0632EFB4D14C4E5A9 /* FSTGoogleTestTests.mm in Sources */, F72DF72447EA7AB9D100816A /* FSTHelpers.mm in Sources */, AEBF3F80ACC01AA8A27091CD /* FSTIntegrationTestCase.mm in Sources */, @@ -4523,6 +4540,7 @@ D550446303227FB1B381133C /* FSTAPIHelpers.mm in Sources */, A4ECA8335000CBDF94586C94 /* FSTDatastoreTests.mm in Sources */, 2E169CF1E9E499F054BB873A /* FSTEventAccumulator.mm in Sources */, + D34E3F7FC4DC5210E671EF4D /* FSTExceptionCatcher.m in Sources */, 1817DEF8FF479D218381C541 /* FSTGoogleTestTests.mm in Sources */, 086E10B1B37666FB746D56BC /* FSTHelpers.mm in Sources */, 02C953A7B0FA5EF87DB0361A /* FSTIntegrationTestCase.mm in Sources */, @@ -4536,6 +4554,7 @@ D77941FD93DBE862AEF1F623 /* FSTTransactionTests.mm in Sources */, 432056C4D1259F76C80FC2A8 /* FSTUserDataReaderTests.mm in Sources */, 3B1E27D951407FD237E64D07 /* FirestoreEncoderTests.swift in Sources */, + 62E54B862A9E910B003347C8 /* IndexingTests.swift in Sources */, 621D620C28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, 4D42E5C756229C08560DD731 /* XCTestCase+Await.mm in Sources */, 09BE8C01EC33D1FD82262D5D /* aggregate_query_test.cc in Sources */, @@ -4759,6 +4778,7 @@ 881E55152AB34465412F8542 /* FSTAPIHelpers.mm in Sources */, 4A64A339BCA77B9F875D1D8B /* FSTDatastoreTests.mm in Sources */, 1C7254742A9F6F7042C9D78E /* FSTEventAccumulator.mm in Sources */, + B510921E4CD441289F6B2B78 /* FSTExceptionCatcher.m in Sources */, 8D0EF43F1B7B156550E65C20 /* FSTGoogleTestTests.mm in Sources */, 198F193BD9484E49375A7BE7 /* FSTHelpers.mm in Sources */, 0F54634745BA07B09BDC14D7 /* FSTIntegrationTestCase.mm in Sources */, @@ -4772,6 +4792,7 @@ 5E5B3B8B3A41C8EB70035A6B /* FSTTransactionTests.mm in Sources */, 75A176239B37354588769206 /* FSTUserDataReaderTests.mm in Sources */, 5E89B1A5A5430713C79C4854 /* FirestoreEncoderTests.swift in Sources */, + 62E54B852A9E910B003347C8 /* IndexingTests.swift in Sources */, 621D620B28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, 736C4E82689F1CA1859C4A3F /* XCTestCase+Await.mm in Sources */, 412BE974741729A6683C386F /* aggregate_query_test.cc in Sources */, @@ -4989,6 +5010,7 @@ 85A33A9CE33207C2333DDD32 /* FIRTransactionOptionsTests.mm in Sources */, 5492E058202154AB00B64F25 /* FSTAPIHelpers.mm in Sources */, 5492E03E2021401F00B64F25 /* FSTEventAccumulator.mm in Sources */, + 38C37F0CE0AB18F1AAE6E67C /* FSTExceptionCatcher.m in Sources */, 54764FAF1FAA21B90085E60A /* FSTGoogleTestTests.mm in Sources */, 5492E03F2021401F00B64F25 /* FSTHelpers.mm in Sources */, 5491BC721FB44593008B3588 /* FSTIntegrationTestCase.mm in Sources */, @@ -5240,6 +5262,7 @@ D9EF7FC0E3F8646B272B427E /* FSTAPIHelpers.mm in Sources */, 5492E082202154EC00B64F25 /* FSTDatastoreTests.mm in Sources */, 5492E041202143E700B64F25 /* FSTEventAccumulator.mm in Sources */, + D0CD302D79FF5CE4F418FF0E /* FSTExceptionCatcher.m in Sources */, 1E6E2AE74B7C9DEDFC07E76B /* FSTGoogleTestTests.mm in Sources */, 5492E0422021440500B64F25 /* FSTHelpers.mm in Sources */, 5491BC731FB44593008B3588 /* FSTIntegrationTestCase.mm in Sources */, @@ -5253,6 +5276,7 @@ 5492E07F202154EC00B64F25 /* FSTTransactionTests.mm in Sources */, F5BDECEB3B43BD1591EEADBD /* FSTUserDataReaderTests.mm in Sources */, 6F45846C159D3C063DBD3CBE /* FirestoreEncoderTests.swift in Sources */, + 62E54B842A9E910B003347C8 /* IndexingTests.swift in Sources */, 621D620A28F9CE7400D2FA26 /* QueryIntegrationTests.swift in Sources */, 5492E0442021457E00B64F25 /* XCTestCase+Await.mm in Sources */, B04E4FE20930384DF3A402F9 /* aggregate_query_test.cc in Sources */, diff --git a/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm b/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm index 6031a054be4..9d207824aab 100644 --- a/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm +++ b/Firestore/Example/Tests/Integration/API/FIRDatabaseTests.mm @@ -1844,7 +1844,7 @@ - (void)testGetValidPersistentCacheIndexManager { XCTAssertNotNil(db2.persistentCacheIndexManager); // Disable persistent disk cache - FIRFirestore *db3 = [FIRFirestore firestoreForDatabase:@"PersistentCacheIndexManagerDB3"]; + FIRFirestore *db3 = [FIRFirestore firestoreForDatabase:@"MemoryCacheIndexManagerDB1"]; FIRFirestoreSettings *settings3 = [db3 settings]; [settings3 setCacheSettings:[[FIRMemoryCacheSettings alloc] init]]; [db3 setSettings:settings3]; diff --git a/Firestore/Example/Tests/Integration/API/FIRIndexingTests.mm b/Firestore/Example/Tests/Integration/API/FIRIndexingTests.mm index 108fda54256..7c4b63771ae 100644 --- a/Firestore/Example/Tests/Integration/API/FIRIndexingTests.mm +++ b/Firestore/Example/Tests/Integration/API/FIRIndexingTests.mm @@ -14,15 +14,17 @@ * limitations under the License. */ +// TODO(csi): Delete this once setIndexConfigurationFromJSON and setIndexConfigurationFromStream +// are removed. +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #import #import -#import "Firestore/Source/API/FIRFirestore+Internal.h" -#import "Firestore/Source/API/FIRPersistentCacheIndexManager+Internal.h" - #import "Firestore/Example/Tests/Util/FSTHelpers.h" #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h" +#import "Firestore/Source/Public/FirebaseFirestore/FIRPersistentCacheIndexManager.h" @interface FIRIndexingTests : FSTIntegrationTestCase @end @@ -194,13 +196,13 @@ - (void)testAutoIndexCreationSetSuccessfullyUsingDefault { - (void)testAutoIndexCreationAfterFailsTermination { [self terminateFirestore:self.db]; - FSTAssertThrows([self.db.persistentCacheIndexManager enableIndexAutoCreation], + XCTAssertThrows([self.db.persistentCacheIndexManager enableIndexAutoCreation], @"The client has already been terminated."); - FSTAssertThrows([self.db.persistentCacheIndexManager disableIndexAutoCreation], + XCTAssertThrows([self.db.persistentCacheIndexManager disableIndexAutoCreation], @"The client has already been terminated."); - FSTAssertThrows([self.db.persistentCacheIndexManager deleteAllIndexes], + XCTAssertThrows([self.db.persistentCacheIndexManager deleteAllIndexes], @"The client has already been terminated."); } diff --git a/Firestore/Example/Tests/Util/FSTExceptionCatcher.h b/Firestore/Example/Tests/Util/FSTExceptionCatcher.h new file mode 100644 index 00000000000..093aba3ea42 --- /dev/null +++ b/Firestore/Example/Tests/Util/FSTExceptionCatcher.h @@ -0,0 +1,27 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FSTExceptionCatcher : NSObject + +typedef void (^ThrowingBlock)(void); + ++ (BOOL)catchException:(ThrowingBlock)block error:(__autoreleasing NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Firestore/Example/Tests/Util/FSTExceptionCatcher.m b/Firestore/Example/Tests/Util/FSTExceptionCatcher.m new file mode 100644 index 00000000000..e7ca672280b --- /dev/null +++ b/Firestore/Example/Tests/Util/FSTExceptionCatcher.m @@ -0,0 +1,40 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#import "Firestore/Example/Tests/Util/FSTExceptionCatcher.h" + +@implementation FSTExceptionCatcher + ++ (BOOL)catchException:(ThrowingBlock)block error:(__autoreleasing NSError **)error { + @try { + block(); + return YES; + } @catch (NSException *exception) { + NSMutableDictionary *info = [NSMutableDictionary dictionary]; + [info setValue:exception.name forKey:@"ExceptionName"]; + [info setValue:exception.reason forKey:@"ExceptionReason"]; + [info setValue:exception.callStackReturnAddresses forKey:@"ExceptionCallStackReturnAddresses"]; + [info setValue:exception.callStackSymbols forKey:@"ExceptionCallStackSymbols"]; + [info setValue:exception.userInfo forKey:@"ExceptionUserInfo"]; + + // Just using error code `FIRErrorCodeConfigFailed` for now + NSInteger FIRErrorCodeConfigFailed = -114; + *error = [[NSError alloc] initWithDomain:exception.name + code:FIRErrorCodeConfigFailed + userInfo:info]; + return NO; + } +} + +@end diff --git a/Firestore/Source/API/FIRFirestore+Internal.h b/Firestore/Source/API/FIRFirestore+Internal.h index d0216c7f3c1..5c5da4c525d 100644 --- a/Firestore/Source/API/FIRFirestore+Internal.h +++ b/Firestore/Source/API/FIRFirestore+Internal.h @@ -79,9 +79,6 @@ NS_ASSUME_NONNULL_BEGIN - (const std::shared_ptr &)workerQueue; -// TODO(csi): make this function public -@property(nonatomic, readonly) FIRPersistentCacheIndexManager *persistentCacheIndexManager; - @property(nonatomic, assign, readonly) std::shared_ptr wrapped; @property(nonatomic, assign, readonly) const model::DatabaseId &databaseID; diff --git a/Firestore/Source/API/FIRFirestore.mm b/Firestore/Source/API/FIRFirestore.mm index db3ee8d6934..29b56fd2a6b 100644 --- a/Firestore/Source/API/FIRFirestore.mm +++ b/Firestore/Source/API/FIRFirestore.mm @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(csi): Delete this once setIndexConfigurationFromJSON and setIndexConfigurationFromStream +// are removed. +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + #import "FIRFirestore+Internal.h" #include @@ -535,12 +539,14 @@ @implementation FIRFirestore (Internal) return _firestore->worker_queue(); } -- (FIRPersistentCacheIndexManager *)persistentCacheIndexManager { +- (nullable FIRPersistentCacheIndexManager *)persistentCacheIndexManager { if (!_indexManager) { auto index_manager = _firestore->persistent_cache_index_manager(); if (index_manager) { _indexManager = [[FIRPersistentCacheIndexManager alloc] initWithPersistentCacheIndexManager:index_manager]; + } else { + return nil; } } return _indexManager; diff --git a/Firestore/Source/API/FIRPersistentCacheIndexManager+Internal.h b/Firestore/Source/API/FIRPersistentCacheIndexManager+Internal.h index ab7a3014c3e..2445e992bf9 100644 --- a/Firestore/Source/API/FIRPersistentCacheIndexManager+Internal.h +++ b/Firestore/Source/API/FIRPersistentCacheIndexManager+Internal.h @@ -13,51 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#import "FIRPersistentCacheIndexManager.h" #import #include - #include "Firestore/core/src/api/persistent_cache_index_manager.h" NS_ASSUME_NONNULL_BEGIN -// TODO(sum/avg) move the contents of this category to -// ../Public/FirebaseFirestore/FIRPersistentCacheIndexManager.h -/** - * A PersistentCacheIndexManager which you can config persistent cache indexes used for - * local query execution. - */ -NS_SWIFT_NAME(PersistentCacheIndexManager) -@interface FIRPersistentCacheIndexManager : NSObject - -/** :nodoc: */ -- (instancetype)init - __attribute__((unavailable("FIRPersistentCacheIndexManager cannot be created directly."))); - -/** - * Enables SDK to create persistent cache indexes automatically for local query execution when SDK - * believes cache indexes can help improves performance. - * - * This feature is disabled by default. - */ -- (void)enableIndexAutoCreation NS_SWIFT_NAME(enableIndexAutoCreation()); - -/** - * Stops creating persistent cache indexes automatically for local query execution. The indexes - * which have been created by calling `enableIndexAutoCreation` still take effect. - */ -- (void)disableIndexAutoCreation NS_SWIFT_NAME(disableIndexAutoCreation()); - -/** - * Removes all persistent cache indexes. Please note this function will also deletes indexes - * generated by [[FIRFirestore firestore] setIndexConfigurationFromJSON] and [[FIRFirestore - * firestore] setIndexConfigurationFromStream], which are deprecated. - */ -- (void)deleteAllIndexes NS_SWIFT_NAME(deleteAllIndexes()); - -@end - @interface FIRPersistentCacheIndexManager (/* Init */) - (instancetype)initWithPersistentCacheIndexManager: diff --git a/Firestore/Source/Public/FirebaseFirestore/FIRFirestore.h b/Firestore/Source/Public/FirebaseFirestore/FIRFirestore.h index 697ead2e046..8882c91eff1 100644 --- a/Firestore/Source/Public/FirebaseFirestore/FIRFirestore.h +++ b/Firestore/Source/Public/FirebaseFirestore/FIRFirestore.h @@ -28,6 +28,7 @@ @class FIRTransaction; @class FIRTransactionOptions; @class FIRWriteBatch; +@class FIRPersistentCacheIndexManager; NS_ASSUME_NONNULL_BEGIN @@ -103,7 +104,16 @@ NS_SWIFT_NAME(Firestore) #pragma mark - Configure FieldIndexes /** - * This method is in preview. API signature and functionality are subject to change. + * A PersistentCacheIndexManager which you can config persistent cache indexes used for + * local query execution. + */ +@property(nonatomic, readonly, nullable) + FIRPersistentCacheIndexManager *persistentCacheIndexManager; + +/** + * NOTE: This preview method will be deprecated in a future major release. Consider using + * `PersistentCacheIndexManager.enableIndexAutoCreation()` to let the SDK decide whether to create + * cache indexes for queries running locally. * * Configures indexing for local query execution. Any previous index configuration is overridden. * @@ -121,10 +131,15 @@ NS_SWIFT_NAME(Firestore) */ - (void)setIndexConfigurationFromJSON:(NSString *)json completion:(nullable void (^)(NSError *_Nullable error))completion - NS_SWIFT_NAME(setIndexConfiguration(_:completion:)); + NS_SWIFT_NAME(setIndexConfiguration(_:completion:)) DEPRECATED_MSG_ATTRIBUTE( + "Instead of creating cache indexes manually, consider using " + "`PersistentCacheIndexManager.enableIndexAutoCreation()` to let the SDK decide whether to " + "create cache indexes for queries running locally."); /** - * This method is in preview. API signature and functionality are subject to change. + * NOTE: This preview method will be deprecated in a future major release. Consider using + * `PersistentCacheIndexManager.enableIndexAutoCreation()` to let the SDK decide whether to create + * cache indexes for queries running locally. * * Configures indexing for local query execution. Any previous index configuration is overridden. * @@ -145,7 +160,10 @@ NS_SWIFT_NAME(Firestore) */ - (void)setIndexConfigurationFromStream:(NSInputStream *)stream completion:(nullable void (^)(NSError *_Nullable error))completion - NS_SWIFT_NAME(setIndexConfiguration(_:completion:)); + NS_SWIFT_NAME(setIndexConfiguration(_:completion:)) DEPRECATED_MSG_ATTRIBUTE( + "Instead of creating cache indexes manually, consider using " + "`PersistentCacheIndexManager.enableIndexAutoCreation()` to let the SDK decide whether to " + "create cache indexes for queries running locally."); #pragma mark - Collections and Documents diff --git a/Firestore/Source/Public/FirebaseFirestore/FIRPersistentCacheIndexManager.h b/Firestore/Source/Public/FirebaseFirestore/FIRPersistentCacheIndexManager.h new file mode 100644 index 00000000000..216db79e7ad --- /dev/null +++ b/Firestore/Source/Public/FirebaseFirestore/FIRPersistentCacheIndexManager.h @@ -0,0 +1,55 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A PersistentCacheIndexManager, for configuring persistent cache indexes used for local query + * execution. + */ +NS_SWIFT_NAME(PersistentCacheIndexManager) +@interface FIRPersistentCacheIndexManager : NSObject + +/** :nodoc: */ +- (instancetype)init + __attribute__((unavailable("FIRPersistentCacheIndexManager cannot be created directly."))); + +/** + * Enables the SDK to create persistent cache indexes automatically for local query execution when + * the SDK believes cache indexes can improve performance. + * + * This feature is disabled by default. + */ +- (void)enableIndexAutoCreation NS_SWIFT_NAME(enableIndexAutoCreation()); + +/** + * Stops creating persistent cache indexes automatically for local query execution. The indexes + * which have been created by calling `enableIndexAutoCreation` still take effect. + */ +- (void)disableIndexAutoCreation NS_SWIFT_NAME(disableIndexAutoCreation()); + +/** + * Removes all persistent cache indexes. Please note this function also deletes indexes generated by + * [[FIRFirestore firestore] setIndexConfigurationFromJSON] and [[FIRFirestore firestore] + * setIndexConfigurationFromStream], which are deprecated. + */ +- (void)deleteAllIndexes NS_SWIFT_NAME(deleteAllIndexes()); + +@end + +NS_ASSUME_NONNULL_END diff --git a/Firestore/Swift/Tests/BridgingHeader.h b/Firestore/Swift/Tests/BridgingHeader.h index 40b1c318f1b..5bfed83adf4 100644 --- a/Firestore/Swift/Tests/BridgingHeader.h +++ b/Firestore/Swift/Tests/BridgingHeader.h @@ -18,6 +18,7 @@ #define FIRESTORE_SWIFT_TESTS_BRIDGINGHEADER_H_ #import "Firestore/Example/Tests/API/FSTAPIHelpers.h" +#import "Firestore/Example/Tests/Util/FSTExceptionCatcher.h" #import "Firestore/Example/Tests/Util/FSTIntegrationTestCase.h" #endif /* FIRESTORE_SWIFT_TESTS_BRIDGINGHEADER_H_ */ diff --git a/Firestore/Swift/Tests/Integration/AsyncAwaitIntegrationTests.swift b/Firestore/Swift/Tests/Integration/AsyncAwaitIntegrationTests.swift index 91771383fb6..c9d6d78f166 100644 --- a/Firestore/Swift/Tests/Integration/AsyncAwaitIntegrationTests.swift +++ b/Firestore/Swift/Tests/Integration/AsyncAwaitIntegrationTests.swift @@ -93,5 +93,33 @@ let emptyBundle = """ XCTAssertEqual(FIRQuerySnapshotGetIDs(snapshot), ["doc1", "doc2", "doc4", "doc5"]) } + + func testAutoIndexCreationAfterFailsTermination() async throws { + try await db.terminate() + + let enableIndexAutoCreation = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager?.enableIndexAutoCreation() + } + } + XCTAssertThrowsError(try enableIndexAutoCreation(), "The client has already been terminated.") + + let disableIndexAutoCreation = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager?.disableIndexAutoCreation() + } + } + XCTAssertThrowsError( + try disableIndexAutoCreation(), + "The client has already been terminated." + ) + + let deleteAllIndexes = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager?.deleteAllIndexes() + } + } + XCTAssertThrowsError(try deleteAllIndexes(), "The client has already been terminated.") + } } #endif diff --git a/Firestore/Swift/Tests/Integration/DatabaseTests.swift b/Firestore/Swift/Tests/Integration/DatabaseTests.swift index 556837dd99a..f918e005074 100644 --- a/Firestore/Swift/Tests/Integration/DatabaseTests.swift +++ b/Firestore/Swift/Tests/Integration/DatabaseTests.swift @@ -99,5 +99,59 @@ import FirebaseFirestore let result = try? await db.document("coll/doc").getDocument(source: .cache) XCTAssertNil(result) } + + func testGetValidPersistentCacheIndexManager() async throws { + // [FIRApp resetApps] is an internal api, while Swift test can only test again public api. + // So `FirebaseApp.configure()` can only be called once for the whole test class. + FirebaseApp.configure() + + let db1 = Firestore.firestore(database: "SwiftPersistentCacheIndexManagerDB1") + let settings1 = db1.settings + settings1.cacheSettings = PersistentCacheSettings() + db1.settings = settings1 + + XCTAssertNotNil(db1.persistentCacheIndexManager) + + // Use persistent disk cache (default) + let db2 = Firestore.firestore(database: "SwiftPersistentCacheIndexManagerDB2") + XCTAssertNotNil(db2.persistentCacheIndexManager) + + // Disable persistent disk cache + let db3 = Firestore.firestore(database: "SwiftMemoryCacheIndexManagerDB1") + let settings3 = db3.settings + settings3.cacheSettings = MemoryCacheSettings() + db3.settings = settings3 + XCTAssertNil(db3.persistentCacheIndexManager) + + // Disable persistent disk cache (deprecated) + let db4 = Firestore.firestore(database: "SwiftPersistentCacheIndexManagerDB4") + let settings4 = db4.settings + settings4.isPersistenceEnabled = false + db4.settings = settings4 + XCTAssertNil(db4.persistentCacheIndexManager) + + let db5 = Firestore.firestore(database: "SwiftPersistentCacheIndexManagerDB5") + let settings5 = db5.settings + settings5.cacheSettings = PersistentCacheSettings() + db5.settings = settings5 + XCTAssertEqual(db5.persistentCacheIndexManager, db5.persistentCacheIndexManager) + + // Use persistent disk cache (default) + let db6 = Firestore.firestore(database: "SwiftPersistentCacheIndexManagerDB6") + XCTAssertEqual(db6.persistentCacheIndexManager, db6.persistentCacheIndexManager) + + let db7 = Firestore.firestore(database: "SwiftMemoryCacheIndexManagerDB2") + let settings7 = db7.settings + settings7.cacheSettings = PersistentCacheSettings() + db7.settings = settings7 + XCTAssertNotEqual(db5.persistentCacheIndexManager, db7.persistentCacheIndexManager) + XCTAssertNotEqual(db6.persistentCacheIndexManager, db7.persistentCacheIndexManager) + + // Use persistent disk cache (default) + let db8 = Firestore.firestore(database: "SwiftPersistentCacheIndexManagerDB8") + XCTAssertNotEqual(db5.persistentCacheIndexManager, db8.persistentCacheIndexManager) + XCTAssertNotEqual(db6.persistentCacheIndexManager, db8.persistentCacheIndexManager) + XCTAssertNotEqual(db7.persistentCacheIndexManager, db8.persistentCacheIndexManager) + } } #endif diff --git a/Firestore/Swift/Tests/Integration/IndexingTests.swift b/Firestore/Swift/Tests/Integration/IndexingTests.swift new file mode 100644 index 00000000000..4eeef02fd6d --- /dev/null +++ b/Firestore/Swift/Tests/Integration/IndexingTests.swift @@ -0,0 +1,131 @@ +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import FirebaseFirestore +import FirebaseFirestoreSwift +import Foundation + +class IndexingTests: FSTIntegrationTestCase { + func testAutoIndexCreationSetSuccessfully() throws { + // Use persistent disk cache (explict) + let settings = db.settings + settings.cacheSettings = PersistentCacheSettings() + db.settings = settings + + let coll = collectionRef() + let testDocs = [ + "a": ["match": true], + "b": ["match": false], + "c": ["match": false], + ] + writeAllDocuments(testDocs, toCollection: coll) + + coll.whereField("match", isEqualTo: true) + .getDocuments(source: .cache) { querySnapshot, err in + XCTAssertNil(err) + XCTAssertEqual(querySnapshot!.count, 1) + } + + let enableIndexAutoCreation = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager!.enableIndexAutoCreation() + } + } + XCTAssertNoThrow(try enableIndexAutoCreation()) + coll.whereField("match", isEqualTo: true) + .getDocuments(source: .cache) { querySnapshot, err in + XCTAssertNil(err) + XCTAssertEqual(querySnapshot!.count, 1) + } + + let disableIndexAutoCreation = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager!.disableIndexAutoCreation() + } + } + XCTAssertNoThrow(try disableIndexAutoCreation()) + coll.whereField("match", isEqualTo: true) + .getDocuments(source: .cache) { querySnapshot, err in + XCTAssertNil(err) + XCTAssertEqual(querySnapshot!.count, 1) + } + + let deleteAllIndexes = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager!.deleteAllIndexes() + } + } + XCTAssertNoThrow(try deleteAllIndexes()) + coll.whereField("match", isEqualTo: true) + .getDocuments(source: .cache) { querySnapshot, err in + XCTAssertNil(err) + XCTAssertEqual(querySnapshot!.count, 1) + } + } + + func testAutoIndexCreationSetSuccessfullyUsingDefault() throws { + // Use persistent disk cache (default) + let coll = collectionRef() + let testDocs = [ + "a": ["match": true], + "b": ["match": false], + "c": ["match": false], + ] + writeAllDocuments(testDocs, toCollection: coll) + + coll.whereField("match", isEqualTo: true) + .getDocuments(source: .cache) { querySnapshot, err in + XCTAssertNil(err) + XCTAssertEqual(querySnapshot!.count, 1) + } + + let enableIndexAutoCreation = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager!.enableIndexAutoCreation() + } + } + XCTAssertNoThrow(try enableIndexAutoCreation()) + coll.whereField("match", isEqualTo: true) + .getDocuments(source: .cache) { querySnapshot, err in + XCTAssertNil(err) + XCTAssertEqual(querySnapshot!.count, 1) + } + + let disableIndexAutoCreation = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager!.disableIndexAutoCreation() + } + } + XCTAssertNoThrow(try disableIndexAutoCreation()) + coll.whereField("match", isEqualTo: true) + .getDocuments(source: .cache) { querySnapshot, err in + XCTAssertNil(err) + XCTAssertEqual(querySnapshot!.count, 1) + } + + let deleteAllIndexes = { + try FSTExceptionCatcher.catchException { + self.db.persistentCacheIndexManager!.deleteAllIndexes() + } + } + XCTAssertNoThrow(try deleteAllIndexes()) + coll.whereField("match", isEqualTo: true) + .getDocuments(source: .cache) { querySnapshot, err in + XCTAssertNil(err) + XCTAssertEqual(querySnapshot!.count, 1) + } + } +}