/*
* Copyright 2017 Google Inc.
*
* 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.
*/
package com.google.firebase.database.integration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.google.common.collect.ImmutableList;
import com.google.firebase.FirebaseApp;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.MapBuilder;
import com.google.firebase.database.TestFailure;
import com.google.firebase.database.TestHelpers;
import com.google.firebase.database.core.view.Event;
import com.google.firebase.database.future.ReadFuture;
import com.google.firebase.database.future.WriteFuture;
import com.google.firebase.testing.IntegrationTestUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeoutException;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class OrderTestIT {
private static FirebaseApp masterApp;
@BeforeClass
public static void setUpClass() throws TestFailure, TimeoutException, InterruptedException {
masterApp = IntegrationTestUtils.ensureDefaultApp();
// Make sure we're connected before any of these tests run
DatabaseReference ref = FirebaseDatabase.getInstance(masterApp).getReference();
ReadFuture.untilEquals(ref.child(".info/connected"), true).timedGet();
}
@Before
public void prepareApp() {
TestHelpers.wrapForErrorHandling(masterApp);
}
@After
public void checkAndCleanupApp() {
TestHelpers.assertAndUnwrapErrorHandlers(masterApp);
}
@Test
public void testPushAndEnumerate()
throws TestFailure, TimeoutException, InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
for (int i = 0; i < 10; ++i) {
ref.push().setValue(i);
}
DataSnapshot snap = new ReadFuture(ref).timedGet().get(0).getSnapshot();
long i = 0;
for (DataSnapshot child : snap.getChildren()) {
assertEquals(i, child.getValue());
i++;
}
assertEquals(10L, i);
}
@Test
public void testPushWriteAndEnumerate()
throws TestFailure, TimeoutException, InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
List<DatabaseReference> paths = new ArrayList<>(20);
// Generate children quickly to try to get a few in the same millisecond
for (int i = 0; i < 20; ++i) {
paths.add(ref.push());
}
for (int i = 0; i < paths.size(); ++i) {
paths.get(i).setValue(i);
}
DataSnapshot snap = new ReadFuture(ref).timedGet().get(0).getSnapshot();
long i = 0;
for (DataSnapshot child : snap.getChildren()) {
assertEquals(i, child.getValue());
i++;
}
assertEquals(20L, i);
}
@Test
public void testReconnectAndRead()
throws TestFailure, ExecutionException, TimeoutException, InterruptedException {
List<DatabaseReference> refs = IntegrationTestUtils.getRandomNode(masterApp, 2);
final DatabaseReference writer = refs.get(0);
final DatabaseReference reader = refs.get(1);
for (int i = 0; i < 9; ++i) {
writer.push().setValue(i);
}
new WriteFuture(writer.push(), 9).timedGet();
DataSnapshot snap = TestHelpers.getSnap(writer);
long i = 0;
for (DataSnapshot child : snap.getChildren()) {
assertEquals(i, child.getValue());
i++;
}
assertEquals(10L, i);
snap = TestHelpers.getSnap(reader);
i = 0;
for (DataSnapshot child : snap.getChildren()) {
assertEquals(i, child.getValue());
i++;
}
assertEquals(10L, i);
}
@Test
public void testReconnectAndReadWithPriority()
throws TestFailure, ExecutionException, TimeoutException, InterruptedException {
List<DatabaseReference> refs = IntegrationTestUtils.getRandomNode(masterApp, 2);
final DatabaseReference writer = refs.get(0);
final DatabaseReference reader = refs.get(1);
for (int i = 0; i < 9; ++i) {
writer.push().setValue(i, 10 - i);
}
new WriteFuture(writer.push(), 9, 1).timedGet();
DataSnapshot snap = TestHelpers.getSnap(writer);
long i = 9;
for (DataSnapshot child : snap.getChildren()) {
assertEquals(i, child.getValue());
i--;
}
assertEquals(-1L, i);
snap = TestHelpers.getSnap(reader);
i = 9;
for (DataSnapshot child : snap.getChildren()) {
assertEquals(i, child.getValue());
i--;
}
assertEquals(-1L, i);
}
@Test
public void testExponentialPriority()
throws TestFailure, ExecutionException, TimeoutException, InterruptedException {
List<DatabaseReference> refs = IntegrationTestUtils.getRandomNode(masterApp, 2);
final DatabaseReference writer = refs.get(0);
final DatabaseReference reader = refs.get(1);
for (int i = 0; i < 9; ++i) {
writer.push().setValue(i, 111111111111111111111111111111.0 / Math.pow(10, i));
}
new WriteFuture(writer.push(), 9, 111111111111111111111111111111.0 / Math.pow(10, 9))
.timedGet();
DataSnapshot snap = TestHelpers.getSnap(writer);
long i = 9;
for (DataSnapshot child : snap.getChildren()) {
assertEquals(i, child.getValue());
i--;
}
assertEquals(-1L, i);
snap = TestHelpers.getSnap(reader);
i = 9;
for (DataSnapshot child : snap.getChildren()) {
assertEquals(i, child.getValue());
i--;
}
assertEquals(-1L, i);
}
@Test
public void testEnumerateNodesWithoutValues() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
ref.child("foo");
ref.child("bar").setValue("test");
DataSnapshot snap = TestHelpers.getSnap(ref);
int i = 0;
for (DataSnapshot child : snap.getChildren()) {
i++;
assertEquals("bar", child.getKey());
}
assertEquals(1, i);
}
@Test
public void testChildEventsOnPriorityChanges() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final EventHelper helper =
new EventHelper()
.addChildExpectation(ref, Event.EventType.CHILD_ADDED, "a")
.addValueExpectation(ref)
.addChildExpectation(ref, Event.EventType.CHILD_ADDED, "b")
.addValueExpectation(ref)
.addChildExpectation(ref, Event.EventType.CHILD_ADDED, "c")
.addValueExpectation(ref)
.addChildExpectation(ref, Event.EventType.CHILD_MOVED, "a")
.addChildExpectation(ref, Event.EventType.CHILD_CHANGED, "a")
.addValueExpectation(ref)
.startListening(true);
ref.child("a").setValue("first", 1);
ref.child("b").setValue("second", 5);
ref.child("c").setValue("third", 10);
ref.child("a").setPriority(15);
assertTrue(helper.waitForEvents());
helper.cleanup();
}
@Test
public void testResetPriorityToNull() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
ref.child("a").setValue("a", 1);
ref.child("b").setValue("b", 2);
TestHelpers.waitForRoundtrip(ref);
EventHelper helper =
new EventHelper()
.addChildExpectation(ref, Event.EventType.CHILD_ADDED, "a")
.addChildExpectation(ref, Event.EventType.CHILD_ADDED, "b")
.addValueExpectation(ref)
.startListening();
assertTrue(helper.waitForEvents());
helper
.addChildExpectation(ref, Event.EventType.CHILD_MOVED, "b")
.addChildExpectation(ref, Event.EventType.CHILD_CHANGED, "b")
.addValueExpectation(ref)
.startListening();
ref.child("b").setPriority(null);
assertTrue(helper.waitForEvents());
DataSnapshot snap = TestHelpers.getSnap(ref);
assertNull(snap.child("b").getPriority());
helper.cleanup();
}
@Test
public void testInsertingNodeUnderLeaf()
throws TestFailure, TimeoutException, InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
ReadFuture readFuture = ReadFuture.untilCountAfterNull(ref, 2);
ref.setValue("a", 10);
ref.child("deeper").setValue("deeper");
DataSnapshot snap = readFuture.timedGet().get(1).getSnapshot();
assertEquals(10.0, snap.getPriority());
}
@Test
public void testMixedPriorityTypes()
throws TestFailure, ExecutionException, TimeoutException, InterruptedException {
List<DatabaseReference> refs = IntegrationTestUtils.getRandomNode(masterApp, 2);
final DatabaseReference writer = refs.get(0);
final DatabaseReference reader = refs.get(1);
writer.child("alpha42").setValue(1, "zed");
writer.child("noPriorityC").setValue(1, (String) null);
writer.child("num41").setValue(1, 500);
writer.child("noPriorityB").setValue(1, (String) null);
writer.child("num80").setValue(1, 4000.1);
writer.child("num50").setValue(1, 4000);
writer.child("num10").setValue(1, 24);
writer.child("alpha41").setValue(1, "zed");
writer.child("alpha20").setValue(1, "horse");
writer.child("num20").setValue(1, 123);
writer.child("num70").setValue(1, 4000.01);
writer.child("noPriorityA").setValue(1, (String) null);
writer.child("alpha30").setValue(1, "tree");
writer.child("num30").setValue(1, 300);
writer.child("num60").setValue(1, 4000.001);
writer.child("alpha10").setValue(1, "0horse");
writer.child("num42").setValue(1, 500);
writer.child("alpha40").setValue(1, "zed");
new WriteFuture(writer.child("num40"), 1, 500).timedGet();
List<String> expected = ImmutableList.<String>builder().add(
"noPriorityA",
"noPriorityB",
"noPriorityC",
"num10",
"num20",
"num30",
"num40",
"num41",
"num42",
"num50",
"num60",
"num70",
"num80",
"alpha10",
"alpha20",
"alpha30",
"alpha40",
"alpha41",
"alpha42").build();
List<String> actual = new ArrayList<>(expected.size());
DataSnapshot snap = TestHelpers.getSnap(writer);
for (DataSnapshot child : snap.getChildren()) {
actual.add(child.getKey());
}
TestHelpers.assertDeepEquals(expected, actual);
actual.clear();
snap = TestHelpers.getSnap(reader);
for (DataSnapshot child : snap.getChildren()) {
actual.add(child.getKey());
}
TestHelpers.assertDeepEquals(expected, actual);
}
@Test
public void testIntegerKeyOrder()
throws TestFailure, ExecutionException, TimeoutException, InterruptedException {
List<DatabaseReference> refs = IntegrationTestUtils.getRandomNode(masterApp, 2);
DatabaseReference writer = refs.get(0);
writer.child("foo").setValue(0);
writer.child("bar").setValue(0);
writer.child("03").setValue(0);
writer.child("0").setValue(0);
writer.child("100").setValue(0);
writer.child("20").setValue(0);
writer.child("5").setValue(0);
writer.child("3").setValue(0);
writer.child("003").setValue(0);
new WriteFuture(writer.child("9"), 0).timedGet();
List<String> expected = ImmutableList.of(
"0", "3", "03", "003", "5", "9", "20", "100", "bar", "foo");
List<String> actual = new ArrayList<>(expected.size());
DataSnapshot snap = TestHelpers.getSnap(writer);
for (DataSnapshot child : snap.getChildren()) {
actual.add(child.getKey());
}
TestHelpers.assertDeepEquals(expected, actual);
}
@Test
public void testLargeIntegerKeyOrder()
throws TestFailure, ExecutionException, TimeoutException, InterruptedException {
List<DatabaseReference> refs = IntegrationTestUtils.getRandomNode(masterApp, 2);
DatabaseReference writer = refs.get(0);
writer.child("2000000000").setValue(0);
new WriteFuture(writer.child("-2000000000"), 0).timedGet();
List<String> expected = ImmutableList.of("-2000000000", "2000000000");
List<String> actual = new ArrayList<>(expected.size());
DataSnapshot snap = TestHelpers.getSnap(writer);
for (DataSnapshot child : snap.getChildren()) {
actual.add(child.getKey());
}
TestHelpers.assertDeepEquals(expected, actual);
}
@Test
public void testPrevNameOnChildAddedEvent() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final List<String> results = new ArrayList<>();
final Semaphore semaphore = new Semaphore(0);
final ChildEventListener listener =
ref.addChildEventListener(
new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
results.add(snapshot.getKey());
results.add(previousChildName);
semaphore.release(1);
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
fail("Should not happen");
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
fail("Should not happen");
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
fail("Should not happen");
}
@Override
public void onCancelled(DatabaseError error) {}
});
ref.setValue(new MapBuilder().put("a", 1).put("b", 2).put("c", 3).build());
TestHelpers.waitFor(semaphore, 3);
List<String> expected = Arrays.asList("a", null, "b", "a", "c", "b");
TestHelpers.assertDeepEquals(expected, results);
ref.removeEventListener(listener);
}
@Test
public void testPrevNameOnAddingNewNodes() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final List<String> results = new ArrayList<>();
final Semaphore semaphore = new Semaphore(0);
final ChildEventListener listener =
ref.addChildEventListener(
new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
results.add(snapshot.getKey());
results.add(previousChildName);
semaphore.release(1);
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
fail("Should not happen");
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
fail("Should not happen");
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
fail("Should not happen");
}
@Override
public void onCancelled(DatabaseError error) {}
});
ref.setValue(MapBuilder.of("b", 2, "c", 3, "d", 4));
ref.child("a").setValue(1);
ref.child("e").setValue(5);
TestHelpers.waitFor(semaphore, 5);
List<String> expected = Arrays.asList("b", null, "c", "b", "d", "c", "a", null, "e", "d");
TestHelpers.assertDeepEquals(expected, results);
ref.removeEventListener(listener);
}
@Test
public void testPrevNameOnAddingNewNodesWithJSON() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final List<String> results = new ArrayList<>();
final Semaphore semaphore = new Semaphore(0);
final ChildEventListener listener =
ref.addChildEventListener(
new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
results.add(snapshot.getKey());
results.add(previousChildName);
semaphore.release(1);
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
fail("Should not happen");
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
fail("Should not happen");
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
fail("Should not happen");
}
@Override
public void onCancelled(DatabaseError error) {}
});
ref.setValue(MapBuilder.of("b", 2, "c", 3, "d", 4));
ref.setValue(new MapBuilder().put("a", 1).put("b", 2).put("c", 3).put("d", 4).build());
ref.setValue(new MapBuilder().put("a", 1).put("b", 2).put("c", 3)
.put("d", 4).put("e", 5).build());
TestHelpers.waitFor(semaphore, 5);
List<String> expected = Arrays.asList("b", null, "c", "b", "d", "c", "a", null, "e", "d");
TestHelpers.assertDeepEquals(expected, results);
ref.removeEventListener(listener);
}
@Test
public void testPrevNameIOnMovingNodes() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final List<String> results = new ArrayList<>();
final Semaphore semaphore = new Semaphore(0);
final ChildEventListener listener =
ref.addChildEventListener(
new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
// No-op
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
results.add("CHANGED:" + snapshot.getKey() + "/" + previousChildName);
semaphore.release(1);
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
fail("Should not happen");
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
results.add("MOVED:" + snapshot.getKey() + "/" + previousChildName);
semaphore.release(1);
}
@Override
public void onCancelled(DatabaseError error) {}
});
ref.child("a").setValue("a", 1);
ref.child("b").setValue("b", 2);
ref.child("c").setValue("c", 3);
ref.child("d").setValue("d", 4);
ref.child("d").setPriority(0);
ref.child("a").setPriority(4);
ref.child("c").setPriority(0.5);
TestHelpers.waitFor(semaphore, 6);
List<String> expected = ImmutableList.of("MOVED:d/null", "CHANGED:d/null", "MOVED:a/c",
"CHANGED:a/c", "MOVED:c/d", "CHANGED:c/d");
TestHelpers.assertDeepEquals(expected, results);
ref.removeEventListener(listener);
}
@Test
public void testPrevNameOnWhenMovingNodesBySettingJson() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final List<String> results = new ArrayList<>();
final Semaphore semaphore = new Semaphore(0);
final ChildEventListener listener =
ref.addChildEventListener(
new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
// No-op
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
results.add("CHANGED:" + snapshot.getKey() + "/" + previousChildName);
semaphore.release(1);
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
fail("Should not happen");
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
results.add("MOVED:" + snapshot.getKey() + "/" + previousChildName);
semaphore.release(1);
}
@Override
public void onCancelled(DatabaseError error) {}
});
ref.setValue(
new MapBuilder()
.put("a", new MapBuilder().put(".value", "a").put(".priority", 1).build())
.put("b", new MapBuilder().put(".value", "b").put(".priority", 2).build())
.put("c", new MapBuilder().put(".value", "c").put(".priority", 3).build())
.put("d", new MapBuilder().put(".value", "d").put(".priority", 4).build())
.build());
ref.setValue(
new MapBuilder()
.put("d", new MapBuilder().put(".value", "d").put(".priority", 0).build())
.put("a", new MapBuilder().put(".value", "a").put(".priority", 1).build())
.put("b", new MapBuilder().put(".value", "b").put(".priority", 2).build())
.put("c", new MapBuilder().put(".value", "c").put(".priority", 3).build())
.build());
ref.setValue(
new MapBuilder()
.put("d", new MapBuilder().put(".value", "d").put(".priority", 0).build())
.put("b", new MapBuilder().put(".value", "b").put(".priority", 2).build())
.put("c", new MapBuilder().put(".value", "c").put(".priority", 3).build())
.put("a", new MapBuilder().put(".value", "a").put(".priority", 4).build())
.build());
ref.setValue(
new MapBuilder()
.put("d", new MapBuilder().put(".value", "d").put(".priority", 0).build())
.put("c", new MapBuilder().put(".value", "c").put(".priority", 0.5).build())
.put("b", new MapBuilder().put(".value", "b").put(".priority", 2).build())
.put("a", new MapBuilder().put(".value", "a").put(".priority", 4).build())
.build());
TestHelpers.waitFor(semaphore, 6);
List<String> expected = ImmutableList.of("MOVED:d/null", "CHANGED:d/null", "MOVED:a/c",
"CHANGED:a/c", "MOVED:c/d", "CHANGED:c/d");
TestHelpers.assertDeepEquals(expected, results);
ref.removeEventListener(listener);
}
@Test
public void testCase595DeletingPrioritizedGrandChild()
throws TestFailure, ExecutionException, TimeoutException, InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final ChildEventListener listener =
ref.addChildEventListener(
new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
// No-op
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
// No-op
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
// No-op
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
fail("Should not happen");
}
@Override
public void onCancelled(DatabaseError error) {}
});
ref.child("test/foo").setValue(42, "5");
ref.child("test/f002").setValue(42, "10");
ref.child("test/foo").removeValue();
new WriteFuture(ref.child("test/foo2"), null).timedGet();
// If child_moved has been raised, the test will have failed by now
ref.removeEventListener(listener);
}
@Test
public void testSetValuePriorityToZero()
throws TestFailure, TimeoutException, InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
ReadFuture readFuture = new ReadFuture(ref);
ref.setValue("test", 0);
DataSnapshot snap = readFuture.timedGet().get(0).getSnapshot();
assertEquals(0.0, snap.getPriority());
}
@Test
public void testSetObjectPriorityToZero()
throws TestFailure, TimeoutException, InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
ReadFuture readFuture = new ReadFuture(ref);
ref.setValue(new MapBuilder().put("x", "test").put("y", 7).build(), 0);
DataSnapshot snap = readFuture.timedGet().get(0).getSnapshot();
assertEquals(0.0, snap.getPriority());
}
@Test
public void testCase2003ChildMovedForPriorityChange1() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final List<String> results = new ArrayList<>();
final Semaphore semaphore = new Semaphore(0);
final ChildEventListener listener =
ref.addChildEventListener(
new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
// No-op
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
results.add("CHANGED:" + snapshot.getKey() + "/" + previousChildName);
semaphore.release(1);
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
fail("Should not happen");
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
results.add("MOVED:" + snapshot.getKey() + "/" + previousChildName);
semaphore.release(1);
}
@Override
public void onCancelled(DatabaseError error) {}
});
ref.setValue(
new MapBuilder()
.put("a", new MapBuilder().put(".value", "a").put(".priority", 0).build())
.put("b", new MapBuilder().put(".value", "b").put(".priority", 1).build())
.put("c", new MapBuilder().put(".value", "c").put(".priority", 2).build())
.put("d", new MapBuilder().put(".value", "d").put(".priority", 3).build())
.build());
ref.child("b").setPriority(1.5);
TestHelpers.waitFor(semaphore, 2);
assertEquals(2, results.size());
assertEquals(ImmutableList.of("MOVED:b/a", "CHANGED:b/a"), results);
ref.removeEventListener(listener);
}
@Test
public void testCase2003ChildMovedForPriorityChange2() throws InterruptedException {
DatabaseReference ref = IntegrationTestUtils.getRandomNode(masterApp);
final List<String> results = new ArrayList<>();
final Semaphore semaphore = new Semaphore(0);
final ChildEventListener listener =
ref.addChildEventListener(
new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildName) {
// No-op
}
@Override
public void onChildChanged(DataSnapshot snapshot, String previousChildName) {
results.add("CHANGED:" + snapshot.getKey() + "/" + previousChildName);
semaphore.release(1);
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
fail("Should not happen");
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildName) {
results.add("MOVED:" + snapshot.getKey() + "/" + previousChildName);
semaphore.release(1);
}
@Override
public void onCancelled(DatabaseError error) {
fail("Should not happen");
}
});
ref.setValue(
new MapBuilder()
.put("a", new MapBuilder().put(".value", "a").put(".priority", 0).build())
.put("b", new MapBuilder().put(".value", "b").put(".priority", 1).build())
.put("c", new MapBuilder().put(".value", "c").put(".priority", 2).build())
.put("d", new MapBuilder().put(".value", "d").put(".priority", 3).build())
.build());
ref.setValue(
new MapBuilder()
.put("a", new MapBuilder().put(".value", "a").put(".priority", 0).build())
.put("b", new MapBuilder().put(".value", "b").put(".priority", 1.5).build())
.put("c", new MapBuilder().put(".value", "c").put(".priority", 2).build())
.put("d", new MapBuilder().put(".value", "d").put(".priority", 3).build())
.build());
TestHelpers.waitFor(semaphore, 2);
assertEquals(2, results.size());
assertEquals(ImmutableList.of("MOVED:b/a", "CHANGED:b/a"), results);
ref.removeEventListener(listener);
}
}