diff --git a/router/java/test/junit/net/i2p/router/tunnel/GatewayTestBase.java b/router/java/test/junit/net/i2p/router/tunnel/GatewayTestBase.java
index 0b1f64fd1fb52b569430a48a1eaf6c7d974fb9d7..14fdc0ff05bef10773dbda346e79c8d828b23cba 100644
--- a/router/java/test/junit/net/i2p/router/tunnel/GatewayTestBase.java
+++ b/router/java/test/junit/net/i2p/router/tunnel/GatewayTestBase.java
@@ -16,17 +16,18 @@ import net.i2p.router.RouterContext;
 
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Test;
 
 public abstract class GatewayTestBase {
 
     protected static RouterContext _context;
-    protected static TunnelGatewayPumper _pumper;
+    private static TunnelGatewayPumper _pumper;
     protected static TunnelCreatorConfig _config;
     
-    protected TunnelGateway.QueuePreprocessor _preprocessor;
+    private TunnelGateway.QueuePreprocessor _preprocessor;
     protected TunnelGateway.Sender _sender;
     protected TestReceiver _receiver;
-    protected TunnelGateway _gw;
+    private TunnelGateway _gw;
     
     @BeforeClass
     public static void globalSetUp() {
@@ -50,8 +51,104 @@ public abstract class GatewayTestBase {
         _gw = new PumpedTunnelGateway(_context, _preprocessor, _sender, _receiver, _pumper);
     }
     
+    /** sets up the sender and receiver.  Subclasses must override */
     protected abstract void setupSenderAndReceiver();
     
+    /**
+     * @return at which hop to start the decryption process
+     */
+    protected abstract int getLastHop();
+    
+    @Test
+    public void testSmall() throws Exception {
+        int runCount = 1;
+        
+        List messages = new ArrayList(runCount);
+        long start = _context.clock().now();
+    
+        for (int i = 0; i < runCount; i++) {
+            DataMessage m = getTestMessage(64);
+            messages.add(m);
+            _gw.add(m, null, null);
+        }
+        
+        Thread.sleep(1000);
+        
+        List received = _receiver.clearReceived();
+        for (int i = 0; i < messages.size(); i++) {
+            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
+        }
+    }
+    
+    @Test
+    public void testRouter() throws Exception {
+        int runCount = 1;
+        
+        List messages = new ArrayList(runCount);
+        long start = _context.clock().now();
+    
+        for (int i = 0; i < runCount; i++) {
+            DataMessage m = getTestMessage(64);
+            Hash to = new Hash(new byte[Hash.HASH_LENGTH]);
+            java.util.Arrays.fill(to.getData(), (byte)0xFF);
+            messages.add(m);
+            _gw.add(m, to, null);
+        }
+        
+        Thread.sleep(1000);
+        
+        List received = _receiver.clearReceived();
+        for (int i = 0; i < messages.size(); i++) {
+            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
+        }
+    }
+    
+    @Test
+    public void testTunnel() throws Exception {
+        int runCount = 1;
+        
+        List messages = new ArrayList(runCount);
+        long start = _context.clock().now();
+    
+        for (int i = 0; i < runCount; i++) {
+            DataMessage m = getTestMessage(64);
+            Hash to = new Hash(new byte[Hash.HASH_LENGTH]);
+            java.util.Arrays.fill(to.getData(), (byte)0xFF);
+            TunnelId tunnel = new TunnelId(42);
+            byte data[] = m.toByteArray();
+            messages.add(m);
+            _gw.add(m, to, tunnel);
+        }
+        
+        Thread.sleep(1000);
+        
+        List received = _receiver.clearReceived();
+        for (int i = 0; i < messages.size(); i++) {
+            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
+        }
+    }
+    
+    @Test
+    public void testLarge() throws Exception {
+        int runCount = 1;
+        
+        List messages = new ArrayList(runCount);
+        long start = _context.clock().now();
+    
+        for (int i = 0; i < runCount; i++) {
+            DataMessage m = getTestMessage(1024);
+            messages.add(m);
+            _gw.add(m, null, null);
+        }
+        
+        Thread.sleep(1000);
+        
+        List received = _receiver.clearReceived();
+        for (int i = 0; i < messages.size(); i++) {
+            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
+        }
+    }
+    
     private static class TestRouterIdentity extends RouterIdentity {
         @Override
         public Hash getHash() {
@@ -59,7 +156,7 @@ public abstract class GatewayTestBase {
         }
     }
     
-    protected static DataMessage getTestMessage(int size) {
+    private static DataMessage getTestMessage(int size) {
         DataMessage m = new DataMessage(_context);
         m.setData(new byte[size]);
         java.util.Arrays.fill(m.getData(), (byte)0xFF);
@@ -82,7 +179,7 @@ public abstract class GatewayTestBase {
         public long receiveEncrypted(byte[] encrypted) {
             // fake all the hops...
             
-            for (int i = 1; i <= _config.getLength() - 2; i++) {
+            for (int i = 1; i <= _config.getLength() - getLastHop(); i++) {
                 HopProcessor hop = new HopProcessor(_context, _config.getConfig(i));
                 assertTrue(hop.process(encrypted, 0, encrypted.length, _config.getConfig(i).getReceiveFrom()));
             }
diff --git a/router/java/test/junit/net/i2p/router/tunnel/InboundGatewayTest.java b/router/java/test/junit/net/i2p/router/tunnel/InboundGatewayTest.java
index dd2a0a44c70fd150da43d147ec7edb75d6db0d70..ede9eae4eb81b3bfc1bd63ff374b8073d5101bfa 100644
--- a/router/java/test/junit/net/i2p/router/tunnel/InboundGatewayTest.java
+++ b/router/java/test/junit/net/i2p/router/tunnel/InboundGatewayTest.java
@@ -8,16 +8,8 @@ package net.i2p.router.tunnel;
  *
  */
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
 
 import static junit.framework.TestCase.*;
-import net.i2p.data.Hash;
-import net.i2p.data.TunnelId;
-import net.i2p.data.i2np.DataMessage;
-import net.i2p.data.i2np.I2NPMessage;
 
 /**
  * Quick unit test for base functionality of inbound tunnel 
@@ -32,93 +24,9 @@ public class InboundGatewayTest extends GatewayTestBase {
         _receiver = new InboundTestReceiver(_config);
     }
     
-    @Test
-    public void testSmall() throws Exception {
-    	int runCount = 1;
-    	
-        List messages = new ArrayList(runCount);
-        long start = _context.clock().now();
-    
-        for (int i = 0; i < runCount; i++) {
-           DataMessage m = getTestMessage(64);
-            messages.add(m);
-            _gw.add(m, null, null);
-        }
-
-        Thread.sleep(1000);
-        
-        List received = _receiver.clearReceived();
-        for (int i = 0; i < messages.size(); i++) {
-            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
-        }
-    }
-    
-    @Test
-    public void testRouter() throws Exception{
-    	int runCount = 1;
-    	
-        List messages = new ArrayList(runCount);
-        long start = _context.clock().now();
-    
-        for (int i = 0; i < runCount; i++) {
-            DataMessage m = getTestMessage(64);
-            Hash to = new Hash(new byte[Hash.HASH_LENGTH]);
-            java.util.Arrays.fill(to.getData(), (byte)0xFF);
-            messages.add(m);
-            _gw.add(m, to, null);
-        }
-        
-        Thread.sleep(1000);
-        
-        List received = _receiver.clearReceived();
-        for (int i = 0; i < messages.size(); i++) {
-            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
-        }
-    }
-    
-    @Test
-    public void testTunnel() throws Exception {
-    	int runCount = 1;
-    	
-        List messages = new ArrayList(runCount);
-        long start = _context.clock().now();
-    
-        for (int i = 0; i < runCount; i++) {
-            DataMessage m = getTestMessage(64);
-            Hash to = new Hash(new byte[Hash.HASH_LENGTH]);
-            java.util.Arrays.fill(to.getData(), (byte)0xFF);
-            TunnelId tunnel = new TunnelId(42);
-            messages.add(m);
-            _gw.add(m, to, tunnel);
-        }
-        
-        Thread.sleep(1000);
-        
-        List received = _receiver.clearReceived();
-        for (int i = 0; i < messages.size(); i++) {
-            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
-        }
-    }
-    
-    @Test
-    public void testLarge() throws Exception {
-    	int runCount = 1;
-    	
-        List messages = new ArrayList(runCount);
-        long start = _context.clock().now();
-    
-        for (int i = 0; i < runCount; i++) {
-            DataMessage m = getTestMessage(1024);
-            messages.add(m);
-            _gw.add(m, null, null);
-        }
-        
-        Thread.sleep(1000);
-        
-        List received = _receiver.clearReceived();
-        for (int i = 0; i < messages.size(); i++) {
-            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
-        }
+    @Override
+    protected int getLastHop() {
+        return 2;
     }
     
     private class InboundTestReceiver extends TestReceiver {
diff --git a/router/java/test/junit/net/i2p/router/tunnel/OutboundGatewayTest.java b/router/java/test/junit/net/i2p/router/tunnel/OutboundGatewayTest.java
index a5bb4adc5fffc9ced34cd368ef68a93e6e5247a2..e6eee6908f0e05b72b1f9669f7ef28fc3b628197 100644
--- a/router/java/test/junit/net/i2p/router/tunnel/OutboundGatewayTest.java
+++ b/router/java/test/junit/net/i2p/router/tunnel/OutboundGatewayTest.java
@@ -8,17 +8,6 @@ package net.i2p.router.tunnel;
  *
  */
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-
-import static junit.framework.TestCase.*;
-import net.i2p.data.Hash;
-import net.i2p.data.TunnelId;
-import net.i2p.data.i2np.DataMessage;
-import net.i2p.data.i2np.I2NPMessage;
-
 /**
  * Quick unit test for base functionality of outbound tunnel 
  * operation
@@ -31,131 +20,8 @@ public class OutboundGatewayTest extends GatewayTestBase {
         _receiver = new TestReceiver(_config);
     }
     
-    @Test
-    public void testSmall() throws Exception {
-    	int runCount = 1;
-    	
-        List messages = new ArrayList(runCount);
-        long start = _context.clock().now();
-    
-        for (int i = 0; i < runCount; i++) {
-            DataMessage m = getTestMessage(64);
-            messages.add(m);
-            _gw.add(m, null, null);
-        }
-        
-        Thread.sleep(10000);
-        
-        List received = _receiver.clearReceived();
-        for (int i = 0; i < messages.size(); i++) {
-            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
-        }
-    }
-    
-    @Test
-    public void testRouter() {
-    	int runCount = 1;
-    	
-        List messages = new ArrayList(runCount);
-        long start = _context.clock().now();
-    
-        for (int i = 0; i < runCount; i++) {
-            DataMessage m = getTestMessage(64);
-            Hash to = new Hash(new byte[Hash.HASH_LENGTH]);
-            java.util.Arrays.fill(to.getData(), (byte)0xFF);
-            messages.add(m);
-            _gw.add(m, to, null);
-        }
-        
-        long time = _context.clock().now() - start;
-        
-        List received = _receiver.clearReceived();
-        for (int i = 0; i < messages.size(); i++) {
-            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
-        }
-    }
-    
-    @Test
-    public void testTunnel() {
-    	int runCount = 1;
-    	
-        List messages = new ArrayList(runCount);
-        long start = _context.clock().now();
-    
-        for (int i = 0; i < runCount; i++) {
-            DataMessage m = getTestMessage(64);
-            Hash to = new Hash(new byte[Hash.HASH_LENGTH]);
-            java.util.Arrays.fill(to.getData(), (byte)0xFF);
-            TunnelId tunnel = new TunnelId(42);
-            byte data[] = m.toByteArray();
-            messages.add(m);
-            _gw.add(m, to, tunnel);
-        }
-        
-        long time = _context.clock().now() - start;
-        
-        List received = _receiver.clearReceived();
-        for (int i = 0; i < messages.size(); i++) {
-            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
-        }
-    }
-    
-    @Test
-    public void testLarge() {
-    	int runCount = 1;
-    	
-        List messages = new ArrayList(runCount);
-        long start = _context.clock().now();
-    
-        for (int i = 0; i < runCount; i++) {
-            DataMessage m = getTestMessage(1024);
-            messages.add(m);
-            _gw.add(m, null, null);
-        }
-        
-        long time = _context.clock().now() - start;
-        //try { Thread.sleep(60*1000); } catch (Exception e) {}
-        
-        List received = _receiver.clearReceived();
-        for (int i = 0; i < messages.size(); i++) {
-            assertTrue(received.contains(((I2NPMessage)messages.get(i))));
-        }
-    }
-    
-    private class TestReceiverr implements TunnelGateway.Receiver, FragmentHandler.DefragmentedReceiver {
-        private TunnelCreatorConfig _config;
-        private FragmentHandler _handler;
-        private List _received;
-        public TestReceiverr(TunnelCreatorConfig config) {
-            _config = config;
-            _handler = new FragmentHandler(_context, TestReceiverr.this);
-            _received = new ArrayList(1000);
-        }
-        public long receiveEncrypted(byte[] encrypted) {
-            // fake all the hops...
-            
-            for (int i = 1; i < _config.getLength(); i++) {
-                HopProcessor hop = new HopProcessor(_context, _config.getConfig(i));
-                assertTrue(hop.process(encrypted, 0, encrypted.length, _config.getConfig(i).getReceiveFrom()));
-                
-            }
-            
-
-            _handler.receiveTunnelMessage(encrypted, 0, encrypted.length);
-            return -1; // or do we need to return the real message ID?
-        }        
-        public void receiveComplete(I2NPMessage msg, Hash toRouter, TunnelId toTunnel) {
-            _received.add(msg);
-        }
-        public List clearReceived() { 
-            List rv = _received; 
-            _received = new ArrayList();
-            return rv;
-        }
-        @Override
-        public Hash getSendTo() {
-            // TODO Auto-generated method stub
-            return null;
-        }
+    @Override
+    protected int getLastHop() {
+        return 1;
     }
 }