[jbosscache-commits] JBoss Cache SVN: r6914 - in core/branches/flat/src: main/java/org/jboss/starobrno/commands/read and 3 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Mon Oct 13 12:03:46 EDT 2008


Author: manik.surtani at jboss.com
Date: 2008-10-13 12:03:46 -0400 (Mon, 13 Oct 2008)
New Revision: 6914

Added:
   core/branches/flat/src/test/java/org/jboss/starobrno/notifications/AsyncNotificationTest.java
   core/branches/flat/src/test/java/org/jboss/starobrno/notifications/CacheListenerTest.java
   core/branches/flat/src/test/java/org/jboss/starobrno/notifications/ConcurrentNotificationTest.java
   core/branches/flat/src/test/java/org/jboss/starobrno/notifications/EventLog.java
   core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifierAnnotationsTest.java
   core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifierTest.java
   core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifyNodeInvalidatedTest.java
Modified:
   core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactoryImpl.java
   core/branches/flat/src/main/java/org/jboss/starobrno/commands/read/GetKeyValueCommand.java
   core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/RemoveCommand.java
   core/branches/flat/src/main/java/org/jboss/starobrno/container/MVCCEntryCreator.java
Log:
Migrated notifications

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactoryImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactoryImpl.java	2008-10-13 14:50:38 UTC (rev 6913)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/CommandsFactoryImpl.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -64,7 +64,7 @@
 
    public RemoveCommand buildRemoveCommand(Object key, Object value)
    {
-      return new RemoveCommand(key, value);
+      return new RemoveCommand(key, value, notifier);
    }
 
    public ReplaceCommand buildReplaceCommand(Object key, Object oldValue, Object newValue)
@@ -134,6 +134,7 @@
          case RemoveCommand.METHOD_ID:
          {
             RemoveCommand c = new RemoveCommand();
+            c.init(notifier);
             command = c;
             break;
          }

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/read/GetKeyValueCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/read/GetKeyValueCommand.java	2008-10-13 14:50:38 UTC (rev 6913)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/read/GetKeyValueCommand.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -69,11 +69,10 @@
          if (trace) log.trace("Entry has been deleted and is of type " + entry.getClass().getSimpleName());
          return null;
       }
-      // TODO - notifier stuff
-      // notifier.notifyNodeVisited(fqn, true, ctx);
+      notifier.notifyCacheEntryVisited(key, true, ctx);
       Object result = entry.getValue();
       if (trace) log.trace("Found value " + result);
-//      if (sendNodeEvent) notifier.notifyNodeVisited(fqn, false, ctx);
+      notifier.notifyCacheEntryVisited(key, false, ctx);
       return result;
    }
 

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/RemoveCommand.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/RemoveCommand.java	2008-10-13 14:50:38 UTC (rev 6913)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/commands/write/RemoveCommand.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -25,6 +25,7 @@
 import org.jboss.starobrno.commands.read.AbstractDataCommand;
 import org.jboss.starobrno.container.MVCCEntry;
 import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.notifications.Notifier;
 
 
 /**
@@ -33,15 +34,22 @@
 public class RemoveCommand extends AbstractDataCommand
 {
    public static final byte METHOD_ID = 6;
+   private Notifier notifier;
 
    protected Object value;
 
-   public RemoveCommand(Object key, Object value)
+   public RemoveCommand(Object key, Object value, Notifier notifier)
    {
       super(key);
       this.value = value;
+      this.notifier = notifier;
    }
 
+   public void init(Notifier notifier)
+   {
+      this.notifier = notifier;
+   }
+
    public RemoveCommand()
    {
    }
@@ -55,9 +63,12 @@
    {
       MVCCEntry e = ctx.lookupEntry(key);
       if (e == null || e.isNullEntry()) return null;
+      notifier.notifyCacheEntryRemoved(key, true, ctx);
       e.setDeleted(true);
       e.setValid(false);
+      notifier.notifyCacheEntryRemoved(key, false, ctx);
       return e.getValue();
+
    }
 
    public byte getCommandId()

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/container/MVCCEntryCreator.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/container/MVCCEntryCreator.java	2008-10-13 14:50:38 UTC (rev 6913)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/container/MVCCEntryCreator.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -30,6 +30,7 @@
 import org.jboss.starobrno.factories.annotations.Inject;
 import org.jboss.starobrno.factories.annotations.Start;
 import org.jboss.starobrno.lock.LockManager;
+import org.jboss.starobrno.notifications.Notifier;
 
 /**
  * Wraps mvcc entries.
@@ -45,18 +46,20 @@
    Configuration configuration;
    long defaultLockAcquisitionTimeout;
    EntryFactory entryFactory;
+   Notifier notifier;
 
    private static final Log log = LogFactory.getLog(MVCCEntryCreator.class);
    private static final boolean trace = log.isTraceEnabled();
 
 
    @Inject
-   public void injectDependencies(DataContainer dataContainer, LockManager lockManager, Configuration configuration, EntryFactory entryFactory)
+   public void injectDependencies(DataContainer dataContainer, LockManager lockManager, Configuration configuration, EntryFactory entryFactory, Notifier notifier)
    {
       this.container = dataContainer;
       this.configuration = configuration;
       this.lockManager = lockManager;
       this.entryFactory = entryFactory;
+      this.notifier = notifier;
    }
 
    @Start
@@ -135,13 +138,16 @@
          }
          else if (createIfAbsent) // else, do we need to create one?
          {
+            // this is the *only* point where new entries can be created!!
             if (trace) log.trace("Creating new entry.");
             // now to lock and create the node.  Lock first to prevent concurrent creation!
             acquireLock(ctx, key);
+            notifier.notifyCacheEntryCreated(key, true, ctx);
             mvccEntry = entryFactory.createWrappedEntry(key, value, true);
             mvccEntry.setCreated(true);
             ctx.putLookedUpEntry(key, mvccEntry);
             mvccEntry.copyForUpdate(container, writeSkewCheck);
+            notifier.notifyCacheEntryCreated(key, false, ctx);
          }
       }
 

Added: core/branches/flat/src/test/java/org/jboss/starobrno/notifications/AsyncNotificationTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/notifications/AsyncNotificationTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/notifications/AsyncNotificationTest.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -0,0 +1,88 @@
+package org.jboss.starobrno.notifications;
+
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.notifications.annotation.CacheEntryCreated;
+import org.jboss.starobrno.notifications.annotation.CacheListener;
+import org.jboss.starobrno.notifications.event.CacheEntryCreatedEvent;
+import org.jboss.starobrno.util.TestingUtil;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+ at Test(groups = "functional")
+public class AsyncNotificationTest
+{
+   public void testAsyncNotification() throws InterruptedException
+   {
+      Cache<String, String> c = null;
+      try
+      {
+         c = new DefaultCacheFactory<String, String>().createCache();
+         CountDownLatch latch = new CountDownLatch(2);
+         AbstractListener syncListener = new Listener(latch);
+         AbstractListener asyncListener = new AsyncListener(latch);
+         c.addCacheListener(syncListener);
+         c.addCacheListener(asyncListener);
+         c.put("k", "v");
+         assert latch.await(30, TimeUnit.SECONDS) : "No notifications in 30 secs!";
+         assert syncListener.caller == Thread.currentThread();
+         assert asyncListener.caller != Thread.currentThread();
+      }
+      finally
+      {
+         TestingUtil.killCaches(c);
+      }
+   }
+
+   public abstract static class AbstractListener
+   {
+      Thread caller;
+      CountDownLatch latch;
+
+      protected AbstractListener(CountDownLatch latch)
+      {
+         this.latch = latch;
+      }
+   }
+
+   @CacheListener(sync = true)
+   public static class Listener extends AbstractListener
+   {
+      public Listener(CountDownLatch latch)
+      {
+         super(latch);
+      }
+
+      @CacheEntryCreated
+      public void handle(CacheEntryCreatedEvent e)
+      {
+         if (e.isPre())
+         {
+            caller = Thread.currentThread();
+            latch.countDown();
+         }
+      }
+   }
+
+   @CacheListener(sync = false)
+   public static class AsyncListener extends AbstractListener
+   {
+      public AsyncListener(CountDownLatch latch)
+      {
+         super(latch);
+      }
+
+      @CacheEntryCreated
+      public void handle(CacheEntryCreatedEvent e)
+      {
+         if (e.isPre())
+         {
+            caller = Thread.currentThread();
+            latch.countDown();
+         }
+      }
+   }
+
+}

Added: core/branches/flat/src/test/java/org/jboss/starobrno/notifications/CacheListenerTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/notifications/CacheListenerTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/notifications/CacheListenerTest.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -0,0 +1,388 @@
+package org.jboss.starobrno.notifications;
+
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.lock.IsolationLevel;
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.notifications.event.Event;
+import static org.jboss.starobrno.notifications.event.Event.Type.*;
+import org.jboss.starobrno.notifications.event.EventImpl;
+import org.jboss.starobrno.util.TestingUtil;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Note that this is significantly different from the old <b>TreeCacheListenerTest</b> of the JBoss Cache 1.x series, and
+ * exercises the new CacheListener annotation.
+ *
+ * @since 2.0.0
+ */
+ at Test(groups = "functional")
+public class CacheListenerTest
+{
+   private Cache<Object, Object> cache;
+   private TransactionManager tm;
+   private EventLog eventLog = new EventLog();
+   private Object key = "key";
+
+   @BeforeMethod(alwaysRun = true)
+   public void setUp() throws Exception
+   {
+      Configuration c = new Configuration();
+      c.setCacheMode(Configuration.CacheMode.LOCAL);
+      c.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
+      c.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
+      cache = new DefaultCacheFactory<Object, Object>().createCache(c);
+      tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+      eventLog.events.clear();
+      cache.addCacheListener(eventLog);
+   }
+
+   @AfterMethod(alwaysRun = true)
+   public void tearDown() throws Exception
+   {
+      TestingUtil.killCaches(cache);
+   }
+
+   // simple tests first
+
+   public void testCreation() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      cache.put(key, "value");
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      assertEquals(expected, eventLog.events);
+      assertEquals("value", cache.get(key));
+   }
+
+   public void testOnlyModification() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      cache.put(key, "value");
+      Map<Object, Object> oldData = new HashMap<Object, Object>();
+      oldData.put(key, "value");
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      cache.put(key, "value2");
+      Map<Object, Object> newData = new HashMap<Object, Object>();
+      newData.put(key, "value2");
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+
+      assertEquals(expected.size(), eventLog.events.size());
+      assertEquals(expected, eventLog.events);
+   }
+
+   public void testOnlyRemoval() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      cache.put(key, "value");
+      Map<Object, Object> oldData = new HashMap<Object, Object>();
+      oldData.put(key, "value");
+
+      assertEquals("value", cache.get(key));
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      cache.remove(key);
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_REMOVED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_REMOVED));
+
+      assertEquals(expected, eventLog.events);
+
+      // test that the node has in fact been removed.
+      assertNull("Should be null", cache.get(key));
+   }
+
+   public void testNonexistentRemove() throws Exception
+   {
+      cache.remove("/does/not/exist");
+      List<Event> expected = new ArrayList<Event>();
+      assertEquals(expected, eventLog.events);
+   }
+
+   public void testRemoveData() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      cache.put(key, "value");
+      cache.put(key + "2", "value2");
+      Map<Object, Object> oldData = new HashMap<Object, Object>();
+      oldData.put(key, "value");
+      oldData.put(key + "2", "value2");
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      cache.remove(key + "2");
+      Map<Object, Object> removedData = new HashMap<Object, Object>();
+      removedData.put("key2", "value2");
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+
+      expected.add(new EventImpl(true, cache, key + "2", null, true, null, false, null, CACHE_ENTRY_REMOVED));
+      expected.add(new EventImpl(false, cache, key + "2", null, true, null, false, null, CACHE_ENTRY_REMOVED));
+
+      assertEquals(expected, eventLog.events);
+   }
+
+   public void testPutMap() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      String key2 = "key2";
+      Map<Object, Object> oldData = new HashMap<Object, Object>();
+      oldData.put(key, "value");
+      oldData.put(key2, "value2");
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      cache.putAll(oldData);
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(true, cache, key2, null, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(false, cache, key2, null, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(true, cache, key2, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(false, cache, key2, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+
+      assertEquals(expected, eventLog.events);
+   }
+
+   public void testPutKeyVal() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      cache.put(key, "value");
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_MODIFIED));
+
+      assertEquals(expected, eventLog.events);
+   }
+
+   public void testVisit() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      String key2 = "key2";
+      Map<Object, String> m = new HashMap<Object, String>();
+      m.put(key, "value");
+      m.put(key2, "value");
+      cache.putAll(m);
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      cache.get(key);
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(true, cache, key, null, true, null, false, null, CACHE_ENTRY_VISITED));
+      expected.add(new EventImpl(false, cache, key, null, true, null, false, null, CACHE_ENTRY_VISITED));
+
+      assertEquals(expected, eventLog.events);
+   }
+
+   // -- now the transactional ones
+
+   public void testTxNonexistentRemove() throws Exception
+   {
+      tm.begin();
+      Transaction tx = tm.getTransaction();
+      cache.remove("/does/not/exist");
+      tm.commit();
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+      expected.add(new EventImpl(false, cache, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+      assertEquals(expected, eventLog.events);
+   }
+
+   public void testTxCreationCommit() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      tm.begin();
+      Transaction tx = tm.getTransaction();
+      cache.put(key, "value");
+      //expected
+      Map<Object, Object> data = new HashMap<Object, Object>();
+      data.put(key, "value");
+      List<Event> expected = new ArrayList<Event>();
+
+      expected.add(new EventImpl(false, cache, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+      expected.add(new EventImpl(true, cache, key, tx, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(false, cache, key, tx, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(true, cache, key, tx, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(false, cache, key, tx, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      assertEquals(expected, eventLog.events);
+      tm.commit();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+      assertEquals(expected, eventLog.events);
+      assertEquals("value", cache.get(key));
+   }
+
+   public void testTxCreationRollback() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      tm.begin();
+      Transaction tx = tm.getTransaction();
+      cache.put(key, "value");
+      //expected
+      Map<Object, Object> data = new HashMap<Object, Object>();
+      data.put(key, "value");
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+      expected.add(new EventImpl(true, cache, key, tx, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(false, cache, key, tx, true, null, false, null, CACHE_ENTRY_CREATED));
+      expected.add(new EventImpl(true, cache, key, tx, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(false, cache, key, tx, true, null, false, null, CACHE_ENTRY_MODIFIED));
+
+      assertEquals(expected, eventLog.events);
+      tm.rollback();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, false, null, TRANSACTION_COMPLETED));
+      assertEquals(expected, eventLog.events);
+   }
+
+   public void testTxOnlyModification() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      cache.put(key, "value");
+      Map<Object, Object> oldData = new HashMap<Object, Object>();
+      oldData.put(key, "value");
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      tm.begin();
+      Transaction tx = tm.getTransaction();
+      cache.put(key, "value2");
+      Map<Object, Object> newData = new HashMap<Object, Object>();
+      newData.put(key, "value2");
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+      expected.add(new EventImpl(true, cache, key, tx, true, null, false, null, CACHE_ENTRY_MODIFIED));
+      expected.add(new EventImpl(false, cache, key, tx, true, null, false, null, CACHE_ENTRY_MODIFIED));
+
+      assertEquals(expected, eventLog.events);
+      tm.commit();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+      assertEquals(expected, eventLog.events);
+   }
+
+   public void testTxOnlyRemoval() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      cache.put(key, "value");
+      Map<Object, Object> oldData = new HashMap<Object, Object>();
+      oldData.put(key, "value");
+
+      assertEquals("value", cache.get(key));
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      tm.begin();
+      Transaction tx = tm.getTransaction();
+      cache.remove(key);
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+
+      expected.add(new EventImpl(false, cache, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+      expected.add(new EventImpl(true, cache, key, tx, true, null, false, null, CACHE_ENTRY_REMOVED));
+      expected.add(new EventImpl(false, cache, key, tx, true, null, false, null, CACHE_ENTRY_REMOVED));
+
+      assertEquals(expected, eventLog.events);
+      tm.commit();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+      assertEquals(expected, eventLog.events);
+      // test that the node has in fact been removed.
+      assertNull("Should be null", cache.get(key));
+   }
+
+   public void testTxRemoveData() throws Exception
+   {
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+      cache.put(key, "value");
+      cache.put(key + "2", "value2");
+      Map<Object, Object> oldData = new HashMap<Object, Object>();
+      oldData.put(key, "value");
+      oldData.put(key + "2", "value2");
+
+      // clear Event log
+      eventLog.events.clear();
+      assertEquals("Event log should be empty", Collections.emptyList(), eventLog.events);
+
+      // modify existing node
+      tm.begin();
+      Transaction tx = tm.getTransaction();
+      cache.remove("key2");
+      Map<Object, Object> removedData = new HashMap<Object, Object>();
+      removedData.put(key + "2", "value2");
+
+      //expected
+      List<Event> expected = new ArrayList<Event>();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, false, null, TRANSACTION_REGISTERED));
+      expected.add(new EventImpl(true, cache, key + "2", tx, true, null, false, null, CACHE_ENTRY_REMOVED));
+      expected.add(new EventImpl(false, cache, key + "2", tx, true, null, false, null, CACHE_ENTRY_REMOVED));
+
+      tm.commit();
+      expected.add(new EventImpl(false, cache, null, tx, true, null, true, null, TRANSACTION_COMPLETED));
+      assertEquals(expected, eventLog.events);
+
+      assertEquals(expected, eventLog.events);
+   }
+}

Added: core/branches/flat/src/test/java/org/jboss/starobrno/notifications/ConcurrentNotificationTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/notifications/ConcurrentNotificationTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/notifications/ConcurrentNotificationTest.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -0,0 +1,132 @@
+package org.jboss.starobrno.notifications;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheFactory;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.notifications.annotation.CacheEntryCreated;
+import org.jboss.starobrno.notifications.annotation.CacheEntryModified;
+import org.jboss.starobrno.notifications.annotation.CacheEntryRemoved;
+import org.jboss.starobrno.notifications.annotation.CacheEntryVisited;
+import org.jboss.starobrno.notifications.annotation.CacheListener;
+import org.jboss.starobrno.notifications.event.Event;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author <a href="mailto:manik at jboss.org">Manik Surtani</a>
+ * @since 2.0.0
+ */
+ at Test(groups = {"functional"})
+public class ConcurrentNotificationTest
+{
+   private Cache<String, String> cache;
+   private Listener listener;
+   private static final Log log = LogFactory.getLog(ConcurrentNotificationTest.class);
+
+   @BeforeMethod(alwaysRun = true)
+   public void setUp()
+   {
+      CacheFactory<String, String> instance = new DefaultCacheFactory<String, String>();
+      cache = instance.createCache();
+      listener = new Listener();
+      cache.addCacheListener(listener);
+   }
+
+   @AfterMethod(alwaysRun = true)
+   public void tearDown()
+   {
+      cache.stop();
+   }
+
+   public void testThreads() throws Exception
+   {
+      Thread workers[] = new Thread[20];
+      final List<Exception> exceptions = new LinkedList<Exception>();
+      final int loops = 100;
+      final CountDownLatch latch = new CountDownLatch(1);
+
+      for (int i = 0; i < workers.length; i++)
+      {
+         workers[i] = new Thread()
+         {
+            public void run()
+            {
+               try
+               {
+                  latch.await();
+               }
+               catch (InterruptedException e)
+               {
+               }
+
+               for (int j = 0; j < loops; j++)
+               {
+                  try
+                  {
+                     cache.put("key", "value");
+                  }
+                  catch (Exception e)
+                  {
+                     log.error("Exception doing put in loop " + j, e);
+                     exceptions.add(new Exception("Caused on thread " + getName() + " in loop " + j + " when doing a put()", e));
+                  }
+
+                  try
+                  {
+                     cache.remove("key");
+                  }
+                  catch (Exception e)
+                  {
+                     log.error("Exception doing remove in loop " + j, e);
+                     exceptions.add(new Exception("Caused on thread " + getName() + " in loop " + j + " when doing a remove()", e));
+                  }
+
+                  try
+                  {
+                     cache.get("key");
+                  }
+                  catch (Exception e)
+                  {
+                     log.error("Exception doing get in loop " + j, e);
+                     exceptions.add(new Exception("Caused on thread " + getName() + " in loop " + j + " when doing a get()", e));
+                  }
+               }
+            }
+         };
+
+         workers[i].start();
+      }
+
+      latch.countDown();
+
+      for (Thread t : workers)
+         t.join();
+
+      for (Exception e : exceptions)
+         throw e;
+   }
+
+   @CacheListener
+   public class Listener
+   {
+      private AtomicInteger counter = new AtomicInteger(0);
+
+      @CacheEntryModified
+      @CacheEntryRemoved
+      @CacheEntryVisited
+      @CacheEntryCreated
+      public void catchEvent(Event e)
+      {
+         if (e.isPre())
+            counter.getAndIncrement();
+      }
+   }
+}

Added: core/branches/flat/src/test/java/org/jboss/starobrno/notifications/EventLog.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/notifications/EventLog.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/notifications/EventLog.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -0,0 +1,56 @@
+package org.jboss.starobrno.notifications;
+
+import org.jboss.starobrno.notifications.annotation.CacheEntryActivated;
+import org.jboss.starobrno.notifications.annotation.CacheEntryCreated;
+import org.jboss.starobrno.notifications.annotation.CacheEntryEvicted;
+import org.jboss.starobrno.notifications.annotation.CacheEntryInvalidated;
+import org.jboss.starobrno.notifications.annotation.CacheEntryModified;
+import org.jboss.starobrno.notifications.annotation.CacheEntryPassivated;
+import org.jboss.starobrno.notifications.annotation.CacheEntryRemoved;
+import org.jboss.starobrno.notifications.annotation.CacheEntryVisited;
+import org.jboss.starobrno.notifications.annotation.CacheListener;
+import org.jboss.starobrno.notifications.annotation.TransactionCompleted;
+import org.jboss.starobrno.notifications.annotation.TransactionRegistered;
+import org.jboss.starobrno.notifications.event.Event;
+import org.jboss.starobrno.notifications.event.EventImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+ at CacheListener
+public class EventLog
+{
+   public final List<Event> events = new ArrayList<Event>();
+
+   @CacheEntryCreated
+   @CacheEntryRemoved
+   @CacheEntryModified
+   @CacheEntryVisited
+   @TransactionCompleted
+   @TransactionRegistered
+   @CacheEntryEvicted
+   @CacheEntryPassivated
+   @CacheEntryActivated
+   @CacheEntryInvalidated
+   public void callback(Event e)
+   {
+      events.add(e);
+   }
+
+   public String toString()
+   {
+      return "EventLog{" +
+            "events=" + events +
+            '}';
+   }
+
+   /**
+    * Done when we don't have a Transaction reference to compare with, e.g., when using implicit transactions in
+    * opt locking.
+    */
+   public void scrubImplicitTransactions()
+   {
+      for (Event e : events) ((EventImpl) e).setTransaction(null);
+   }
+}
\ No newline at end of file

Added: core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifierAnnotationsTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifierAnnotationsTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifierAnnotationsTest.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -0,0 +1,359 @@
+package org.jboss.starobrno.notifications;
+
+import static org.easymock.EasyMock.createNiceMock;
+import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.notifications.annotation.CacheEntryCreated;
+import org.jboss.starobrno.notifications.annotation.CacheListener;
+import org.jboss.starobrno.notifications.annotation.CacheStarted;
+import org.jboss.starobrno.notifications.annotation.CacheStopped;
+import org.jboss.starobrno.notifications.event.CacheEntryCreatedEvent;
+import org.jboss.starobrno.notifications.event.Event;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+/**
+ * Tests both correct and incorrect annotations for listeners
+ *
+ * @author <a href="mailto:manik at jboss.org">Manik Surtani</a>
+ * @since 2.0.0
+ */
+ at Test(groups = {"functional"})
+public class NotifierAnnotationsTest
+{
+   private NotifierImpl n;
+
+   @BeforeMethod(alwaysRun = true)
+   public void setUp()
+   {
+      n = new NotifierImpl();
+      n.injectDependencies(createNiceMock(CacheSPI.class), new Configuration());
+      n.start();
+   }
+
+   @AfterMethod
+   public void tearDown()
+   {
+      n.stop();
+      n.destroy();
+   }
+
+   public void testControl()
+   {
+      Object l = new TestControlListener();
+      n.addCacheListener(l);
+      assertEquals(1, n.getCacheListeners().size());
+   }
+
+   public void testCacheListenerNoMethods()
+   {
+      Object l = new TestCacheListenerNoMethodsListener();
+      n.addCacheListener(l);
+      assertEquals("Hello", l.toString());
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty()); // since the valid listener has no methods to listen
+   }
+
+   public void testNonAnnotatedListener()
+   {
+      Object l = new TestNonAnnotatedListener();
+      try
+      {
+         n.addCacheListener(l);
+         fail("Should not accept an un-annotated cache listener");
+      }
+      catch (IncorrectCacheListenerException icle)
+      {
+         // expected
+      }
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty());
+   }
+
+   public void testNonPublicListener()
+   {
+      Object l = new TestNonPublicListener();
+      try
+      {
+         n.addCacheListener(l);
+         fail("Should not accept a private callback class");
+      }
+      catch (IncorrectCacheListenerException icle)
+      {
+         // expected
+      }
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty());
+   }
+
+   public void testNonPublicListenerMethod()
+   {
+      Object l = new TestNonPublicListenerMethodListener();
+      n.addCacheListener(l);
+
+      // should not fail, should just not register anything
+
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty());
+   }
+
+   public void testNonVoidReturnTypeMethod()
+   {
+      Object l = new TestNonVoidReturnTypeMethodListener();
+      try
+      {
+         n.addCacheListener(l);
+         fail("Should not accept a listener method with a return type");
+      }
+      catch (IncorrectCacheListenerException icle)
+      {
+         // expected
+      }
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty());
+   }
+
+   public void testIncorrectMethodSignature1()
+   {
+      Object l = new TestIncorrectMethodSignature1Listener();
+      try
+      {
+         n.addCacheListener(l);
+         fail("Should not accept a cache listener with a bad method signature");
+      }
+      catch (IncorrectCacheListenerException icle)
+      {
+         // expected
+      }
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty());
+   }
+
+   public void testIncorrectMethodSignature2()
+   {
+      Object l = new TestIncorrectMethodSignature2Listener();
+      try
+      {
+         n.addCacheListener(l);
+         fail("Should not accept a cache listener with a bad method signature");
+      }
+      catch (IncorrectCacheListenerException icle)
+      {
+         // expected
+      }
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty());
+   }
+
+   public void testIncorrectMethodSignature3()
+   {
+      Object l = new TestIncorrectMethodSignature3Listener();
+      try
+      {
+         n.addCacheListener(l);
+         fail("Should not accept a cache listener with a bad method signature");
+      }
+      catch (IncorrectCacheListenerException icle)
+      {
+         // expected
+      }
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty());
+   }
+
+   public void testUnassignableMethodSignature()
+   {
+      Object l = new TestUnassignableMethodSignatureListener();
+      try
+      {
+         n.addCacheListener(l);
+         fail("Should not accept a cache listener with a bad method signature");
+      }
+      catch (IncorrectCacheListenerException icle)
+      {
+         // expected
+      }
+      assertTrue("No listeners should be registered.", n.getCacheListeners().isEmpty());
+   }
+
+   public void testPartlyUnassignableMethodSignature()
+   {
+      Object l = new TestPartlyUnassignableMethodSignatureListener();
+      try
+      {
+         n.addCacheListener(l);
+         fail("Should not accept a cache listener with a bad method signature");
+      }
+      catch (IncorrectCacheListenerException icle)
+      {
+         // expected
+      }
+   }
+
+   public void testMultipleMethods()
+   {
+      Object l = new TestMultipleMethodsListener();
+      n.addCacheListener(l);
+      List invocations = n.cacheStartedListeners;
+      assertEquals(1, invocations.size());
+      invocations = n.cacheStoppedListeners;
+      assertEquals(1, invocations.size());
+      assertEquals(1, n.getCacheListeners().size());
+   }
+
+   public void testMultipleAnnotationsOneMethod()
+   {
+      Object l = new TestMultipleAnnotationsOneMethodListener();
+      n.addCacheListener(l);
+      List invocations = n.cacheStartedListeners;
+      assertEquals(1, invocations.size());
+      invocations = n.cacheStoppedListeners;
+      assertEquals(1, invocations.size());
+      assertEquals(1, n.getCacheListeners().size());
+   }
+
+   public void testMultipleMethodsOneAnnotation()
+   {
+      Object l = new TestMultipleMethodsOneAnnotationListener();
+      n.addCacheListener(l);
+      List invocations = n.cacheStartedListeners;
+      assertEquals(2, invocations.size());
+      assertEquals(1, n.getCacheListeners().size());
+   }
+
+   @CacheListener
+   public class TestControlListener
+   {
+      @CacheStarted
+      @CacheStopped
+      public void callback(Event e)
+      {
+         System.out.println("Hello");
+      }
+   }
+
+   @CacheListener
+   public class TestCacheListenerNoMethodsListener
+   {
+      public String toString()
+      {
+         return "Hello";
+      }
+   }
+
+   public class TestNonAnnotatedListener
+   {
+      public String toString()
+      {
+         return "Hello";
+      }
+   }
+
+   @CacheListener
+   protected class TestNonPublicListener
+   {
+      @CacheStarted
+      public void callback()
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestNonPublicListenerMethodListener
+   {
+      @CacheStarted
+      protected void callback(Event e)
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestNonVoidReturnTypeMethodListener
+   {
+      @CacheStarted
+      public String callback(Event e)
+      {
+         return "Hello";
+      }
+   }
+
+   @CacheListener
+   public class TestIncorrectMethodSignature1Listener
+   {
+      @CacheStarted
+      public void callback()
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestIncorrectMethodSignature2Listener
+   {
+      @CacheStarted
+      public void callback(Event e, String s)
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestIncorrectMethodSignature3Listener
+   {
+      @CacheStarted
+      public void callback(Event e, String... s)
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestUnassignableMethodSignatureListener
+   {
+      @CacheStarted
+      public void callback(CacheEntryCreated nme)
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestPartlyUnassignableMethodSignatureListener
+   {
+      @CacheStarted
+      @CacheEntryCreated
+      public void callback(CacheEntryCreatedEvent nme) // sig valid for NodeMoved but not CacheStarted
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestMultipleMethodsListener
+   {
+      @CacheStarted
+      public void callback1(Event e)
+      {
+      }
+
+      @CacheStopped
+      public void callback2(Event e)
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestMultipleAnnotationsOneMethodListener
+   {
+      @CacheStopped
+      @CacheStarted
+      public void callback(Event nme)
+      {
+      }
+   }
+
+   @CacheListener
+   public class TestMultipleMethodsOneAnnotationListener
+   {
+      @CacheStarted
+      public void callback1(Event e)
+      {
+      }
+
+      @CacheStarted
+      public void callback2(Event e)
+      {
+      }
+   }
+}

Added: core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifierTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifierTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifierTest.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -0,0 +1,290 @@
+package org.jboss.starobrno.notifications;
+
+import static org.easymock.EasyMock.*;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.buddyreplication.BuddyGroup;
+import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.context.InvocationContextImpl;
+import org.jboss.starobrno.notifications.annotation.*;
+import org.jboss.starobrno.notifications.event.*;
+import org.jgroups.View;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.transaction.Transaction;
+
+/**
+ * Tester class for {@link org.jboss.cache.notifications.NotifierImpl}.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 2.2
+ */
+ at Test(groups = "unit")
+public class NotifierTest
+{
+   private NotifierImpl notifier;
+   private InvocationContext ctx;
+   private AllEventsListener allEventsListener;
+   private Fqn fqn = Fqn.fromString("/a/b/c");
+
+   @BeforeMethod
+   public void setUp()
+   {
+      notifier = new NotifierImpl();
+      CacheSPI cacheSPI = createNiceMock(CacheSPI.class);
+      expect(cacheSPI.getInvocationContext()).andStubReturn(new InvocationContextImpl());
+      replay(cacheSPI);
+      notifier.injectDependencies(cacheSPI, new Configuration());
+      notifier.start();
+      ctx = new InvocationContextImpl();
+      allEventsListener = new AllEventsListener();
+      notifier.addCacheListener(allEventsListener);
+   }
+
+   @AfterMethod
+   public void tearDown()
+   {
+      notifier.stop();
+      notifier.destroy();
+   }
+
+   public void testNotifyNodeCreated()
+   {
+      assert allEventsListener.nodeCreatedEvent == null;
+      notifier.notifyCacheEntryCreated("K", true, ctx);
+      assert allEventsListener.nodeCreatedEvent != null;
+      assert allEventsListener.nodeCreatedEvent.getType() == Event.Type.CACHE_ENTRY_CREATED;
+   }
+
+
+   public void testShouldNotifyOnNodeModified()
+   {
+      assert notifier.shouldNotifyOnNodeModified();
+      notifier.destroy();
+      assert !notifier.shouldNotifyOnNodeModified();
+   }
+
+   public void testNotifyNodeModified()
+   {
+      assert allEventsListener.nodeModifiedEvent == null;
+      notifier.notifyCacheEntryModified("key", true, ctx);
+      assert allEventsListener.nodeModifiedEvent != null;
+      assert allEventsListener.nodeModifiedEvent.getKey().equals("key");
+   }
+
+   public void testNotifyNodeRemoved()
+   {
+      assert allEventsListener.nodeRemoveEvent == null;
+      notifier.notifyCacheEntryRemoved("key", true, ctx);
+      assert allEventsListener.nodeRemoveEvent != null;
+      assert allEventsListener.nodeRemoveEvent.getKey().equals("key");
+      assert allEventsListener.nodeRemoveEvent.getType() == Event.Type.CACHE_ENTRY_REMOVED;
+   }
+
+   public void testNotifyNodeVisited()
+   {
+      assert allEventsListener.nodeVisistedEvent == null;
+      notifier.notifyCacheEntryVisited(fqn, true, ctx);
+      assert allEventsListener.nodeVisistedEvent != null;
+      assert allEventsListener.nodeVisistedEvent.getType() == Event.Type.CACHE_ENTRY_VISITED;
+   }
+
+   public void testNotifyNodeEvicted()
+   {
+      assert allEventsListener.nodeEvictedEvent == null;
+      notifier.notifyCacheEntryEvicted("key", true, ctx);
+      assert allEventsListener.nodeEvictedEvent != null;
+      assert allEventsListener.nodeEvictedEvent.getKey().equals("key");
+      assert allEventsListener.nodeEvictedEvent.getType() == Event.Type.CACHE_ENTRY_EVICTED;
+   }
+
+   public void testNotifyNodeLoaded()
+   {
+      assert allEventsListener.nodeLoadedEvent == null;
+      notifier.notifyCacheEntryLoaded("key", true, ctx);
+      assert allEventsListener.nodeLoadedEvent != null;
+      assert allEventsListener.nodeLoadedEvent.getKey().equals("key");
+      assert allEventsListener.nodeLoadedEvent.getType() == Event.Type.CACHE_ENTRY_LOADED;
+   }
+
+   public void testNotifyNodeActivated()
+   {
+      assert allEventsListener.nodeActivatedEvent == null;
+      notifier.notifyCacheEntryActivated("key", true, ctx);
+      assert allEventsListener.nodeActivatedEvent != null;
+      assert allEventsListener.nodeActivatedEvent.getKey().equals("key");
+      assert allEventsListener.nodeActivatedEvent.getType() == Event.Type.CACHE_ENTRY_ACTIVATED;
+   }
+
+   public void testNotifyNodePassivated()
+   {
+      assert allEventsListener.nodePassivatedEvent == null;
+      notifier.notifyCacheEntryPassivated("key", true, ctx);
+      assert allEventsListener.nodePassivatedEvent != null;
+      assert allEventsListener.nodePassivatedEvent.getKey().equals("key");
+      assert allEventsListener.nodePassivatedEvent.getType() == Event.Type.CACHE_ENTRY_PASSIVATED;
+   }
+
+   public void testNotifyCacheStarted()
+   {
+      assert allEventsListener.cacheStartedEvent == null;
+      notifier.notifyCacheStarted();
+      assert allEventsListener.cacheStartedEvent != null;
+      assert allEventsListener.cacheStartedEvent.getType() == Event.Type.CACHE_STARTED;
+   }
+
+   public void testNotifyCacheStopped()
+   {
+      assert allEventsListener.cacheStoppedEvent == null;
+      notifier.notifyCacheStopped();
+      assert allEventsListener.cacheStoppedEvent != null;
+      assert allEventsListener.cacheStoppedEvent.getType() == Event.Type.CACHE_STOPPED;
+   }
+
+   public void testNotifyViewChange()
+   {
+      assert allEventsListener.viewChanged == null;
+      View view = new View();
+      notifier.notifyViewChange(view, ctx);
+      assert allEventsListener.viewChanged != null;
+      assert allEventsListener.viewChanged.getNewView().equals(view);
+      assert allEventsListener.viewChanged.getType() == Event.Type.VIEW_CHANGED;
+   }
+
+   public void testNotifyBuddyGroupChange()
+   {
+      assert allEventsListener.buddyGroupChangedEvent == null;
+      BuddyGroup buddyGroup = new BuddyGroup();
+      notifier.notifyBuddyGroupChange(buddyGroup, true);
+      assert allEventsListener.buddyGroupChangedEvent != null;
+      assert allEventsListener.buddyGroupChangedEvent.getBuddyGroup().equals(buddyGroup);
+      assert allEventsListener.buddyGroupChangedEvent.getType() == Event.Type.BUDDY_GROUP_CHANGED;
+   }
+
+   public void testNotifyTransactionCompleted()
+   {
+      assert allEventsListener.transactionCompleted == null;
+      Transaction tx = createNiceMock(Transaction.class);
+      notifier.notifyTransactionCompleted(tx, false, ctx);
+      assert allEventsListener.transactionCompleted != null;
+      assert allEventsListener.transactionCompleted.getTransaction() == tx;
+      assert !allEventsListener.transactionCompleted.isSuccessful();
+      assert allEventsListener.transactionCompleted.getType() == Event.Type.TRANSACTION_COMPLETED;
+   }
+
+   public void testNotifyTransactionRegistered()
+   {
+      assert allEventsListener.transactionRegistered == null;
+      Transaction tx = createNiceMock(Transaction.class);
+      notifier.notifyTransactionRegistered(tx, ctx);
+      assert allEventsListener.transactionRegistered != null;
+      assert allEventsListener.transactionRegistered.getTransaction() == tx;
+      assert allEventsListener.transactionRegistered.getType() == Event.Type.TRANSACTION_REGISTERED;
+   }
+
+   @CacheListener
+   public static class AllEventsListener
+   {
+      CacheStartedEvent cacheStartedEvent;
+      CacheStoppedEvent cacheStoppedEvent;
+      CacheEntryCreatedEvent nodeCreatedEvent;
+      CacheEntryRemovedEvent nodeRemoveEvent;
+      CacheEntryVisitedEvent nodeVisistedEvent;
+      CacheEntryModifiedEvent nodeModifiedEvent;
+      CacheEntryActivatedEvent nodeActivatedEvent;
+      CacheEntryPassivatedEvent nodePassivatedEvent;
+      CacheEntryLoadedEvent nodeLoadedEvent;
+      CacheEntryEvictedEvent nodeEvictedEvent;
+      TransactionRegisteredEvent transactionRegistered;
+      TransactionCompletedEvent transactionCompleted;
+      ViewChangedEvent viewChanged;
+      BuddyGroupChangedEvent buddyGroupChangedEvent;
+
+      @CacheStarted
+      public void onCacheStarted(CacheStartedEvent event)
+      {
+         cacheStartedEvent = event;
+      }
+
+      @CacheStopped
+      public void onCacheStopped(CacheStoppedEvent event)
+      {
+         cacheStoppedEvent = event;
+      }
+
+      @CacheEntryCreated
+      public void onNodeCreated(CacheEntryCreatedEvent event)
+      {
+         nodeCreatedEvent = event;
+      }
+
+      @CacheEntryRemoved
+      public void onNodeRemoved(CacheEntryRemovedEvent event)
+      {
+         nodeRemoveEvent = event;
+      }
+
+      @CacheEntryVisited
+      public void onNodeVisited(CacheEntryVisitedEvent event)
+      {
+         nodeVisistedEvent = event;
+      }
+
+      @CacheEntryModified
+      public void onNodeModified(CacheEntryModifiedEvent event)
+      {
+         nodeModifiedEvent = event;
+      }
+
+      @CacheEntryActivated
+      public void onNodeActivated(CacheEntryActivatedEvent event)
+      {
+         nodeActivatedEvent = event;
+      }
+
+      @CacheEntryPassivated
+      public void onNodePassivated(CacheEntryPassivatedEvent event)
+      {
+         nodePassivatedEvent = event;
+      }
+
+      @CacheEntryLoaded
+      public void onNodeLoaded(CacheEntryLoadedEvent event)
+      {
+         nodeLoadedEvent = event;
+      }
+
+      @CacheEntryEvicted
+      public void onNodeEvicted(CacheEntryEvictedEvent event)
+      {
+         nodeEvictedEvent = event;
+      }
+
+      @TransactionRegistered
+      public void onTransactionRegistered(TransactionRegisteredEvent event)
+      {
+         transactionRegistered = event;
+      }
+
+      @TransactionCompleted
+      public void onTransactionCompleted(TransactionCompletedEvent event)
+      {
+         transactionCompleted = event;
+      }
+
+      @ViewChanged
+      public void onViewChanged(ViewChangedEvent event)
+      {
+         viewChanged = event;
+      }
+
+      @BuddyGroupChanged
+      public void onBuddyGroupChanged(BuddyGroupChangedEvent event)
+      {
+         buddyGroupChangedEvent = event;
+      }
+   }
+}

Added: core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifyNodeInvalidatedTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifyNodeInvalidatedTest.java	                        (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/notifications/NotifyNodeInvalidatedTest.java	2008-10-13 16:03:46 UTC (rev 6914)
@@ -0,0 +1,45 @@
+package org.jboss.starobrno.notifications;
+
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.config.Configuration.CacheMode;
+import org.jboss.starobrno.notifications.event.Event;
+import org.jboss.starobrno.notifications.event.EventImpl;
+import org.jboss.starobrno.util.TestingUtil;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+ at Test(groups = "functional")
+public class NotifyNodeInvalidatedTest
+{
+   public void testInvalidatedCallback() throws CloneNotSupportedException
+   {
+      Cache<String, String> c1 = null, c2 = null;
+      try
+      {
+         Configuration cfg = new Configuration();
+         cfg.setCacheMode(CacheMode.INVALIDATION_SYNC);
+         c1 = new DefaultCacheFactory<String, String>().createCache(cfg.clone());
+         c2 = new DefaultCacheFactory<String, String>().createCache(cfg.clone());
+         EventLog eventLog = new EventLog();
+         c2.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+         c2.put("k", "y");
+         c2.addCacheListener(eventLog);
+         c1.put("k", "v");
+
+         List<Event> expected = new ArrayList<Event>();
+         expected.add(new EventImpl(true, c2, "k", null, false, null, false, null, Event.Type.CACHE_ENTRY_INVALIDATED));
+         expected.add(new EventImpl(false, c2, "k", null, false, null, false, null, Event.Type.CACHE_ENTRY_INVALIDATED));
+
+         assert expected.equals(eventLog.events) : "Expected " + expected + " but got " + eventLog.events;
+         assert c2.get("k") == null;
+      }
+      finally
+      {
+         TestingUtil.killCaches(c1, c2);
+      }
+   }
+}




More information about the jbosscache-commits mailing list