Moving /of to /openflow
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/HashValueUtilsTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/HashValueUtilsTest.java
new file mode 100644
index 0000000..1fe36ac
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/HashValueUtilsTest.java
@@ -0,0 +1,23 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+
+public class HashValueUtilsTest {
+ @Test
+ public void testBasic() {
+ long key = 0x1234_5678_1234_5678L;
+ long value = 0x8765_4321_8765_4321L;
+ long firstword = 0xFFFF_FFFF_0000_0000L;
+ long secondword = 0x0000_0000_FFFF_FFFFL;
+ long xor = key ^ value;
+
+ assertThat(HashValueUtils.combineWithValue(key, value, 0), equalTo(xor));
+ assertThat(HashValueUtils.combineWithValue(key, value, 64), equalTo(key));
+ assertThat(HashValueUtils.combineWithValue(key, value, 32), equalTo(key & firstword | xor & secondword ));
+ assertThat(HashValueUtils.combineWithValue(key, value, 8), equalTo(0x1251_1559_9551_1559L));
+ }
+
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java
new file mode 100644
index 0000000..2ba4528
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPAddressTest.java
@@ -0,0 +1,133 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Test;
+
+/**
+ * Most tests are in IPv4AddressTest and IPv6AddressTest
+ * Just exception testing here
+ * @author gregor
+ *
+ */
+public class IPAddressTest {
+ @Test
+ public void testOfException() {
+ try {
+ IPAddress.of("Foobar");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ IPAddressWithMask.of("Foobar");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ IPAddress.of((String) null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPAddressWithMask.of(null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPAddress.of((String) null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPAddressWithMask.of(null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testOfString() {
+ IPAddress<?> ip0 = IPAddress.of("1.2.3.4");
+ IPAddress<?> ip1 = IPAddress.of("abcd::1234");
+ assertTrue(ip0 instanceof IPv4Address);
+ assertTrue(ip1 instanceof IPv6Address);
+ assertEquals(ip0, IPv4Address.of("1.2.3.4"));
+ assertEquals(ip1, IPv6Address.of("abcd::1234"));
+ }
+
+ @Test
+ public void testOfInetAddress() throws Exception {
+ InetAddress ia0 = InetAddress.getByName("192.168.1.123");
+ InetAddress ia1 = InetAddress.getByName("fd00::4321");
+ IPAddress<?> ip0 = IPAddress.of(ia0);
+ IPAddress<?> ip1 = IPAddress.of(ia1);
+ assertTrue(ip0 instanceof IPv4Address);
+ assertTrue(ip1 instanceof IPv6Address);
+ assertEquals(ip0, IPv4Address.of(ia0));
+ assertEquals(ip1, IPv6Address.of(ia1));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testFromInetAddressException() throws UnknownHostException {
+ try {
+ IPAddress.fromInetAddress(null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
+ @Test
+ public void testContains() {
+
+ // Test IPv4 Mask
+ IPAddressWithMask<?> mask = IPAddressWithMask.of("1.2.3.4/24");
+
+ IPAddress<?> validIp = IPAddress.of("1.2.3.5");
+ assertTrue(mask.contains(validIp));
+
+ IPAddress<?> invalidIp = IPAddress.of("1.2.5.5");
+ assertFalse(mask.contains(invalidIp));
+
+ IPAddress<?> invalidIpv6 = IPAddress.of("10:10::ffff");
+ assertFalse(mask.contains(invalidIpv6));
+
+ // Test IPv6 Mask
+ mask = IPAddressWithMask.of("10:10::1/112");
+
+ validIp = IPAddress.of("10:10::f");
+ assertTrue(mask.contains(validIp));
+
+ invalidIp = IPAddress.of("11:10::f");
+ assertFalse(mask.contains(invalidIp));
+
+ IPAddress<?> invalidIpv4 = IPAddress.of("10.0.0.1");
+ assertFalse(mask.contains(invalidIpv4));
+ }
+
+ @Test
+ public void testContainsException() {
+ try {
+ IPAddressWithMask<?> mask = IPAddressWithMask.of("1.2.3.4/24");
+ mask.contains(null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java
new file mode 100644
index 0000000..0716b50
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java
@@ -0,0 +1,463 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+
+import org.hamcrest.CoreMatchers;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+
+public class IPv4AddressTest {
+ byte[][] testAddresses = new byte[][] {
+ {0x01, 0x02, 0x03, 0x04 },
+ {127, 0, 0, 1},
+ {(byte) 192, (byte) 168, 0, 100 },
+ {(byte) 255, (byte) 255, (byte) 255, (byte) 255 }
+ };
+
+ String[] testStrings = {
+ "1.2.3.4",
+ "127.0.0.1",
+ "192.168.0.100",
+ "255.255.255.255"
+ };
+
+ int[] testInts = {
+ 0x01020304,
+ 0x7f000001,
+ (192 << 24) | (168 << 16) | 100,
+ 0xffffffff
+ };
+
+ String[] invalidIPs = {
+ "",
+ ".",
+ "1.2..3.4",
+ "1.2.3.4.",
+ "257.11.225.1",
+ "256.11.225.1",
+ "-1.2.3.4",
+ "1.2.3.4.5",
+ "1.x.3.4",
+ "1.2x.3.4"
+ };
+
+ String[] ipsWithMask = {
+ "1.2.3.4/24",
+ "192.168.130.140/255.255.192.0",
+ "127.0.0.1/8",
+ "8.8.8.8",
+ "8.8.8.8/32",
+ "0.0.0.0/0",
+ "192.168.130.140/255.0.255.0",
+ "1.2.3.4/0.127.0.255"
+ };
+
+ boolean[] hasMask = {
+ true,
+ true,
+ true,
+ false,
+ false,
+ true,
+ true,
+ true
+ };
+
+ byte[][][] ipsWithMaskValues = {
+ new byte[][] { new byte[] { (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00 } },
+ new byte[][] { new byte[] { (byte)0xC0, (byte)0xA8, (byte)0x82, (byte)0x8C }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xC0, (byte)0x00 } },
+ new byte[][] { new byte[] { (byte)0x7F, (byte)0x00, (byte)0x00, (byte)0x01 }, new byte[] { (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0x00 } },
+ new byte[][] { new byte[] { (byte)0x08, (byte)0x08, (byte)0x08, (byte)0x08 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF } },
+ new byte[][] { new byte[] { (byte)0x08, (byte)0x08, (byte)0x08, (byte)0x08 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF } },
+ new byte[][] { new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }, new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 } },
+ new byte[][] { new byte[] { (byte)0xC0, (byte)0xA8, (byte)0x82, (byte)0x8C }, new byte[] { (byte)0xFF, (byte)0x00, (byte)0xFF, (byte)0x00 } },
+ new byte[][] { new byte[] { (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04 }, new byte[] { (byte)0x00, (byte)0x7F, (byte)0x00, (byte)0xFF } }
+ };
+
+ int[] ipsWithMaskLengths = {
+ 24,
+ 18,
+ 8,
+ 32,
+ 32,
+ 0,
+ -1,
+ -1
+ };
+
+ String[] invalidIpsWithMask = {
+ "asdf",
+ "1.2.3.4/33",
+ "1.2.3.4/34",
+ "1.2.3.4/-1",
+ "1.2.3.4/256.0.0.0",
+ "1.256.3.4/255.255.0.0",
+ "1.2.3.4/255.255.0.0.0",
+ };
+
+ @Test
+ public void testLogicalOperatorsBroadcast() {
+ assertTrue(IPv4Address.NO_MASK.not().equals(IPv4Address.FULL_MASK));
+ assertTrue(IPv4Address.NO_MASK.or(IPv4Address.FULL_MASK).
+ equals(IPv4Address.NO_MASK));
+ assertTrue(IPv4Address.NO_MASK.and(IPv4Address.FULL_MASK).
+ equals(IPv4Address.FULL_MASK));
+
+ assertTrue(IPv4Address.NO_MASK.isBroadcast());
+ assertTrue(!IPv4Address.FULL_MASK.isBroadcast());
+ }
+
+ @Test
+ public void testMaskedSubnetBroadcast() {
+ assertTrue(IPv4AddressWithMask.of("10.10.10.1/24")
+ .getSubnetBroadcastAddress()
+ .equals(IPv4Address.of("10.10.10.255")));
+ assertTrue(IPv4AddressWithMask.of("10.10.10.1/24")
+ .isSubnetBroadcastAddress(IPv4Address.of("10.10.10.255")));
+ assertTrue(!IPv4AddressWithMask.of("10.10.10.1/24")
+ .isSubnetBroadcastAddress(IPv4Address.of("10.10.10.254")));
+ }
+
+ @Test
+ public void testMaskedMatchesCidr() {
+ IPv4AddressWithMask slash28 = IPv4AddressWithMask.of("10.0.42.16/28");
+
+ String[] notContained = {"0.0.0.0", "11.0.42.16", "10.0.41.1", "10.0.42.0", "10.0.42.15",
+ "10.0.42.32", "255.255.255.255" };
+
+ for(String n: notContained) {
+ assertThat(String.format("slash 28 %s should not contain address %s",
+ slash28, n),
+ slash28.matches(IPv4Address.of(n)), equalTo(false));
+ }
+ for(int i=16; i < 32; i++) {
+ IPv4Address c = IPv4Address.of(String.format("10.0.42.%d", i));
+ assertThat(String.format("slash 28 %s should contain address %s",
+ slash28, c),
+ slash28.matches(c), equalTo(true));
+ }
+ }
+
+ @Test
+ public void testMaskedMatchesArbitrary() {
+ // irregular octect on the 3rd bitmask requires '1'bit to be set
+ // 4 bit unset, all others arbitrary
+ IPv4AddressWithMask slash28 = IPv4AddressWithMask.of("1.2.1.4/255.255.5.255");
+
+ String[] notContained = {"0.0.0.0", "1.2.3.5", "1.2.3.3",
+ "1.2.0.4", "1.2.2.4", "1.2.4.4", "1.2.5.4", "1.2.6.4", "1.2.7.4",
+ "1.2.8.4", "1.2.12.4", "1.2.13.4"
+ };
+ String[] contained = {"1.2.1.4", "1.2.3.4", "1.2.9.4", "1.2.11.4", "1.2.251.4",
+ };
+
+ for(String n: notContained) {
+ assertThat(String.format("slash 28 %s should not contain address %s",
+ slash28, n),
+ slash28.matches(IPv4Address.of(n)), equalTo(false));
+ }
+ for(String c: contained) {
+ IPv4Address addr = IPv4Address.of(c);
+ assertThat(String.format("slash 28 %s should contain address %s",
+ slash28, addr),
+ slash28.matches(addr), equalTo(true));
+ }
+
+ }
+
+
+ @Test
+ public void testConstants() {
+ byte[] zeros = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
+ byte[] ones = { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF };
+ // Make sure class initializtation and static assignment don't get
+ // messed up. Test everything twice for cached values
+ assertTrue(IPv4Address.NONE.isCidrMask());
+ assertEquals(0, IPv4Address.NONE.asCidrMaskLength());
+ assertArrayEquals(zeros, IPv4Address.NONE.getBytes());
+ assertTrue(IPv4Address.NONE.isCidrMask());
+ assertEquals(0, IPv4Address.NONE.asCidrMaskLength());
+ assertArrayEquals(zeros, IPv4Address.NONE.getBytes());
+
+ assertTrue(IPv4Address.NO_MASK.isCidrMask());
+ assertEquals(32, IPv4Address.NO_MASK.asCidrMaskLength());
+ assertArrayEquals(ones, IPv4Address.NO_MASK.getBytes());
+ assertTrue(IPv4Address.NO_MASK.isCidrMask());
+ assertEquals(32, IPv4Address.NO_MASK.asCidrMaskLength());
+ assertArrayEquals(ones, IPv4Address.NO_MASK.getBytes());
+
+ assertTrue(IPv4Address.FULL_MASK.isCidrMask());
+ assertEquals(0, IPv4Address.FULL_MASK.asCidrMaskLength());
+ assertArrayEquals(zeros, IPv4Address.FULL_MASK.getBytes());
+ assertTrue(IPv4Address.FULL_MASK.isCidrMask());
+ assertEquals(0, IPv4Address.FULL_MASK.asCidrMaskLength());
+ assertArrayEquals(zeros, IPv4Address.FULL_MASK.getBytes());
+ }
+
+
+ @Test
+ public void testOfString() {
+ for(int i=0; i < testAddresses.length; i++ ) {
+ IPv4Address ip = IPv4Address.of(testStrings[i]);
+ assertEquals(testInts[i], ip.getInt());
+ assertArrayEquals(testAddresses[i], ip.getBytes());
+ assertEquals(testStrings[i], ip.toString());
+ }
+ }
+
+ @Test
+ public void testOfByteArray() {
+ for(int i=0; i < testAddresses.length; i++ ) {
+ IPv4Address ip = IPv4Address.of(testAddresses[i]);
+ assertEquals(testInts[i], ip.getInt());
+ assertArrayEquals(testAddresses[i], ip.getBytes());
+ assertEquals(testStrings[i], ip.toString());
+ }
+ }
+
+ @Test
+ public void testOfCidrMaskLength() {
+ for (int i = 0; i <= 32; i++) {
+ assertEquals(IPv4Address.ofCidrMaskLength(i).asCidrMaskLength(), i);
+ }
+
+ assertEquals(IPv4Address.ofCidrMaskLength(0).getInt(), 0x0000_0000);
+
+ assertEquals(IPv4Address.ofCidrMaskLength(1).getInt(), 0x8000_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(2).getInt(), 0xC000_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(3).getInt(), 0xE000_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(4).getInt(), 0xF000_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(5).getInt(), 0xF800_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(6).getInt(), 0xFC00_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(7).getInt(), 0xFE00_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(8).getInt(), 0xFF00_0000);
+
+ assertEquals(IPv4Address.ofCidrMaskLength(9).getInt(), 0xFF80_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(10).getInt(), 0xFFC0_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(11).getInt(), 0xFFE0_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(12).getInt(), 0xFFF0_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(13).getInt(), 0xFFF8_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(14).getInt(), 0xFFFC_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(15).getInt(), 0xFFFE_0000);
+ assertEquals(IPv4Address.ofCidrMaskLength(16).getInt(), 0xFFFF_0000);
+
+ assertEquals(IPv4Address.ofCidrMaskLength(17).getInt(), 0xFFFF_8000);
+ assertEquals(IPv4Address.ofCidrMaskLength(18).getInt(), 0xFFFF_C000);
+ assertEquals(IPv4Address.ofCidrMaskLength(19).getInt(), 0xFFFF_E000);
+ assertEquals(IPv4Address.ofCidrMaskLength(20).getInt(), 0xFFFF_F000);
+ assertEquals(IPv4Address.ofCidrMaskLength(21).getInt(), 0xFFFF_F800);
+ assertEquals(IPv4Address.ofCidrMaskLength(22).getInt(), 0xFFFF_FC00);
+ assertEquals(IPv4Address.ofCidrMaskLength(23).getInt(), 0xFFFF_FE00);
+ assertEquals(IPv4Address.ofCidrMaskLength(24).getInt(), 0xFFFF_FF00);
+
+ assertEquals(IPv4Address.ofCidrMaskLength(25).getInt(), 0xFFFF_FF80);
+ assertEquals(IPv4Address.ofCidrMaskLength(26).getInt(), 0xFFFF_FFC0);
+ assertEquals(IPv4Address.ofCidrMaskLength(27).getInt(), 0xFFFF_FFE0);
+ assertEquals(IPv4Address.ofCidrMaskLength(28).getInt(), 0xFFFF_FFF0);
+ assertEquals(IPv4Address.ofCidrMaskLength(29).getInt(), 0xFFFF_FFF8);
+ assertEquals(IPv4Address.ofCidrMaskLength(30).getInt(), 0xFFFF_FFFC);
+ assertEquals(IPv4Address.ofCidrMaskLength(31).getInt(), 0xFFFF_FFFE);
+ assertEquals(IPv4Address.ofCidrMaskLength(32).getInt(), 0xFFFF_FFFF);
+ }
+
+ @Test
+ public void testWithMask() throws Exception {
+ // Sanity tests for the withMask*() syntactic sugars
+
+ IPv4Address original = IPv4Address.of("192.168.1.101");
+ IPv4Address expectedValue = IPv4Address.of("192.168.1.0");
+ IPv4Address expectedMask = IPv4Address.of("255.255.255.0");
+
+ IPv4AddressWithMask v;
+
+ v = original.withMask(IPv4Address.of(new byte[] {-1, -1, -1, 0}));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMask(IPv4Address.of(0xFFFF_FF00));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMask(IPv4Address.of("255.255.255.0"));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ Inet4Address i4a = (Inet4Address) InetAddress.getByName("255.255.255.0");
+ v = original.withMask(IPv4Address.of(i4a));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMaskOfLength(24);
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+ }
+
+ @Test
+ public void testReadFrom() throws OFParseError {
+ for(int i=0; i < testAddresses.length; i++ ) {
+ IPv4Address ip = IPv4Address.read4Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
+ assertEquals(testInts[i], ip.getInt());
+ assertArrayEquals(testAddresses[i], ip.getBytes());
+ assertEquals(testStrings[i], ip.toString());
+ }
+ }
+
+
+ @Test
+ public void testInvalidIPs() throws OFParseError {
+ for(String invalid : invalidIPs) {
+ try {
+ IPv4Address.of(invalid);
+ fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+ } catch(IllegalArgumentException e) {
+ // ok
+ }
+ }
+ }
+
+ @Test
+ public void testOfMasked() throws OFParseError {
+ for (int i = 0; i < ipsWithMask.length; i++) {
+ IPv4AddressWithMask value = IPv4AddressWithMask.of(ipsWithMask[i]);
+ if (!hasMask[i]) {
+ IPv4Address ip = value.getValue();
+ assertArrayEquals(ipsWithMaskValues[i][0], ip.getBytes());
+ }
+ IPv4Address mask = value.getMask();
+ if (ipsWithMaskLengths[i] == -1) {
+ assertFalse(mask.isCidrMask());
+ try {
+ mask.asCidrMaskLength();
+ fail("Expected IllegalStateException not thrown");
+ } catch(IllegalStateException e) {
+ //expected
+ }
+ } else {
+ assertTrue(mask.isCidrMask());
+ assertEquals(ipsWithMaskLengths[i], mask.asCidrMaskLength());
+ }
+ assertArrayEquals(ipsWithMaskValues[i][1], mask.getBytes());
+ byte[] ipBytes = new byte[4];
+ System.arraycopy(ipsWithMaskValues[i][0], 0, ipBytes, 0, 4);
+ assertEquals(ipBytes.length, value.getValue().getBytes().length);
+ for (int j = 0; j < ipBytes.length; j++) {
+ ipBytes[j] &= ipsWithMaskValues[i][1][j];
+ }
+
+ assertArrayEquals(ipBytes, value.getValue().getBytes());
+ assertThat(String.format("Byte comparison for mask of %s (%s)", ipsWithMask[i], value),
+ value.getMask().getBytes(), CoreMatchers.equalTo(ipsWithMaskValues[i][1]));
+ }
+ }
+
+ @Test
+ public void testOfMaskedInvalid() throws Exception {
+ for(String invalid : invalidIpsWithMask) {
+ try {
+ IPv4Address.of(invalid);
+ fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+ } catch(IllegalArgumentException e) {
+ // ok
+ }
+ }
+ }
+
+ @Test
+ public void testSuperclass() throws Exception {
+ for(String ipString: testStrings) {
+ IPAddress<?> superIp = IPAddress.of(ipString);
+ assertEquals(IPVersion.IPv4, superIp.getIpVersion());
+ assertEquals(IPv4Address.of(ipString), superIp);
+ }
+
+ for(String ipMaskedString: ipsWithMask) {
+ IPAddressWithMask<?> superIp = IPAddressWithMask.of(ipMaskedString);
+ assertEquals(IPVersion.IPv4, superIp.getIpVersion());
+ assertEquals(IPv4AddressWithMask.of(ipMaskedString), superIp);
+ }
+ }
+
+ @Test
+ public void testOfExceptions() {
+ // We check if the message of a caught NPE is set to a useful message
+ // as a hacky way of verifying that we got an NPE thrown by use rather
+ // than one the JVM created for a null access.
+ try {
+ String s = null;
+ IPv4Address.of(s);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ byte[] b = null;
+ IPv4Address.of(b);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ byte[] b = new byte[3];
+ IPv4Address.of(b);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ byte[] b = new byte[5];
+ IPv4Address.of(b);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ IPv4AddressWithMask.of(null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv4AddressWithMask.of(IPv4Address.of("1.2.3.4"), null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv4AddressWithMask.of(null, IPv4Address.of("255.0.0.0"));
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv4AddressWithMask.of(IPv4Address.of("10.10.10.0"),
+ IPv4Address.of("255.0.255.0"))
+ .getSubnetBroadcastAddress();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv4Address.ofCidrMaskLength(-1);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv4Address.ofCidrMaskLength(33);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
new file mode 100644
index 0000000..a397c2a
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
@@ -0,0 +1,402 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.junit.Assert.*;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.hamcrest.CoreMatchers;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+
+import com.google.common.io.BaseEncoding;
+
+public class IPv6AddressTest {
+
+ String[] testStrings = {
+ "::",
+ "::1",
+ "ffe0::",
+ "1:2:3:4:5:6:7:8"
+ };
+
+
+ private final BaseEncoding hex = BaseEncoding.base16().omitPadding().lowerCase();
+
+ private class WithMaskTaskCase {
+ final String input;
+ boolean hasMask;
+ int expectedMaskLength = 128;
+ byte[] expectedMask = hex.decode("ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff".replaceAll(" ", ""));
+
+ public WithMaskTaskCase(String input) {
+ super();
+ this.input = input;
+ }
+
+ public WithMaskTaskCase maskHex(String string) {
+ string = string.replaceAll(" ", "");
+ this.hasMask = true;
+ expectedMask = hex.decode(string);
+ return this;
+ }
+
+ public WithMaskTaskCase expectedMaskLength(int expectedLength) {
+ this.expectedMaskLength = expectedLength;
+ return this;
+ }
+
+ }
+
+ WithMaskTaskCase[] withMasks = new WithMaskTaskCase[] {
+ new WithMaskTaskCase("1::1/80")
+ .maskHex("ff ff ff ff ff ff ff ff ff ff 00 00 00 00 00 00")
+ .expectedMaskLength(80),
+
+ new WithMaskTaskCase("ffff:ffee:1::/ff00:ff00:ff00:ff00::")
+ .maskHex("ff 00 ff 00 ff 00 ff 00 00 00 00 00 00 00 00 00")
+ .expectedMaskLength(-1),
+ new WithMaskTaskCase("1:2:3:4:5:6:7:8/1::ff00:ff00")
+ .maskHex("00 01 00 00 00 00 00 00 00 00 00 00 ff 00 ff 00")
+ .expectedMaskLength(-1),
+ new WithMaskTaskCase("1:2:3:4:5:6:7:8/::ff00:ff00")
+ .maskHex("00 00 00 00 00 00 00 00 00 00 00 00 ff 00 ff 00")
+ .expectedMaskLength(-1),
+ new WithMaskTaskCase("1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff::ff00:ff00")
+ .maskHex("ff ff ff ff ff ff ff ff ff ff 00 00 ff 00 ff 00")
+ .expectedMaskLength(-1),
+ new WithMaskTaskCase("8:8:8:8:8:8:8:8"),
+ new WithMaskTaskCase("8:8:8:8:8:8:8:8"),
+ new WithMaskTaskCase("1:2:3:4:5:6:7:8/128"),
+ new WithMaskTaskCase("::/0")
+ .maskHex("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00")
+ .expectedMaskLength(0),
+ };
+
+ @Test
+ public void testLogicalOperatorsBroadcast() {
+ assertTrue(IPv6Address.NO_MASK.not().equals(IPv6Address.FULL_MASK));
+ assertTrue(IPv6Address.NO_MASK.or(IPv6Address.FULL_MASK).
+ equals(IPv6Address.NO_MASK));
+ assertTrue(IPv6Address.NO_MASK.and(IPv6Address.FULL_MASK).
+ equals(IPv6Address.FULL_MASK));
+
+ assertTrue(IPv6Address.NO_MASK.isBroadcast());
+ assertTrue(!IPv6Address.FULL_MASK.isBroadcast());
+ }
+
+ @Test
+ public void testMaskedSubnetBroadcast() {
+ assertTrue(IPv6AddressWithMask.of("10:10::1/112")
+ .getSubnetBroadcastAddress()
+ .equals(IPv6Address.of("10:10::ffff")));
+ assertTrue(IPv6AddressWithMask.of("10:10::1/112")
+ .isSubnetBroadcastAddress(IPv6Address.of("10:10::ffff")));
+ assertTrue(!IPv6AddressWithMask.of("10:10::1/112")
+ .isSubnetBroadcastAddress(IPv6Address.of("10:10::fffd")));
+ }
+
+ @Test
+ public void testConstants() {
+ byte[] zeros = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
+ byte[] ones = { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
+ (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
+ (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF,
+ (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF };
+ // Make sure class initializtation and static assignment don't get
+ // messed up. Test everything twice for cached values
+ assertTrue(IPv6Address.NONE.isCidrMask());
+ assertEquals(0, IPv6Address.NONE.asCidrMaskLength());
+ assertArrayEquals(zeros, IPv6Address.NONE.getBytes());
+ assertTrue(IPv6Address.NONE.isCidrMask());
+ assertEquals(0, IPv6Address.NONE.asCidrMaskLength());
+ assertArrayEquals(zeros, IPv6Address.NONE.getBytes());
+
+ assertTrue(IPv6Address.NO_MASK.isCidrMask());
+ assertEquals(128, IPv6Address.NO_MASK.asCidrMaskLength());
+ assertArrayEquals(ones, IPv6Address.NO_MASK.getBytes());
+ assertTrue(IPv6Address.NO_MASK.isCidrMask());
+ assertEquals(128, IPv6Address.NO_MASK.asCidrMaskLength());
+ assertArrayEquals(ones, IPv6Address.NO_MASK.getBytes());
+
+ assertTrue(IPv6Address.FULL_MASK.isCidrMask());
+ assertEquals(0, IPv6Address.FULL_MASK.asCidrMaskLength());
+ assertArrayEquals(zeros, IPv6Address.FULL_MASK.getBytes());
+ assertTrue(IPv6Address.FULL_MASK.isCidrMask());
+ assertEquals(0, IPv6Address.FULL_MASK.asCidrMaskLength());
+ assertArrayEquals(zeros, IPv6Address.FULL_MASK.getBytes());
+ }
+
+ @Test
+ public void testMasked() throws UnknownHostException {
+ for(WithMaskTaskCase w: withMasks) {
+ IPv6AddressWithMask value = IPv6AddressWithMask.of(w.input);
+ if (!w.hasMask) {
+ IPv6Address ip = value.getValue();
+ InetAddress inetAddress = InetAddress.getByName(w.input.split("/")[0]);
+
+ assertArrayEquals(ip.getBytes(), inetAddress.getAddress());
+ assertEquals(w.input.split("/")[0], ip.toString());
+ }
+ InetAddress inetAddress = InetAddress.getByName(w.input.split("/")[0]);
+
+ if (w.expectedMaskLength == -1) {
+ assertFalse(value.getMask().isCidrMask());
+ try {
+ value.getMask().asCidrMaskLength();
+ fail("Expected IllegalStateException not thrown");
+ } catch(IllegalStateException e) {
+ //expected
+ }
+ } else {
+ assertTrue(value.getMask().isCidrMask());
+ assertEquals("Input " + w.input, w.expectedMaskLength,
+ value.getMask().asCidrMaskLength());
+ }
+
+ byte[] address = inetAddress.getAddress();
+ assertEquals(address.length, value.getValue().getBytes().length);
+
+ for (int j = 0; j < address.length; j++) {
+ address[j] &= w.expectedMask[j];
+ }
+
+ assertThat("Address bytes for input " + w.input + ", value=" + value, value.getValue().getBytes(), CoreMatchers.equalTo(address));
+ assertThat("mask check for input " + w.input + ", value=" + value, value.getMask().getBytes(), CoreMatchers.equalTo(w.expectedMask));
+ }
+ for (int i = 0; i <= 128; i++) {
+ String ipString = String.format("8001:2::1/%d", i);
+ IPv6AddressWithMask value = IPv6AddressWithMask.of(ipString);
+ assertEquals("Input " + ipString, i, value.getMask().asCidrMaskLength());
+ }
+ }
+
+
+ @Test
+ public void testOfString() throws UnknownHostException {
+ for(int i=0; i < testStrings.length; i++ ) {
+ IPv6Address ip = IPv6Address.of(testStrings[i]);
+ InetAddress inetAddress = InetAddress.getByName(testStrings[i]);
+
+ assertArrayEquals(ip.getBytes(), inetAddress.getAddress());
+ assertEquals(testStrings[i], ip.toString());
+ }
+ }
+
+ @Test
+ public void testOfByteArray() throws UnknownHostException {
+ for(int i=0; i < testStrings.length; i++ ) {
+ byte[] bytes = Inet6Address.getByName(testStrings[i]).getAddress();
+ IPv6Address ip = IPv6Address.of(bytes);
+ assertEquals(testStrings[i], ip.toString());
+ assertArrayEquals(bytes, ip.getBytes());
+ }
+ }
+
+ private static void testOfCidrMaskLengthHelper(
+ int cidrMaskLength, String ipStr) throws UnknownHostException {
+ byte[] ba0 = IPv6Address.ofCidrMaskLength(cidrMaskLength).getBytes();
+ byte[] ba1 = Inet6Address.getByName(ipStr).getAddress();
+ assertArrayEquals(ba0, ba1);
+ }
+
+ @Test
+ public void testOfCidrMaskLength() throws UnknownHostException {
+ for (int i = 0; i <= 128; i++) {
+ assertTrue(IPv6Address.ofCidrMaskLength(i).isCidrMask());
+ assertEquals(IPv6Address.ofCidrMaskLength(i).asCidrMaskLength(), i);
+ }
+ testOfCidrMaskLengthHelper(0, "::");
+ testOfCidrMaskLengthHelper(1, "8000::");
+ testOfCidrMaskLengthHelper(2, "c000::");
+ testOfCidrMaskLengthHelper(8, "ff00::");
+ testOfCidrMaskLengthHelper(16, "ffff::");
+ testOfCidrMaskLengthHelper(17, "ffff:8000::");
+ testOfCidrMaskLengthHelper(31, "ffff:fffe::");
+ testOfCidrMaskLengthHelper(32, "ffff:ffff::");
+ testOfCidrMaskLengthHelper(33, "ffff:ffff:8000::");
+ testOfCidrMaskLengthHelper(46, "ffff:ffff:fffc::");
+ testOfCidrMaskLengthHelper(48, "ffff:ffff:ffff::");
+ testOfCidrMaskLengthHelper(55, "ffff:ffff:ffff:fe00::");
+ testOfCidrMaskLengthHelper(56, "ffff:ffff:ffff:ff00::");
+ testOfCidrMaskLengthHelper(59, "ffff:ffff:ffff:ffe0::");
+ testOfCidrMaskLengthHelper(63, "ffff:ffff:ffff:fffe::");
+ testOfCidrMaskLengthHelper(64, "ffff:ffff:ffff:ffff::");
+ testOfCidrMaskLengthHelper(65, "ffff:ffff:ffff:ffff:8000::");
+ testOfCidrMaskLengthHelper(67, "ffff:ffff:ffff:ffff:e000::");
+ testOfCidrMaskLengthHelper(100, "ffff:ffff:ffff:ffff:ffff:ffff:f000::");
+ testOfCidrMaskLengthHelper(101, "ffff:ffff:ffff:ffff:ffff:ffff:f800::");
+ testOfCidrMaskLengthHelper(126, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc");
+ testOfCidrMaskLengthHelper(127, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe");
+ testOfCidrMaskLengthHelper(128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ }
+
+ @Test
+ public void testWithMask() throws Exception {
+ // Sanity tests for the withMask*() syntactic sugars
+
+ IPv6Address original = IPv6Address.of("fd12:3456:ABCD:7890::1");
+ IPv6Address expectedValue = IPv6Address.of("fd12:3456:ABCD::");
+ IPv6Address expectedMask = IPv6Address.of("ffff:ffff:ffff::");
+
+ IPv6AddressWithMask v;
+
+ v = original.withMask(IPv6Address.of(new byte[] {
+ -1, -1, -1, -1, -1, -1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMask(IPv6Address.of(
+ 0xFFFF_FFFF_FFFF_0000L, 0x0000_0000_0000_0000L));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMask(IPv6Address.of("ffff:ffff:ffff::"));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ Inet6Address i6a = (Inet6Address) InetAddress.getByName("ffff:ffff:ffff::");
+ v = original.withMask(IPv6Address.of(i6a));
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+
+ v = original.withMaskOfLength(48);
+ assertEquals(v.getValue(), expectedValue);
+ assertEquals(v.getMask(), expectedMask);
+ }
+
+ @Test
+ public void testReadFrom() throws OFParseError, UnknownHostException {
+ for(int i=0; i < testStrings.length; i++ ) {
+ byte[] bytes = Inet6Address.getByName(testStrings[i]).getAddress();
+ IPv6Address ip = IPv6Address.read16Bytes(ChannelBuffers.copiedBuffer(bytes));
+ assertEquals(testStrings[i], ip.toString());
+ assertArrayEquals(bytes, ip.getBytes());
+ }
+ }
+
+ String[] invalidIPs = {
+ "",
+ ":",
+ "1:2:3:4:5:6:7:8:9",
+ "1:2:3:4:5:6:7:8:",
+ "1:2:3:4:5:6:7:8g",
+ "1:2:3:",
+ "12345::",
+ "1::3::8",
+ "::3::"
+ };
+
+ @Test
+ public void testInvalidIPs() throws OFParseError {
+ for(String invalid : invalidIPs) {
+ try {
+ IPv6Address.of(invalid);
+ fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+ } catch(IllegalArgumentException e) {
+ // ok
+ }
+ }
+ }
+
+ @Test
+ public void testZeroCompression() throws OFParseError {
+ assertEquals("::", IPv6Address.of("::").toString(true, false));
+ assertEquals("0:0:0:0:0:0:0:0", IPv6Address.of("::").toString(false, false));
+ assertEquals("0000:0000:0000:0000:0000:0000:0000:0000", IPv6Address.of("::").toString(false, true));
+ assertEquals("1::4:5:6:0:8", IPv6Address.of("1:0:0:4:5:6:0:8").toString(true, false));
+ assertEquals("1:0:0:4::8", IPv6Address.of("1:0:0:4:0:0:0:8").toString(true, false));
+ }
+
+ @Test
+ public void testSuperclass() throws Exception {
+ for(String ipString: testStrings) {
+ IPAddress<?> superIp = IPAddress.of(ipString);
+ assertEquals(IPVersion.IPv6, superIp.getIpVersion());
+ assertEquals(IPv6Address.of(ipString), superIp);
+ }
+
+ for(WithMaskTaskCase w: withMasks) {
+ String ipMaskedString = w.input;
+ IPAddressWithMask<?> superIp = IPAddressWithMask.of(ipMaskedString);
+ assertEquals(IPVersion.IPv6, superIp.getIpVersion());
+ assertEquals(IPv6AddressWithMask.of(ipMaskedString), superIp);
+ }
+ }
+
+ @Test
+ public void testOfExceptions() throws Exception {
+ try {
+ IPv6AddressWithMask.of(null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ String s = null;
+ IPv6Address.of(s);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ byte[] b = null;
+ IPv6Address.of(b);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ byte[] b = new byte[7];
+ IPv6Address.of(b);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ byte[] b = new byte[9];
+ IPv6Address.of(b);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ IPv6AddressWithMask.of(IPv6Address.of("1::"), null);
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv6AddressWithMask.of(null, IPv6Address.of("255::"));
+ fail("Should have thrown NullPointerException");
+ } catch (NullPointerException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv6AddressWithMask.of(IPv6Address.of("10:10::0"),
+ IPv6Address.of("ffff:0:ffff::"))
+ .getSubnetBroadcastAddress();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv6Address.ofCidrMaskLength(-1);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
+ try {
+ IPv6Address.ofCidrMaskLength(129);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertNotNull(e.getMessage());
+ }
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
new file mode 100644
index 0000000..a13fdd4
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
@@ -0,0 +1,154 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+
+public class MacAddressTest {
+ byte[][] testAddresses = new byte[][] {
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
+ {(byte) 0x80, 0x0, 0x0, 0x0, 0x0, 0x01},
+ {(byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255, (byte) 255 }
+ };
+
+ String[] testStrings = {
+ "01:02:03:04:05:06",
+ "80:00:00:00:00:01",
+ "ff:ff:ff:ff:ff:ff"
+ };
+
+ long[] testInts = {
+ 0x00010203040506L,
+ 0x00800000000001L,
+ 0x00ffffffffffffL
+ };
+
+ String[] invalidMacStrings = {
+ "",
+ "1.2.3.4",
+ "0T:00:01:02:03:04",
+ "00:01:02:03:04:05:06",
+ "00:ff:ef:12:12:ff:",
+ "00:fff:ef:12:12:ff",
+ "01:02:03:04:05;06",
+ "0:1:2:3:4:5:6",
+ "01:02:03:04"
+ };
+
+ byte[][] invalidMacBytes = {
+ new byte[]{0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
+ new byte[]{0x01, 0x01, 0x02, 0x03, 0x04}
+ };
+
+ @Test
+ public void testOfString() {
+ for(int i=0; i < testAddresses.length; i++ ) {
+ MacAddress ip = MacAddress.of(testStrings[i]);
+ assertEquals(testInts[i], ip.getLong());
+ assertArrayEquals(testAddresses[i], ip.getBytes());
+ assertEquals(testStrings[i], ip.toString());
+ }
+ }
+
+ @Test
+ public void testOfByteArray() {
+ for(int i=0; i < testAddresses.length; i++ ) {
+ MacAddress ip = MacAddress.of(testAddresses[i]);
+ assertEquals("error checking long representation of "+Arrays.toString(testAddresses[i]) + "(should be "+Long.toHexString(testInts[i]) +")", testInts[i], ip.getLong());
+ assertArrayEquals(testAddresses[i], ip.getBytes());
+ assertEquals(testStrings[i], ip.toString());
+ }
+ }
+
+ @Test
+ public void testReadFrom() throws OFParseError {
+ for(int i=0; i < testAddresses.length; i++ ) {
+ MacAddress ip = MacAddress.read6Bytes(ChannelBuffers.copiedBuffer(testAddresses[i]));
+ assertEquals(testInts[i], ip.getLong());
+ assertArrayEquals(testAddresses[i], ip.getBytes());
+ assertEquals(testStrings[i], ip.toString());
+ }
+ }
+
+
+ @Test
+ public void testInvalidMacStrings() throws OFParseError {
+ for(String invalid : invalidMacStrings) {
+ try {
+ MacAddress.of(invalid);
+ fail("Invalid MAC address "+invalid+ " should have raised IllegalArgumentException");
+ } catch(IllegalArgumentException e) {
+ // ok
+ }
+ }
+ }
+
+ @Test
+ public void testInvalidMacBytes() throws OFParseError {
+ for(byte[] invalid : invalidMacBytes) {
+ try {
+ MacAddress.of(invalid);
+ fail("Invalid MAC address bytes "+ Arrays.toString(invalid) + " should have raised IllegalArgumentException");
+ } catch(IllegalArgumentException e) {
+ // ok
+ }
+ }
+ }
+
+ // Test data is imported from org.projectfloodlight.packet.EthernetTest
+ @Test
+ public void testToLong() {
+ assertEquals(
+ 281474976710655L,
+ MacAddress.of(new byte[]{(byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}).getLong());
+
+ assertEquals(
+ 1103823438081L,
+ MacAddress.of(new byte[] { (byte) 0x01, (byte) 0x01,
+ (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01 }).getLong());
+
+ assertEquals(
+ 141289400074368L,
+ MacAddress.of(new byte[] { (byte) 0x80, (byte) 0x80,
+ (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80 }).getLong());
+
+ }
+
+ @Test
+ public void testIsBroadcast() {
+ assertTrue(MacAddress.of("FF:FF:FF:FF:FF:FF").isBroadcast());
+ assertTrue(MacAddress.of(-1).isBroadcast());
+ assertTrue(MacAddress.of(0x05FFFFFFFFFFFFL).isBroadcast());
+ assertFalse(MacAddress.of("11:22:33:44:55:66").isBroadcast());
+ }
+
+ @Test
+ public void testIsMulticast() {
+ assertTrue(MacAddress.of("01:80:C2:00:00:00").isMulticast());
+ assertFalse(MacAddress.of("00:80:C2:00:00:00").isMulticast());
+ assertFalse(MacAddress.of("FE:80:C2:00:00:00").isMulticast());
+ assertFalse(MacAddress.of(-1).isMulticast());
+ assertFalse(MacAddress.of(0x05FFFFFFFFFFFFL).isMulticast());
+ assertFalse(MacAddress.of("FF:FF:FF:FF:FF:FF").isMulticast());
+ }
+
+ @Test
+ public void testIsLLDPAddress() {
+ assertTrue(MacAddress.of("01:80:C2:00:00:00").isLLDPAddress());
+ assertTrue(MacAddress.of("01:80:C2:00:00:0f").isLLDPAddress());
+ assertFalse(MacAddress.of("01:80:C2:00:00:50").isLLDPAddress());
+ assertFalse(MacAddress.of("01:80:C2:00:10:00").isLLDPAddress());
+ assertFalse(MacAddress.of("01:80:C2:40:00:01").isLLDPAddress());
+ assertFalse(MacAddress.of("00:80:C2:f0:00:00").isLLDPAddress());
+ assertFalse(MacAddress.of("FE:80:C2:00:00:00").isLLDPAddress());
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFErrorCauseDataTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFErrorCauseDataTest.java
new file mode 100644
index 0000000..9a5a4dc
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFErrorCauseDataTest.java
@@ -0,0 +1,74 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.hamcrest.Matchers;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFlowAdd;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+public class OFErrorCauseDataTest {
+ @Test
+ public void testEmpty() {
+ OFErrorCauseData emptyCause = OFErrorCauseData.of(new byte[] {}, OFVersion.OF_13);
+ assertThat(emptyCause.getData(), equalTo(new byte[] {}));
+ assertThat(emptyCause.getParsedMessage().isPresent(), equalTo(false));
+ assertThat(emptyCause.toString(), Matchers.containsString("unparsed"));
+ }
+
+ @Test
+ public void testTooShort() {
+ OFErrorCauseData emptyCause = OFErrorCauseData.of(new byte[] {0x1, 0x2}, OFVersion.OF_13);
+ assertThat(emptyCause.getData(), equalTo(new byte[] {0x1, 0x2}));
+ assertThat(emptyCause.getParsedMessage().isPresent(), equalTo(false));
+ assertThat(emptyCause.toString(), Matchers.containsString("unparsed"));
+ assertThat(emptyCause.toString(), Matchers.containsString("01 02"));
+ }
+
+ byte[] truncatedFlowAddd = new byte[] {
+ 0x04, 0x0e, // version, type
+ 0x00, (byte) 0x80, // length
+ 0x12, 0x34, 0x56, 0x78, // xid
+ (byte) 0xfe, (byte) 0xdc , (byte) 0xba, (byte) 0x98, 0x76, 0x54, 0x32, 0x10, // cookie
+ (byte) 0xff, 0x00, (byte) 0xff, 0x00, (byte) 0xff, 0x00, (byte) 0xff, 0x00, // cookie_mask
+ 0x03 // table_id
+ // rest truncated
+ };
+
+ @Test
+ public void testTruncated() {
+ OFErrorCauseData emptyCause = OFErrorCauseData.of(truncatedFlowAddd, OFVersion.OF_13);
+ assertThat(emptyCause.getData(), equalTo(truncatedFlowAddd));
+ assertThat(emptyCause.getParsedMessage().isPresent(), equalTo(false));
+ assertThat(emptyCause.toString(), Matchers.containsString("unparsed"));
+ assertThat(emptyCause.toString(), Matchers.containsString("04 0e 00 80"));
+ }
+
+ @Test
+ public void testFlowAdd() {
+ OFFlowAdd flowAdd = OFFactories.getFactory(OFVersion.OF_13).buildFlowAdd()
+ .setXid(0x12345678)
+ .setCookie(U64.parseHex("FEDCBA9876543210"))
+ .setCookieMask(U64.parseHex("FF00FF00FF00FF00"))
+ .setTableId(TableId.of(3))
+ .setIdleTimeout(5)
+ .setHardTimeout(10)
+ .setPriority(6000)
+ .build();
+
+ ChannelBuffer bb = ChannelBuffers.dynamicBuffer();
+ flowAdd.writeTo(bb);
+ byte[] flowAddBytes = new byte[bb.readableBytes()];
+ bb.readBytes(flowAddBytes);
+
+ OFErrorCauseData emptyCause = OFErrorCauseData.of(flowAddBytes, OFVersion.OF_13);
+ assertThat(emptyCause.getData(), equalTo(flowAddBytes));
+ assertThat(emptyCause.getParsedMessage().isPresent(), equalTo(true));
+ assertThat(emptyCause.toString(), Matchers.containsString("OFFlowAdd"));
+ assertThat(emptyCause.toString(), Matchers.containsString("idleTimeout=5"));
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
new file mode 100644
index 0000000..4db84f1
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFPortBitMapTest.java
@@ -0,0 +1,71 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.Matchers.contains;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertThat;
+import junit.framework.TestCase;
+
+import org.junit.Test;
+
+public class OFPortBitMapTest extends TestCase {
+ @Test
+ public void testCreateAndIterate() {
+ OFPortBitMap map = OFPortBitMap.ofPorts(OFPort.of(1), OFPort.of(2), OFPort.of(5));
+
+ assertThat(map.getOnPorts(), contains(OFPort.of(1), OFPort.of(2), OFPort.of(5)));
+ }
+
+ @Test
+ public void testOFBitMap() {
+ OFBitMask128 bitmap = OFBitMask128.of(0xFFFF_FFFF_FFFF_FFFFL, 0xFFFF_FFFF_FFFF_FFD9L);
+
+ OFPortBitMap map = OFPortBitMap.of(bitmap);
+
+ assertThat(map.getOnPorts(), contains(OFPort.of(1), OFPort.of(2), OFPort.of(5)));
+ }
+
+ @Test
+ public void testOFPortBitMap() {
+ Boolean[] on = new Boolean[127];
+ for (int i = 0; i < 127; i++) {
+ on[i] = false;
+ }
+
+ OFPortBitMap.Builder builder = new OFPortBitMap.Builder();
+
+ for (int i = 0; i < 127; i += 3) {
+ OFPort p = OFPort.of(i);
+ builder.set(p);
+ on[p.getPortNumber()] = true;
+ }
+
+ // Test that all ports that were added are actually on, and all other ports are off
+ OFPortBitMap portmap = builder.build();
+ //System.out.println(portmap);
+ Boolean[] actual = new Boolean[127];
+ for (int i = 0; i < 127; i++) {
+ actual[i] = false;
+ }
+ for (int i = 0; i < 127; i++) {
+ actual[i] = portmap.isOn(OFPort.of(i));
+ }
+ assertArrayEquals(on, actual);
+
+ // Turn some ports off
+ for (int i = 0; i < 127; i += 7) {
+ on[i] = false;
+ builder.unset(OFPort.of(i));
+ }
+
+ // Test again
+ portmap = builder.build();
+ actual = new Boolean[127];
+ for (int i = 0; i < 127; i++) {
+ actual[i] = false;
+ }
+ for (int i = 0; i < 127; i++) {
+ actual[i] = portmap.isOn(OFPort.of(i));
+ }
+ assertArrayEquals(on, actual);
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFVlanVidMatchTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFVlanVidMatchTest.java
new file mode 100644
index 0000000..ce6e7a2
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/OFVlanVidMatchTest.java
@@ -0,0 +1,44 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Test;
+
+public class OFVlanVidMatchTest {
+ @Test
+ public void testofVlanVid() {
+ assertThat(
+ (int) OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(1)).getRawVid(),
+ equalTo(0x1001));
+ assertThat(
+ (int) OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(0xFFF)).getRawVid(),
+ equalTo(0x1FFF));
+ assertThat(OFVlanVidMatch.ofVlanVid(null), equalTo(OFVlanVidMatch.UNTAGGED));
+ assertThat(OFVlanVidMatch.ofVlanVid(VlanVid.NO_MASK),
+ equalTo(OFVlanVidMatch.NO_MASK));
+ // a fully masked VlanVid means "PRESENT" in OFVlanVid
+ // (because a VlanVid always specifies a Vlan)
+ assertThat(OFVlanVidMatch.ofVlanVid(VlanVid.FULL_MASK),
+ equalTo(OFVlanVidMatch.PRESENT));
+ }
+ @Test
+ public void testtoVlanVid() {
+ assertThat(
+ OFVlanVidMatch.ofRawVid((short)0x1001).getVlanVid(),
+ equalTo(VlanVid.ofVlan(1)));
+ assertThat(
+ OFVlanVidMatch.ofRawVid((short)0x1FFF).getVlanVid(),
+ equalTo(VlanVid.ofVlan(0xFFF)));
+ assertThat(OFVlanVidMatch.UNTAGGED.getVlanVid(), CoreMatchers.nullValue());
+ assertThat(
+ OFVlanVidMatch.NO_MASK.getVlanVid(),
+ equalTo(VlanVid.NO_MASK));
+ assertThat(
+ OFVlanVidMatch.PRESENT.getVlanVid(),
+ equalTo(VlanVid.FULL_MASK));
+ }
+
+
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/U128Test.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
new file mode 100644
index 0000000..81d9d7f
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/U128Test.java
@@ -0,0 +1,285 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.text.MessageFormat;
+
+import org.hamcrest.Matchers;
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.hash.HashCode;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+public class U128Test {
+ private Triple[] triples;
+
+
+ @Test
+ public void testPositiveRaws() {
+ assertThat(U128.of(0, 0).getMsb(), equalTo(0L));
+ assertThat(U128.of(0, 0).getLsb(), equalTo(0L));
+
+ assertThat(U128.of(1, 2).getMsb(), equalTo(1L));
+ assertThat(U128.of(1, 2).getLsb(), equalTo(2L));
+ }
+
+ @Test
+ public void testReadBytes() {
+ ChannelBuffer empty = ChannelBuffers.wrappedBuffer(new byte[16]);
+ U128 uEmpty = U128.read16Bytes(empty);
+ assertThat(uEmpty.getMsb(), equalTo(0L));
+ assertThat(uEmpty.getLsb(), equalTo(0L));
+
+ ChannelBuffer value = ChannelBuffers.wrappedBuffer(
+ new byte[] { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0x88,
+ (byte) 0x99, (byte) 0xaa, (byte) 0xbb, (byte) 0xcc, (byte) 0xdd,
+ (byte) 0xee, (byte) 0xff, 0x11 });
+ U128 uValue = U128.read16Bytes(value);
+ assertThat(uValue.getMsb(), equalTo(0x1122334455667788L));
+ assertThat(uValue.getLsb(), equalTo(0x99aabbccddeeff11L));
+ }
+
+ @Test
+ public void testPutTo() {
+ U128 h = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+ U128 hSame = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+
+ U128 hBothDiff = U128.of(0x1234_5678_90ab_cdefL,0x1234_5678_90ab_cdefL);
+ U128 hMsbDiff = U128.of(0x0234_5678_90ab_cdefL,0xdeafbeefdeadbeefL);
+ U128 hLsbDiff = U128.of(0x1234_5678_90ab_cdefL,0xdeafbeefdeadbeeeL);
+
+ assertThat(hash(h), equalTo(hash(hSame)));
+ assertThat(hash(h), not(hash(hBothDiff)));
+ assertThat(hash(h), not(hash(hMsbDiff)));
+ assertThat(hash(h), not(hash(hLsbDiff)));
+ }
+
+ private HashCode hash(U128 f) {
+ Hasher hash = Hashing.murmur3_128().newHasher();
+ f.putTo(hash);
+ return hash.hash();
+
+ }
+
+ @Test
+ public void testEqualHashCode() {
+ U128 h1 = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+ U128 h2 = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+ U128 h3 = U128.of(0xeeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+ U128 h3_2 = U128.of(0xdeafbeefdeadbeefL, 0xeeafbeefdeadbeefL);
+
+ assertTrue(h1.equals(h1));
+ assertTrue(h1.equals(h2));
+ assertFalse(h1.equals(h3));
+ assertFalse(h1.equals(h3_2));
+ assertTrue(h2.equals(h1));
+
+ assertEquals(h1.hashCode(), h2.hashCode());
+ assertNotEquals(h1.hashCode(), h3.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+ assertNotEquals(h1.hashCode(), h3_2.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+ }
+
+ @Test
+ public void testXor() {
+ U128 hNull = U128.of(0, 0);
+ U128 hDeadBeef = U128.of(0xdeafbeefdeadbeefL, 0xdeafbeefdeadbeefL);
+ assertThat(hNull.xor(hNull), equalTo(hNull));
+ assertThat(hNull.xor(hDeadBeef), equalTo(hDeadBeef));
+ assertThat(hDeadBeef.xor(hNull), equalTo(hDeadBeef));
+ assertThat(hDeadBeef.xor(hDeadBeef), equalTo(hNull));
+
+
+ U128 h1_0 = U128.of(1L, 0);
+ U128 h8_0 = U128.of(0x8000000000000000L, 0);
+ U128 h81_0 = U128.of(0x8000000000000001L, 0);
+ assertThat(h1_0.xor(h8_0), equalTo(h81_0));
+
+ U128 h0_1 = U128.of(0, 1L);
+ U128 h0_8 = U128.of(0, 0x8000000000000000L);
+ U128 h0_81 = U128.of(0, 0x8000000000000001L);
+ assertThat(h0_1.xor(h0_8), equalTo(h0_81));
+ }
+
+ @Test
+ public void testKeyBits() {
+ U128 zeroU = U128.of(0,0);
+ assertThat(zeroU.prefixBits(0), equalTo(0));
+ assertThat(zeroU.prefixBits(16), equalTo(0));
+ assertThat(zeroU.prefixBits(32), equalTo(0));
+
+ checkInvalidKeyBitSize(zeroU, 33);
+ checkInvalidKeyBitSize(zeroU, 64);
+ assertThat(zeroU.prefixBits(3), equalTo(0));
+
+ U128 positiveU = U128.of(0x1234_5678_1234_5678L, 0x1234_5678_1234_5678L);
+ assertThat(positiveU.prefixBits(0), equalTo(0));
+ assertThat(positiveU.prefixBits(16), equalTo(0x1234));
+ assertThat(positiveU.prefixBits(32), equalTo(0x12345678));
+ checkInvalidKeyBitSize(positiveU, 33);
+ checkInvalidKeyBitSize(positiveU, 64);
+
+ U128 signedBitU = U128.of(0x8765_4321_8765_4321L, 0x1234_5678_1234_5678L);
+ assertThat(signedBitU.prefixBits(0), equalTo(0));
+ assertThat(signedBitU.prefixBits(16), equalTo(0x8765));
+ assertThat(signedBitU.prefixBits(32), equalTo(0x8765_4321));
+ checkInvalidKeyBitSize(signedBitU, 33);
+ checkInvalidKeyBitSize(signedBitU, 64);
+ }
+
+ private void
+ checkInvalidKeyBitSize(U128 u, int prefixBit) {
+ try {
+ u.prefixBits(prefixBit);
+ fail("Expected exception not thrown for "+prefixBit + " bits");
+ } catch(IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public static class Triple {
+ U128 a, b, c;
+
+ public Triple(U128 a, U128 b, U128 c) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+
+ public static Triple of(U128 a, U128 b, U128 c) {
+ return new Triple(a, b, c);
+ }
+
+ public String msg(String string) {
+ return MessageFormat.format(string, a,b,c);
+ }
+ }
+
+ @Before
+ public void setup() {
+ U128 u0_0 = U128.of(0, 0);
+ U128 u0_1 = U128.of(0, 1);
+ U128 u1_0 = U128.of(1, 0);
+ U128 u1_1 = U128.of(1, 1);
+
+ U128 u0_2 = U128.of(0, 2);
+ U128 u2_0 = U128.of(2, 0);
+
+ U128 u0_f = U128.of(0, -1L);
+ U128 uf_0 = U128.of(-1L, 0);
+
+ triples = new Triple[] {
+ Triple.of(u0_0, u0_0, u0_0),
+ Triple.of(u0_0, u0_1, u0_1),
+ Triple.of(u0_0, u1_0, u1_0),
+ Triple.of(u0_1, u1_0, u1_1),
+
+ Triple.of(u0_1, u0_1, u0_2),
+ Triple.of(u1_0, u1_0, u2_0),
+
+ Triple.of(u0_1, u0_f, u1_0),
+
+ Triple.of(u0_1, u0_f, u1_0),
+ Triple.of(u0_f, u0_f, U128.of(1, 0xffff_ffff_ffff_fffeL)),
+ Triple.of(uf_0, u0_f, U128.of(-1, -1)),
+ Triple.of(uf_0, u1_0, U128.ZERO),
+
+ Triple.of(U128.of(0x1234_5678_9abc_def1L, 0x1234_5678_9abc_def1L),
+ U128.of(0xedcb_a987_6543_210eL, 0xedcb_a987_6543_210fL),
+ U128.ZERO)
+ };
+ }
+
+ @Test
+ public void testAddSubtract() {
+ for(Triple t: triples) {
+ assertThat(t.msg("{0} + {1} = {2}"), t.a.add(t.b), equalTo(t.c));
+ assertThat(t.msg("{1} + {0} = {2}"), t.b.add(t.a), equalTo(t.c));
+
+ assertThat(t.msg("{2} - {0} = {1}"), t.c.subtract(t.a), equalTo(t.b));
+ assertThat(t.msg("{2} - {1} = {0}"), t.c.subtract(t.b), equalTo(t.a));
+ }
+ }
+
+ @Test
+ public void testAddSubtractBuilder() {
+ for(Triple t: triples) {
+ assertThat(t.msg("{0} + {1} = {2}"), t.a.builder().add(t.b).build(), equalTo(t.c));
+ assertThat(t.msg("{1} + {0} = {2}"), t.b.builder().add(t.a).build(), equalTo(t.c));
+
+ assertThat(t.msg("{2} - {0} = {1}"), t.c.builder().subtract(t.a).build(), equalTo(t.b));
+ assertThat(t.msg("{2} - {1} = {0}"), t.c.builder().subtract(t.b).build(), equalTo(t.a));
+ }
+ }
+
+ @Test
+ public void testCompare() {
+ U128 u0_0 = U128.of(0, 0);
+ U128 u0_1 = U128.of(0, 1);
+ U128 u0_8 = U128.of(0, 0x8765_4321_8765_4321L);
+ U128 u1_0 = U128.of(0x1234_5678_1234_5678L, 0);
+ U128 u8_0 = U128.of(0x8765_4321_8765_4321L, 0);
+ U128 uf_0 = U128.of(0xFFFF_FFFF_FFFF_FFFFL, 0);
+
+ U128[] us = new U128[] { u0_0, u0_1, u0_8, u1_0, u8_0, uf_0 };
+
+ for(int i = 0; i< us.length; i++) {
+ U128 u_base = us[i];
+ assertThat(
+ String.format("%s should be equal to itself (compareTo)", u_base),
+ u_base.compareTo(u_base), equalTo(0));
+ assertThat(
+ String.format("%s should be equal to itself (equals)", u_base),
+ u_base.equals(u_base), equalTo(true));
+ assertThat(
+ String.format("%s should be equal to itself (equals, by value)", u_base),
+ u_base.equals(U128.of(u_base.getMsb(), u_base.getLsb())), equalTo(true));
+
+ for(int j = i+1; j< us.length; j++) {
+ U128 u_greater = us[j];
+ assertThat(
+ String.format("%s should not be equal to %s", u_base, u_greater),
+ u_base.equals(u_base), equalTo(true));
+ assertThat(
+ String.format("%s should be smaller than %s", u_base, u_greater),
+ u_base.compareTo(u_greater), Matchers.lessThan(0));
+ assertThat(
+ String.format("%s should be greater than %s", u_greater, u_base),
+ u_greater.compareTo(u_base), Matchers.greaterThan(0));
+ }
+ }
+ }
+
+ @Test
+ public void testBitwiseOperators() {
+ U128 one = U128.of(0x5, 0x8);
+ U128 two = U128.of(0x7, 0x3);
+
+ assertThat(one.inverse(), equalTo(U128.of(0xfffffffffffffffaL, 0xfffffffffffffff7L)));
+ assertThat(one.and(two), equalTo(U128.of(0x5L, 0x0L)));
+ assertThat(one.or(two), equalTo(U128.of(0x7L, 0xbL)));
+ assertThat(one.xor(two), equalTo(U128.of(0x2L, 0xbL)));
+ }
+
+ @Test
+ public void testBitwiseOperatorsBuilder() {
+ U128 one = U128.of(0x5, 0x8);
+ U128 two = U128.of(0x7, 0x3);
+
+ assertThat(one.builder().invert().build(), equalTo(U128.of(0xfffffffffffffffaL, 0xfffffffffffffff7L)));
+ assertThat(one.builder().and(two).build(), equalTo(U128.of(0x5L, 0x0L)));
+ assertThat(one.builder().or(two).build(), equalTo(U128.of(0x7L, 0xbL)));
+ assertThat(one.builder().xor(two).build(), equalTo(U128.of(0x2L, 0xbL)));
+ }
+
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/U64Test.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
new file mode 100644
index 0000000..4066bf8
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/types/U64Test.java
@@ -0,0 +1,195 @@
+package org.projectfloodlight.openflow.types;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.math.BigInteger;
+import java.text.MessageFormat;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class U64Test {
+
+ private Triple[] triples;
+
+ @Test
+ public void testPositiveRaws() {
+ for(long positive: new long[] { 0, 1, 100, Long.MAX_VALUE }) {
+ assertEquals(positive, U64.ofRaw(positive).getValue());
+ assertEquals(BigInteger.valueOf(positive), U64.ofRaw(positive).getBigInteger());
+ }
+ }
+
+ @Test
+ public void testNegativeRaws() {
+ long minu1 = 0xFFFF_FFFF_FFFF_FFFFL;
+ assertEquals(minu1, U64.ofRaw(minu1).getValue());
+ assertEquals(new BigInteger("FFFF_FFFF_FFFF_FFFF".replace("_", ""), 16), U64.ofRaw(minu1).getBigInteger());
+ assertEquals(new BigInteger("18446744073709551615"), U64.ofRaw(minu1).getBigInteger());
+ }
+
+ @Test
+ public void testEqualHashCode() {
+ U64 h1 = U64.of(0xdeafbeefdeadbeefL);
+ U64 h2 = U64.of(0xdeafbeefdeadbeefL);
+ U64 h3 = U64.of(0xeeafbeefdeadbeefL);
+
+ assertTrue(h1.equals(h1));
+ assertTrue(h1.equals(h2));
+ assertFalse(h1.equals(h3));
+ assertTrue(h2.equals(h1));
+
+ assertEquals(h1.hashCode(), h2.hashCode());
+ assertNotEquals(h1.hashCode(), h3.hashCode()); // not technically a requirement, but we'll hopefully be lucky.
+ }
+
+ @Test
+ public void testXor() {
+ U64 hNull = U64.of(0);
+ U64 hDeadBeef = U64.of(0xdeafbeefdeadbeefL);
+ assertThat(hNull.xor(hNull), equalTo(hNull));
+ assertThat(hNull.xor(hDeadBeef), equalTo(hDeadBeef));
+ assertThat(hDeadBeef.xor(hNull), equalTo(hDeadBeef));
+ assertThat(hDeadBeef.xor(hDeadBeef), equalTo(hNull));
+
+
+ U64 h1 = U64.of(1L);
+ U64 h8 = U64.of(0x8000000000000000L);
+ U64 h81 = U64.of(0x8000000000000001L);
+ assertThat(h1.xor(h8), equalTo(h81));
+ }
+
+ @Test
+ public void testKeyBits() {
+ U64 zeroU = U64.of(0);
+ assertThat(zeroU.prefixBits(0), equalTo(0));
+ assertThat(zeroU.prefixBits(16), equalTo(0));
+ assertThat(zeroU.prefixBits(32), equalTo(0));
+
+ checkInvalidKeyBitSize(zeroU, 33);
+ checkInvalidKeyBitSize(zeroU, 64);
+ assertThat(zeroU.prefixBits(3), equalTo(0));
+
+ U64 positiveU = U64.of(0x1234_5678_1234_5678L);
+ assertThat(positiveU.prefixBits(0), equalTo(0));
+ assertThat(positiveU.prefixBits(16), equalTo(0x1234));
+ assertThat(positiveU.prefixBits(32), equalTo(0x12345678));
+ checkInvalidKeyBitSize(positiveU, 33);
+ checkInvalidKeyBitSize(positiveU, 64);
+
+ U64 signedBitU = U64.of(0x8765_4321_8765_4321L);
+ assertThat(signedBitU.prefixBits(0), equalTo(0));
+ assertThat(signedBitU.prefixBits(16), equalTo(0x8765));
+ assertThat(signedBitU.prefixBits(32), equalTo(0x8765_4321));
+ checkInvalidKeyBitSize(signedBitU, 33);
+ checkInvalidKeyBitSize(signedBitU, 64);
+ }
+
+ public static class Triple {
+ U64 a, b, c;
+
+ public Triple(U64 a, U64 b, U64 c) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+
+ public static Triple of(U64 a, U64 b, U64 c) {
+ return new Triple(a, b, c);
+ }
+
+ public String msg(String string) {
+ return MessageFormat.format(string, a,b,c);
+ }
+ }
+
+ @Before
+ public void setup() {
+ U64 u0 = U64.of(0);
+ U64 u1 = U64.of(1);
+
+ U64 u2 = U64.of(2);
+ U64 u7f = U64.of(0x7fff_ffff_ffff_ffffL);
+ U64 u8 = U64.of(0x8000_0000_0000_0000L);
+
+ U64 uf = U64.of(-1L);
+
+ triples = new Triple[] {
+ Triple.of(u0, u0, u0),
+ Triple.of(u0, u1, u1),
+
+ Triple.of(u1, u1, u2),
+
+ Triple.of(u1, uf, u0),
+
+ Triple.of(uf, uf, U64.of(0xffff_ffff_ffff_fffeL)),
+ Triple.of(u0, uf, uf),
+
+ Triple.of(u7f, u1, u8),
+
+ Triple.of(U64.of(0x1234_5678_9abc_def1L),
+ U64.of(0xedcb_a987_6543_210fL),
+ U64.ZERO)
+ };
+ }
+
+ @Test
+ public void testAddSubtract() {
+ for(Triple t: triples) {
+ assertThat(t.msg("{0} + {1} = {2}"), t.a.add(t.b), equalTo(t.c));
+ assertThat(t.msg("{1} + {0} = {2}"), t.b.add(t.a), equalTo(t.c));
+
+ assertThat(t.msg("{2} - {0} = {1}"), t.c.subtract(t.a), equalTo(t.b));
+ assertThat(t.msg("{2} - {1} = {0}"), t.c.subtract(t.b), equalTo(t.a));
+ }
+ }
+
+ @Test
+ public void testAddSubtractBuilder() {
+ for(Triple t: triples) {
+ assertThat(t.msg("{0} + {1} = {2}"), t.a.builder().add(t.b).build(), equalTo(t.c));
+ assertThat(t.msg("{1} + {0} = {2}"), t.b.builder().add(t.a).build(), equalTo(t.c));
+
+ assertThat(t.msg("{2} - {0} = {1}"), t.c.builder().subtract(t.a).build(), equalTo(t.b));
+ assertThat(t.msg("{2} - {1} = {0}"), t.c.builder().subtract(t.b).build(), equalTo(t.a));
+ }
+ }
+
+ private void
+ checkInvalidKeyBitSize(U64 u, int prefixBit) {
+ try {
+ u.prefixBits(prefixBit);
+ fail("Expected exception not thrown for "+prefixBit + " bits");
+ } catch(IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void testBitwiseOperators() {
+ U64 notPi = U64.of(0x3141_5926_5358_9793L);
+ U64 notE = U64.of(0x2718_2818_8459_4523L);
+
+ assertThat(notPi.inverse(), equalTo(U64.of(0xcebe_a6d9_aca7_686cL)));
+ assertThat(notPi.and(notE), equalTo(U64.of(0x2100_0800_0058_0503L)));
+ assertThat(notPi.or(notE), equalTo(U64.of(0x3759_793e_d759_d7b3L)));
+ assertThat(notPi.xor(notE), equalTo(U64.of(0x1659_713e_d701_d2b0L)));
+ }
+
+ @Test
+ public void testBitwiseOperatorsBuilder() {
+ U64 notPi = U64.of(0x3141_5926_5358_9793L);
+ U64 notE = U64.of(0x2718_2818_8459_4523L);
+
+ assertThat(notPi.builder().invert().build(), equalTo(U64.of(0xcebe_a6d9_aca7_686cL)));
+ assertThat(notPi.builder().and(notE).build(), equalTo(U64.of(0x2100_0800_0058_0503L)));
+ assertThat(notPi.builder().or(notE).build(), equalTo(U64.of(0x3759_793e_d759_d7b3L)));
+ assertThat(notPi.builder().xor(notE).build(), equalTo(U64.of(0x1659_713e_d701_d2b0L)));
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/util/HexStringTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/util/HexStringTest.java
new file mode 100644
index 0000000..360cb5a6
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/util/HexStringTest.java
@@ -0,0 +1,103 @@
+/**
+* Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior
+* University
+*
+* Licensed under the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License. You may obtain
+* a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+**/
+
+package org.projectfloodlight.openflow.util;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+/**
+ * Does hexstring conversion work?
+ *
+ * @author Rob Sherwood (rob.sherwood@stanford.edu)
+ */
+public class HexStringTest {
+
+ @Test
+ public void testMarshalling() throws Exception {
+ String dpidStr = "00:00:00:23:20:2d:16:71";
+ long dpid = HexString.toLong(dpidStr);
+ String testStr = HexString.toHexString(dpid);
+ assertEquals(dpidStr, testStr);
+ }
+
+ @Test
+ public void testToLong() {
+ String dpidStr = "3e:1f:01:fc:72:8c:63:31";
+ long valid = 0x3e1f01fc728c6331L;
+ long testLong = HexString.toLong(dpidStr);
+ assertEquals(valid, testLong);
+ }
+
+ @Test
+ public void testToLong2() {
+ String dpidStr = "1f:1:fc:72:3:f:31";
+ long valid = 0x1f01fc72030f31L;
+ long testLong = HexString.toLong(dpidStr);
+ assertEquals(valid, testLong);
+ }
+
+ @Test
+ public void testToLongMSB() {
+ String dpidStr = "ca:7c:5e:d1:64:7a:95:9b";
+ long valid = -3856102927509056101L;
+ long testLong = HexString.toLong(dpidStr);
+ assertEquals(valid, testLong);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorTooManyBytes() {
+ HexString.toLong("09:08:07:06:05:04:03:02:01");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorByteValueTooLong() {
+ HexString.toLong("234:01");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorEmptyByte() {
+ HexString.toLong("03::01");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorInvalidHexDigit() {
+ HexString.toLong("ss:01");
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testToLongErrorEmptyString() {
+ HexString.toLong("");
+ }
+
+
+ @Test
+ public void testToStringBytes() {
+ byte[] dpid = { 0, 0, 0, 0, 0, 0, 0, -1 };
+ String valid = "00:00:00:00:00:00:00:ff";
+ String testString = HexString.toHexString(dpid);
+ assertEquals(valid, testString);
+ }
+
+ @Test(expected=NumberFormatException.class)
+ public void testFromHexStringError() {
+ String invalidStr = "00:00:00:00:00:00:ffff";
+ HexString.fromHexString(invalidStr);
+ }
+}
+
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/util/PrimitiveSinkUtilsTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/util/PrimitiveSinkUtilsTest.java
new file mode 100644
index 0000000..f5bf3e4
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/openflow/util/PrimitiveSinkUtilsTest.java
@@ -0,0 +1,130 @@
+package org.projectfloodlight.openflow.util;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.PrimitiveSinkable;
+
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.hash.HashCode;
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+public class PrimitiveSinkUtilsTest {
+
+ private HashFunction hash;
+
+ @Before
+ public void setup() {
+ hash = Hashing.murmur3_128();
+ }
+
+ @Test
+ public void testPutNullableString() {
+ // test that these different invocations of putNullable
+ // differ pairwise
+ HashCode[] hs = new HashCode[] {
+ calcPutNullableString((String) null),
+ calcPutNullableString(""),
+ calcPutNullableString(null, null),
+ calcPutNullableString(null, ""),
+ calcPutNullableString("", null),
+ calcPutNullableString("a\0a", null),
+ calcPutNullableString(null, "a\0a"),
+ };
+
+ checkPairwiseDifferent(hs);
+ }
+
+ @Test
+ public void testPutNullable() {
+ // test that these different invocations of putNullable
+ // differ pairwise
+ HashCode[] hs = new HashCode[] {
+ calcPutNullables(),
+ calcPutNullables(OFPort.of(1)),
+ calcPutNullables(OFPort.of(1), null),
+ calcPutNullables(OFPort.of(1), null, null),
+ calcPutNullables(null, OFPort.of(1), null),
+ calcPutNullables(null, null, OFPort.of(1))
+ };
+
+ checkPairwiseDifferent(hs);
+ }
+
+ private void checkPairwiseDifferent(HashCode[] hs) {
+ for(int i=0;i<hs.length;i++) {
+ for(int j=i+1; j<hs.length;j++) {
+ assertThat(hs[i], not(hs[j]));
+ }
+ }
+ }
+
+ @Test
+ public void testPutList() {
+ HashCode[] hs = new HashCode[] {
+ calcPutList(),
+ calcPutList(OFPort.of(1)),
+ calcPutList(OFPort.of(2)),
+ calcPutList(OFPort.of(1), OFPort.of(2)),
+ calcPutList(OFPort.of(2), OFPort.of(1)),
+ calcPutList(OFPort.of(1), OFPort.of(3)),
+ calcPutList(OFPort.of(1), OFPort.of(2), OFPort.of(3)),
+ };
+
+ checkPairwiseDifferent(hs);
+ }
+
+ @Test
+ public void testPutSortedSet() {
+ HashCode[] hs = new HashCode[] {
+ calcPutSortedSet(),
+ calcPutSortedSet(OFPort.of(1)),
+ calcPutSortedSet(OFPort.of(2)),
+ calcPutSortedSet(OFPort.of(1), OFPort.of(2)),
+ calcPutSortedSet(OFPort.of(1), OFPort.of(3)),
+ calcPutSortedSet(OFPort.of(1), OFPort.of(2), OFPort.of(3)),
+ };
+
+ checkPairwiseDifferent(hs);
+
+ assertThat(calcPutSortedSet(OFPort.of(1), OFPort.of(2)),
+ equalTo(calcPutSortedSet(OFPort.of(2), OFPort.of(1))));
+ }
+
+ private HashCode calcPutNullableString(String... strings) {
+ Hasher h = hash.newHasher();
+ for(String s: strings) {
+ PrimitiveSinkUtils.putNullableStringTo(h, s);
+ }
+ return h.hash();
+ }
+
+ private HashCode calcPutSortedSet(OFPort... ports) {
+ Hasher h = hash.newHasher();
+ PrimitiveSinkUtils.putSortedSetTo(h, ImmutableSortedSet.copyOf(ports));
+ return h.hash();
+ }
+
+ private HashCode calcPutList(OFPort... ports) {
+ Hasher h = hash.newHasher();
+ PrimitiveSinkUtils.putListTo(h, Arrays.asList(ports));
+ return h.hash();
+ }
+
+
+ private HashCode calcPutNullables(PrimitiveSinkable... ps) {
+ Hasher h = hash.newHasher();
+ for(PrimitiveSinkable p : ps) {
+ PrimitiveSinkUtils.putNullableTo(h, p);
+ }
+ return h.hash();
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/OFOxmListTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/OFOxmListTest.java
new file mode 100644
index 0000000..39e8c0c
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/OFOxmListTest.java
@@ -0,0 +1,41 @@
+package org.projectfloodlight.protocol;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFOxmList;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6DstMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6SrcMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxms;
+import org.projectfloodlight.openflow.types.IPv6AddressWithMask;
+
+public class OFOxmListTest {
+ private OFOxms oxms;
+
+ @Before
+ public void setup() {
+ oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+ }
+
+ @Test
+ public void testCanonicalize() {
+ OFOxmList.Builder builder = new OFOxmList.Builder();
+ IPv6AddressWithMask fullMasked = IPv6AddressWithMask.of("::/0");
+ OFOxmIpv6DstMasked fullMaskedOxm = oxms.ipv6DstMasked(fullMasked.getValue(), fullMasked.getMask());
+ builder.set(fullMaskedOxm);
+
+ IPv6AddressWithMask address= IPv6AddressWithMask.of("1:2:3:4:5:6::8");
+ OFOxmIpv6SrcMasked addressSrcOxm = oxms.ipv6SrcMasked(address.getValue(), address.getMask());
+ builder.set(addressSrcOxm);
+
+ OFOxmList list = builder.build();
+ assertThat(list.get(MatchField.IPV6_DST), CoreMatchers.nullValue());
+ assertFalse(list.get(MatchField.IPV6_SRC).isMasked());
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/OFOxmTest.java b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/OFOxmTest.java
new file mode 100644
index 0000000..8482886
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/OFOxmTest.java
@@ -0,0 +1,62 @@
+package org.projectfloodlight.protocol;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Src;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4SrcMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxms;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IPv4AddressWithMask;
+
+public class OFOxmTest {
+ private OFOxms oxms;
+
+ @Before
+ public void setup() {
+ oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+ }
+
+ @Test
+ public void testGetCanonicalFullMask() {
+ IPv4AddressWithMask empty = IPv4AddressWithMask.of("0.0.0.0/0");
+ assertEquals(IPv4Address.FULL_MASK, empty.getMask());
+ OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(empty.getValue(), empty.getMask());
+ // canonicalize should remove /0
+ assertNull(ipv4SrcMasked.getCanonical());
+ }
+
+ @Test
+ public void testGetCanonicalNoMask() {
+ IPv4AddressWithMask fullIp = IPv4AddressWithMask.of("1.2.3.4/32");
+ assertEquals(IPv4Address.NO_MASK, fullIp.getMask());
+ OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(fullIp.getValue(), fullIp.getMask());
+ assertTrue(ipv4SrcMasked.isMasked());
+ assertEquals(IPv4Address.NO_MASK, ipv4SrcMasked.getMask());
+
+ // canonicalize should convert the masked oxm to the non-masked one
+ OFOxm<IPv4Address> canonical = ipv4SrcMasked.getCanonical();
+ assertThat(canonical, CoreMatchers.instanceOf(OFOxmIpv4Src.class));
+ assertFalse(canonical.isMasked());
+ }
+
+ @Test
+ public void testGetCanonicalNormalMask() {
+ IPv4AddressWithMask ip = IPv4AddressWithMask.of("1.2.3.0/24");
+ OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(ip.getValue(), ip.getMask());
+ assertTrue(ipv4SrcMasked.isMasked());
+
+ // canonicalize should convert the masked oxm to the non-masked one
+ OFOxm<IPv4Address> canonical = ipv4SrcMasked.getCanonical();
+ assertEquals(ipv4SrcMasked, canonical);
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIteration10Test.java b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIteration10Test.java
new file mode 100644
index 0000000..c6f4471
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIteration10Test.java
@@ -0,0 +1,10 @@
+package org.projectfloodlight.protocol.match;
+
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+public class MatchFieldIteration10Test extends MatchFieldIterationBase {
+ public MatchFieldIteration10Test() {
+ super(OFFactories.getFactory(OFVersion.OF_10));
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIteration13Test.java b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIteration13Test.java
new file mode 100644
index 0000000..b654a53
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIteration13Test.java
@@ -0,0 +1,10 @@
+package org.projectfloodlight.protocol.match;
+
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+public class MatchFieldIteration13Test extends MatchFieldIterationBase {
+ public MatchFieldIteration13Test() {
+ super(OFFactories.getFactory(OFVersion.OF_13));
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIterationBase.java b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIterationBase.java
new file mode 100644
index 0000000..9c72e37
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/protocol/match/MatchFieldIterationBase.java
@@ -0,0 +1,249 @@
+package org.projectfloodlight.protocol.match;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.util.Iterator;
+
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.match.Match;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.protocol.match.MatchFields;
+import org.projectfloodlight.openflow.types.ArpOpcode;
+import org.projectfloodlight.openflow.types.EthType;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IpProtocol;
+import org.projectfloodlight.openflow.types.MacAddress;
+import org.projectfloodlight.openflow.types.Masked;
+import org.projectfloodlight.openflow.types.OFPort;
+import org.projectfloodlight.openflow.types.TransportPort;
+
+import com.google.common.collect.Iterables;
+
+public class MatchFieldIterationBase {
+
+ private OFFactory factory;
+
+ protected MatchFieldIterationBase(OFFactory factory) {
+ this.factory = factory;
+ }
+
+ @Test
+ public void iterateEmptyMatch() {
+ Match match = factory.buildMatch().build();
+ Iterator<MatchField<?>> iter = match.getMatchFields().iterator();
+ assertThat(iter.hasNext(), is(false));
+ }
+
+ @Test
+ public void iterateSingleExactMatchField() {
+ OFPort port5 = OFPort.of(5);
+ Match match = factory.buildMatch()
+ .setExact(MatchField.IN_PORT, port5)
+ .build();
+ Iterator<MatchField<?>> iter = match.getMatchFields().iterator();
+ assertThat(iter.hasNext(), is(true));
+ MatchField<?> matchField = iter.next();
+ assertThat(matchField.id, is(MatchFields.IN_PORT));
+ assertThat(match.isExact(matchField), is(true));
+ @SuppressWarnings("unchecked")
+ MatchField<OFPort> portMatchField = (MatchField<OFPort>) matchField;
+ OFPort port = match.get(portMatchField);
+ assertThat(port, is(port5));
+ assertThat(iter.hasNext(), is(false));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void iterateExactMatchFields() {
+ OFPort port5 = OFPort.of(5);
+ MacAddress macSrc = MacAddress.of("00:01:02:03:04:05");
+ MacAddress macDst = MacAddress.of("01:01:02:02:03:03");
+ IPv4Address ipSrc = IPv4Address.of("10.192.20.1");
+ IPv4Address ipDst = IPv4Address.of("10.192.20.2");
+ TransportPort tcpSrc = TransportPort.of(100);
+ TransportPort tcpDst = TransportPort.of(200);
+ Match match = factory.buildMatch()
+ .setExact(MatchField.IN_PORT, port5)
+ .setExact(MatchField.ETH_TYPE, EthType.IPv4)
+ .setExact(MatchField.ETH_SRC, macSrc)
+ .setExact(MatchField.ETH_DST, macDst)
+ .setExact(MatchField.IP_PROTO, IpProtocol.TCP)
+ .setExact(MatchField.IPV4_SRC, ipSrc)
+ .setExact(MatchField.IPV4_DST, ipDst)
+ .setExact(MatchField.TCP_SRC, tcpSrc)
+ .setExact(MatchField.TCP_DST, tcpDst)
+ .build();
+ assertThat(Iterables.size(match.getMatchFields()), is(9));
+ for (MatchField<?> matchField: match.getMatchFields()) {
+ switch (matchField.id) {
+ case IN_PORT:
+ OFPort port = match.get((MatchField<OFPort>) matchField);
+ assertThat(port, is(port5));
+ break;
+ case ETH_TYPE:
+ EthType ethType = match.get((MatchField<EthType>) matchField);
+ assertThat(ethType, is(EthType.IPv4));
+ break;
+ case ETH_SRC:
+ MacAddress mac = match.get((MatchField<MacAddress>) matchField);
+ assertThat(mac, is(macSrc));
+ break;
+ case ETH_DST:
+ mac = match.get((MatchField<MacAddress>) matchField);
+ assertThat(mac, is(macDst));
+ break;
+ case IP_PROTO:
+ IpProtocol ipProtocol = match.get((MatchField<IpProtocol>) matchField);
+ assertThat(ipProtocol, is(IpProtocol.TCP));
+ break;
+ case IPV4_SRC:
+ IPv4Address ip = match.get((MatchField<IPv4Address>) matchField);
+ assertThat(ip, is(ipSrc));
+ break;
+ case IPV4_DST:
+ ip = match.get((MatchField<IPv4Address>) matchField);
+ assertThat(ip, is(ipDst));
+ break;
+ case TCP_SRC:
+ TransportPort tcp = match.get((MatchField<TransportPort>) matchField);
+ assertThat(tcp, is(tcpSrc));
+ break;
+ case TCP_DST:
+ tcp = match.get((MatchField<TransportPort>) matchField);
+ assertThat(tcp, is(tcpDst));
+ break;
+ default:
+ fail("Unexpected match field returned from iterator");
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void iterateArpFields() {
+ MacAddress macSrc = MacAddress.of("00:01:02:03:04:05");
+ MacAddress macDst = MacAddress.of("01:01:02:02:03:03");
+ IPv4Address ipSrc = IPv4Address.of("10.192.20.1");
+ IPv4Address ipDst = IPv4Address.of("10.192.20.2");
+ OFVersion version = factory.getVersion();
+ boolean supportsArpHardwareAddress = (version != OFVersion.OF_10) &&
+ (version != OFVersion.OF_11) && (version != OFVersion.OF_12);
+ int matchFieldCount = 4;
+ Match.Builder builder = factory.buildMatch();
+ builder.setExact(MatchField.ETH_TYPE, EthType.ARP)
+ .setExact(MatchField.ARP_OP, ArpOpcode.REPLY)
+ .setExact(MatchField.ARP_SPA, ipSrc)
+ .setExact(MatchField.ARP_TPA, ipDst);
+ if (supportsArpHardwareAddress) {
+ builder.setExact(MatchField.ARP_SHA, macSrc);
+ builder.setExact(MatchField.ARP_THA, macDst);
+ matchFieldCount += 2;
+ }
+ Match match = builder.build();
+ assertThat(Iterables.size(match.getMatchFields()), is(matchFieldCount));
+ for (MatchField<?> matchField: match.getMatchFields()) {
+ switch (matchField.id) {
+ case ETH_TYPE:
+ EthType ethType = match.get((MatchField<EthType>) matchField);
+ assertThat(ethType, is(EthType.ARP));
+ break;
+ case ARP_OP:
+ ArpOpcode opcode = match.get((MatchField<ArpOpcode>) matchField);
+ assertThat(opcode, is(ArpOpcode.REPLY));
+ break;
+ case ARP_SHA:
+ MacAddress mac = match.get((MatchField<MacAddress>) matchField);
+ assertThat(mac, is(macSrc));
+ break;
+ case ARP_THA:
+ mac = match.get((MatchField<MacAddress>) matchField);
+ assertThat(mac, is(macDst));
+ break;
+ case ARP_SPA:
+ IPv4Address ip = match.get((MatchField<IPv4Address>) matchField);
+ assertThat(ip, is(ipSrc));
+ break;
+ case ARP_TPA:
+ ip = match.get((MatchField<IPv4Address>) matchField);
+ assertThat(ip, is(ipDst));
+ break;
+ default:
+ fail("Unexpected match field returned from iterator");
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void iterateMaskedFields() {
+ MacAddress macSrc = MacAddress.of("01:02:03:04:00:00");
+ MacAddress macSrcMask = MacAddress.of("FF:FF:FF:FF:00:00");
+ MacAddress macDst = MacAddress.of("11:22:33:00:00:00");
+ MacAddress macDstMask = MacAddress.of("FF:FF:FF:00:00:00");
+ IPv4Address ipSrc = IPv4Address.of("10.192.20.0");
+ IPv4Address ipSrcMask = IPv4Address.of("255.255.255.0");
+ IPv4Address ipDst = IPv4Address.of("10.192.20.0");
+ IPv4Address ipDstMask = IPv4Address.of("255.255.255.128");
+ TransportPort tcpSrcMask = TransportPort.of(0x01F0);
+ OFVersion version = factory.getVersion();
+ boolean supportsAllMasks = (version != OFVersion.OF_10) &&
+ (version != OFVersion.OF_11) && (version != OFVersion.OF_12);
+ int matchFieldCount = 4;
+ Match.Builder builder = factory.buildMatch()
+ .setExact(MatchField.ETH_TYPE, EthType.IPv4)
+ .setMasked(MatchField.IPV4_SRC, ipSrc, ipSrcMask)
+ .setMasked(MatchField.IPV4_DST, ipDst, ipDstMask)
+ .setExact(MatchField.IP_PROTO, IpProtocol.TCP);
+ if (supportsAllMasks) {
+ builder.setMasked(MatchField.ETH_SRC, macSrc, macSrcMask);
+ builder.setMasked(MatchField.ETH_DST, macDst, macDstMask);
+ builder.setMasked(MatchField.TCP_SRC, tcpSrcMask, tcpSrcMask);
+ matchFieldCount += 3;
+ }
+ Match match = builder.build();
+ assertThat(Iterables.size(match.getMatchFields()), is(matchFieldCount));
+ for (MatchField<?> matchField: match.getMatchFields()) {
+ switch (matchField.id) {
+ case ETH_TYPE:
+ EthType ethType = match.get((MatchField<EthType>) matchField);
+ assertThat(ethType, is(EthType.IPv4));
+ break;
+ case ETH_SRC:
+ Masked<MacAddress> mac = match.getMasked((MatchField<MacAddress>) matchField);
+ assertThat(mac.getValue(), is(macSrc));
+ assertThat(mac.getMask(), is(macSrcMask));
+ break;
+ case ETH_DST:
+ mac = match.getMasked((MatchField<MacAddress>) matchField);
+ assertThat(mac.getValue(), is(macDst));
+ assertThat(mac.getMask(), is(macDstMask));
+ break;
+ case IP_PROTO:
+ IpProtocol ipProtocol = match.get((MatchField<IpProtocol>) matchField);
+ assertThat(ipProtocol, is(IpProtocol.TCP));
+ break;
+ case IPV4_SRC:
+ Masked<IPv4Address> ip = match.getMasked((MatchField<IPv4Address>) matchField);
+ assertThat(ip.getValue(), is(ipSrc));
+ assertThat(ip.getMask(), is(ipSrcMask));
+ break;
+ case IPV4_DST:
+ ip = match.getMasked((MatchField<IPv4Address>) matchField);
+ assertThat(ip.getValue(), is(ipDst));
+ assertThat(ip.getMask(), is(ipDstMask));
+ break;
+ case TCP_SRC:
+ Masked<TransportPort> tcp = match.getMasked((MatchField<TransportPort>) matchField);
+ assertThat(tcp.getValue(), is(tcpSrcMask));
+ assertThat(tcp.getMask(), is(tcpSrcMask));
+ break;
+ default:
+ fail("Unexpected match field returned from iterator");
+ }
+ }
+ }
+}
diff --git a/openflow/openflowj/src/test/java/org/projectfloodlight/test/TestUtils.java b/openflow/openflowj/src/test/java/org/projectfloodlight/test/TestUtils.java
new file mode 100644
index 0000000..7a5b8b0
--- /dev/null
+++ b/openflow/openflowj/src/test/java/org/projectfloodlight/test/TestUtils.java
@@ -0,0 +1,62 @@
+package org.projectfloodlight.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Assert;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Bytes;
+
+public class TestUtils {
+ private TestUtils() {}
+
+ private static final int PER_LINE = 8;
+
+ public static void betterAssertArrayEquals(byte[] expected, byte[] got) {
+ int maxlen = Math.max(expected.length, got.length);
+
+ List<String> expectedList = formatHex(Bytes.asList(expected));
+ List<String> gotList = formatHex(Bytes.asList(got));
+
+ boolean fail = false;
+ for (int i = 0; i < maxlen;i+= PER_LINE) {
+ int maxThisLine = Math.min(maxlen, PER_LINE);
+ boolean print = false;
+
+ ArrayList<String> changeMarkers = new ArrayList<String>();
+
+ for (int j = i; j < maxThisLine; j++) {
+ if (j >= expected.length || j >= got.length || expected[j] != got[j]) {
+ print = true;
+ fail = true;
+ changeMarkers.add("==");
+ break;
+ } else {
+ changeMarkers.add(" ");
+ }
+ }
+ if(print) {
+ System.out.println(String.format("%4x: %s", i, Joiner.on(" ").join(expectedList.subList(i, Math.min(expectedList.size(), i+PER_LINE)))));
+ System.out.println(String.format("%4x: %s", i, Joiner.on(" ").join(gotList.subList(i, Math.min(gotList.size(), i+PER_LINE)))));
+ System.out.println(String.format("%4s %s", "", Joiner.on(" ").join(changeMarkers)));
+ System.out.println("\n");
+ }
+ }
+ if(fail) {
+ Assert.fail("Array comparison failed");
+ }
+
+ }
+
+ private static List<String> formatHex(List<Byte> b) {
+ return Lists.transform(b, new Function<Byte, String>() {
+ @Override
+ public String apply(Byte input) {
+ return String.format("%02x", input);
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/openflow/openflowj/src/test/resources/logback-test.xml b/openflow/openflowj/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..e759962
--- /dev/null
+++ b/openflow/openflowj/src/test/resources/logback-test.xml
@@ -0,0 +1,13 @@
+<configuration scan="true">
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} %level [%logger{20}:%thread] %msg%n</pattern>
+ </encoder>
+ </appender>
+ <root level="INFO">
+ <appender-ref ref="STDOUT" />
+ </root>
+ <logger name="org" level="WARN"/>
+ <logger name="LogService" level="WARN"/> <!-- Restlet access logging -->
+ <logger name="org.projectfloodlight.openflow" level="DEBUG"/>
+</configuration>