/** Make sure that all events get fired to all listeners. */
  public void testVeryBasicChain() {
    SequenceDependenciesEventPublisher publisher = new SequenceDependenciesEventPublisher();
    SimpleSubjectListener a = new SimpleSubjectListener("A", publisher);
    SimpleSubjectListener b = new SimpleSubjectListener("B", publisher);
    SimpleSubjectListener c = new SimpleSubjectListener("C", publisher);

    a.setValue("apple");
    assertEquals("apple", a.getValue());
    assertEquals(null, b.getValue());
    assertEquals(null, c.getValue());

    a.addListener(b);
    a.setValue("banana");
    assertEquals("banana", a.getValue());
    assertEquals("[A:banana]", b.getValue());
    assertEquals(null, c.getValue());

    a.addListener(c);
    a.setValue("chocolate");
    assertEquals("chocolate", a.getValue());
    assertEquals("[A:chocolate]", b.getValue());
    assertEquals("[A:chocolate]", c.getValue());

    a.removeListener(b);
    a.setValue("ducks");
    assertEquals("ducks", a.getValue());
    assertEquals("[A:chocolate]", b.getValue());
    assertEquals("[A:ducks]", c.getValue());

    c.addListener(b);
    a.setValue("elephants");
    assertEquals("elephants", a.getValue());
    assertEquals("[C:[A:elephants]]", b.getValue());
    assertEquals("[A:elephants]", c.getValue());

    c.setValue("foxes");
    assertEquals("elephants", a.getValue());
    assertEquals("[C:foxes]", b.getValue());
    assertEquals("foxes", c.getValue());

    a.removeListener(c);
    a.setValue("gorillas");
    assertEquals("gorillas", a.getValue());
    assertEquals("[C:foxes]", b.getValue());
    assertEquals("foxes", c.getValue());

    a.addListener(c);
    a.setValue("horses");
    assertEquals("horses", a.getValue());
    assertEquals("[C:[A:horses]]", b.getValue());
    assertEquals("[A:horses]", c.getValue());
  }
  /**
   * Make sure that when the listener graph changes during an event, it gets processed only at the
   * conclusion of that event.
   */
  public void testRemovesAndAddsDuringEvent() {
    SequenceDependenciesEventPublisher publisher = new SequenceDependenciesEventPublisher();
    SimpleSubjectListener a = new SimpleSubjectListener("A", publisher);
    SimpleSubjectListener b = new SimpleSubjectListener("B", publisher);
    SimpleSubjectListener c = new SimpleSubjectListener("C", publisher);
    SimpleSubjectListener d = new SimpleSubjectListener("D", publisher);
    a.addListener(b);

    // add c as a listener to b, it shouldn't receive the first event
    b.setRunOnceRunnable(new AddListenerRunnable(b, c));
    a.setValue("Saskatchwan");
    assertEquals(1, b.getReceivedEvents().size());
    assertEquals(0, c.getReceivedEvents().size());

    a.setValue("Tiger-Cats");
    assertEquals(2, b.getReceivedEvents().size());
    assertEquals(1, c.getReceivedEvents().size());

    // remove c as a listener to b, it should still receive the event
    b.setRunOnceRunnable(new RemoveListenerRunnable(b, c));
    a.setValue("Blue Bombers");
    assertEquals(3, b.getReceivedEvents().size());
    assertEquals(2, c.getReceivedEvents().size());
    a.setValue("Stampeders");
    assertEquals(4, b.getReceivedEvents().size());
    assertEquals(2, c.getReceivedEvents().size());

    // add a completely unrelated listener b to do events for c and d
    a.addListener(c);
    b.setRunOnceRunnable(new AddListenerRunnable(c, d));
    a.setValue("Argonauts");
    assertEquals(3, c.getReceivedEvents().size());
    assertEquals(0, d.getReceivedEvents().size());

    a.setValue("Lions");
    assertEquals(4, c.getReceivedEvents().size());
    assertEquals(1, d.getReceivedEvents().size());

    // remove the unrelated listener b to do events for c and d
    b.setRunOnceRunnable(new RemoveListenerRunnable(c, d));
    a.setValue("Eskimos");
    assertEquals(5, c.getReceivedEvents().size());
    assertEquals(2, d.getReceivedEvents().size());

    a.setValue("Alouettes");
    assertEquals(6, c.getReceivedEvents().size());
    assertEquals(2, d.getReceivedEvents().size());
  }
  /** Make sure we throw an exception when attempting to remove something that's not a listener. */
  public void testUnknownRemoveThrowsException() {
    SequenceDependenciesEventPublisher publisher = new SequenceDependenciesEventPublisher();
    SimpleSubjectListener a = new SimpleSubjectListener("A", publisher);
    SimpleSubjectListener b = new SimpleSubjectListener("B", publisher);
    SimpleSubjectListener c = new SimpleSubjectListener("C", publisher);

    // add a listener
    a.addListener(b);
    try {
      a.removeListener(c);
      fail("No exception thrown when removing a non-existent listener");
    } catch (IllegalArgumentException e) {
      // expected
    }

    // remove the other listener, this shouldn't throw
    a.removeListener(b);
  }
 public void run() {
   subject.addListener(listener);
 }