Reimplementation of classes Ip4Address/Ip6Address/Ip4Prefix/Ip6Prefix
and the corresponding unit tests.

* Reimplemented classes Ip4Address and Ip6Address by inheriting from
  class IpAddress
* Reimplemented classes Ip4Prefix and Ip6Prefix by inheriting from
  class IpPrefix
* Reimplemented the unit tests Ip4AddressTest and Ip6AddressTest to
  match the corresponding IpAddressTest unit tests
* Reimplemented the unit tests Ip4PrefixTest and Ip6PrefixTest to
  match the corresponding IpPrefixTest unit tests
* Minor refactoring/cleanup of classes IpAddress and IpPrefix
diff --git a/utils/misc/src/test/java/org/onlab/packet/Ip6PrefixTest.java b/utils/misc/src/test/java/org/onlab/packet/Ip6PrefixTest.java
index 59b19f6..dceeb84 100644
--- a/utils/misc/src/test/java/org/onlab/packet/Ip6PrefixTest.java
+++ b/utils/misc/src/test/java/org/onlab/packet/Ip6PrefixTest.java
@@ -15,12 +15,14 @@
  */
 package org.onlab.packet;
 
+import com.google.common.testing.EqualsTester;
 import org.junit.Test;
 
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
 
 /**
@@ -36,235 +38,531 @@
     }
 
     /**
-     * Tests default class constructor.
+     * Tests the IPv4 prefix address version constant.
      */
     @Test
-    public void testDefaultConstructor() {
-        Ip6Prefix ip6prefix = new Ip6Prefix();
-        assertThat(ip6prefix.toString(), is("::/0"));
+    public void testAddressVersion() {
+        assertThat(Ip6Prefix.VERSION, is(IpAddress.Version.INET6));
     }
 
     /**
-     * Tests valid class copy constructor.
+     * Tests the maximum mask length.
      */
     @Test
-    public void testCopyConstructor() {
-        Ip6Prefix fromAddr = new Ip6Prefix("1100::/8");
-        Ip6Prefix ip6prefix = new Ip6Prefix(fromAddr);
-        assertThat(ip6prefix.toString(), is("1100::/8"));
-
-        fromAddr = new Ip6Prefix("::/0");
-        ip6prefix = new Ip6Prefix(fromAddr);
-        assertThat(ip6prefix.toString(), is("::/0"));
-
-        fromAddr =
-            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
-        ip6prefix = new Ip6Prefix(fromAddr);
-        assertThat(ip6prefix.toString(),
-                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
+    public void testMaxMaskLength() {
+        assertThat(Ip6Prefix.MAX_MASK_LENGTH, is(128));
     }
 
     /**
-     * Tests invalid class copy constructor for a null object to copy from.
+     * Tests returning the IP version of the prefix.
      */
-    @Test(expected = NullPointerException.class)
-    public void testInvalidConstructorNullObject() {
-        Ip6Prefix fromAddr = null;
-        Ip6Prefix ip6prefix = new Ip6Prefix(fromAddr);
+    @Test
+    public void testVersion() {
+        Ip6Prefix ipPrefix;
+
+        // IPv6
+        ipPrefix = Ip6Prefix.valueOf("::/0");
+        assertThat(ipPrefix.version(), is(IpAddress.Version.INET6));
     }
 
     /**
-     * Tests valid class constructor for an address and prefix length.
+     * Tests returning the IP address value and IP address prefix length of
+     * an IPv6 prefix.
      */
     @Test
-    public void testConstructorForAddressAndPrefixLength() {
-        Ip6Prefix ip6prefix =
-            new Ip6Prefix(new Ip6Address("1100::"), (short) 8);
-        assertThat(ip6prefix.toString(), is("1100::/8"));
+    public void testAddressAndPrefixLengthIPv6() {
+        Ip6Prefix ipPrefix;
 
-        ip6prefix =
-            new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
-                        (short) 8);
-        assertThat(ip6prefix.toString(), is("1100::/8"));
+        ipPrefix = Ip6Prefix.valueOf("1100::/8");
+        assertThat(ipPrefix.address(), equalTo(Ip6Address.valueOf("1100::")));
+        assertThat(ipPrefix.prefixLength(), is(8));
 
-        ip6prefix =
-            new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8800"),
-                        (short) 120);
-        assertThat(ip6prefix.toString(),
+        ipPrefix =
+            Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8885/8");
+        assertThat(ipPrefix.address(), equalTo(Ip6Address.valueOf("1100::")));
+        assertThat(ipPrefix.prefixLength(), is(8));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8800/120");
+        assertThat(ipPrefix.address(),
+                   equalTo(Ip6Address.valueOf("1111:2222:3333:4444:5555:6666:7777:8800")));
+        assertThat(ipPrefix.prefixLength(), is(120));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8885/128");
+        assertThat(ipPrefix.address(),
+                   equalTo(Ip6Address.valueOf("1111:2222:3333:4444:5555:6666:7777:8885")));
+        assertThat(ipPrefix.prefixLength(), is(128));
+
+        ipPrefix = Ip6Prefix.valueOf("::/0");
+        assertThat(ipPrefix.address(), equalTo(Ip6Address.valueOf("::")));
+        assertThat(ipPrefix.prefixLength(), is(0));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertThat(ipPrefix.address(),
+                   equalTo(Ip6Address.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
+        assertThat(ipPrefix.prefixLength(), is(128));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8885/64");
+        assertThat(ipPrefix.address(),
+                   equalTo(Ip6Address.valueOf("1111:2222:3333:4444::")));
+        assertThat(ipPrefix.prefixLength(), is(64));
+    }
+
+    /**
+     * Tests valueOf() converter for IPv6 byte array.
+     */
+    @Test
+    public void testValueOfByteArrayIPv6() {
+        Ip6Prefix ipPrefix;
+        byte[] value;
+
+        value = new byte[] {0x11, 0x11, 0x22, 0x22,
+                            0x33, 0x33, 0x44, 0x44,
+                            0x55, 0x55, 0x66, 0x66,
+                            0x77, 0x77, (byte) 0x88, (byte) 0x88};
+        ipPrefix = Ip6Prefix.valueOf(value, 120);
+        assertThat(ipPrefix.toString(),
                    is("1111:2222:3333:4444:5555:6666:7777:8800/120"));
 
-        ip6prefix = new Ip6Prefix(new Ip6Address("::"), (short) 0);
-        assertThat(ip6prefix.toString(), is("::/0"));
+        ipPrefix = Ip6Prefix.valueOf(value, 128);
+        assertThat(ipPrefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888/128"));
 
-        ip6prefix =
-            new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
-                        (short) 128);
-        assertThat(ip6prefix.toString(),
-                   is("1111:2222:3333:4444:5555:6666:7777:8885/128"));
+        value = new byte[] {0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00, 0x00, 0x00,
+                            0x00, 0x00, 0x00, 0x00};
+        ipPrefix = Ip6Prefix.valueOf(value, 0);
+        assertThat(ipPrefix.toString(), is("::/0"));
 
-        ip6prefix =
-            new Ip6Prefix(new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
-                        (short) 128);
-        assertThat(ip6prefix.toString(),
+        ipPrefix = Ip6Prefix.valueOf(value, 128);
+        assertThat(ipPrefix.toString(), is("::/128"));
+
+        value = new byte[] {(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};
+        ipPrefix = Ip6Prefix.valueOf(value, 0);
+        assertThat(ipPrefix.toString(), is("::/0"));
+
+        ipPrefix = Ip6Prefix.valueOf(value, 64);
+        assertThat(ipPrefix.toString(), is("ffff:ffff:ffff:ffff::/64"));
+
+        ipPrefix = Ip6Prefix.valueOf(value, 128);
+        assertThat(ipPrefix.toString(),
                    is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
-
-        ip6prefix =
-            new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
-                        (short) 64);
-        assertThat(ip6prefix.toString(), is("1111:2222:3333:4444::/64"));
     }
 
     /**
-     * Tests valid class constructor for a string.
-     */
-    @Test
-    public void testConstructorForString() {
-        Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
-        assertThat(ip6prefix.toString(), is("1100::/8"));
-
-        ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
-        assertThat(ip6prefix.toString(), is("1100::/8"));
-
-        ip6prefix =
-            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8800/120");
-        assertThat(ip6prefix.toString(),
-                   is("1111:2222:3333:4444:5555:6666:7777:8800/120"));
-
-        ip6prefix = new Ip6Prefix("::/0");
-        assertThat(ip6prefix.toString(), is("::/0"));
-
-        ip6prefix =
-            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/128");
-        assertThat(ip6prefix.toString(),
-                   is("1111:2222:3333:4444:5555:6666:7777:8885/128"));
-
-        ip6prefix = new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
-        assertThat(ip6prefix.toString(),
-                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
-
-        ip6prefix =
-            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/64");
-        assertThat(ip6prefix.toString(), is("1111:2222:3333:4444::/64"));
-    }
-
-    /**
-     * Tests invalid class constructor for a null string.
+     * Tests invalid valueOf() converter for a null array for IPv6.
      */
     @Test(expected = NullPointerException.class)
-    public void testInvalidConstructorNullString() {
-        String fromString = null;
-        Ip6Prefix ip6prefix = new Ip6Prefix(fromString);
+    public void testInvalidValueOfNullArrayIPv6() {
+        Ip6Prefix ipPrefix;
+        byte[] value;
+
+        value = null;
+        ipPrefix = Ip6Prefix.valueOf(value, 120);
     }
 
     /**
-     * Tests invalid class constructor for an empty string.
+     * Tests invalid valueOf() converter for a short array for IPv6.
      */
     @Test(expected = IllegalArgumentException.class)
-    public void testInvalidConstructors() {
-        // Check constructor for invalid ID: empty string
-        Ip6Prefix ip6prefix = new Ip6Prefix("");
+    public void testInvalidValueOfShortArrayIPv6() {
+        Ip6Prefix ipPrefix;
+        byte[] value;
+
+        value = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
+        ipPrefix = Ip6Prefix.valueOf(value, 120);
     }
 
     /**
-     * Tests getting the value of an address.
+     * Tests invalid valueOf() converter for IPv6 byte array and
+     * negative prefix length.
      */
-    @Test
-    public void testGetValue() {
-        Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
-        assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("1100::")));
-        assertThat(ip6prefix.getPrefixLen(), is((short) 8));
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidValueOfByteArrayNegativePrefixLengthIPv6() {
+        Ip6Prefix ipPrefix;
+        byte[] value;
 
-        ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
-        assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("1100::")));
-        assertThat(ip6prefix.getPrefixLen(), is((short) 8));
-
-        ip6prefix =
-            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8800/120");
-        assertThat(ip6prefix.getAddress(),
-                   equalTo(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8800")));
-        assertThat(ip6prefix.getPrefixLen(), is((short) 120));
-
-        ip6prefix = new Ip6Prefix("::/0");
-        assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("::")));
-        assertThat(ip6prefix.getPrefixLen(), is((short) 0));
-
-        ip6prefix =
-            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/128");
-        assertThat(ip6prefix.getAddress(),
-                   equalTo(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885")));
-        assertThat(ip6prefix.getPrefixLen(), is((short) 128));
-
-        ip6prefix =
-            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
-        assertThat(ip6prefix.getAddress(),
-                   equalTo(new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
-        assertThat(ip6prefix.getPrefixLen(), is((short) 128));
-
-        ip6prefix =
-            new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/64");
-        assertThat(ip6prefix.getAddress(),
-                   equalTo(new Ip6Address("1111:2222:3333:4444::")));
-        assertThat(ip6prefix.getPrefixLen(), is((short) 64));
+        value = new byte[] {0x11, 0x11, 0x22, 0x22,
+                            0x33, 0x33, 0x44, 0x44,
+                            0x55, 0x55, 0x66, 0x66,
+                            0x77, 0x77, (byte) 0x88, (byte) 0x88};
+        ipPrefix = Ip6Prefix.valueOf(value, -1);
     }
 
     /**
-     * Tests equality of {@link Ip6Address}.
+     * Tests invalid valueOf() converter for IPv6 byte array and
+     * too long prefix length.
      */
-    @Test
-    public void testEquality() {
-        Ip6Prefix addr1net = new Ip6Prefix("1100::/8");
-        Ip6Prefix addr2net = new Ip6Prefix("1100::/8");
-        assertThat(addr1net, is(addr2net));
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidValueOfByteArrayTooLongPrefixLengthIPv6() {
+        Ip6Prefix ipPrefix;
+        byte[] value;
 
-        addr1net = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
-        addr2net = new Ip6Prefix("1100::/8");
-        assertThat(addr1net, is(addr2net));
-
-        addr1net = new Ip6Prefix("::/0");
-        addr2net = new Ip6Prefix("::/0");
-        assertThat(addr1net, is(addr2net));
-
-        addr1net =
-            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
-        addr2net =
-            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
-        assertThat(addr1net, is(addr2net));
+        value = new byte[] {0x11, 0x11, 0x22, 0x22,
+                            0x33, 0x33, 0x44, 0x44,
+                            0x55, 0x55, 0x66, 0x66,
+                            0x77, 0x77, (byte) 0x88, (byte) 0x88};
+        ipPrefix = Ip6Prefix.valueOf(value, 129);
     }
 
     /**
-     * Tests non-equality of {@link Ip6Address}.
+     * Tests valueOf() converter for IPv6 address.
      */
     @Test
-    public void testNonEquality() {
-        Ip6Prefix addr1net = new Ip6Prefix("1100::/8");
-        Ip6Prefix addr2net = new Ip6Prefix("1200::/8");
-        Ip6Prefix addr3net = new Ip6Prefix("1200::/12");
-        Ip6Prefix addr4net = new Ip6Prefix("::/0");
-        Ip6Prefix addr5net =
-            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
-        assertThat(addr1net, is(not(addr2net)));
-        assertThat(addr3net, is(not(addr2net)));
-        assertThat(addr4net, is(not(addr2net)));
-        assertThat(addr5net, is(not(addr2net)));
+    public void testValueOfAddressIPv6() {
+        Ip6Address ipAddress;
+        Ip6Prefix ipPrefix;
+
+        ipAddress =
+            Ip6Address.valueOf("1111:2222:3333:4444:5555:6666:7777:8888");
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 120);
+        assertThat(ipPrefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8800/120"));
+
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 128);
+        assertThat(ipPrefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888/128"));
+
+        ipAddress = Ip6Address.valueOf("::");
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 0);
+        assertThat(ipPrefix.toString(), is("::/0"));
+
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 128);
+        assertThat(ipPrefix.toString(), is("::/128"));
+
+        ipAddress =
+            Ip6Address.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 0);
+        assertThat(ipPrefix.toString(), is("::/0"));
+
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 64);
+        assertThat(ipPrefix.toString(), is("ffff:ffff:ffff:ffff::/64"));
+
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 128);
+        assertThat(ipPrefix.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
     }
 
     /**
-     * Tests object string representation.
+     * Tests invalid valueOf() converter for a null IP address.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidValueOfNullAddress() {
+        Ip6Address ipAddress;
+        Ip6Prefix ipPrefix;
+
+        ipAddress = null;
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 24);
+    }
+
+    /**
+     * Tests invalid valueOf() converter for IPv6 address and
+     * negative prefix length.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidValueOfAddressNegativePrefixLengthIPv6() {
+        Ip6Address ipAddress;
+        Ip6Prefix ipPrefix;
+
+        ipAddress =
+            Ip6Address.valueOf("1111:2222:3333:4444:5555:6666:7777:8888");
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, -1);
+    }
+
+    /**
+     * Tests invalid valueOf() converter for IPv6 address and
+     * too long prefix length.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidValueOfAddressTooLongPrefixLengthIPv6() {
+        Ip6Address ipAddress;
+        Ip6Prefix ipPrefix;
+
+        ipAddress =
+            Ip6Address.valueOf("1111:2222:3333:4444:5555:6666:7777:8888");
+        ipPrefix = Ip6Prefix.valueOf(ipAddress, 129);
+    }
+
+    /**
+     * Tests valueOf() converter for IPv6 string.
      */
     @Test
-    public void testToString() {
-        Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
-        assertThat(ip6prefix.toString(), is("1100::/8"));
+    public void testValueOfStringIPv6() {
+        Ip6Prefix ipPrefix;
 
-        ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
-        assertThat(ip6prefix.toString(), is("1100::/8"));
+        ipPrefix =
+            Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8888/120");
+        assertThat(ipPrefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8800/120"));
 
-        ip6prefix = new Ip6Prefix("::/0");
-        assertThat(ip6prefix.toString(), is("::/0"));
+        ipPrefix =
+            Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8888/128");
+        assertThat(ipPrefix.toString(),
+                   is("1111:2222:3333:4444:5555:6666:7777:8888/128"));
 
-        ip6prefix =
-            new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
-        assertThat(ip6prefix.toString(),
+        ipPrefix = Ip6Prefix.valueOf("::/0");
+        assertThat(ipPrefix.toString(), is("::/0"));
+
+        ipPrefix = Ip6Prefix.valueOf("::/128");
+        assertThat(ipPrefix.toString(), is("::/128"));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/0");
+        assertThat(ipPrefix.toString(), is("::/0"));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/64");
+        assertThat(ipPrefix.toString(), is("ffff:ffff:ffff:ffff::/64"));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertThat(ipPrefix.toString(),
+                   is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
+    }
+
+    /**
+     * Tests invalid valueOf() converter for a null string.
+     */
+    @Test(expected = NullPointerException.class)
+    public void testInvalidValueOfNullString() {
+        Ip6Prefix ipPrefix;
+        String fromString;
+
+        fromString = null;
+        ipPrefix = Ip6Prefix.valueOf(fromString);
+    }
+
+    /**
+     * Tests invalid valueOf() converter for an empty string.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidValueOfEmptyString() {
+        Ip6Prefix ipPrefix;
+        String fromString;
+
+        fromString = "";
+        ipPrefix = Ip6Prefix.valueOf(fromString);
+    }
+
+    /**
+     * Tests invalid valueOf() converter for an incorrect string.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidValueOfIncorrectString() {
+        Ip6Prefix ipPrefix;
+        String fromString;
+
+        fromString = "NoSuchIpPrefix";
+        ipPrefix = Ip6Prefix.valueOf(fromString);
+    }
+
+    /**
+     * Tests invalid valueOf() converter for IPv6 string and
+     * negative prefix length.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidValueOfStringNegativePrefixLengthIPv6() {
+        Ip6Prefix ipPrefix;
+
+        ipPrefix =
+            Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8888/-1");
+    }
+
+    /**
+     * Tests invalid valueOf() converter for IPv6 string and
+     * too long prefix length.
+     */
+    @Test(expected = IllegalArgumentException.class)
+    public void testInvalidValueOfStringTooLongPrefixLengthIPv6() {
+        Ip6Prefix ipPrefix;
+
+        ipPrefix =
+            Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8888/129");
+    }
+
+    /**
+     * Tests IP prefix contains another IP prefix for IPv6.
+     */
+    @Test
+    public void testContainsIpPrefixIPv6() {
+        Ip6Prefix ipPrefix;
+
+        ipPrefix = Ip6Prefix.valueOf("1111:2222:3333:4444::/120");
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/120")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/128")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::1/128")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/64")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4445::/120")));
+        assertFalse(ipPrefix.contains(Ip6Prefix.valueOf("::/64")));
+        assertFalse(ipPrefix.contains(Ip6Prefix.valueOf("::/0")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128")));
+
+        ipPrefix = Ip6Prefix.valueOf("1111:2222:3333:4444::/128");
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/120")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/128")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::1/128")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/64")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4445::/120")));
+        assertFalse(ipPrefix.contains(Ip6Prefix.valueOf("::/64")));
+        assertFalse(ipPrefix.contains(Ip6Prefix.valueOf("::/0")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128")));
+
+        ipPrefix = Ip6Prefix.valueOf("::/0");
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/120")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/128")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::1/128")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/64")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4445::/120")));
+        assertTrue(ipPrefix.contains(Ip6Prefix.valueOf("::/64")));
+        assertTrue(ipPrefix.contains(Ip6Prefix.valueOf("::/0")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128")));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/120")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/128")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::1/128")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/64")));
+        assertFalse(ipPrefix.contains(
+                Ip6Prefix.valueOf("1111:2222:3333:4445::/120")));
+        assertFalse(ipPrefix.contains(Ip6Prefix.valueOf("::/64")));
+        assertFalse(ipPrefix.contains(Ip6Prefix.valueOf("::/0")));
+        assertTrue(ipPrefix.contains(
+                Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128")));
+    }
+
+    /**
+     * Tests IP prefix contains IP address for IPv6.
+     */
+    @Test
+    public void testContainsIpAddressIPv6() {
+        Ip6Prefix ipPrefix;
+
+        ipPrefix = Ip6Prefix.valueOf("1111:2222:3333:4444::/120");
+        assertTrue(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4444::")));
+        assertTrue(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4444::1")));
+        assertFalse(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4445::")));
+        assertFalse(ipPrefix.contains(Ip6Address.valueOf("::")));
+        assertFalse(ipPrefix.contains(
+                Ip6Address.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
+
+        ipPrefix = Ip6Prefix.valueOf("1111:2222:3333:4444::/128");
+        assertTrue(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4444::")));
+        assertFalse(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4444::1")));
+        assertFalse(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4445::")));
+        assertFalse(ipPrefix.contains(Ip6Address.valueOf("::")));
+        assertFalse(ipPrefix.contains(
+                Ip6Address.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
+
+        ipPrefix = Ip6Prefix.valueOf("::/0");
+        assertTrue(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4444::")));
+        assertTrue(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4444::1")));
+        assertTrue(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4445::")));
+        assertTrue(ipPrefix.contains(Ip6Address.valueOf("::")));
+        assertTrue(ipPrefix.contains(
+                Ip6Address.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
+
+        ipPrefix =
+            Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertFalse(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4444::")));
+        assertFalse(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4444::1")));
+        assertFalse(ipPrefix.contains(
+                Ip6Address.valueOf("1111:2222:3333:4445::")));
+        assertFalse(ipPrefix.contains(Ip6Address.valueOf("::")));
+        assertTrue(ipPrefix.contains(
+                Ip6Address.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
+    }
+
+    /**
+     * Tests equality of {@link Ip6Prefix} for IPv6.
+     */
+    @Test
+    public void testEqualityIPv6() {
+        new EqualsTester()
+            .addEqualityGroup(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/120"),
+                Ip6Prefix.valueOf("1111:2222:3333:4444::1/120"),
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/120"))
+            .addEqualityGroup(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/64"),
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/64"))
+            .addEqualityGroup(
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/128"),
+                Ip6Prefix.valueOf("1111:2222:3333:4444::/128"))
+            .addEqualityGroup(
+                Ip6Prefix.valueOf("1111:2222:3333:4445::/64"),
+                Ip6Prefix.valueOf("1111:2222:3333:4445::/64"))
+            .addEqualityGroup(
+                Ip6Prefix.valueOf("::/0"),
+                Ip6Prefix.valueOf("::/0"))
+            .addEqualityGroup(
+                Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"),
+                Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"))
+            .testEquals();
+    }
+
+    /**
+     * Tests object string representation for IPv6.
+     */
+    @Test
+    public void testToStringIPv6() {
+        Ip6Prefix ipPrefix;
+
+        ipPrefix = Ip6Prefix.valueOf("1100::/8");
+        assertThat(ipPrefix.toString(), is("1100::/8"));
+
+        ipPrefix = Ip6Prefix.valueOf("1111:2222:3333:4444:5555:6666:7777:8885/8");
+        assertThat(ipPrefix.toString(), is("1100::/8"));
+
+        ipPrefix = Ip6Prefix.valueOf("::/0");
+        assertThat(ipPrefix.toString(), is("::/0"));
+
+        ipPrefix = Ip6Prefix.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
+        assertThat(ipPrefix.toString(),
                    is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
     }
 }