Add interest filters; additional tests
diff --git a/src/test/java/com/intel/jndn/mock/MockFaceTest.java b/src/test/java/com/intel/jndn/mock/MockFaceTest.java
index afab856..ea46687 100644
--- a/src/test/java/com/intel/jndn/mock/MockFaceTest.java
+++ b/src/test/java/com/intel/jndn/mock/MockFaceTest.java
@@ -16,10 +16,13 @@
 import java.io.IOException;
 import java.util.logging.Logger;
 import net.named_data.jndn.Data;
+import net.named_data.jndn.Face;
 import net.named_data.jndn.Interest;
+import net.named_data.jndn.InterestFilter;
 import net.named_data.jndn.Name;
 import net.named_data.jndn.OnData;
 import net.named_data.jndn.OnInterest;
+import net.named_data.jndn.OnInterestCallback;
 import net.named_data.jndn.encoding.EncodingException;
 import net.named_data.jndn.security.SecurityException;
 import net.named_data.jndn.transport.Transport;
@@ -55,7 +58,7 @@
     face.addResponse(new Name("/test/with/responses"), response);
 
     // make request
-    final Counter count = new Counter();
+    final TestCounter count = new TestCounter();
     logger.info("Express interest: /test/with/responses");
     face.expressInterest(new Interest(new Name("/test/with/responses")), new OnData() {
       @Override
@@ -103,7 +106,7 @@
     }, null);
 
     // make request
-    final Counter count = new Counter();
+    final TestCounter count = new TestCounter();
     logger.info("Express interest: /test/with/responses");
     face.expressInterest(new Interest(new Name("/test/with/handlers")), new OnData() {
       @Override
@@ -123,23 +126,6 @@
     assertEquals(1, count.get());
   }
 
-  // TODO add childInherit test
-  /**
-   * Count reference
-   */
-  class Counter {
-
-    int count = 0;
-
-    public void inc() {
-      count++;
-    }
-
-    public int get() {
-      return count;
-    }
-  }
-
   /**
    * Ensure registering a prefix connects the underlying transport
    *
@@ -153,4 +139,54 @@
     face.registerPrefix(new Name("/fake/prefix"), (OnInterest) null, null);
     assertTrue(face.getTransport().getIsConnected());
   }
+  
+  /**
+   * Test that interest filters work as expected
+   */
+  @Test
+  public void testInterestFilters() throws IOException, SecurityException, EncodingException {
+    MockFace face = new MockFace();
+    
+    final TestCounter count = new TestCounter();
+    face.setInterestFilter(new InterestFilter("/a/b"), new OnInterestCallback() {
+      @Override
+      public void onInterest(Name prefix, Interest interest, Face face, long interestFilterId, InterestFilter filter) {
+        count.inc();
+      }
+    });
+    
+    face.expressInterest(new Interest(new Name("/a/b")).setInterestLifetimeMilliseconds(100), null);
+    face.processEvents();
+    
+    assertEquals(1, count.get());
+  }
+  
+  @Test
+  public void testResponseFromInsideElementReader() throws IOException, SecurityException, EncodingException{
+    MockFace face = new MockFace();
+    face.setInterestFilter(new InterestFilter("/a/b"), new OnInterestCallback() {
+      @Override
+      public void onInterest(Name prefix, Interest interest, Face face, long interestFilterId, InterestFilter filter) {
+        try {
+          face.putData(new Data(interest.getName()).setContent(new Blob("......")));
+        } catch (IOException ex) {
+          fail("Failed to put data.");
+        }
+      }
+    });
+    
+    final TestCounter count = new TestCounter();
+    face.expressInterest(new Interest(new Name("/a/b/c")), new OnData() {
+      @Override
+      public void onData(Interest interest, Data data) {
+        logger.info("Data returned: " + data.getContent().toString());
+        count.inc();
+      }
+    });
+    assertEquals(0, count.get());
+    
+    face.processEvents();
+    face.processEvents(); // the second processEvents() is required because the InterestFilter sends data from within the first processEvents loop
+    assertEquals(1, count.get());
+  }
 }
diff --git a/src/test/java/com/intel/jndn/mock/MockTransportTest.java b/src/test/java/com/intel/jndn/mock/MockTransportTest.java
index 7cd808f..dfbf514 100644
--- a/src/test/java/com/intel/jndn/mock/MockTransportTest.java
+++ b/src/test/java/com/intel/jndn/mock/MockTransportTest.java
@@ -55,7 +55,7 @@
     transport.respondWith(response);
 
     // express interest on the face
-    final Counter count = new Counter();
+    final TestCounter count = new TestCounter();
     face.expressInterest(new Interest(new Name("/a/b/c")), new OnData() {
       @Override
       public void onData(Interest interest, Data data) {
@@ -95,7 +95,7 @@
     transport.respondWith(response2);
 
     // express interest on the face
-    final Counter count = new Counter();
+    final TestCounter count = new TestCounter();
     face.expressInterest(new Interest(new Name("/a/b/c/1")), new OnData() {
       @Override
       public void onData(Interest interest, Data data) {
@@ -117,7 +117,7 @@
     // express interest again, but this time it should time out because there 
     // is no data left on the wire; the first processEvents() has already 
     // picked it up
-    final Counter count2 = new Counter();
+    final TestCounter count2 = new TestCounter();
     Interest failingInterest = new Interest(new Name("/a/b/c/2"));
     failingInterest.setInterestLifetimeMilliseconds(50);
     face.expressInterest(failingInterest, new OnData() {
@@ -145,18 +145,41 @@
   }
 
   /**
-   * Count reference
+   * Test for buffer overflow exceptions
    */
-  class Counter {
+  @Test
+  public void testBufferOverflowException() throws IOException {
+    MockTransport transport = new MockTransport();
 
-    int count = 0;
+    Interest interest = buildInterest();
+    Data data = buildData();
+    assertTrue(data.wireEncode().size() > interest.wireEncode().size());
 
-    public void inc() {
-      count++;
-    }
+    transport.send(interest.wireEncode().buf());
+    transport.send(data.wireEncode().buf());
+  }
+  
+  /**
+   * Verify that processing no events does not cause errors
+   */
+  @Test
+  public void testProcessNoEvents() throws IOException, EncodingException{
+    MockFace face = new MockFace();
+    face.expressInterest((Name) null, null);
+    face.processEvents();
+    face.processEvents();
+  }
 
-    public int get() {
-      return count;
-    }
+  private Data buildData() {
+    Data data = new Data(new Name("/a/b/c/1"));
+    data.setContent(new Blob("............................................"));
+    data.getMetaInfo().setFreshnessPeriod(1000);
+    return data;
+  }
+
+  private Interest buildInterest() {
+    Interest interest = new Interest(new Name("/a/b/c"));
+    interest.setInterestLifetimeMilliseconds(50);
+    return interest;
   }
 }
diff --git a/src/test/java/com/intel/jndn/mock/TestCounter.java b/src/test/java/com/intel/jndn/mock/TestCounter.java
new file mode 100644
index 0000000..3627ac4
--- /dev/null
+++ b/src/test/java/com/intel/jndn/mock/TestCounter.java
@@ -0,0 +1,31 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2015, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 3, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ */
+package com.intel.jndn.mock;
+
+/**
+ *
+ * @author Andrew Brown <andrew.brown@intel.com>
+ */
+public class TestCounter {
+
+  private int count = 0;
+
+  public void inc() {
+    count++;
+  }
+
+  public int get() {
+    return count;
+  }
+}