| Index: base/android/javatests/src/org/chromium/base/ObserverListTest.java
|
| 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 0000000000000000000000000000000000000000..10c898c2a3a3c0f12600de205111bceb7b83940a
|
| --- /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);
|
| + }
|
| +}
|
|
|