1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.base;
7 import android.test.InstrumentationTestCase;
8 import android.test.suitebuilder.annotation.SmallTest;
10 import org.chromium.base.ObserverList;
11 import org.chromium.base.test.util.Feature;
13 import java.lang.Iterable;
14 import java.util.Iterator;
15 import java.util.NoSuchElementException;
18 * Tests for (@link ObserverList}.
20 public class ObserverListTest extends InstrumentationTestCase {
25 private static class Foo implements Observer {
26 private final int mScalar;
27 private int mTotal = 0;
34 public void observe(int x) {
35 mTotal += x * mScalar;
40 * An observer which add a given Observer object to the list when observe is called.
42 private static class FooAdder implements Observer {
43 private final ObserverList<Observer> mList;
44 private final Observer mLucky;
46 FooAdder(ObserverList<Observer> list, Observer oblivious) {
52 public void observe(int x) {
53 mList.addObserver(mLucky);
58 * An observer which removes a given Observer object from the list when observe is called.
60 private static class FooRemover implements Observer {
61 private final ObserverList<Observer> mList;
62 private final Observer mDoomed;
64 FooRemover(ObserverList<Observer> list, Observer innocent) {
70 public void observe(int x) {
71 mList.removeObserver(mDoomed);
75 private static <T> int getSizeOfIterable(Iterable<T> iterable) {
83 @Feature({"Android-AppBase"})
84 public void testRemoveWhileIteration() {
85 ObserverList<Observer> observerList = new ObserverList<Observer>();
91 FooRemover evil = new FooRemover(observerList, c);
93 observerList.addObserver(a);
94 observerList.addObserver(b);
96 for (Observer obs : observerList)
99 // Removing an observer not in the list should do nothing.
100 observerList.removeObserver(e);
102 observerList.addObserver(evil);
103 observerList.addObserver(c);
104 observerList.addObserver(d);
106 for (Observer obs : observerList)
109 // observe should be called twice on a.
110 assertEquals(20, a.mTotal);
111 // observe should be called twice on b.
112 assertEquals(-20, b.mTotal);
113 // evil removed c from the observerList before it got any callbacks.
114 assertEquals(0, c.mTotal);
115 // observe should be called once on d.
116 assertEquals(-10, d.mTotal);
117 // e was never added to the list, observe should not be called.
118 assertEquals(0, e.mTotal);
122 @Feature({"Android-AppBase"})
123 public void testAddWhileIteration() {
124 ObserverList<Observer> observerList = new ObserverList<Observer>();
128 FooAdder evil = new FooAdder(observerList, c);
130 observerList.addObserver(evil);
131 observerList.addObserver(a);
132 observerList.addObserver(b);
134 for (Observer obs : observerList)
137 assertTrue(observerList.hasObserver(c));
138 assertEquals(10, a.mTotal);
139 assertEquals(-10, b.mTotal);
140 assertEquals(0, c.mTotal);
144 @Feature({"Android-AppBase"})
145 public void testIterator() {
146 ObserverList<Integer> observerList = new ObserverList<Integer>();
147 observerList.addObserver(5);
148 observerList.addObserver(10);
149 observerList.addObserver(15);
150 assertEquals(3, getSizeOfIterable(observerList));
152 observerList.removeObserver(10);
153 assertEquals(2, getSizeOfIterable(observerList));
155 Iterator<Integer> it = observerList.iterator();
156 assertTrue(it.hasNext());
157 assertTrue(5 == it.next());
158 assertTrue(it.hasNext());
159 assertTrue(15 == it.next());
160 assertFalse(it.hasNext());
162 boolean removeExceptionThrown = false;
165 fail("Expecting UnsupportedOperationException to be thrown here.");
166 } catch (UnsupportedOperationException e) {
167 removeExceptionThrown = true;
169 assertTrue(removeExceptionThrown);
170 assertEquals(2, getSizeOfIterable(observerList));
172 boolean noElementExceptionThrown = false;
175 fail("Expecting NoSuchElementException to be thrown here.");
176 } catch (NoSuchElementException e) {
177 noElementExceptionThrown = true;
179 assertTrue(noElementExceptionThrown);
183 @Feature({"Android-AppBase"})
184 public void testRewindableIterator() {
185 ObserverList<Integer> observerList = new ObserverList<Integer>();
186 observerList.addObserver(5);
187 observerList.addObserver(10);
188 observerList.addObserver(15);
189 assertEquals(3, getSizeOfIterable(observerList));
191 ObserverList.RewindableIterator<Integer> it = observerList.rewindableIterator();
192 assertTrue(it.hasNext());
193 assertTrue(5 == it.next());
194 assertTrue(it.hasNext());
195 assertTrue(10 == it.next());
196 assertTrue(it.hasNext());
197 assertTrue(15 == it.next());
198 assertFalse(it.hasNext());
202 assertTrue(it.hasNext());
203 assertTrue(5 == it.next());
204 assertTrue(it.hasNext());
205 assertTrue(10 == it.next());
206 assertTrue(it.hasNext());
207 assertTrue(15 == it.next());
208 assertEquals(5, (int) observerList.mObservers.get(0));
209 observerList.removeObserver(5);
210 assertEquals(null, observerList.mObservers.get(0));
214 assertEquals(10, (int) observerList.mObservers.get(0));
215 assertTrue(it.hasNext());
216 assertTrue(10 == it.next());
217 assertTrue(it.hasNext());
218 assertTrue(15 == it.next());