diff --git a/components/net/sf/briar/transport/ConnectionWindowImpl.java b/components/net/sf/briar/transport/ConnectionWindowImpl.java
index 25910776f..fe0c1735a 100644
--- a/components/net/sf/briar/transport/ConnectionWindowImpl.java
+++ b/components/net/sf/briar/transport/ConnectionWindowImpl.java
@@ -31,6 +31,7 @@ class ConnectionWindowImpl implements ConnectionWindow {
public void setSeen(long connectionNumber) {
int offset = getOffset(connectionNumber);
int mask = 0x80000000 >>> offset;
+ if((bitmap & mask) != 0) throw new IllegalArgumentException();
bitmap |= mask;
// If the new connection number is above the centre, slide the window
if(connectionNumber >= centre) {
diff --git a/components/net/sf/briar/transport/TransportModule.java b/components/net/sf/briar/transport/TransportModule.java
index a2a6807cb..e1dd260a0 100644
--- a/components/net/sf/briar/transport/TransportModule.java
+++ b/components/net/sf/briar/transport/TransportModule.java
@@ -1,7 +1,6 @@
package net.sf.briar.transport;
import net.sf.briar.api.transport.ConnectionWindowFactory;
-import net.sf.briar.api.transport.PacketWriter;
import com.google.inject.AbstractModule;
diff --git a/test/build.xml b/test/build.xml
index a7b466eef..f034b76f4 100644
--- a/test/build.xml
+++ b/test/build.xml
@@ -32,6 +32,7 @@
+
diff --git a/test/net/sf/briar/transport/ConnectionWindowImplTest.java b/test/net/sf/briar/transport/ConnectionWindowImplTest.java
new file mode 100644
index 000000000..32a32ff6a
--- /dev/null
+++ b/test/net/sf/briar/transport/ConnectionWindowImplTest.java
@@ -0,0 +1,82 @@
+package net.sf.briar.transport;
+
+import junit.framework.TestCase;
+
+import org.junit.Test;
+
+public class ConnectionWindowImplTest extends TestCase {
+
+ @Test
+ public void testWindowSliding() {
+ ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0);
+ for(int i = 0; i < 100; i++) {
+ assertFalse(w.isSeen(i));
+ w.setSeen(i);
+ assertTrue(w.isSeen(i));
+ }
+ }
+
+ @Test
+ public void testWindowJumping() {
+ ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0);
+ for(int i = 0; i < 100; i += 13) {
+ assertFalse(w.isSeen(i));
+ w.setSeen(i);
+ assertTrue(w.isSeen(i));
+ }
+ }
+
+ @Test
+ public void testWindowUpperLimit() {
+ ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0);
+ // Centre is 0, highest value in window is 15
+ w.setSeen(15);
+ // Centre is 16, highest value in window is 31
+ w.setSeen(31);
+ try {
+ // Centre is 32, highest value in window is 47
+ w.setSeen(48);
+ fail();
+ } catch(IllegalArgumentException expected) {}
+ }
+
+ @Test
+ public void testWindowLowerLimit() {
+ ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0);
+ // Centre is 0, negative values should never be allowed
+ try {
+ w.setSeen(-1);
+ fail();
+ } catch(IllegalArgumentException expected) {}
+ // Slide the window
+ w.setSeen(15);
+ // Centre is 16, lowest value in window is 0
+ w.setSeen(0);
+ // Slide the window
+ w.setSeen(16);
+ // Centre is 17, lowest value in window is 1
+ w.setSeen(1);
+ try {
+ w.setSeen(0);
+ fail();
+ } catch(IllegalArgumentException expected) {}
+ // Slide the window
+ w.setSeen(25);
+ // Centre is 26, lowest value in window is 10
+ w.setSeen(10);
+ try {
+ w.setSeen(9);
+ fail();
+ } catch(IllegalArgumentException expected) {}
+ }
+
+ @Test
+ public void testCannotSetSameValueTwice() {
+ ConnectionWindowImpl w = new ConnectionWindowImpl(0L, 0);
+ w.setSeen(15);
+ try {
+ w.setSeen(15);
+ fail();
+ } catch(IllegalArgumentException expected) {}
+ }
+}