From 8bd159faec54c62c1d77d5ed4e3f90c94d2ae2b3 Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 1 Feb 2023 12:29:10 -0800 Subject: [PATCH 1/2] Add a test for whether unregistered listeners are called. --- .../Sample/Database/UIHandlerAutomated.cs | 106 ++++++++++++++++-- 1 file changed, 98 insertions(+), 8 deletions(-) diff --git a/database/testapp/Assets/Firebase/Sample/Database/UIHandlerAutomated.cs b/database/testapp/Assets/Firebase/Sample/Database/UIHandlerAutomated.cs index db78e9f0..1f86b27d 100644 --- a/database/testapp/Assets/Firebase/Sample/Database/UIHandlerAutomated.cs +++ b/database/testapp/Assets/Firebase/Sample/Database/UIHandlerAutomated.cs @@ -41,6 +41,8 @@ protected override void Start() { TestDbRefChild, TestDbRefPush, TestDbRefSetValue, + TestDbRefSetValueWithUnregisteredListener, + TestDbRefSetValueWithUnregisteredListenerAtSamePath, TestDbRefSetJson, TestDbRefSetInvalid, TestDbRefSetWPriority, @@ -440,6 +442,21 @@ public void WaitForEvents() { allEventsReceived.WaitOne(20 * NumMillisPerSecond); } + public void UnregisterListeners() { + UnregisterListeners(this.reference); + } + + public void UnregisterListeners(DatabaseReference dbref) { + dbref.ChildAdded -= childAddedListener; + dbref.ChildAdded -= childAddedListenerThrowException; + dbref.ChildChanged -= childChangedListener; + dbref.ChildChanged -= childChangedListenerThrowException; + dbref.ChildMoved -= childMovedListener; + dbref.ChildMoved -= childMovedListenerThrowException; + dbref.ChildRemoved -= childRemovedListener; + dbref.ChildRemoved -= childRemovedListenerThrowException; + } + // Assert that all expected events happened. // This MUST be called, as it also cleans up (i.e. unregisters) the listeners. public void AssertAllEventsDone() { @@ -450,14 +467,7 @@ public void AssertAllEventsDone() { } } // No more events are expected, clean up the listeners. - reference.ChildAdded -= childAddedListener; - reference.ChildAdded -= childAddedListenerThrowException; - reference.ChildChanged -= childChangedListener; - reference.ChildChanged -= childChangedListenerThrowException; - reference.ChildMoved -= childMovedListener; - reference.ChildMoved -= childMovedListenerThrowException; - reference.ChildRemoved -= childRemovedListener; - reference.ChildRemoved -= childRemovedListenerThrowException; + UnregisterListeners(); } // Common handler for all child events. @@ -772,6 +782,86 @@ Task TestDbRefSetValue() { }); } + Task TestDbRefSetValueWithUnregisteredListener() { + return Task.Run(() => { + // This test will register a value and use listeners to verify that + // the value did indeed get set. Then it will unregister the listeners + // and set the value again, ensuring that the listeners aren't called again. + string childKey = "ChildKey"; + object valueAdded = "1st Value"; + object valueChanged = "2nd Value"; + object valueAddedAgain = "Another 1st Value"; + object valueChangedAgain = "Another 2nd Value"; + + // We use Push to create a random child to not interfere with someone else running this test. + var parent = database.RootReference.Child("TestTree").Push(); + AsyncChecks checks = new AsyncChecks(parent); + // We expect two listener events: two for the two calls to SetValue. + checks.ExpectEvent(AsyncChecks.ChildEventType.Added, childKey, valueAdded); + checks.ExpectEvent(AsyncChecks.ChildEventType.Changed, childKey, valueChanged); + + var r = parent.Child(childKey); + // 1. Set a value in a newly created reference; + WaitAndAssertCompleted("First SetValue", r.SetValueAsync(valueAdded)); + // 2. Set the reference's value to something else; + WaitAndAssertCompleted("Second SetValue", r.SetValueAsync(valueChanged)); + + Task.Delay(TimeSpan.FromSeconds(2)).Wait(); + checks.UnregisterListeners(); + WaitAndAssertCompleted("RemoveValue", r.RemoveValueAsync()); + WaitAndAssertCompleted("First SetValue without listener", r.SetValueAsync(valueAddedAgain)); + // 2. Set the reference's value to something else; + WaitAndAssertCompleted("Second SetValue without listener", r.SetValueAsync(valueChangedAgain)); + WaitAndAssertCompleted("RemoveValue without listener", r.RemoveValueAsync()); + checks.WaitForEvents(); + checks.AssertAllEventsDone(); + Task.Delay(TimeSpan.FromSeconds(2)).Wait(); + Assert("All checks in listeners passed.\n" + checks.FailMessage, checks.AllGood); + }); + } + + Task TestDbRefSetValueWithUnregisteredListenerAtSamePath() { + return Task.Run(() => { + // This test will register a value and use listeners to verify that + // the value did indeed get set. Then it will unregister the listeners + // (using the path to get a new DatabaseReference) and set the value again, + // ensuring that the listeners aren't called again. + string childKey = "ChildKey"; + object valueAdded = "1st Value"; + object valueChanged = "2nd Value"; + object valueAddedAgain = "Another 1st Value"; + object valueChangedAgain = "Another 2nd Value"; + + // We use Push to create a random child to not interfere with someone else running this test. + var parent = database.RootReference.Child("TestTree").Push(); + AsyncChecks checks = new AsyncChecks(parent); + // We expect two listener events: two for the two calls to SetValue. + checks.ExpectEvent(AsyncChecks.ChildEventType.Added, childKey, valueAdded); + checks.ExpectEvent(AsyncChecks.ChildEventType.Changed, childKey, valueChanged); + + var r = parent.Child(childKey); + // 1. Set a value in a newly created reference; + WaitAndAssertCompleted("First SetValue", r.SetValueAsync(valueAdded)); + // 2. Set the reference's value to something else; + WaitAndAssertCompleted("Second SetValue", r.SetValueAsync(valueChanged)); + + Task.Delay(TimeSpan.FromSeconds(2)).Wait(); + + // Get a new DatabaseReference pointing to the same path as parent, by doing .Child().Parent. + checks.UnregisterListeners(parent.Child("unused_child").Parent); + + WaitAndAssertCompleted("RemoveValue", r.RemoveValueAsync()); + WaitAndAssertCompleted("First SetValue without listener", r.SetValueAsync(valueAddedAgain)); + // 2. Set the reference's value to something else; + WaitAndAssertCompleted("Second SetValue without listener", r.SetValueAsync(valueChangedAgain)); + WaitAndAssertCompleted("RemoveValue without listener", r.RemoveValueAsync()); + checks.WaitForEvents(); + checks.AssertAllEventsDone(); + Task.Delay(TimeSpan.FromSeconds(2)).Wait(); + Assert("All checks in listeners passed.\n" + checks.FailMessage, checks.AllGood); + }); + } + Task TestDbRefSetJson() { return Task.Run(() => { // This test will set a JSON value twice and use listeners to verify that From d1380a7b140ab0cb353ec1befd3da2baaeaed32e Mon Sep 17 00:00:00 2001 From: Jon Simantov Date: Wed, 1 Feb 2023 12:33:40 -0800 Subject: [PATCH 2/2] Move delay earlier. --- .../Assets/Firebase/Sample/Database/UIHandlerAutomated.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/testapp/Assets/Firebase/Sample/Database/UIHandlerAutomated.cs b/database/testapp/Assets/Firebase/Sample/Database/UIHandlerAutomated.cs index 1f86b27d..efe0aea1 100644 --- a/database/testapp/Assets/Firebase/Sample/Database/UIHandlerAutomated.cs +++ b/database/testapp/Assets/Firebase/Sample/Database/UIHandlerAutomated.cs @@ -813,9 +813,9 @@ Task TestDbRefSetValueWithUnregisteredListener() { // 2. Set the reference's value to something else; WaitAndAssertCompleted("Second SetValue without listener", r.SetValueAsync(valueChangedAgain)); WaitAndAssertCompleted("RemoveValue without listener", r.RemoveValueAsync()); + Task.Delay(TimeSpan.FromSeconds(2)).Wait(); checks.WaitForEvents(); checks.AssertAllEventsDone(); - Task.Delay(TimeSpan.FromSeconds(2)).Wait(); Assert("All checks in listeners passed.\n" + checks.FailMessage, checks.AllGood); }); } @@ -855,9 +855,9 @@ Task TestDbRefSetValueWithUnregisteredListenerAtSamePath() { // 2. Set the reference's value to something else; WaitAndAssertCompleted("Second SetValue without listener", r.SetValueAsync(valueChangedAgain)); WaitAndAssertCompleted("RemoveValue without listener", r.RemoveValueAsync()); + Task.Delay(TimeSpan.FromSeconds(2)).Wait(); checks.WaitForEvents(); checks.AssertAllEventsDone(); - Task.Delay(TimeSpan.FromSeconds(2)).Wait(); Assert("All checks in listeners passed.\n" + checks.FailMessage, checks.AllGood); }); }