Skip to content

Commit 3afbfc8

Browse files
authored
Merge adf7853 into a71dbaf
2 parents a71dbaf + adf7853 commit 3afbfc8

18 files changed

+425
-30
lines changed

Firestore/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Unreleased
2+
- [feature] Added `TransactionOptions` to control how many times a transaction
3+
will retry commits before failing (#9838).
4+
15
# 9.0.0
26
- [fixed] Fixed CMake build errors when building with Xcode 13.3.1 (#9702).
37
- [fixed] **Breaking change:** Fixed an issue where returning `nil` from the

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
15F54E9538839D56A40C5565 /* watch_change_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 2D7472BC70C024D736FF74D9 /* watch_change_test.cc */; };
129129
16791B16601204220623916C /* status_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352C20A3B3D7003E0143 /* status_test.cc */; };
130130
16FE432587C1B40AF08613D2 /* objc_type_traits_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A0CF41BA5AED6049B0BEB2C /* objc_type_traits_apple_test.mm */; };
131+
16FF9073CA381CA43CA9BF29 /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; };
131132
1733601ECCEA33E730DEAF45 /* autoid_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54740A521FC913E500713A1A /* autoid_test.cc */; };
132133
17473086EBACB98CDC3CC65C /* view_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = C7429071B33BDF80A7FA2F8A /* view_test.cc */; };
133134
17638F813B9B556FE7718C0C /* FIRQuerySnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04F202154AA00B64F25 /* FIRQuerySnapshotTests.mm */; };
@@ -266,6 +267,7 @@
266267
336E415DD06E719F9C9E2A14 /* grpc_stream_tester.cc in Sources */ = {isa = PBXBuildFile; fileRef = 87553338E42B8ECA05BA987E /* grpc_stream_tester.cc */; };
267268
338DFD5BCD142DF6C82A0D56 /* cc_compilation_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 1B342370EAE3AA02393E33EB /* cc_compilation_test.cc */; };
268269
339CFFD1323BDCA61EAAFE31 /* query_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B9C261C26C5D311E1E3C0CB9 /* query_test.cc */; };
270+
339D4DD13E1518BA79FF12EA /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; };
269271
340987A77D72C80A3E0FDADF /* view_snapshot_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = CC572A9168BBEF7B83E4BBC5 /* view_snapshot_test.cc */; };
270272
3409F2AEB7D6D95478D4344A /* random_access_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 014C60628830D95031574D15 /* random_access_queue_test.cc */; };
271273
34202A37E0B762386967AF3D /* grpc_stream_tester.cc in Sources */ = {isa = PBXBuildFile; fileRef = 87553338E42B8ECA05BA987E /* grpc_stream_tester.cc */; };
@@ -541,6 +543,7 @@
541543
57BDB8DBEDEC4C61DB497CB4 /* append_only_list_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5477CDE922EE71C8000FCC1E /* append_only_list_test.cc */; };
542544
583DF65751B7BBD0A222CAB4 /* byte_stream_cpp_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 01D10113ECC5B446DB35E96D /* byte_stream_cpp_test.cc */; };
543545
58693C153EC597BC25EE9648 /* firebase_auth_credentials_provider_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = F869D85E900E5AF6CD02E2FC /* firebase_auth_credentials_provider_test.mm */; };
546+
58B84B550725D9812729C7F7 /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; };
544547
58E377DCCC64FE7D2C6B59A1 /* database_id_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB71064B201FA60300344F18 /* database_id_test.cc */; };
545548
5958E3E3A0446A88B815CB70 /* grpc_connection_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D9649021544D4F00EB9CFB /* grpc_connection_test.cc */; };
546549
59880AE766F7FBFF0C41A94E /* remote_event_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 584AE2C37A55B408541A6FF3 /* remote_event_test.cc */; };
@@ -784,6 +787,7 @@
784787
84E75527F3739131C09BEAA5 /* target_index_matcher_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 63136A2371C0C013EC7A540C /* target_index_matcher_test.cc */; };
785788
851346D66DEC223E839E3AA9 /* memory_mutation_queue_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 74FBEFA4FE4B12C435011763 /* memory_mutation_queue_test.cc */; };
786789
856A1EAAD674ADBDAAEDAC37 /* bundle_builder.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4F5B96F3ABCD2CA901DB1CD4 /* bundle_builder.cc */; };
790+
85A33A9CE33207C2333DDD32 /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; };
787791
85B8918FC8C5DC62482E39C3 /* resource_path_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B686F2B02024FFD70028D6BE /* resource_path_test.cc */; };
788792
85BC2AB572A400114BF59255 /* limbo_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 54DA129E1F315EE100DD57A1 /* limbo_spec_test.json */; };
789793
85D61BDC7FB99B6E0DD3AFCA /* mutation.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 618BBE8220B89AAC00B5BCE7 /* mutation.pb.cc */; };
@@ -830,6 +834,7 @@
830834
90B9302B082E6252AF4E7DC7 /* leveldb_migrations_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = EF83ACD5E1E9F25845A9ACED /* leveldb_migrations_test.cc */; };
831835
90FE088B8FD9EC06EEED1F39 /* memory_index_manager_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = DB5A1E760451189DA36028B3 /* memory_index_manager_test.cc */; };
832836
911931696309D2EABB325F17 /* strerror_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 358C3B5FE573B1D60A4F7592 /* strerror_test.cc */; };
837+
913C2DB6951A2ED24778686C /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; };
833838
913F6E57AF18F84C5ECFD414 /* lru_garbage_collector_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 277EAACC4DD7C21332E8496A /* lru_garbage_collector_test.cc */; };
834839
915A9B8DB280DB4787D83FFE /* byte_stream_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 432C71959255C5DBDF522F52 /* byte_stream_test.cc */; };
835840
91AEFFEE35FBE15FEC42A1F4 /* memory_local_store_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F6CA0C5638AB6627CB5B4CF4 /* memory_local_store_test.cc */; };
@@ -1166,6 +1171,7 @@
11661171
DB3ADDA51FB93E84142EA90D /* FIRBundlesTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 776530F066E788C355B78457 /* FIRBundlesTests.mm */; };
11671172
DB7E9C5A59CCCDDB7F0C238A /* path_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 403DBF6EFB541DFD01582AA3 /* path_test.cc */; };
11681173
DBDC8E997E909804F1B43E92 /* log_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54C2294E1FECABAE007D065B /* log_test.cc */; };
1174+
DBFE8B2E803C1D0DECB71FF6 /* FIRTransactionOptionsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */; };
11691175
DC0B0E50DBAE916E6565AA18 /* string_win_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 79507DF8378D3C42F5B36268 /* string_win_test.cc */; };
11701176
DC0E186BDD221EAE9E4D2F41 /* sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA4E20A36DBB00BCEB75 /* sorted_map_test.cc */; };
11711177
DC1C711290E12F8EF3601151 /* array_sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54EB764C202277B30088B8F3 /* array_sorted_map_test.cc */; };
@@ -1708,6 +1714,7 @@
17081714
CD422AF3E4515FB8E9BE67A0 /* equals_tester.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = equals_tester.h; sourceTree = "<group>"; };
17091715
CE37875365497FFA8687B745 /* message_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = message_test.cc; path = nanopb/message_test.cc; sourceTree = "<group>"; };
17101716
CF39535F2C41AB0006FA6C0E /* create_noop_connectivity_monitor.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = create_noop_connectivity_monitor.cc; sourceTree = "<group>"; };
1717+
CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; path = FIRTransactionOptionsTests.mm; sourceTree = "<group>"; };
17111718
D0A6E9136804A41CEC9D55D4 /* delayed_constructor_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = delayed_constructor_test.cc; sourceTree = "<group>"; };
17121719
D3CC3DC5338DCAF43A211155 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
17131720
D5B2593BCB52957D62F1C9D3 /* perf_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = perf_spec_test.json; sourceTree = "<group>"; };
@@ -2520,6 +2527,7 @@
25202527
FF73B39D04D1760190E6B84A /* FIRQueryUnitTests.mm */,
25212528
5492E04D202154AA00B64F25 /* FIRSnapshotMetadataTests.mm */,
25222529
B65D34A7203C99090076A5E1 /* FIRTimestampTest.m */,
2530+
CF39ECA1293D21A0A2AB2626 /* FIRTransactionOptionsTests.mm */,
25232531
5492E047202154AA00B64F25 /* FSTAPIHelpers.h */,
25242532
5492E04E202154AA00B64F25 /* FSTAPIHelpers.mm */,
25252533
8D9892F204959C50613F16C8 /* FSTUserDataReaderTests.mm */,
@@ -3539,6 +3547,7 @@
35393547
D39F0216BF1EA8CD54C76CF8 /* FIRQueryUnitTests.mm in Sources */,
35403548
2EAD77559EC654E6CA4D3E21 /* FIRSnapshotMetadataTests.mm in Sources */,
35413549
CD0AA9E5D83C00CAAE7C2F67 /* FIRTimestampTest.m in Sources */,
3550+
16FF9073CA381CA43CA9BF29 /* FIRTransactionOptionsTests.mm in Sources */,
35423551
9D71628E38D9F64C965DF29E /* FSTAPIHelpers.mm in Sources */,
35433552
F4F00BF4E87D7F0F0F8831DB /* FSTEventAccumulator.mm in Sources */,
35443553
0A6FBE65A7FE048BAD562A15 /* FSTGoogleTestTests.mm in Sources */,
@@ -3740,6 +3749,7 @@
37403749
518BF03D57FBAD7C632D18F8 /* FIRQueryUnitTests.mm in Sources */,
37413750
ED420D8F49DA5C41EEF93913 /* FIRSnapshotMetadataTests.mm in Sources */,
37423751
36E174A66C323891AEA16A2A /* FIRTimestampTest.m in Sources */,
3752+
DBFE8B2E803C1D0DECB71FF6 /* FIRTransactionOptionsTests.mm in Sources */,
37433753
6E4854B19B120C6F0F8192CC /* FSTAPIHelpers.mm in Sources */,
37443754
73E42D984FB36173A2BDA57C /* FSTEventAccumulator.mm in Sources */,
37453755
E375FBA0632EFB4D14C4E5A9 /* FSTGoogleTestTests.mm in Sources */,
@@ -3948,6 +3958,7 @@
39483958
FA7837C5CDFB273DE447E447 /* FIRServerTimestampTests.mm in Sources */,
39493959
67BC2B77C1CC47388E79D774 /* FIRSnapshotMetadataTests.mm in Sources */,
39503960
041CF73F67F6A22BF317625A /* FIRTimestampTest.m in Sources */,
3961+
58B84B550725D9812729C7F7 /* FIRTransactionOptionsTests.mm in Sources */,
39513962
75D124966E727829A5F99249 /* FIRTypeTests.mm in Sources */,
39523963
12DB753599571E24DCED0C2C /* FIRValidationTests.mm in Sources */,
39533964
BC0C98A9201E8F98B9A176A9 /* FIRWriteBatchTests.mm in Sources */,
@@ -4163,6 +4174,7 @@
41634174
27E46C94AAB087C80A97FF7F /* FIRServerTimestampTests.mm in Sources */,
41644175
59F512D155DE361095A04ED4 /* FIRSnapshotMetadataTests.mm in Sources */,
41654176
FE1C0263F6570DAC54A60F5C /* FIRTimestampTest.m in Sources */,
4177+
339D4DD13E1518BA79FF12EA /* FIRTransactionOptionsTests.mm in Sources */,
41664178
5F05A801B1EA44BC1264E55A /* FIRTypeTests.mm in Sources */,
41674179
8403D519C916C72B9C7F2FA1 /* FIRValidationTests.mm in Sources */,
41684180
8705C4856498F66E471A0997 /* FIRWriteBatchTests.mm in Sources */,
@@ -4381,6 +4393,7 @@
43814393
CB2C731116D6C9464220626F /* FIRQueryUnitTests.mm in Sources */,
43824394
5492E057202154AB00B64F25 /* FIRSnapshotMetadataTests.mm in Sources */,
43834395
B65D34A9203C995B0076A5E1 /* FIRTimestampTest.m in Sources */,
4396+
85A33A9CE33207C2333DDD32 /* FIRTransactionOptionsTests.mm in Sources */,
43844397
5492E058202154AB00B64F25 /* FSTAPIHelpers.mm in Sources */,
43854398
5492E03E2021401F00B64F25 /* FSTEventAccumulator.mm in Sources */,
43864399
54764FAF1FAA21B90085E60A /* FSTGoogleTestTests.mm in Sources */,
@@ -4608,6 +4621,7 @@
46084621
5492E077202154D600B64F25 /* FIRServerTimestampTests.mm in Sources */,
46094622
716289F99B5316B3CC5E5CE9 /* FIRSnapshotMetadataTests.mm in Sources */,
46104623
02B83EB79020AE6CBA60A410 /* FIRTimestampTest.m in Sources */,
4624+
913C2DB6951A2ED24778686C /* FIRTransactionOptionsTests.mm in Sources */,
46114625
5492E07A202154D600B64F25 /* FIRTypeTests.mm in Sources */,
46124626
5492E076202154D600B64F25 /* FIRValidationTests.mm in Sources */,
46134627
5492E078202154D600B64F25 /* FIRWriteBatchTests.mm in Sources */,
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#import <FirebaseFirestore/FIRTransactionOptions.h>
18+
19+
#import <XCTest/XCTest.h>
20+
21+
NS_ASSUME_NONNULL_BEGIN
22+
23+
@interface FIRTransactionOptionsTests : XCTestCase
24+
@end
25+
26+
@implementation FIRTransactionOptionsTests
27+
28+
- (void)testDefaults {
29+
FIRTransactionOptions* options = [[FIRTransactionOptions alloc] init];
30+
XCTAssertEqual(options.maxAttempts, 5);
31+
}
32+
33+
- (void)testSetMaxAttempts {
34+
FIRTransactionOptions* options = [[FIRTransactionOptions alloc] init];
35+
options.maxAttempts = 10;
36+
XCTAssertEqual(options.maxAttempts, 10);
37+
options.maxAttempts = 99;
38+
XCTAssertEqual(options.maxAttempts, 99);
39+
}
40+
41+
- (void)testSetMaxAttemptsThrowsOnInvalidValue {
42+
FIRTransactionOptions* options = [[FIRTransactionOptions alloc] init];
43+
XCTAssertThrows(options.maxAttempts = 0);
44+
XCTAssertThrows(options.maxAttempts = -1);
45+
XCTAssertThrows(options.maxAttempts = INT32_MIN);
46+
XCTAssertThrows(options.maxAttempts = INT32_MAX + 1);
47+
}
48+
49+
- (void)testHash {
50+
XCTAssertEqual([[[FIRTransactionOptions alloc] init] hash],
51+
[[[FIRTransactionOptions alloc] init] hash]);
52+
53+
FIRTransactionOptions* options1a = [[FIRTransactionOptions alloc] init];
54+
options1a.maxAttempts = 99;
55+
FIRTransactionOptions* options1b = [[FIRTransactionOptions alloc] init];
56+
options1b.maxAttempts = 99;
57+
FIRTransactionOptions* options2a = [[FIRTransactionOptions alloc] init];
58+
options2a.maxAttempts = 11;
59+
FIRTransactionOptions* options2b = [[FIRTransactionOptions alloc] init];
60+
options2b.maxAttempts = 11;
61+
62+
XCTAssertEqual([options1a hash], [options1b hash]);
63+
XCTAssertEqual([options2a hash], [options2b hash]);
64+
XCTAssertNotEqual([options1a hash], [options2a hash]);
65+
}
66+
67+
- (void)testIsEqual {
68+
FIRTransactionOptions* options1a = [[FIRTransactionOptions alloc] init];
69+
options1a.maxAttempts = 99;
70+
FIRTransactionOptions* options1b = [[FIRTransactionOptions alloc] init];
71+
options1b.maxAttempts = 99;
72+
FIRTransactionOptions* options2a = [[FIRTransactionOptions alloc] init];
73+
options2a.maxAttempts = 11;
74+
FIRTransactionOptions* options2b = [[FIRTransactionOptions alloc] init];
75+
options2b.maxAttempts = 11;
76+
77+
XCTAssertTrue([options1a isEqual:options1a]);
78+
79+
XCTAssertTrue([options1a isEqual:options1b]);
80+
XCTAssertTrue([options2a isEqual:options2b]);
81+
82+
XCTAssertFalse([options1a isEqual:options2a]);
83+
84+
XCTAssertFalse([options1a isEqual:@"definitely not equal"]);
85+
}
86+
87+
- (void)testCopy {
88+
FIRTransactionOptions* options1 = [[FIRTransactionOptions alloc] init];
89+
options1.maxAttempts = 99;
90+
FIRTransactionOptions* options2 = [options1 copy];
91+
XCTAssertEqual(options2.maxAttempts, 99);
92+
93+
// Verify that the copy is independent of the copied object.
94+
options1.maxAttempts = 55;
95+
XCTAssertEqual(options2.maxAttempts, 99);
96+
options2.maxAttempts = 22;
97+
XCTAssertEqual(options1.maxAttempts, 55);
98+
}
99+
100+
@end
101+
102+
NS_ASSUME_NONNULL_END

Firestore/Example/Tests/Integration/FSTTransactionTests.mm

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
using firebase::firestore::util::TimerId;
2626

2727
@interface FSTTransactionTests : FSTIntegrationTestCase
28+
- (void)runFailedPreconditionTransactionWithOptions:(FIRTransactionOptions *_Nullable)options
29+
expectNumAttempts:(int)expectedNumAttempts;
2830
@end
2931

3032
/**
@@ -795,4 +797,62 @@ - (void)testUpdateNestedFieldsTransactionally {
795797
[self awaitExpectations];
796798
}
797799

800+
- (void)runFailedPreconditionTransactionWithOptions:(FIRTransactionOptions *_Nullable)options
801+
expectNumAttempts:(int)expectedNumAttempts {
802+
// Note: The logic below to force retries is heavily based on
803+
// testRetriesWhenDocumentThatWasReadWithoutBeingWrittenChanges.
804+
805+
FIRFirestore *firestore = [self firestore];
806+
FIRDocumentReference *doc = [[firestore collectionWithPath:@"counters"] documentWithAutoID];
807+
auto attemptCount = std::make_shared<std::atomic_int>(0);
808+
attemptCount->store(0);
809+
810+
[self writeDocumentRef:doc data:@{@"count" : @"initial value"}];
811+
812+
// Skip backoff delays.
813+
[firestore workerQueue]->SkipDelaysForTimerId(TimerId::RetryTransaction);
814+
815+
XCTestExpectation *expectation = [self expectationWithDescription:@"transaction"];
816+
[firestore runTransactionWithOptions:options
817+
block:^id _Nullable(FIRTransaction *transaction, NSError **error) {
818+
++(*attemptCount);
819+
820+
[transaction getDocument:doc error:error];
821+
XCTAssertNil(*error);
822+
823+
// Do a write outside of the transaction. This will force the transaction to be retried.
824+
dispatch_semaphore_t writeSemaphore = dispatch_semaphore_create(0);
825+
[doc setData:@{
826+
@"count" : @(attemptCount->load())
827+
}
828+
completion:^(NSError *) {
829+
dispatch_semaphore_signal(writeSemaphore);
830+
}];
831+
dispatch_semaphore_wait(writeSemaphore, DISPATCH_TIME_FOREVER);
832+
833+
// Now try to update the doc from within the transaction.
834+
// This will fail since the document was modified outside of the transaction.
835+
[transaction setData:@{@"count" : @"this write should fail"} forDocument:doc];
836+
return nil;
837+
}
838+
completion:^(id, NSError *_Nullable error) {
839+
[self assertError:error
840+
message:@"the transaction should fail due to retries exhausted"
841+
code:FIRFirestoreErrorCodeFailedPrecondition];
842+
XCTAssertEqual(attemptCount->load(), expectedNumAttempts);
843+
[expectation fulfill];
844+
}];
845+
[self awaitExpectations];
846+
}
847+
848+
- (void)testTransactionOptionsNil {
849+
[self runFailedPreconditionTransactionWithOptions:nil expectNumAttempts:5];
850+
}
851+
852+
- (void)testTransactionOptionsMaxAttempts {
853+
FIRTransactionOptions *options = [[FIRTransactionOptions alloc] init];
854+
options.maxAttempts = 7;
855+
[self runFailedPreconditionTransactionWithOptions:options expectNumAttempts:7];
856+
}
857+
798858
@end

0 commit comments

Comments
 (0)