/** * Copyright 2010 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 org.waveprotocol.wave.model.util; import junit.framework.Assert; import junit.framework.TestCase; import org.waveprotocol.wave.model.wave.ObservableMap; import org.waveprotocol.wave.model.wave.ObservableMapImpl; import java.util.Collections; import java.util.HashSet; import java.util.Queue; import java.util.Set; /** * Test case for {@link ObservableMapImpl}. * */ public final class ObservableMapImplTest extends TestCase { private static class MockListener<K, V> implements ObservableMap.Listener<K, V> { private final Queue<Pair<K, V>> added = CollectionUtils.createQueue(); private final Queue<Pair<K, V>> removed = CollectionUtils.createQueue(); private final ObservableMap.Listener<K, V> verifier = new ObservableMap.Listener<K, V>() { @Override public void onEntryAdded(K key, V value) { assertEquals(Pair.of(key, value), added.remove()); } @Override public void onEntryRemoved(K key, V value) { assertEquals(Pair.of(key, value), removed.remove()); } }; @Override public void onEntryAdded(K key, V value) { added.add(Pair.of(key, value)); } @Override public void onEntryRemoved(K key, V value) { removed.add(Pair.of(key, value)); } ObservableMap.Listener<K, V> verify() { return verifier; } void verifyNoMoreInteractions() { assertTrue(added.isEmpty()); assertTrue(removed.isEmpty()); } } private static final Object a = new Object(); private static final Object b = new Object(); private ObservableMapImpl<String, Object> target; private MockListener<String, Object> listener; @Override protected void setUp() { target = ObservableMapImpl.create(); listener = new MockListener<String, Object>(); } private static <T> void assertEquals(Set<T> expected, Iterable<T> actual) { Set<T> actualSet = new HashSet<T>(); for (T x : actual) { actualSet.add(x); } Assert.assertEquals(new HashSet<T>(expected), actualSet); } // // Basic structural tests. // public void testPutIsReturnedByGet() { target.put("a", a); assertEquals(a, target.get("a")); } public void testTwoPutsAreReturnedByTwoGets() { target.put("a", a); target.put("b", b); assertEquals(a, target.get("a")); assertEquals(b, target.get("b")); } public void testPutClobbers() { target.put("a", new Object()); target.put("a", a); assertEquals(a, target.get("a")); } public void testRemoveIsNotReturnedByGet() { target.put("a", a); target.remove("a"); assertNull(target.get("a")); } public void testTwoRemovesAreNotReturnedByTwoGets() { target.put("a", a); target.put("b", b); target.remove("a"); target.remove("b"); assertNull(target.get("a")); assertNull(target.get("b")); } public void testRemoveOnlyRemovesOne() { target.put("a", a); target.put("b", b); target.remove("a"); assertEquals(b, target.get("b")); } // // Keys // public void testKeyCollectionWithOneKey() { target.put("a", new Object()); assertEquals(Collections.singleton("a"), target.copyKeys()); } public void testKeyCollectionWithManyKeys() { target.put("a", new Object()); target.put("b", new Object()); target.put("c", new Object()); target.put("d", new Object()); assertEquals(CollectionUtils.newHashSet("a", "b", "c", "d"), target.copyKeys()); } public void testKeyCollectionWithManyKeysAfterMutations() { target.put("a", new Object()); target.put("b", new Object()); target.put("c", new Object()); target.put("d", new Object()); target.remove("c"); target.remove("d"); target.put("d", new Object()); assertEquals(CollectionUtils.newHashSet("a", "b", "d"), target.copyKeys()); } // // Events. // public void testSinglePutBroadcastsEvent() { target.addListener(listener); target.put("a", a); listener.verify().onEntryAdded("a", a); listener.verifyNoMoreInteractions(); } public void testTwoPutsBroadcastTwoEvents() { target.addListener(listener); target.put("a", a); target.put("b", b); listener.verify().onEntryAdded("a", a); listener.verify().onEntryAdded("b", b); listener.verifyNoMoreInteractions(); } public void testObserveAfterPutDoesNotBroadcastPriorEvent() { target.put("a", a); target.addListener(listener); target.put("b", b); listener.verify().onEntryAdded("b", b); listener.verifyNoMoreInteractions(); } public void testRemoveBroadcastsEvent() { target.addListener(listener); target.put("a", a); target.remove("a"); listener.verify().onEntryRemoved("a", a); } public void testClobberBroadcastsRemoveThenAdd() { target.put("x", a); target.addListener(listener); target.put("x", b); listener.verify().onEntryRemoved("x", a); listener.verify().onEntryAdded("x", b); listener.verifyNoMoreInteractions(); } }