in firestore/testapp/Assets/Firebase/Sample/Firestore/UIHandlerAutomated.cs [2454:2580]
Task TestTerminate() {
return Async(() => {
var db1 = NonDefaultFirestore("TestTerminate");
FirebaseApp app = db1.App;
var doc = db1.Document("ColA/DocA/ColB/DocB");
var doc2 = db1.Document("ColA/DocA/ColB/DocC");
var collection = doc.Parent;
var writeBatch = db1.StartBatch();
var accumulator = new EventAccumulator<DocumentSnapshot>(MainThreadId, FailTest);
var registration = doc.Listen(accumulator.Listener);
// Multiple calls to terminate should go through.
AssertTaskSucceeds(db1.TerminateAsync());
AssertTaskSucceeds(db1.TerminateAsync());
// Can call registration.Stop multiple times even after termination.
registration.Stop();
registration.Stop();
var taskCompletionSource = new TaskCompletionSource<string>();
taskCompletionSource.SetException(new InvalidOperationException("forced exception"));
Task sampleUntypedTask = taskCompletionSource.Task;
Task<string> sampleTypedTask = taskCompletionSource.Task;
// Verify that the `App` property is still valid after `TerminateAsync()`.
Assert("App property should not have changed", db1.App == app);
// Verify that synchronous methods in `FirebaseFirestore` still return values after
// `TerminateAsync()`.
AssertNotNull("Collection() returned null", db1.Collection("a"));
AssertNotNull("CollectionGroup() returned null", db1.CollectionGroup("c"));
AssertNotNull("Document() returned null", db1.Document("a/b"));
AssertNotNull("StartBatch() returned null", db1.StartBatch());
// Verify that adding a listener via `ListenForSnapshotsInSync()` is not notified
// after `TerminateAsync()`.
bool snapshotsInSyncListenerInvoked = false;
Action snapshotsInSyncListener = () => { snapshotsInSyncListenerInvoked = true; };
#if UNITY_ANDROID
AssertException(typeof(InvalidOperationException),
() => db1.ListenForSnapshotsInSync(snapshotsInSyncListener));
#else
// TODO(b/201438171) `ListenForSnapshotsInSync()` should throw `InvalidOperationException`,
// like it does on Android and like `CollectionReference.Listen()` and
// `DocumentReference.Listen()` do.
db1.ListenForSnapshotsInSync(snapshotsInSyncListener);
#endif
// Verify that all non-static methods in `FirebaseFirestore` that start a `Task`, other
// than `ClearPersistenceAsync()` fail.
AssertTaskFaults(typeof(InvalidOperationException),
db1.RunTransactionAsync(transaction => sampleUntypedTask));
AssertTaskFaults(typeof(InvalidOperationException),
db1.RunTransactionAsync<string>(transaction => sampleTypedTask));
// TODO(b/201098348) Change `AssertException()` to `AssertTaskFaults()` for the 5 bundle
// loading methods below, since they should be consistent with the rest of the methods.
AssertException(typeof(InvalidOperationException), () => db1.LoadBundleAsync("BundleData"));
AssertException(typeof(InvalidOperationException),
() => db1.LoadBundleAsync("BundleData", (sender, progress) => {}));
AssertException(typeof(InvalidOperationException), () => db1.LoadBundleAsync(new byte[0]));
AssertException(typeof(InvalidOperationException),
() => db1.LoadBundleAsync(new byte[0], (sender, progress) => {}));
AssertException(typeof(InvalidOperationException),
() => db1.GetNamedQueryAsync("QueryName"));
AssertTaskFaults(typeof(InvalidOperationException), db1.DisableNetworkAsync());
AssertTaskFaults(typeof(InvalidOperationException), db1.EnableNetworkAsync());
AssertTaskFaults(typeof(InvalidOperationException), db1.WaitForPendingWritesAsync());
// Verify the behavior of methods in `CollectionReference` after `TerminateAsync()`.
Assert("collection.Firestore is not correct", collection.Firestore == db1);
AssertEq(collection.Id, "ColB");
AssertEq(collection.Path, "ColA/DocA/ColB");
bool collectionListenerInvoked = false;
Action<QuerySnapshot> collectionListener = snap => { collectionListenerInvoked = true; };
AssertException(typeof(InvalidOperationException),
() => collection.Listen(collectionListener));
AssertNotNull("Collection.Document() returned null", collection.Document());
AssertNotNull("Collection.Document(string) returned null", collection.Document("abc"));
AssertTaskFaults(typeof(InvalidOperationException), collection.AddAsync(TestData(1)));
// TODO(b/201438328) Change `AssertException()` to `AssertTaskFaults()` for
// `GetSnapshotAsync()`, since it should be consistent with other methods.
AssertException(typeof(InvalidOperationException),
() => collection.GetSnapshotAsync(Source.Default));
// Verify the behavior of methods in `DocumentReference` after `TerminateAsync()`.
Assert("doc.Firestore is not correct", doc.Firestore == db1);
AssertEq(doc.Id, "DocB");
AssertEq(doc.Path, "ColA/DocA/ColB/DocB");
AssertEq(doc.Parent, collection);
bool docListenerInvoked = false;
Action<DocumentSnapshot> docListener = snap => { docListenerInvoked = true; };
AssertException(typeof(InvalidOperationException), () => doc.Listen(docListener));
AssertNotNull("DocumentReference.Collection() returned null", doc.Collection("zzz"));
AssertTaskFaults(typeof(InvalidOperationException), doc.DeleteAsync());
AssertTaskFaults(typeof(InvalidOperationException), doc.SetAsync(TestData(1)));
AssertTaskFaults(typeof(InvalidOperationException), doc.UpdateAsync("life", 42));
// TODO(b/201438328) Change `AssertException()` to `AssertTaskFaults()` for
// `GetSnapshotAsync()`, since it should be consistent with other methods.
AssertException(typeof(InvalidOperationException),
() => doc.GetSnapshotAsync(Source.Default));
// Verify the behavior of methods in `WriteBatch` after `TerminateAsync()`.
writeBatch.Delete(doc);
writeBatch.Set(doc2, TestData(1), null);
AssertTaskFaults(typeof(InvalidOperationException), writeBatch.CommitAsync());
// Verify that the listeners were not notified. Do it here instead of above to allow
// some time to pass for unexpected notifications to be received.
Assert("The listener registered with FirebaseFirestore.ListenForSnapshotsInSync() " +
"should not be notified after TerminateAsync()",
!snapshotsInSyncListenerInvoked);
Assert("The listener registered with CollectionReference.Listen() " +
"should not be notified after TerminateAsync()",
!collectionListenerInvoked);
Assert("The listener registered with DocumentReference.Listen() " +
"should not be notified after TerminateAsync()",
!docListenerInvoked);
// Create a new functional instance.
var db2 = FirebaseFirestore.GetInstance(app);
Assert("Should create a new instance.", db1 != db2);
AssertTaskSucceeds(db2.DisableNetworkAsync());
AssertTaskSucceeds(db2.EnableNetworkAsync());
app.Dispose();
});
}