summaryrefslogtreecommitdiffstats
path: root/base/android/javatests
diff options
context:
space:
mode:
authornileshagrawal@chromium.org <nileshagrawal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 21:35:34 +0000
committernileshagrawal@chromium.org <nileshagrawal@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-01 21:35:34 +0000
commit2afee1373c1233260f32bccb86483b53a3a280cc (patch)
tree5fb6229161a97bb75f576a6f13c9f45bcd57dea3 /base/android/javatests
parent644f4fba5a0fd2b13ef21e7f76e419ae3dc9db56 (diff)
downloadchromium_src-2afee1373c1233260f32bccb86483b53a3a280cc.zip
chromium_src-2afee1373c1233260f32bccb86483b53a3a280cc.tar.gz
chromium_src-2afee1373c1233260f32bccb86483b53a3a280cc.tar.bz2
Android: Add a java version of ObserverList.
Provides a safe container to maintain observer/listener lists which can be modified during iteration. This is heavily based on the C++ version. TBR=jam@chromium.org BUG= Review URL: https://codereview.chromium.org/12378004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@185595 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/android/javatests')
-rw-r--r--base/android/javatests/src/org/chromium/base/ObserverListTest.java180
1 files changed, 180 insertions, 0 deletions
diff --git a/base/android/javatests/src/org/chromium/base/ObserverListTest.java b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
new file mode 100644
index 0000000..10c898c
--- /dev/null
+++ b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
@@ -0,0 +1,180 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+
+import java.lang.Iterable;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Tests for (@link ObserverList}.
+ */
+public class ObserverListTest extends InstrumentationTestCase {
+ interface Observer {
+ void observe(int x);
+ }
+
+ private static class Foo implements Observer {
+ private final int mScalar;
+ private int mTotal = 0;
+
+ Foo(int scalar) {
+ mScalar = scalar;
+ }
+
+ @Override
+ public void observe(int x) {
+ mTotal += x * mScalar;
+ }
+ }
+
+ /**
+ * An observer which add a given Observer object to the list when observe is called.
+ */
+ private static class FooAdder implements Observer {
+ private final ObserverList<Observer> mList;
+ private final Observer mLucky;
+
+ FooAdder(ObserverList<Observer> list, Observer oblivious) {
+ mList = list;
+ mLucky = oblivious;
+ }
+
+ @Override
+ public void observe(int x) {
+ mList.addObserver(mLucky);
+ }
+ }
+
+ /**
+ * An observer which removes a given Observer object from the list when observe is called.
+ */
+ private static class FooRemover implements Observer {
+ private final ObserverList<Observer> mList;
+ private final Observer mDoomed;
+
+ FooRemover(ObserverList<Observer> list, Observer innocent) {
+ mList = list;
+ mDoomed = innocent;
+ }
+
+ @Override
+ public void observe(int x) {
+ mList.removeObserver(mDoomed);
+ }
+ }
+
+ private static <T> int getSizeOfIterable(Iterable<T> iterable) {
+ int num = 0;
+ for (T el : iterable)
+ num++;
+ return num;
+ }
+
+ @SmallTest
+ @Feature({"Android-AppBase"})
+ public void testRemoveWhileIteration() {
+ ObserverList<Observer> observerList = new ObserverList<Observer>();
+ Foo a = new Foo(1);
+ Foo b = new Foo(-1);
+ Foo c = new Foo(1);
+ Foo d = new Foo(-1);
+ Foo e = new Foo(-1);
+ FooRemover evil = new FooRemover(observerList, c);
+
+ observerList.addObserver(a);
+ observerList.addObserver(b);
+
+ for (Observer obs : observerList)
+ obs.observe(10);
+
+ // Removing an observer not in the list should do nothing.
+ observerList.removeObserver(e);
+
+ observerList.addObserver(evil);
+ observerList.addObserver(c);
+ observerList.addObserver(d);
+
+ for (Observer obs : observerList)
+ obs.observe(10);
+
+ // observe should be called twice on a.
+ assertEquals(20, a.mTotal);
+ // observe should be called twice on b.
+ assertEquals(-20, b.mTotal);
+ // evil removed c from the observerList before it got any callbacks.
+ assertEquals(0, c.mTotal);
+ // observe should be called once on d.
+ assertEquals(-10, d.mTotal);
+ // e was never added to the list, observe should not be called.
+ assertEquals(0, e.mTotal);
+ }
+
+ @SmallTest
+ @Feature({"Android-AppBase"})
+ public void testAddWhileIteration() {
+ ObserverList<Observer> observerList = new ObserverList<Observer>();
+ Foo a = new Foo(1);
+ Foo b = new Foo(-1);
+ Foo c = new Foo(1);
+ FooAdder evil = new FooAdder(observerList, c);
+
+ observerList.addObserver(evil);
+ observerList.addObserver(a);
+ observerList.addObserver(b);
+
+ for (Observer obs : observerList)
+ obs.observe(10);
+
+ assertTrue(observerList.hasObserver(c));
+ assertEquals(10, a.mTotal);
+ assertEquals(-10, b.mTotal);
+ assertEquals(0, c.mTotal);
+ }
+
+ @SmallTest
+ @Feature({"Android-AppBase"})
+ public void testIterator() {
+ ObserverList<Integer> observerList = new ObserverList<Integer>();
+ observerList.addObserver(5);
+ observerList.addObserver(10);
+ observerList.addObserver(15);
+ assertEquals(3, getSizeOfIterable(observerList));
+
+ observerList.removeObserver(10);
+ assertEquals(2, getSizeOfIterable(observerList));
+
+ Iterator<Integer> it = observerList.iterator();
+ assertTrue(it.hasNext());
+ assertTrue(5 == it.next());
+ assertTrue(it.hasNext());
+ assertTrue(15 == it.next());
+ assertFalse(it.hasNext());
+
+ boolean removeExceptionThrown = false;
+ try {
+ it.remove();
+ fail("Expecting UnsupportedOperationException to be thrown here.");
+ } catch (UnsupportedOperationException e) {
+ removeExceptionThrown = true;
+ }
+ assertTrue(removeExceptionThrown);
+ assertEquals(2, getSizeOfIterable(observerList));
+
+ boolean noElementExceptionThrown = false;
+ try {
+ it.next();
+ fail("Expecting NoSuchElementException to be thrown here.");
+ } catch (NoSuchElementException e) {
+ noElementExceptionThrown = true;
+ }
+ assertTrue(noElementExceptionThrown);
+ }
+}