[ONOS-5916] Add various MappingAddress impl classes with unit tests

Change-Id: Ie373601d1406d161e8071e78cd584e5cc8b8f5af
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingKey.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingKey.java
index 965767b..a7c3f7f 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingKey.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingKey.java
@@ -15,7 +15,7 @@
  */
 package org.onosproject.mapping;
 
-import org.onosproject.mapping.address.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddress;
 
 /**
  * Default mapping key implementation.
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingValue.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingValue.java
index 2575764..d38b782 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingValue.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/DefaultMappingValue.java
@@ -15,7 +15,7 @@
  */
 package org.onosproject.mapping;
 
-import org.onosproject.mapping.address.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddress;
 import org.onosproject.mapping.instructions.MappingInstruction;
 
 import java.util.List;
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingKey.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingKey.java
index cbce738..146fbf9 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingKey.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingKey.java
@@ -15,7 +15,7 @@
  */
 package org.onosproject.mapping;
 
-import org.onosproject.mapping.address.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddress;
 
 /**
  * Abstraction of network mapping key.
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingValue.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingValue.java
index a41d749..07f4594 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingValue.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/MappingValue.java
@@ -15,7 +15,7 @@
  */
 package org.onosproject.mapping;
 
-import org.onosproject.mapping.address.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddress;
 import org.onosproject.mapping.instructions.MappingInstruction;
 
 import java.util.List;
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/ASMappingAddress.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/ASMappingAddress.java
new file mode 100644
index 0000000..b98d790
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/ASMappingAddress.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.onosproject.mapping.addresses;
+
+import java.util.Objects;
+
+/**
+ * Implementation of AS mapping address.
+ */
+public final class ASMappingAddress implements MappingAddress {
+
+    private final String asNumber;
+
+    /**
+     * Default constructor of ASMappingAddress.
+     *
+     * @param asNumber AS number
+     */
+    ASMappingAddress(String asNumber) {
+        this.asNumber = asNumber;
+    }
+
+    @Override
+    public Type type() {
+        return Type.AS;
+    }
+
+    /**
+     * Obtains AS number.
+     *
+     * @return AS number
+     */
+    public String asNumber() {
+        return this.asNumber;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString() + TYPE_SEPARATOR + asNumber;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type().ordinal(), asNumber);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ASMappingAddress) {
+            ASMappingAddress that = (ASMappingAddress) obj;
+            return Objects.equals(asNumber, that.asNumber);
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/DNMappingAddress.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/DNMappingAddress.java
new file mode 100644
index 0000000..320f118
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/DNMappingAddress.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.onosproject.mapping.addresses;
+
+import java.util.Objects;
+
+/**
+ * Implementation of distinguished name mapping address.
+ */
+public final class DNMappingAddress implements MappingAddress {
+
+    private final String name;
+
+    /**
+     * Default constructor of DNMappingAddress.
+     *
+     * @param name distinguished name
+     */
+    DNMappingAddress(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public Type type() {
+        return Type.DN;
+    }
+
+    /**
+     * Obtains distinguished name.
+     *
+     * @return distinguished name
+     */
+    public String name() {
+        return this.name;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString() + TYPE_SEPARATOR + name;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type().ordinal(), name);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof DNMappingAddress) {
+            DNMappingAddress that = (DNMappingAddress) obj;
+            return Objects.equals(name, that.name);
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/EthMappingAddress.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/EthMappingAddress.java
new file mode 100644
index 0000000..805f92a
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/EthMappingAddress.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.onosproject.mapping.addresses;
+
+import org.onlab.packet.MacAddress;
+
+import java.util.Objects;
+
+/**
+ * Implementation of MAC mapping address.
+ */
+public final class EthMappingAddress implements MappingAddress {
+    private final MacAddress mac;
+
+    /**
+     * Default constructor of EthMappingAddress.
+     *
+     * @param mac the MAC address to look up
+     */
+    EthMappingAddress(MacAddress mac) {
+        this.mac = mac;
+    }
+
+    @Override
+    public Type type() {
+        return Type.ETH;
+    }
+
+    /**
+     * Obtains the MAC address to look up.
+     *
+     * @return the MAC address to look up
+     */
+    public MacAddress mac() {
+        return this.mac;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString() + TYPE_SEPARATOR + mac;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(Type.ETH, mac);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof EthMappingAddress) {
+            EthMappingAddress that = (EthMappingAddress) obj;
+            return Objects.equals(mac, that.mac);
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/ExtensionMappingAddress.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/ExtensionMappingAddress.java
new file mode 100644
index 0000000..853fd97
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/ExtensionMappingAddress.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.onosproject.mapping.addresses;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+
+import java.util.Objects;
+
+/**
+ * Mapping address for implementing extensions.
+ */
+public final class ExtensionMappingAddress implements MappingAddress {
+
+    private final ExtensionSelector extensionSelector;
+    private final DeviceId deviceId;
+
+    /**
+     * Default constructor of ExtensionMappingAddress.
+     *
+     * @param extensionSelector extension selector
+     * @param deviceId          device identifier
+     */
+    public ExtensionMappingAddress(ExtensionSelector extensionSelector, DeviceId deviceId) {
+        this.extensionSelector = extensionSelector;
+        this.deviceId = deviceId;
+    }
+
+    @Override
+    public Type type() {
+        return Type.EXTENSION;
+    }
+
+    /**
+     * Returns the extension selector.
+     *
+     * @return extension selector
+     */
+    public ExtensionSelector extensionSelector() {
+        return extensionSelector;
+    }
+
+    /**
+     * Returns the device identifier.
+     *
+     * @return the device identifier
+     */
+    public DeviceId deviceId() {
+        return deviceId;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString() + TYPE_SEPARATOR + deviceId + "/" + extensionSelector;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type().ordinal(), extensionSelector, deviceId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ExtensionMappingAddress) {
+            ExtensionMappingAddress that = (ExtensionMappingAddress) obj;
+            return Objects.equals(extensionSelector, that.extensionSelector) &&
+                    Objects.equals(deviceId, that.deviceId);
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/IPMappingAddress.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/IPMappingAddress.java
new file mode 100644
index 0000000..89b652a
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/IPMappingAddress.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.onosproject.mapping.addresses;
+
+import org.onlab.packet.IpPrefix;
+
+import java.util.Objects;
+
+/**
+ * Implementation of IP mapping address.
+ */
+public final class IPMappingAddress implements MappingAddress {
+
+    private final IpPrefix ip;
+    private final Type type;
+
+    /**
+     * Default constructor of IPMappingAddress.
+     *
+     * @param ip   the IP prefix to match. Could be either IPv4 or IPv6
+     * @param type the match type, the type can be one of the following:
+     *             Type.IPV4, Type.IPV6
+     */
+    IPMappingAddress(IpPrefix ip, Type type) {
+        this.ip = ip;
+        this.type = type;
+    }
+
+    @Override
+    public Type type() {
+        return type;
+    }
+
+    /**
+     * Obtains the IP prefix to look up.
+     *
+     * @return the IP prefix to look up
+     */
+    public IpPrefix ip() {
+        return this.ip;
+    }
+
+    @Override
+    public String toString() {
+        return type().toString() + TYPE_SEPARATOR + ip;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type().ordinal(), ip);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof IPMappingAddress) {
+            IPMappingAddress that = (IPMappingAddress) obj;
+            return Objects.equals(ip, that.ip) &&
+                    Objects.equals(type, that.type);
+        }
+        return false;
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/address/MappingAddress.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/MappingAddress.java
similarity index 93%
rename from apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/address/MappingAddress.java
rename to apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/MappingAddress.java
index c1473e9..5c7775b 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/address/MappingAddress.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/MappingAddress.java
@@ -13,13 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.mapping.address;
+package org.onosproject.mapping.addresses;
 
 /**
  * Presentation of a single mapping selection.
  */
 public interface MappingAddress {
 
+    String TYPE_SEPARATOR = ":";
+
     /**
      * Types of address to which the mapping criterion may apply.
      */
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/MappingAddresses.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/MappingAddresses.java
new file mode 100644
index 0000000..6683190
--- /dev/null
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/MappingAddresses.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.onosproject.mapping.addresses;
+
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+
+/**
+ * Factory class for creating various mapping addresses.
+ */
+public final class MappingAddresses {
+
+    /**
+     * Prevents instantiation from external.
+     */
+    private MappingAddresses() {}
+
+    /**
+     * Creates an ASMappingAddress using the specified value.
+     *
+     * @param asn Autonomous System Number
+     * @return mapping address
+     */
+    public static ASMappingAddress asMappingAddress(String asn) {
+        return new ASMappingAddress(asn);
+    }
+
+    /**
+     * Creates a DNMappingAddress using the specified value.
+     *
+     * @param dn Distinguished Name
+     * @return mapping address
+     */
+    public static DNMappingAddress dnMappingAddress(String dn) {
+        return new DNMappingAddress(dn);
+    }
+
+    /**
+     * Creates an EthMappingAddress using the specified value.
+     *
+     * @param mac MAC address
+     * @return mapping address
+     */
+    public static EthMappingAddress ethMappingAddress(MacAddress mac) {
+        return new EthMappingAddress(mac);
+    }
+
+    /**
+     * Creates an IPv4MappingAddress using the specified value.
+     *
+     * @param ip IP address
+     * @return mapping address
+     */
+    public static IPMappingAddress ipv4MappingAddress(IpPrefix ip) {
+        return new IPMappingAddress(ip, MappingAddress.Type.IPV4);
+    }
+
+    /**
+     * Creates an IPv6MappingAddress using the specified value.
+     *
+     * @param ip IP address
+     * @return mapping address
+     */
+    public static IPMappingAddress ipv6MappingAddress(IpPrefix ip) {
+        return new IPMappingAddress(ip, MappingAddress.Type.IPV6);
+    }
+
+    /**
+     * Creates an ExtensionMappingAddress using the specified value.
+     *
+     * @param selector extension selector
+     * @param deviceId device identifier
+     * @return mapping address
+     */
+    public static ExtensionMappingAddress extension(ExtensionSelector selector,
+                                                    DeviceId deviceId) {
+        return new ExtensionMappingAddress(selector, deviceId);
+    }
+}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/address/package-info.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/package-info.java
similarity index 93%
rename from apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/address/package-info.java
rename to apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/package-info.java
index 8fb2106..fa16171 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/address/package-info.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/package-info.java
@@ -17,4 +17,4 @@
 /**
  * Mapping address package.
  */
-package org.onosproject.mapping.address;
\ No newline at end of file
+package org.onosproject.mapping.addresses;
\ No newline at end of file
diff --git a/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/addresses/MappingAddressesTest.java b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/addresses/MappingAddressesTest.java
new file mode 100644
index 0000000..d55bba7
--- /dev/null
+++ b/apps/mappingmanagement/api/src/test/java/org/onosproject/mapping/addresses/MappingAddressesTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.onosproject.mapping.addresses;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.onlab.junit.UtilityClassChecker.assertThatClassIsUtility;
+
+/**
+ * Unit tests for various mapping address implementation classes.
+ */
+public class MappingAddressesTest {
+
+    private final String asn1 = "1";
+    private final String asn2 = "2";
+    private MappingAddress asMa1 = MappingAddresses.asMappingAddress(asn1);
+    private MappingAddress sameAsAsMa1 = MappingAddresses.asMappingAddress(asn1);
+    private MappingAddress asMa2 = MappingAddresses.asMappingAddress(asn2);
+
+    private final String dn1 = "1";
+    private final String dn2 = "2";
+    private MappingAddress dnMa1 = MappingAddresses.dnMappingAddress(dn1);
+    private MappingAddress sameAsDnMa1 = MappingAddresses.dnMappingAddress(dn1);
+    private MappingAddress dnMa2 = MappingAddresses.dnMappingAddress(dn2);
+
+    private static final String MAC1 = "00:00:00:00:00:01";
+    private static final String MAC2 = "00:00:00:00:00:02";
+    private MacAddress mac1 = MacAddress.valueOf(MAC1);
+    private MacAddress mac2 = MacAddress.valueOf(MAC2);
+    private MappingAddress ethMa1 = MappingAddresses.ethMappingAddress(mac1);
+    private MappingAddress sameAsEthMa1 = MappingAddresses.ethMappingAddress(mac1);
+    private MappingAddress ethMa2 = MappingAddresses.ethMappingAddress(mac2);
+
+    private static final String IP1 = "1.2.3.4/24";
+    private static final String IP2 = "5.6.7.8/24";
+    private static final String IPV61 = "fe80::1/64";
+    private static final String IPV62 = "fc80::2/64";
+    private IpPrefix ip1 = IpPrefix.valueOf(IP1);
+    private IpPrefix ip2 = IpPrefix.valueOf(IP2);
+    private IpPrefix ipv61 = IpPrefix.valueOf(IPV61);
+    private IpPrefix ipv62 = IpPrefix.valueOf(IPV62);
+    private MappingAddress ipMa1 = MappingAddresses.ipv4MappingAddress(ip1);
+    private MappingAddress sameAsIpMa1 = MappingAddresses.ipv4MappingAddress(ip1);
+    private MappingAddress ipMa2 = MappingAddresses.ipv4MappingAddress(ip2);
+    private MappingAddress ipv6Ma1 = MappingAddresses.ipv6MappingAddress(ipv61);
+    private MappingAddress sameAsIpv6Ma1 = MappingAddresses.ipv6MappingAddress(ipv61);
+    private MappingAddress ipv6Ma2 = MappingAddresses.ipv6MappingAddress(ipv62);
+
+    /**
+     * Checks that a MappingAddress object has the proper type, and then converts
+     * it to the proper type.
+     *
+     * @param address MappingAddress object to convert
+     * @param type    Enumerated type value for the MappingAddress class
+     * @param clazz   Desired MappingAddress class
+     * @param <T>     The type the caller wants returned
+     * @return converted object
+     */
+    @SuppressWarnings("unchecked")
+    private <T> T checkAndConvert(MappingAddress address, MappingAddress.Type type, Class clazz) {
+        assertThat(address, is(notNullValue()));
+        assertThat(address.type(), is(equalTo(type)));
+        assertThat(address, instanceOf(clazz));
+        return (T) address;
+    }
+
+    /**
+     * Checks the equals() and toString() methods of a MappingAddress class.
+     *
+     * @param c1      first object to compare
+     * @param c1match object that should be equal to the first
+     * @param c2      object that should not be equal to the first
+     * @param <T>     type of the arguments
+     */
+    private <T extends MappingAddress> void checkEqualsAndToString(T c1,
+                                                                   T c1match,
+                                                                   T c2) {
+        new EqualsTester()
+                .addEqualityGroup(c1, c1match)
+                .addEqualityGroup(c2)
+                .testEquals();
+    }
+
+    /**
+     * Checks that the MappingAddresses class is a valid utility class.
+     */
+    @Test
+    public void testMappingAddressesUtility() {
+        assertThatClassIsUtility(MappingAddresses.class);
+    }
+
+    /**
+     * Checks that the mapping address implementations are immutable.
+     */
+    @Test
+    public void testMappingAddressesImmutability() {
+        assertThatClassIsImmutable(ASMappingAddress.class);
+        assertThatClassIsImmutable(DNMappingAddress.class);
+        assertThatClassIsImmutable(EthMappingAddress.class);
+        assertThatClassIsImmutable(ExtensionMappingAddress.class);
+        assertThatClassIsImmutable(IPMappingAddress.class);
+    }
+
+    /**
+     * Tests the asMappingAddress method.
+     */
+    @Test
+    public void testAsMappingAddressMethod() {
+        String asn = "1";
+        MappingAddress mappingAddress = MappingAddresses.asMappingAddress(asn);
+        ASMappingAddress asMappingAddress =
+                checkAndConvert(mappingAddress,
+                                MappingAddress.Type.AS,
+                                ASMappingAddress.class);
+        assertThat(asMappingAddress.asNumber(), is(equalTo(asn)));
+    }
+
+    /**
+     * Tests the equals() method of the ASMappingAddress class.
+     */
+    @Test
+    public void testAsMappingAddressEquals() {
+        checkEqualsAndToString(asMa1, sameAsAsMa1, asMa2);
+    }
+
+    /**
+     * Tests the dnMappingAddress method.
+     */
+    @Test
+    public void testDnMappingAddressMethod() {
+        String dn = "1";
+        MappingAddress mappingAddress = MappingAddresses.dnMappingAddress(dn);
+        DNMappingAddress dnMappingAddress =
+                checkAndConvert(mappingAddress,
+                                MappingAddress.Type.DN,
+                                DNMappingAddress.class);
+        assertThat(dnMappingAddress.name(), is(equalTo(dn)));
+    }
+
+    /**
+     * Tests the equals() method of the DNMappingAddress class.
+     */
+    @Test
+    public void testDnMappingAddressEquals() {
+        checkEqualsAndToString(dnMa1, sameAsDnMa1, dnMa2);
+    }
+
+    /**
+     * Tests the ethMappingAddress method.
+     */
+    @Test
+    public void testEthMappingAddressMethod() {
+        MacAddress mac = MacAddress.valueOf("00:00:00:00:00:01");
+        MappingAddress mappingAddress = MappingAddresses.ethMappingAddress(mac);
+        EthMappingAddress ethMappingAddress =
+                checkAndConvert(mappingAddress,
+                                MappingAddress.Type.ETH,
+                                EthMappingAddress.class);
+        assertThat(ethMappingAddress.mac(), is(equalTo(mac)));
+    }
+
+    /**
+     * Tests the equals() method of the EthMappingAddress class.
+     */
+    @Test
+    public void testEthMappingAddressEquals() {
+        checkEqualsAndToString(ethMa1, sameAsEthMa1, ethMa2);
+    }
+
+    /**
+     * Tests the ipv4MappingAddress method.
+     */
+    @Test
+    public void testIpv4MappingAddressMethod() {
+        IpPrefix ip = IpPrefix.valueOf("1.2.3.4/24");
+        MappingAddress mappingAddress = MappingAddresses.ipv4MappingAddress(ip);
+        IPMappingAddress ipMappingAddress =
+                checkAndConvert(mappingAddress,
+                                MappingAddress.Type.IPV4,
+                                IPMappingAddress.class);
+        assertThat(ipMappingAddress.ip(), is(equalTo(ip)));
+    }
+
+    /**
+     * Tests the equals() method of the IPMappingAddress class.
+     */
+    @Test
+    public void testIpv4MappingAddressEquals() {
+        checkEqualsAndToString(ipMa1, sameAsIpMa1, ipMa2);
+    }
+
+    /**
+     * Tests the ipv6MappingAddress method.
+     */
+    @Test
+    public void testIpv6MappingAddressMethod() {
+        IpPrefix ipv6 = IpPrefix.valueOf("fe80::1/64");
+        MappingAddress mappingAddress = MappingAddresses.ipv6MappingAddress(ipv6);
+        IPMappingAddress ipMappingAddress =
+                checkAndConvert(mappingAddress,
+                                MappingAddress.Type.IPV6,
+                                IPMappingAddress.class);
+        assertThat(ipMappingAddress.ip(), is(equalTo(ipv6)));
+    }
+
+    /**
+     * Tests the equals() method of the IPMappingAddress class.
+     */
+    @Test
+    public void testIpv6MappingAddressEquals() {
+        checkEqualsAndToString(ipv6Ma1, sameAsIpv6Ma1, ipv6Ma2);
+    }
+}