Home | History | Annotate | Download | only in base
      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.
      4 
      5 package org.chromium.base;
      6 
      7 import android.test.InstrumentationTestCase;
      8 import android.test.suitebuilder.annotation.SmallTest;
      9 
     10 import org.chromium.base.test.util.Feature;
     11 
     12 import java.util.Iterator;
     13 import java.util.NoSuchElementException;
     14 
     15 /**
     16  * Tests for (@link ObserverList}.
     17  */
     18 public class ObserverListTest extends InstrumentationTestCase {
     19     interface Observer {
     20         void observe(int x);
     21     }
     22 
     23     private static class Foo implements Observer {
     24         private final int mScalar;
     25         private int mTotal = 0;
     26 
     27         Foo(int scalar) {
     28             mScalar = scalar;
     29         }
     30 
     31         @Override
     32         public void observe(int x) {
     33             mTotal += x * mScalar;
     34         }
     35     }
     36 
     37     /**
     38      * An observer which add a given Observer object to the list when observe is called.
     39      */
     40     private static class FooAdder implements Observer {
     41         private final ObserverList<Observer> mList;
     42         private final Observer mLucky;
     43 
     44         FooAdder(ObserverList<Observer> list, Observer oblivious) {
     45             mList = list;
     46             mLucky = oblivious;
     47         }
     48 
     49         @Override
     50         public void observe(int x) {
     51             mList.addObserver(mLucky);
     52         }
     53     }
     54 
     55     /**
     56      * An observer which removes a given Observer object from the list when observe is called.
     57      */
     58     private static class FooRemover implements Observer {
     59         private final ObserverList<Observer> mList;
     60         private final Observer mDoomed;
     61 
     62         FooRemover(ObserverList<Observer> list, Observer innocent) {
     63             mList = list;
     64             mDoomed = innocent;
     65         }
     66 
     67         @Override
     68         public void observe(int x) {
     69             mList.removeObserver(mDoomed);
     70         }
     71     }
     72 
     73     private static <T> int getSizeOfIterable(Iterable<T> iterable) {
     74         int num = 0;
     75         for (T el : iterable)
     76             num++;
     77         return num;
     78     }
     79 
     80     @SmallTest
     81     @Feature({"Android-AppBase"})
     82     public void testRemoveWhileIteration() {
     83         ObserverList<Observer> observerList = new ObserverList<Observer>();
     84         Foo a = new Foo(1);
     85         Foo b = new Foo(-1);
     86         Foo c = new Foo(1);
     87         Foo d = new Foo(-1);
     88         Foo e = new Foo(-1);
     89         FooRemover evil = new FooRemover(observerList, c);
     90 
     91         observerList.addObserver(a);
     92         observerList.addObserver(b);
     93 
     94         for (Observer obs : observerList)
     95             obs.observe(10);
     96 
     97         // Removing an observer not in the list should do nothing.
     98         observerList.removeObserver(e);
     99 
    100         observerList.addObserver(evil);
    101         observerList.addObserver(c);
    102         observerList.addObserver(d);
    103 
    104         for (Observer obs : observerList)
    105             obs.observe(10);
    106 
    107         // observe should be called twice on a.
    108         assertEquals(20, a.mTotal);
    109         // observe should be called twice on b.
    110         assertEquals(-20, b.mTotal);
    111         // evil removed c from the observerList before it got any callbacks.
    112         assertEquals(0, c.mTotal);
    113         // observe should be called once on d.
    114         assertEquals(-10, d.mTotal);
    115         // e was never added to the list, observe should not be called.
    116         assertEquals(0, e.mTotal);
    117     }
    118 
    119     @SmallTest
    120     @Feature({"Android-AppBase"})
    121     public void testAddWhileIteration() {
    122         ObserverList<Observer> observerList = new ObserverList<Observer>();
    123         Foo a = new Foo(1);
    124         Foo b = new Foo(-1);
    125         Foo c = new Foo(1);
    126         FooAdder evil = new FooAdder(observerList, c);
    127 
    128         observerList.addObserver(evil);
    129         observerList.addObserver(a);
    130         observerList.addObserver(b);
    131 
    132         for (Observer obs : observerList)
    133             obs.observe(10);
    134 
    135         assertTrue(observerList.hasObserver(c));
    136         assertEquals(10, a.mTotal);
    137         assertEquals(-10, b.mTotal);
    138         assertEquals(0, c.mTotal);
    139     }
    140 
    141     @SmallTest
    142     @Feature({"Android-AppBase"})
    143     public void testIterator() {
    144         ObserverList<Integer> observerList = new ObserverList<Integer>();
    145         observerList.addObserver(5);
    146         observerList.addObserver(10);
    147         observerList.addObserver(15);
    148         assertEquals(3, getSizeOfIterable(observerList));
    149 
    150         observerList.removeObserver(10);
    151         assertEquals(2, getSizeOfIterable(observerList));
    152 
    153         Iterator<Integer> it = observerList.iterator();
    154         assertTrue(it.hasNext());
    155         assertTrue(5 == it.next());
    156         assertTrue(it.hasNext());
    157         assertTrue(15 == it.next());
    158         assertFalse(it.hasNext());
    159 
    160         boolean removeExceptionThrown = false;
    161         try {
    162             it.remove();
    163             fail("Expecting UnsupportedOperationException to be thrown here.");
    164         } catch (UnsupportedOperationException e) {
    165             removeExceptionThrown = true;
    166         }
    167         assertTrue(removeExceptionThrown);
    168         assertEquals(2, getSizeOfIterable(observerList));
    169 
    170         boolean noElementExceptionThrown = false;
    171         try {
    172             it.next();
    173             fail("Expecting NoSuchElementException to be thrown here.");
    174         } catch (NoSuchElementException e) {
    175             noElementExceptionThrown = true;
    176         }
    177         assertTrue(noElementExceptionThrown);
    178     }
    179 
    180     @SmallTest
    181     @Feature({"Android-AppBase"})
    182     public void testRewindableIterator() {
    183         ObserverList<Integer> observerList = new ObserverList<Integer>();
    184         observerList.addObserver(5);
    185         observerList.addObserver(10);
    186         observerList.addObserver(15);
    187         assertEquals(3, getSizeOfIterable(observerList));
    188 
    189         ObserverList.RewindableIterator<Integer> it = observerList.rewindableIterator();
    190         assertTrue(it.hasNext());
    191         assertTrue(5 == it.next());
    192         assertTrue(it.hasNext());
    193         assertTrue(10 == it.next());
    194         assertTrue(it.hasNext());
    195         assertTrue(15 == it.next());
    196         assertFalse(it.hasNext());
    197 
    198         it.rewind();
    199 
    200         assertTrue(it.hasNext());
    201         assertTrue(5 == it.next());
    202         assertTrue(it.hasNext());
    203         assertTrue(10 == it.next());
    204         assertTrue(it.hasNext());
    205         assertTrue(15 == it.next());
    206         assertEquals(5, (int) observerList.mObservers.get(0));
    207         observerList.removeObserver(5);
    208         assertEquals(null, observerList.mObservers.get(0));
    209 
    210         it.rewind();
    211 
    212         assertEquals(10, (int) observerList.mObservers.get(0));
    213         assertTrue(it.hasNext());
    214         assertTrue(10 == it.next());
    215         assertTrue(it.hasNext());
    216         assertTrue(15 == it.next());
    217     }
    218 }
    219