Merge pull request #6 from 01org/add-mock-forwarder
Add mock forwarder
diff --git a/build.gradle b/build.gradle
index bcddbe2..ddc709a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,3 +1,17 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.
+ */
+
buildscript {
repositories {
jcenter()
@@ -13,10 +27,10 @@
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'signing'
-apply plugin: 'checkstyle'
+//apply plugin: 'checkstyle'
group = 'com.intel.jndn.mock'
-version = '1.0.3'
+version = '1.1.0'
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
diff --git a/config/checkstyle/checkstyle-test.xml b/config/checkstyle/checkstyle-test.xml
index 81b48ec..503f6e0 100644
--- a/config/checkstyle/checkstyle-test.xml
+++ b/config/checkstyle/checkstyle-test.xml
@@ -1,4 +1,18 @@
<?xml version="1.0"?>
+<!--
+ ~ jndn-mock
+ ~ Copyright (c) 2016, 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.
+ -->
+
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml
index 86eda33..9fb4286 100644
--- a/config/checkstyle/checkstyle.xml
+++ b/config/checkstyle/checkstyle.xml
@@ -1,4 +1,18 @@
<?xml version="1.0"?>
+<!--
+ ~ jndn-mock
+ ~ Copyright (c) 2016, 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.
+ -->
+
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index cdddf1e..bdeb380 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,3 +1,17 @@
+#
+# jndn-mock
+# Copyright (c) 2016, 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.
+#
+
#Sun Jan 31 16:45:16 PST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
diff --git a/nb-configuration.xml b/nb-configuration.xml
index b51151d..2f96e1e 100644
--- a/nb-configuration.xml
+++ b/nb-configuration.xml
@@ -1,4 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ jndn-mock
+ ~ Copyright (c) 2016, 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.
+ -->
+
<project-shared-configuration>
<!--
This file contains additional configuration written by modules in the NetBeans IDE.
diff --git a/pom.xml b/pom.xml
index c92da38..2b9da0a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.intel.jndn.mock</groupId>
<artifactId>jndn-mock</artifactId>
- <version>1.0.3</version>
+ <version>1.1.0</version>
<name>jndn-mock</name>
<description>Tools for testing NDN Java code without using network IO.</description>
<url>https://github.com/01org/jndn-utils</url>
diff --git a/src/main/java/com/intel/jndn/mock/MeasurableFace.java b/src/main/java/com/intel/jndn/mock/MeasurableFace.java
new file mode 100644
index 0000000..c862756
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/MeasurableFace.java
@@ -0,0 +1,47 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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;
+
+import net.named_data.jndn.Data;
+import net.named_data.jndn.Interest;
+
+import java.util.Collection;
+
+/**
+ * Provide API for measuring packet use on a given face
+ *
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public interface MeasurableFace {
+ /**
+ * @return all interest packets sent by the measured face
+ */
+ Collection<Interest> sentInterests();
+
+ /**
+ * @return all data packets sent by the measured face
+ */
+ Collection<Data> sentDatas();
+
+ /**
+ * @return all interest packets received by the measured face
+ */
+ Collection<Interest> receivedInterests();
+
+ /**
+ * @return all data packets received by the measured face
+ */
+ Collection<Data> receivedDatas();
+}
diff --git a/src/main/java/com/intel/jndn/mock/MockFace.java b/src/main/java/com/intel/jndn/mock/MockFace.java
index 8980fa7..dc1661a 100644
--- a/src/main/java/com/intel/jndn/mock/MockFace.java
+++ b/src/main/java/com/intel/jndn/mock/MockFace.java
@@ -1,6 +1,6 @@
/*
* jndn-mock
- * Copyright (c) 2013-2015 Regents of the University of California.
+ * Copyright (c) 2016, 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,
@@ -36,8 +36,8 @@
/**
* A client-side face for unit testing.
*
- * @author Alexander Afanasyev, <aa@cs.ucla.edu>
- * @author Andrew Brown <andrew.brown@intel.com>
+ * @author Alexander Afanasyev, aa@cs.ucla.edu
+ * @author Andrew Brown, andrew.brown@intel.com
*/
public class MockFace extends Face {
/**
@@ -77,7 +77,7 @@
public final List<SignalOnSendData> onSendData = new ArrayList<>();
private static final Logger LOGGER = Logger.getLogger(MockFace.class.getName());
- private MockFaceTransport transport;
+ private MockTransport transport;
private KeyChain keyChain;
/////////////////////////////////////////////////////////////////////////////
@@ -163,7 +163,7 @@
*
* @throws SecurityException should not be thrown by this test class
*/
- public MockFace() throws SecurityException {
+ public MockFace() {
this(DEFAULT_OPTIONS);
}
@@ -175,7 +175,7 @@
* new MockFace(new Options());
* // use onSendInterest.add(handler) and onSendData.add(handler)
* // to add custom logic when Interest or Data packet are sent
- * // from the upper level (to transport)
+ * // from the upper level (to callback)
* </pre>
*
* To create Face that just logs packets in sentInterests and sentData:
@@ -186,8 +186,8 @@
* @param options see {@link Options}
*/
public MockFace(final Options options) {
- super(new MockFaceTransport(), null);
- transport = (MockFaceTransport) node_.getTransport();
+ super(new MockTransport(), null);
+ transport = (MockTransport) node_.getTransport();
transport.setOnSendBlock(new OnIncomingPacket());
try {
@@ -222,7 +222,7 @@
/**
* Route incoming packets to the correct callbacks.
*/
- private class OnIncomingPacket implements MockFaceTransport.OnSendBlockSignal {
+ private class OnIncomingPacket implements MockTransport.OnSendBlockSignal {
/**
* {@inheritDoc}
*/
@@ -252,7 +252,7 @@
LOGGER.info("Received an unknown packet");
}
} catch (EncodingException e) {
- LOGGER.log(Level.INFO, "Failed to decode incoming packet", e);
+ LOGGER.log(Level.INFO, "Failed to decodeParameters incoming packet", e);
}
}
}
@@ -309,7 +309,7 @@
}
/**
- * Mock reception of the Interest packet on the Face (from transport).
+ * Mock reception of the Interest packet on the Face (from callback).
*
* @param interest the mock-remote interest to add to the PIT
* @throws EncodingException if packet encoding fails (it should not)
@@ -319,7 +319,7 @@
}
/**
- * Mock reception of the Data packet on the Face (from transport).
+ * Mock reception of the Data packet on the Face (from callback).
*
* @param data the mock-remote data to add to the CS
* @throws EncodingException if packet encoding fails (it should not)
@@ -329,7 +329,7 @@
}
/**
- * @return the transport for this face
+ * @return the callback for this face
*/
public Transport getTransport() {
return transport;
diff --git a/src/main/java/com/intel/jndn/mock/MockForwarder.java b/src/main/java/com/intel/jndn/mock/MockForwarder.java
new file mode 100644
index 0000000..11ea73e
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/MockForwarder.java
@@ -0,0 +1,233 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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;
+
+import com.intel.jndn.mock.forwarder.BufferHandler;
+import com.intel.jndn.mock.forwarder.FibImpl;
+import com.intel.jndn.mock.forwarder.LocalFibEntry;
+import com.intel.jndn.mock.forwarder.OnPrefixRegistration;
+import com.intel.jndn.mock.forwarder.PitImpl;
+import net.named_data.jndn.Data;
+import net.named_data.jndn.Face;
+import net.named_data.jndn.ForwardingFlags;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.OnData;
+import net.named_data.jndn.OnNetworkNack;
+import net.named_data.jndn.OnTimeout;
+import net.named_data.jndn.encoding.WireFormat;
+import net.named_data.jndn.security.KeyChain;
+import net.named_data.jndn.security.SecurityException;
+import net.named_data.jndn.transport.Transport;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.logging.Logger;
+
+/**
+ * A mock forwarder for use in testing applications without network IO. It does not fully implement NFD functionality
+ * but currently does allow registering prefixes (to receive sent interests) and limited forwarding flag support.
+ *
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public class MockForwarder {
+ private static final Logger LOGGER = Logger.getLogger(MockForwarder.class.getName());
+ private final KeyChain keyChain;
+ private final Name certName;
+ private final Fib fib = new FibImpl();
+ private final Pit pit = new PitImpl();
+
+ /**
+ * Forwarding information base API; use this for recording FIB entries.
+ */
+ public interface Fib {
+ /**
+ * @param interest the incoming client interest
+ * @return all FIB entries matching the interest
+ */
+ Collection<FibEntry> find(Interest interest);
+
+ /**
+ * @param entry a new FIB entry to add; enables routing to the face (or more correctly, channel) contained in this
+ * entry
+ */
+ void add(FibEntry entry);
+ }
+
+ /**
+ * Entry in the FIB; use this for forwarding interest packets.
+ */
+ public interface FibEntry {
+ /**
+ * @param interest the interest to forward
+ * @param sourceTransport the source of the interest for use in the callback
+ */
+ void forward(Interest interest, Transport sourceTransport);
+
+ /**
+ * @return then entry prefix name
+ */
+ Name getPrefix();
+
+ /**
+ * @return the entry flags
+ */
+ ForwardingFlags getFlags();
+ }
+
+ /**
+ * Pending interest table API; use this for recording incoming interests.
+ */
+ public interface Pit {
+ /**
+ * @param entry the PIT entry to add
+ */
+ void add(PitEntry entry);
+
+ /**
+ * @param interest the incoming interest to match against
+ * @return true if the interest matches an entry already in the PIT
+ */
+ boolean has(Interest interest);
+
+ /**
+ * @param name the name to match against
+ * @return the PIT entries matching a name, removing them from the PIT
+ */
+ Collection<PitEntry> extract(Name name);
+ }
+
+ /**
+ * Entry in the PIT; use this for forwarding data packets.
+ */
+ public interface PitEntry {
+ /**
+ * @param data the packet to forward
+ */
+ void forward(Data data);
+
+ /**
+ * @return the interest that first created the entry
+ */
+ Interest getInterest();
+
+ /**
+ * @return true if the entry has been satisfied (has had a matching data forwarded through it)
+ */
+ boolean isSatisfied();
+ }
+
+ /**
+ * Mock-specific API for recording the source and destination of incoming interests
+ */
+ public interface OnInterestReceived {
+ /**
+ * Called when the mock forwarder receives incoming interests from a face; see {@link #register(Name,
+ * OnInterestReceived, ForwardingFlags)}.
+ *
+ * @param interest the incoming interest
+ * @param destinationTransport the transport that sent the interest; necessary for the forwarder to be able to
+ * register prefixes (TODO in the future this should also be a {@link Face}, perhaps rename as remoteFace).
+ * @param sourceFace the face receiving the interest; use {@link Face#putData(Data)} to reply
+ */
+ void in(Interest interest, Transport destinationTransport, Face sourceFace);
+ }
+
+ public MockForwarder() {
+ try {
+ keyChain = MockKeyChain.configure(new Name("/mock/forwarder"));
+ certName = keyChain.getDefaultCertificateName();
+ } catch (SecurityException e) {
+ throw new IllegalStateException("Failed to set up mock prefix registration", e);
+ }
+
+ OnPrefixRegistration onPrefixRegistration = new OnPrefixRegistration(keyChain, fib);
+ Name registrationPrefix = new Name("/localhost/nfd/rib/register");
+ register(registrationPrefix, onPrefixRegistration, new ForwardingFlags());
+ }
+
+ public Face connect() {
+ MockForwarderFace face = new MockForwarderFace();
+ face.setCommandSigningInfo(keyChain, certName);
+ LOGGER.info("Connected new face using transport: " + face.getTransport());
+ return face;
+ }
+
+ public void register(Name prefix, OnInterestReceived callback, ForwardingFlags flags) {
+ Face registrationFace = this.connect();
+ FibEntry registrationEntry = new LocalFibEntry(prefix, callback, registrationFace, flags);
+ fib.add(registrationEntry);
+ LOGGER.info("Registered new prefix to receive interests: " + prefix);
+ }
+
+ private class MockForwarderFace extends Face implements MeasurableFace {
+ final Collection<Interest> sentInterests = new ArrayList<>();
+ final Collection<Data> sentDatas = new ArrayList<>();
+ final Collection<Interest> receivedInterests = new ArrayList<>();
+ final Collection<Data> receivedDatas = new ArrayList<>();
+
+ MockForwarderFace() {
+ super(new MockTransport(), null);
+ MockTransport transport = (MockTransport) node_.getTransport();
+ transport.setOnSendBlock(new BufferHandler(transport, fib, pit));
+ }
+
+ Transport getTransport() {
+ return node_.getTransport();
+ }
+
+ @Override
+ public long expressInterest(Interest interest, OnData onData, OnTimeout onTimeout,
+ OnNetworkNack onNetworkNack, WireFormat wireFormat) throws IOException {
+ sentInterests.add(interest);
+ return super.expressInterest(interest, onData, onTimeout, onNetworkNack, wireFormat);
+ }
+
+ @Override
+ public long expressInterest(Name name, Interest interestTemplate, OnData onData, OnTimeout onTimeout,
+ OnNetworkNack onNetworkNack, WireFormat wireFormat) throws IOException {
+ sentInterests.add(getInterestCopy(name, interestTemplate));
+ return super.expressInterest(name, interestTemplate, onData, onTimeout, onNetworkNack, wireFormat);
+ }
+
+ @Override
+ public void putData(Data data, WireFormat wireFormat) throws IOException {
+ sentDatas.add(data);
+ super.putData(data, wireFormat);
+ }
+
+ @Override
+ public Collection<Interest> sentInterests() {
+ return Collections.unmodifiableCollection(sentInterests);
+ }
+
+ @Override
+ public Collection<Data> sentDatas() {
+ return Collections.unmodifiableCollection(sentDatas);
+ }
+
+ @Override
+ public Collection<Interest> receivedInterests() {
+ return Collections.unmodifiableCollection(receivedInterests);
+ }
+
+ @Override
+ public Collection<Data> receivedDatas() {
+ return Collections.unmodifiableCollection(receivedDatas);
+ }
+ }
+}
diff --git a/src/main/java/com/intel/jndn/mock/MockKeyChain.java b/src/main/java/com/intel/jndn/mock/MockKeyChain.java
index 1a0bafb..30710e1 100644
--- a/src/main/java/com/intel/jndn/mock/MockKeyChain.java
+++ b/src/main/java/com/intel/jndn/mock/MockKeyChain.java
@@ -1,6 +1,6 @@
/*
* jndn-mock
- * Copyright (c) 2015, Intel Corporation.
+ * Copyright (c) 2016, 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,
@@ -26,7 +26,7 @@
/**
* Create an in-memory key chain for use in NDN-related tests.
*
- * @author Andrew Brown <andrew.brown@intel.com>
+ * @author Andrew Brown, andrew.brown@intel.com
*/
public final class MockKeyChain {
/**
diff --git a/src/main/java/com/intel/jndn/mock/MockTransport.java b/src/main/java/com/intel/jndn/mock/MockTransport.java
index df437e0..7e788a0 100644
--- a/src/main/java/com/intel/jndn/mock/MockTransport.java
+++ b/src/main/java/com/intel/jndn/mock/MockTransport.java
@@ -1,6 +1,6 @@
/*
* jndn-mock
- * Copyright (c) 2015, Intel Corporation.
+ * Copyright (c) 2016, 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,
@@ -28,12 +28,12 @@
* Non-public class for handling data buffering in NDN unit tests; works in
* conjunction with {@link MockFace}.
*
- * @author Alexander Afanasyev, <aa@cs.ucla.edu>
- * @author Andrew Brown <andrew.brown@intel.com>
+ * @author Alexander Afanasyev, aa@cs.ucla.edu
+ * @author Andrew Brown, andrew.brown@intel.com
*/
-class MockFaceTransport extends Transport {
+public class MockTransport extends Transport {
private OnSendBlockSignal onSendBlock;
- private static final Logger LOGGER = Logger.getLogger(MockFaceTransport.class.getName());
+ private static final Logger LOGGER = Logger.getLogger(MockTransport.class.getName());
private boolean connected;
private ElementReader elementReader;
private final List<ByteBuffer> receiveBuffer = new LinkedList<>();
diff --git a/src/main/java/com/intel/jndn/mock/forwarder/BufferHandler.java b/src/main/java/com/intel/jndn/mock/forwarder/BufferHandler.java
new file mode 100644
index 0000000..4572115
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/forwarder/BufferHandler.java
@@ -0,0 +1,101 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.forwarder;
+
+import com.intel.jndn.mock.MockForwarder;
+import com.intel.jndn.mock.MockTransport;
+import net.named_data.jndn.Data;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.encoding.TlvWireFormat;
+import net.named_data.jndn.encoding.tlv.Tlv;
+import net.named_data.jndn.encoding.tlv.TlvDecoder;
+import net.named_data.jndn.transport.Transport;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public class BufferHandler implements MockTransport.OnSendBlockSignal {
+
+ private static final Logger LOGGER = Logger.getLogger(BufferHandler.class.getName());
+ private final MockTransport transport;
+ private final MockForwarder.Fib fib;
+ private final MockForwarder.Pit pit;
+
+ public BufferHandler(MockTransport transport, MockForwarder.Fib fib, MockForwarder.Pit pit) {
+ this.transport = transport;
+ this.fib = fib;
+ this.pit = pit;
+ }
+
+ @Override
+ public void emit(ByteBuffer buffer) {
+ try {
+ if (isInterest(buffer) || isData(buffer)) {
+ TlvDecoder decoder = new TlvDecoder(buffer);
+ if (decoder.peekType(Tlv.Interest, buffer.remaining())) {
+ Interest interest = new Interest();
+ interest.wireDecode(buffer, TlvWireFormat.get());
+ forward(interest, transport);
+ } else if (decoder.peekType(Tlv.Data, buffer.remaining())) {
+ Data data = new Data();
+ data.wireDecode(buffer, TlvWireFormat.get());
+ forward(data);
+ }
+ } else {
+ LOGGER.warning("Received an unknown packet");
+ }
+ } catch (EncodingException e) {
+ LOGGER.log(Level.INFO, "Failed to decodeParameters incoming packet", e);
+ }
+ }
+
+ private boolean isInterest(ByteBuffer buffer) {
+ return buffer.get(0) == Tlv.Interest;
+ }
+
+ private boolean isData(ByteBuffer buffer) {
+ return buffer.get(0) == Tlv.Data;
+ }
+
+ private void forward(Interest interest, Transport transport) {
+ if (pit.has(interest)) {
+ LOGGER.info("Already seen interest, swallowing: " + interest.toUri());
+ return;
+ }
+
+ LOGGER.info("Adding interest to PIT: " + interest.toUri());
+ pit.add(new PitEntryImpl(interest, (MockTransport) transport));
+
+ LOGGER.info("Forwarding interest: " + interest.toUri());
+ for (MockForwarder.FibEntry entry : fib.find(interest)) {
+ entry.forward(interest, transport);
+ }
+ }
+
+ private void forward(Data data) {
+ Collection<MockForwarder.PitEntry> found = pit.extract(data.getName());
+ LOGGER.log(Level.INFO, "Found {0} pending interests", found.size());
+
+ for (MockForwarder.PitEntry pendingInterest : found) {
+ pendingInterest.forward(data);
+ }
+ }
+}
diff --git a/src/main/java/com/intel/jndn/mock/forwarder/ClientFibEntry.java b/src/main/java/com/intel/jndn/mock/forwarder/ClientFibEntry.java
new file mode 100644
index 0000000..020a8fb
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/forwarder/ClientFibEntry.java
@@ -0,0 +1,57 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.forwarder;
+
+import com.intel.jndn.mock.MockForwarder;
+import com.intel.jndn.mock.MockTransport;
+import net.named_data.jndn.ForwardingFlags;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.transport.Transport;
+
+import java.util.logging.Logger;
+
+/**
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+class ClientFibEntry implements MockForwarder.FibEntry {
+
+ private static final Logger LOGGER = Logger.getLogger(ClientFibEntry.class.getName());
+ private final Name prefix;
+ private final MockTransport transport;
+ private final ForwardingFlags flags;
+
+ ClientFibEntry(Name prefix, MockTransport transport, ForwardingFlags flags) {
+ this.prefix = prefix;
+ this.transport = transport;
+ this.flags = flags;
+ }
+
+ @Override
+ public void forward(Interest interest, Transport sourceTransport) {
+ LOGGER.info("Receiving interest on: " + this.transport);
+ transport.receive(interest.wireEncode().buf());
+ }
+
+ @Override
+ public Name getPrefix() {
+ return new Name(prefix);
+ }
+
+ @Override
+ public ForwardingFlags getFlags() {
+ return flags;
+ }
+}
diff --git a/src/main/java/com/intel/jndn/mock/forwarder/FibImpl.java b/src/main/java/com/intel/jndn/mock/forwarder/FibImpl.java
new file mode 100644
index 0000000..e2473a5
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/forwarder/FibImpl.java
@@ -0,0 +1,51 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.forwarder;
+
+import com.intel.jndn.mock.MockForwarder;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.Name;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public class FibImpl implements MockForwarder.Fib {
+
+ private final ConcurrentHashMap<Name, MockForwarder.FibEntry> fib = new ConcurrentHashMap<>();
+
+ @Override
+ public void add(MockForwarder.FibEntry entry) {
+ fib.put(entry.getPrefix(), entry);
+ }
+
+ public List<MockForwarder.FibEntry> find(Interest interest) {
+ ArrayList<MockForwarder.FibEntry> entries = new ArrayList<>();
+ for (int i = interest.getName().size(); i >= 0; i--) {
+ Name prefix = interest.getName().getPrefix(i);
+ MockForwarder.FibEntry entry = fib.get(prefix);
+ if (entry != null) {
+ entries.add(entry);
+ if (!entry.getFlags().getChildInherit() || entry.getFlags().getCapture()) {
+ break;
+ }
+ }
+ }
+ return entries;
+ }
+}
diff --git a/src/main/java/com/intel/jndn/mock/forwarder/LocalFibEntry.java b/src/main/java/com/intel/jndn/mock/forwarder/LocalFibEntry.java
new file mode 100644
index 0000000..c803c3e
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/forwarder/LocalFibEntry.java
@@ -0,0 +1,58 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.forwarder;
+
+import com.intel.jndn.mock.MockForwarder;
+import net.named_data.jndn.Face;
+import net.named_data.jndn.ForwardingFlags;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.transport.Transport;
+
+import java.util.logging.Logger;
+
+/**
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public class LocalFibEntry implements MockForwarder.FibEntry {
+
+ private static final Logger LOGGER = Logger.getLogger(LocalFibEntry.class.getName());
+ private final Name prefix;
+ private final MockForwarder.OnInterestReceived callback;
+ private final Face registrationFace;
+ private final ForwardingFlags flags;
+
+ public LocalFibEntry(Name prefix, MockForwarder.OnInterestReceived callback, Face registrationFace, ForwardingFlags flags) {
+ this.prefix = prefix;
+ this.callback = callback;
+ this.registrationFace = registrationFace;
+ this.flags = flags;
+ }
+
+ public void forward(Interest interest, Transport sourceTransport) {
+ LOGGER.info("Forwarding interest on: " + this.callback);
+ callback.in(interest, sourceTransport, registrationFace);
+ }
+
+ @Override
+ public Name getPrefix() {
+ return new Name(prefix);
+ }
+
+ @Override
+ public ForwardingFlags getFlags() {
+ return flags;
+ }
+}
diff --git a/src/main/java/com/intel/jndn/mock/forwarder/OnPrefixRegistration.java b/src/main/java/com/intel/jndn/mock/forwarder/OnPrefixRegistration.java
new file mode 100644
index 0000000..3bbf56e
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/forwarder/OnPrefixRegistration.java
@@ -0,0 +1,103 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.forwarder;
+
+import com.intel.jndn.mock.MockForwarder;
+import com.intel.jndn.mock.MockTransport;
+import net.named_data.jndn.ControlParameters;
+import net.named_data.jndn.ControlResponse;
+import net.named_data.jndn.Data;
+import net.named_data.jndn.Face;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.encoding.EncodingException;
+import net.named_data.jndn.security.KeyChain;
+import net.named_data.jndn.security.SecurityException;
+import net.named_data.jndn.transport.Transport;
+
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Handle prefix registration requests from clients to a mock forwarder; must conform to specification outlined in
+ * https://redmine.named-data.net/projects/nfd/wiki/RibMgmt.
+ *
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public class OnPrefixRegistration implements MockForwarder.OnInterestReceived {
+ private static final Logger LOGGER = Logger.getLogger(OnPrefixRegistration.class.getName());
+ private static final int STATUS_CODE_OK = 200;
+ private static final int CONTROL_PARAMETERS_NAME_OFFSET = -5;
+ private static final int CONTROL_COMMAND_NAME_OFFSET = 3;
+ private final KeyChain keyChain;
+ private final MockForwarder.Fib fib;
+
+ public OnPrefixRegistration(KeyChain keyChain, MockForwarder.Fib fib) {
+ this.keyChain = keyChain;
+ this.fib = fib;
+ }
+
+ @Override
+ public void in(Interest interest, Transport destinationTransport, Face localFace) {
+ LOGGER.info("Received registration request: " + interest.toUri());
+ ControlParameters params = decodeParameters(interest);
+
+ MockForwarder.FibEntry entry = new ClientFibEntry(params.getName(), (MockTransport) destinationTransport, params.getForwardingFlags());
+ fib.add(entry);
+ LOGGER.info("Added new route " + params.getName() + " to: " + destinationTransport);
+
+ ControlResponse response = encodeResponse(params);
+
+ Data data = new Data();
+ data.setName(interest.getName());
+ data.setContent(response.wireEncode());
+ signResponse(data);
+
+ try {
+ localFace.putData(data);
+ } catch (IOException e) {
+ LOGGER.log(Level.SEVERE, "Failed to send registration response", e);
+ }
+ }
+
+ private ControlParameters decodeParameters(Interest interest) {
+ ControlParameters params = new ControlParameters();
+ try {
+ params.wireDecode(interest.getName().get(CONTROL_PARAMETERS_NAME_OFFSET).getValue());
+ params.setFaceId(1);
+ params.setOrigin(0);
+ params.setCost(0);
+ } catch (EncodingException e) {
+ throw new IllegalArgumentException("", e);
+ }
+ return params;
+ }
+
+ private ControlResponse encodeResponse(ControlParameters params) {
+ ControlResponse response = new ControlResponse();
+ response.setStatusCode(STATUS_CODE_OK);
+ response.setStatusText("OK");
+ response.setBodyAsControlParameters(params);
+ return response;
+ }
+
+ private void signResponse(Data data) {
+ try {
+ keyChain.sign(data);
+ } catch (SecurityException e) {
+ LOGGER.log(Level.FINE, "MockKeyChain signing failed", e);
+ }
+ }
+}
diff --git a/src/main/java/com/intel/jndn/mock/forwarder/PitEntryImpl.java b/src/main/java/com/intel/jndn/mock/forwarder/PitEntryImpl.java
new file mode 100644
index 0000000..d5e3a5b
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/forwarder/PitEntryImpl.java
@@ -0,0 +1,57 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.forwarder;
+
+import com.intel.jndn.mock.MockForwarder;
+import com.intel.jndn.mock.MockTransport;
+import net.named_data.jndn.Data;
+import net.named_data.jndn.Interest;
+
+import java.util.logging.Logger;
+
+/**
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+final class PitEntryImpl implements MockForwarder.PitEntry {
+
+ private static final Logger LOGGER = Logger.getLogger(PitEntryImpl.class.getName());
+ private final Interest interest;
+ private final MockTransport transport;
+ private boolean satisfied = false;
+
+ PitEntryImpl(Interest interest, MockTransport transport) {
+ this.interest = interest;
+ this.transport = transport;
+ }
+
+ public void forward(Data data) {
+ LOGGER.info("Forwarding data on: " + this.transport);
+
+ if (satisfied) {
+ LOGGER.warning("Data already forwarded for PIT entry: " + interest.toUri());
+ }
+
+ transport.receive(data.wireEncode().buf());
+ satisfied = true;
+ }
+
+ public Interest getInterest() {
+ return new Interest(interest);
+ }
+
+ public boolean isSatisfied() {
+ return satisfied;
+ }
+}
diff --git a/src/main/java/com/intel/jndn/mock/forwarder/PitImpl.java b/src/main/java/com/intel/jndn/mock/forwarder/PitImpl.java
new file mode 100644
index 0000000..81eb15f
--- /dev/null
+++ b/src/main/java/com/intel/jndn/mock/forwarder/PitImpl.java
@@ -0,0 +1,59 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.forwarder;
+
+import com.intel.jndn.mock.MockForwarder;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.Name;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Naive implementation of a pending interest table
+ *
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public class PitImpl implements MockForwarder.Pit {
+
+ private final Map<Name, List<MockForwarder.PitEntry>> pit = new ConcurrentHashMap<>();
+
+ public List<MockForwarder.PitEntry> extract(Name name) {
+ ArrayList<MockForwarder.PitEntry> entries = new ArrayList<>();
+ for (int i = name.size(); i >= 0; i--) {
+ Name prefix = name.getPrefix(i);
+ List<MockForwarder.PitEntry> pendingInterests = pit.get(prefix);
+ if (pendingInterests != null) {
+ entries.addAll(pendingInterests);
+ pendingInterests.clear(); // TODO is this necessary
+ }
+ }
+ return entries;
+ }
+
+ public void add(MockForwarder.PitEntry entry) {
+ if (!pit.containsKey(entry.getInterest().getName())) {
+ pit.put(entry.getInterest().getName(), new ArrayList<MockForwarder.PitEntry>(1));
+ }
+ pit.get(entry.getInterest().getName()).add(entry);
+ }
+
+ public boolean has(Interest interest) {
+ List<MockForwarder.PitEntry> entries = pit.get(interest.getName());
+ return entries != null && !entries.isEmpty();
+ }
+}
diff --git a/src/main/java/com/intel/jndn/mock/package-info.java b/src/main/java/com/intel/jndn/mock/package-info.java
index 21dcda2..ae13ee4 100644
--- a/src/main/java/com/intel/jndn/mock/package-info.java
+++ b/src/main/java/com/intel/jndn/mock/package-info.java
@@ -1,3 +1,17 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.
+ */
+
/**
* NDN Face mocking classes.
*/
diff --git a/src/test/java/com/intel/jndn/mock/MockFaceTest.java b/src/test/java/com/intel/jndn/mock/MockFaceTest.java
index 7c8bbc9..015da4b 100644
--- a/src/test/java/com/intel/jndn/mock/MockFaceTest.java
+++ b/src/test/java/com/intel/jndn/mock/MockFaceTest.java
@@ -1,6 +1,6 @@
/*
* jndn-mock
- * Copyright (c) 2015, Intel Corporation.
+ * Copyright (c) 2016, 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,
@@ -168,8 +168,7 @@
@Test
public void testThatTransportConnectsOnPrefixRegistration() throws IOException, SecurityException {
assertFalse(face.getTransport().getIsConnected());
- face.registerPrefix(new Name("/fake/prefix"), (OnInterestCallback) null, (OnRegisterFailed) null,
- (OnRegisterSuccess) null);
+ face.registerPrefix(new Name("/fake/prefix"), null, null, (OnRegisterSuccess) null);
assertTrue(face.getTransport().getIsConnected());
}
@@ -181,8 +180,8 @@
}
final State state = new State();
- // connect transport
- face.registerPrefix(new Name("/fake/prefix"), (OnInterestCallback) null, new OnRegisterFailed() {
+ // connect callback
+ face.registerPrefix(new Name("/fake/prefix"), null, new OnRegisterFailed() {
@Override
public void onRegisterFailed(final Name prefix) {
state.regFailed = true;
diff --git a/src/test/java/com/intel/jndn/mock/MockForwarderTest.java b/src/test/java/com/intel/jndn/mock/MockForwarderTest.java
new file mode 100644
index 0000000..6bf09ab
--- /dev/null
+++ b/src/test/java/com/intel/jndn/mock/MockForwarderTest.java
@@ -0,0 +1,106 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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;
+
+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.OnInterestCallback;
+import net.named_data.jndn.OnRegisterFailed;
+import net.named_data.jndn.OnRegisterSuccess;
+import net.named_data.jndn.OnTimeout;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.logging.Logger;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public class MockForwarderTest {
+ private static final Logger LOGGER = Logger.getLogger(MockForwarderTest.class.getName());
+
+ @Test
+ public void usage() throws Exception {
+ Name prefix = new Name("/test");
+ MockForwarder forwarder = new MockForwarder();
+ Face a = forwarder.connect();
+ Face b = forwarder.connect();
+
+ LOGGER.info("Registering prefix: " + prefix);
+ final CountDownLatch response1 = new CountDownLatch(1);
+ a.registerPrefix(prefix, new OnInterestCallback() {
+ @Override
+ public void onInterest(Name prefix, Interest interest, Face face, long interestFilterId, InterestFilter filter) {
+ LOGGER.info("Received interest: " + interest.toUri());
+ try {
+ face.putData(new Data(interest.getName()));
+ LOGGER.info("Sent data to interest: " + interest.getName());
+ } catch (IOException e) {
+ LOGGER.info("Failed to send data for: " + interest.toUri());
+ }
+ }
+ }, new OnRegisterFailed() {
+ @Override
+ public void onRegisterFailed(Name prefix) {
+ LOGGER.severe("Failed to register prefix for: " + prefix);
+ response1.countDown();
+ }
+ }, new OnRegisterSuccess() {
+ @Override
+ public void onRegisterSuccess(Name prefix, long registeredPrefixId) {
+ LOGGER.info("Prefix registered: " + prefix);
+ response1.countDown();
+ }
+ });
+ a.processEvents();
+ response1.await(1, TimeUnit.SECONDS);
+ assertEquals(0, response1.getCount());
+
+ LOGGER.info("Sending interest to prefix: " + prefix);
+ final CountDownLatch response2 = new CountDownLatch(1);
+ final AtomicBoolean received = new AtomicBoolean(false);
+ b.expressInterest(prefix, new OnData() {
+ @Override
+ public void onData(Interest interest, Data data) {
+ LOGGER.info("Received data: " + data.getName());
+ response2.countDown();
+ received.set(true);
+ }
+ }, new OnTimeout() {
+ @Override
+ public void onTimeout(Interest interest) {
+ LOGGER.info("Failed to receive data for interest: " + interest.toUri());
+ response2.countDown();
+ }
+ });
+ b.processEvents();
+ a.processEvents();
+ b.processEvents();
+ a.processEvents();
+
+ response2.await(1, TimeUnit.SECONDS);
+ assertTrue(received.get());
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/intel/jndn/mock/MockKeyChainTest.java b/src/test/java/com/intel/jndn/mock/MockKeyChainTest.java
index 86d3b13..1448423 100644
--- a/src/test/java/com/intel/jndn/mock/MockKeyChainTest.java
+++ b/src/test/java/com/intel/jndn/mock/MockKeyChainTest.java
@@ -1,6 +1,6 @@
/*
* jndn-mock
- * Copyright (c) 2015, Intel Corporation.
+ * Copyright (c) 2016, 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,
@@ -23,7 +23,7 @@
/**
* Test MockKeyChain.
*
- * @author Andrew Brown <andrew.brown@intel.com>
+ * @author Andrew Brown, andrew.brown@intel.com
*/
public class MockKeyChainTest {
diff --git a/src/test/java/com/intel/jndn/mock/forwarder/MockForwarderVisibilityTest.java b/src/test/java/com/intel/jndn/mock/forwarder/MockForwarderVisibilityTest.java
new file mode 100644
index 0000000..c38fa6e
--- /dev/null
+++ b/src/test/java/com/intel/jndn/mock/forwarder/MockForwarderVisibilityTest.java
@@ -0,0 +1,45 @@
+/*
+ * jndn-mock
+ * Copyright (c) 2016, 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.forwarder;
+
+import com.intel.jndn.mock.MockForwarder;
+import net.named_data.jndn.Face;
+import net.named_data.jndn.ForwardingFlags;
+import net.named_data.jndn.Interest;
+import net.named_data.jndn.Name;
+import net.named_data.jndn.transport.Transport;
+import org.junit.Test;
+
+/**
+ * Ensure MockForwarder methods are visible publicly; does not test functionality
+ *
+ * @author Andrew Brown, andrew.brown@intel.com
+ */
+public class MockForwarderVisibilityTest {
+
+ @Test
+ public void ensureVisibility() {
+ MockForwarder forwarder = new MockForwarder();
+
+ forwarder.connect();
+
+ forwarder.register(new Name("/a/b/c"), new MockForwarder.OnInterestReceived() {
+ @Override
+ public void in(Interest interest, Transport destinationTransport, Face sourceFace) {
+ // do nothing
+ }
+ }, new ForwardingFlags());
+ }
+}
\ No newline at end of file