Task TestFirestoreDispose()

in firestore/testapp/Assets/Firebase/Sample/Firestore/UIHandlerAutomated.cs [3627:3737]


    Task TestFirestoreDispose() {
      return Async(() => {
        // Verify that disposing the `FirebaseApp` in turn disposes the `FirebaseFirestore` object.
        {
          FirebaseApp customApp = FirebaseApp.Create(db.App.Options, "dispose-app-to-firestore");
          FirebaseFirestore customDb = FirebaseFirestore.GetInstance(customApp);
          customApp.Dispose();
          Assert("App property should be null", customDb.App == null);
        }

        // Verify that all non-static methods in `FirebaseFirestore` throw if invoked after
        // the instance is disposed.
        {
          var taskCompletionSource = new TaskCompletionSource<string>();
          taskCompletionSource.SetException(new InvalidOperationException("forced exception"));
          Task sampleUntypedTask = taskCompletionSource.Task;
          Task<string> sampleTypedTask = taskCompletionSource.Task;

          FirebaseApp customApp = FirebaseApp.Create(db.App.Options, "dispose-exceptions");
          FirebaseFirestore customDb = FirebaseFirestore.GetInstance(customApp);
          var doc = customDb.Document("ColA/DocA/ColB/DocB");
          var doc2 = customDb.Document("ColA/DocA/ColB/DocC");
          var collection = doc.Parent;
          var writeBatch = customDb.StartBatch();
          customApp.Dispose();

          // Verify that the `App` property is null valid after `FirebaseFirestore` is disposed.
          Assert("App property should be null", customDb.App == null);

          // Verify that all non-static methods in `FirebaseFirestore` throw after it is disposed.
          AssertException(typeof(InvalidOperationException), () => customDb.Collection("a"));
          AssertException(typeof(InvalidOperationException), () => customDb.Document("a/b"));
          AssertException(typeof(InvalidOperationException), () => customDb.CollectionGroup("c"));
          AssertException(typeof(InvalidOperationException), () => customDb.StartBatch());
          AssertException(typeof(InvalidOperationException),
                          () => customDb.RunTransactionAsync(transaction => sampleUntypedTask));
          AssertException(
              typeof(InvalidOperationException),
              () => customDb.RunTransactionAsync<string>(transaction => sampleTypedTask));
          bool snapshotsInSyncListenerInvoked = false;
          Action snapshotsInSyncListener = () => { snapshotsInSyncListenerInvoked = true; };
          AssertException(typeof(InvalidOperationException),
                          () => customDb.ListenForSnapshotsInSync(snapshotsInSyncListener));
          AssertException(typeof(InvalidOperationException),
                          () => customDb.LoadBundleAsync("BundleData"));
          AssertException(typeof(InvalidOperationException),
                          () => customDb.LoadBundleAsync("BundleData", (sender, progress) => {}));
          AssertException(typeof(InvalidOperationException),
                          () => customDb.LoadBundleAsync(new byte[0]));
          AssertException(typeof(InvalidOperationException),
                          () => customDb.LoadBundleAsync(new byte[0], (sender, progress) => {}));
          AssertException(typeof(InvalidOperationException),
                          () => customDb.GetNamedQueryAsync("QueryName"));
          AssertException(typeof(InvalidOperationException), () => customDb.DisableNetworkAsync());
          AssertException(typeof(InvalidOperationException), () => customDb.EnableNetworkAsync());
          AssertException(typeof(InvalidOperationException),
                          () => customDb.WaitForPendingWritesAsync());
          AssertException(typeof(InvalidOperationException), () => customDb.TerminateAsync());
          AssertException(typeof(InvalidOperationException),
                          () => customDb.ClearPersistenceAsync());

          // Verify the behavior of methods in `CollectionReference` after `FirebaseFirestore` is
          // disposed.
          Assert("collection.Firestore is not correct", collection.Firestore == customDb);
          AssertEq(collection.Id, "");
          AssertEq(collection.Path, "");
          bool collectionListenerInvoked = false;
          Action<QuerySnapshot> collectionListener = snap => { collectionListenerInvoked = true; };
          // TODO(b/201440423) `Listen()` should throw `InvalidOperationException`, not succeed.
          AssertNotNull("Collection.Listen()", collection.Listen(collectionListener));
          AssertNotNull("Collection.Document() returned null", collection.Document());
          AssertNotNull("Collection.Document(string) returned null", collection.Document("abc"));
          AssertTaskFaults(collection.AddAsync(TestData(1)), FirestoreError.FailedPrecondition);
          AssertTaskFaults(collection.GetSnapshotAsync(Source.Default),
                           FirestoreError.FailedPrecondition);

          // Verify the behavior of methods in `DocumentReference` after `FirebaseFirestore` is
          // disposed.
          Assert("doc.Firestore is not correct", doc.Firestore == customDb);
          AssertEq(doc.Id, "");
          AssertEq(doc.Path, "");
          AssertEq(doc.Parent, collection);
          bool docListenerInvoked = false;
          Action<DocumentSnapshot> docListener = snap => { docListenerInvoked = true; };
          // TODO(b/201440423) `Listen()` should throw `InvalidOperationException`, not succeed.
          AssertNotNull("DocumentReference.Listen()", doc.Listen(docListener));
          AssertNotNull("DocumentReference.Collection() returned null", doc.Collection("zzz"));
          AssertTaskFaults(doc.DeleteAsync(), FirestoreError.FailedPrecondition);
          AssertTaskFaults(doc.SetAsync(TestData(1)), FirestoreError.FailedPrecondition);
          AssertTaskFaults(doc.UpdateAsync("life", 42), FirestoreError.FailedPrecondition);
          AssertTaskFaults(doc.GetSnapshotAsync(Source.Default), FirestoreError.FailedPrecondition);

          // Verify the behavior of methods in `WriteBatch` after `FirebaseFirestore` is disposed.
          writeBatch.Delete(doc);
          writeBatch.Set(doc2, TestData(1), null);
          AssertTaskFaults(writeBatch.CommitAsync(), FirestoreError.FailedPrecondition);

          // 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);
        }
      });
    }