unsigned PortNumber

PortNumber class update
- internal representation now uses int
- toString() now converts the value as unsigned integer
- renamed value() to shortValue()
- added value() method returning port number as unsigned long
- added constructor from String
- JSON serialization now uses the new value(), so that special handling for
  unsigned integer is not required

Update classes using PortNumber
- Replaced value() calls with new value(), when the return value was
  converted to long immediately.
- toString() result may change if the object contained PortNumber.
  - e.g., FlowEntryAction, FlowEntry, SwitchPort, ...

Change-Id: I0b1f8aa92208e165b6113c8dd6954076c0513167
diff --git a/src/test/java/net/onrc/onos/core/util/FlowEntryTest.java b/src/test/java/net/onrc/onos/core/util/FlowEntryTest.java
index cca5d02..769198a 100644
--- a/src/test/java/net/onrc/onos/core/util/FlowEntryTest.java
+++ b/src/test/java/net/onrc/onos/core/util/FlowEntryTest.java
@@ -278,7 +278,7 @@
                 + " flowEntryActions=["
                 + "[type=ACTION_OUTPUT action=[port=9 maxLen=0]];"
                 // PORT_CONTROLLER((short) 0xfffd) = 65533 (-3)
-                + "[type=ACTION_OUTPUT action=[port=-3 maxLen=0]];"
+                + "[type=ACTION_OUTPUT action=[port=65533 maxLen=0]];"
                 + "[type=ACTION_SET_VLAN_VID action=[vlanId=3]];"
                 + "[type=ACTION_SET_VLAN_PCP action=[vlanPriority=4]];"
                 + "[type=ACTION_STRIP_VLAN action=[stripVlan=true]];"
diff --git a/src/test/java/net/onrc/onos/core/util/LinkTupleTest.java b/src/test/java/net/onrc/onos/core/util/LinkTupleTest.java
index 88c2ca9..06cce85 100644
--- a/src/test/java/net/onrc/onos/core/util/LinkTupleTest.java
+++ b/src/test/java/net/onrc/onos/core/util/LinkTupleTest.java
@@ -143,8 +143,7 @@
      */
     @Test
     public void testToString() {
-        // FIXME when we start handling unsigned integer properly
-        assertEquals("(00:00:00:00:00:00:00:01/-1=>00:00:00:00:00:00:00:02/-2)",
+        assertEquals("(00:00:00:00:00:00:00:01/65535=>00:00:00:00:00:00:00:02/65534)",
                      L2.toString());
     }
 
diff --git a/src/test/java/net/onrc/onos/core/util/PortNumberTest.java b/src/test/java/net/onrc/onos/core/util/PortNumberTest.java
new file mode 100644
index 0000000..eb9915a
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/util/PortNumberTest.java
@@ -0,0 +1,134 @@
+/**
+ *
+ */
+package net.onrc.onos.core.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+/**
+ * PortNumber test mainly focused on handling unsigned port no correctly.
+ */
+public class PortNumberTest {
+
+    private static final PortNumber PORT_NONE = new PortNumber(0xffff);
+    private static final PortNumber PORT_LOCAL = new PortNumber(0xfffe);
+
+    /**
+     * Test method for {@link PortNumber#PortNumber(String)}.
+     */
+    @Test
+    public void testPortNumberDecimalString() {
+        final PortNumber ref = new PortNumber(PORT_NONE);
+        PortNumber parsed = new PortNumber("65535");
+
+        assertEquals(ref, parsed);
+    }
+
+    /**
+     * Test method for {@link PortNumber#PortNumber(String, int)}.
+     */
+    @Test
+    public void testPortNumberString() {
+        final PortNumber ref = new PortNumber(PORT_NONE);
+        PortNumber parsed = new PortNumber("ffff", 16);
+        // Note: cannot parse "0xffff" now,
+        //       which is the same behavior as Integer.parseInt.
+
+        assertEquals(ref, parsed);
+    }
+
+    /**
+     * Test method for {@link PortNumber#PortNumber(PortNumber)}.
+     */
+    @Test
+    public void testPortNumberPortNumber() {
+        PortNumber p = new PortNumber(PORT_LOCAL);
+        PortNumber copy = new PortNumber(p);
+
+        assertEquals(p, copy);
+    }
+
+    /**
+     * Test method for {@link PortNumber#PortNumber(PortNumber.PortValues)}.
+     */
+    @Test
+    public void testPortNumberPortValues() {
+        PortNumber local = new PortNumber(PORT_LOCAL);
+        assertEquals(0xfffeL, local.value());
+        assertEquals((short) 0xfffe, local.shortValue());
+    }
+
+    /**
+     * Test method for {@link PortNumber#shortToUnsignedLong(short)}.
+     */
+    @Test
+    public void testLongValueShort() {
+        assertEquals(0L, PortNumber.shortToUnsignedLong((short) 0));
+
+        assertEquals(1L, PortNumber.shortToUnsignedLong((short) 1));
+
+        // -1 as unsigned short
+        assertEquals(0xffffL, PortNumber.shortToUnsignedLong((short) -1));
+    }
+
+    /**
+     * Test method for {@link PortNumber#shortValue()}.
+     */
+    @Test
+    public void testShortValue() {
+        assertEquals(0L, new PortNumber((short) 0).shortValue());
+
+        assertEquals(1L, new PortNumber((short) 1).shortValue());
+
+        // user of #shortValue() needs to be careful
+        // simply widening them will result in negative value
+        assertEquals(-1L, new PortNumber(PORT_NONE).shortValue());
+
+        // user of #shortValue() needs to be careful
+        // should use PortNumber.shortToUnsignedLong or mask manually
+        assertEquals(0xffffL, PortNumber.shortToUnsignedLong(new PortNumber(PORT_NONE).shortValue()));
+        assertEquals(0xffffL, 0xffff & new PortNumber(PORT_NONE).shortValue());
+}
+
+    /**
+     * Test method for {@link PortNumber#value()}.
+     */
+    @Test
+    public void testLongValue() {
+        assertEquals(0L, new PortNumber((short) 0).value());
+
+        assertEquals(1L, new PortNumber((short) 1).value());
+
+        assertEquals(0xffffL, new PortNumber(PORT_NONE).value());
+    }
+
+    /**
+     * Test method for {@link PortNumber#toString()}.
+     */
+    @Test
+    public void testToString() {
+        assertEquals("0", new PortNumber((short) 0).toString());
+
+        assertEquals("1", new PortNumber((short) 1).toString());
+
+        // 0xffff in decimal
+        assertEquals("65535", new PortNumber(PORT_NONE).toString());
+    }
+
+    /**
+     * Test method for {@link PortNumber#equals(java.lang.Object)}.
+     */
+    @Test
+    public void testEqualsObject() {
+        // Some trivial
+        assertTrue(new PortNumber(PORT_NONE).equals(new PortNumber((short) 0xffff)));
+        assertFalse(new PortNumber((short) 0).equals(new PortNumber((short) 1)));
+
+        // different type
+        assertFalse(new PortNumber((short) 0).equals(Short.valueOf((short) 0)));
+
+    }
+
+}
diff --git a/src/test/java/net/onrc/onos/core/util/SwitchPortTest.java b/src/test/java/net/onrc/onos/core/util/SwitchPortTest.java
index 48c3b65..1c01e8f 100644
--- a/src/test/java/net/onrc/onos/core/util/SwitchPortTest.java
+++ b/src/test/java/net/onrc/onos/core/util/SwitchPortTest.java
@@ -48,7 +48,7 @@
      */
     @Test
     public void testToString() {
-        assertEquals("00:00:00:00:00:00:00:01/-1", SWP2.toString());
+        assertEquals("00:00:00:00:00:00:00:01/65535", SWP2.toString());
     }
 
     /**