[ONOS-6142] Add nonce and segment extension address with unit test

Change-Id: Ia66304d7da81ee7866640987d196eb50e8eb725d
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispNonceAddress.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispNonceAddress.java
index 747c5f6..a91bfd9 100644
--- a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispNonceAddress.java
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispNonceAddress.java
@@ -16,12 +16,18 @@
 
 package org.onosproject.drivers.lisp.extensions;
 
+import com.google.common.collect.Maps;
 import org.onosproject.mapping.addresses.ExtensionMappingAddress;
 import org.onosproject.mapping.addresses.ExtensionMappingAddressType;
+import org.onosproject.mapping.addresses.MappingAddress;
 import org.onosproject.net.flow.AbstractExtension;
 
+import java.util.Map;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
 import static org.onosproject.mapping.addresses.ExtensionMappingAddressType
-                                .ExtensionMappingAddressTypes.NONCE_ADDRESS;
+        .ExtensionMappingAddressTypes.NONCE_ADDRESS;
 
 /**
  * Implementation of LISP nonce address.
@@ -29,7 +35,49 @@
  * check for a specific nonce value in the LISP encapsulated packet.
  */
 public class LispNonceAddress extends AbstractExtension
-                                            implements ExtensionMappingAddress {
+        implements ExtensionMappingAddress {
+
+    private static final String NONCE = "nonce";
+    private static final String ADDRESS = "address";
+
+    private int nonce;
+    private MappingAddress address;
+
+    /**
+     * Default constructor.
+     */
+    public LispNonceAddress() {
+    }
+
+    /**
+     * Creates an instance with initialized parameters.
+     *
+     * @param nonce   nonce
+     * @param address address
+     */
+    private LispNonceAddress(int nonce, MappingAddress address) {
+        this.nonce = nonce;
+        this.address = address;
+    }
+
+    /**
+     * Obtains nonce.
+     *
+     * @return nonce
+     */
+    public int getNonce() {
+        return nonce;
+    }
+
+    /**
+     * Obtains address.
+     *
+     * @return address
+     */
+    public MappingAddress getAddress() {
+        return address;
+    }
+
     @Override
     public ExtensionMappingAddressType type() {
         return NONCE_ADDRESS.type();
@@ -37,11 +85,86 @@
 
     @Override
     public byte[] serialize() {
-        return new byte[0];
+        Map<String, Object> parameterMap = Maps.newHashMap();
+
+        parameterMap.put(NONCE, nonce);
+        parameterMap.put(ADDRESS, address);
+
+        return APP_KRYO.serialize(parameterMap);
     }
 
     @Override
     public void deserialize(byte[] data) {
+        Map<String, Object> parameterMap = APP_KRYO.deserialize(data);
 
+        this.nonce = (int) parameterMap.get(NONCE);
+        this.address = (MappingAddress) parameterMap.get(ADDRESS);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(nonce, address);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof LispNonceAddress) {
+            final LispNonceAddress other = (LispNonceAddress) obj;
+            return Objects.equals(this.nonce, other.nonce) &&
+                    Objects.equals(this.address, other.address);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("nonce", nonce)
+                .add("address", address)
+                .toString();
+    }
+
+    /**
+     * A builder for building LispNonceAddress.
+     */
+    public static final class Builder {
+        private int nonce;
+        private MappingAddress address;
+
+        /**
+         * Sets nonce.
+         *
+         * @param nonce nonce
+         * @return Builder object
+         */
+        public Builder withNonce(int nonce) {
+            this.nonce = nonce;
+            return this;
+        }
+
+        /**
+         * Sets address.
+         *
+         * @param address address
+         * @return Builder object
+         */
+        public Builder withAddress(MappingAddress address) {
+            this.address = address;
+            return this;
+        }
+
+        /**
+         * Builds LispNonceAddress instance.
+         *
+         * @return LispNonceAddress instance
+         */
+        public LispNonceAddress build() {
+
+            return new LispNonceAddress(nonce, address);
+        }
     }
 }
diff --git a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispSegmentAddress.java b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispSegmentAddress.java
index b251724..aaa90df 100644
--- a/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispSegmentAddress.java
+++ b/drivers/lisp/src/main/java/org/onosproject/drivers/lisp/extensions/LispSegmentAddress.java
@@ -16,12 +16,18 @@
 
 package org.onosproject.drivers.lisp.extensions;
 
+import com.google.common.collect.Maps;
 import org.onosproject.mapping.addresses.ExtensionMappingAddress;
 import org.onosproject.mapping.addresses.ExtensionMappingAddressType;
+import org.onosproject.mapping.addresses.MappingAddress;
 import org.onosproject.net.flow.AbstractExtension;
 
+import java.util.Map;
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
 import static org.onosproject.mapping.addresses.ExtensionMappingAddressType
-                            .ExtensionMappingAddressTypes.SECURITY_ADDRESS;
+                                .ExtensionMappingAddressTypes.SEGMENT_ADDRESS;
 
 /**
  * Implementation of LISP segment address.
@@ -31,18 +37,135 @@
  */
 public class LispSegmentAddress extends AbstractExtension
                                             implements ExtensionMappingAddress {
+
+    private static final String INSTANCE_ID = "instanceId";
+    private static final String ADDRESS = "address";
+
+    private int instanceId;
+    private MappingAddress address;
+
+    /**
+     * Default constructor.
+     */
+    public LispSegmentAddress() {
+    }
+
+    /**
+     * Creates an instance with initialized parameters.
+     *
+     * @param instanceId instance id
+     * @param address    address
+     */
+    private LispSegmentAddress(int instanceId, MappingAddress address) {
+        this.instanceId = instanceId;
+        this.address = address;
+    }
+
+    /**
+     * Obtains instance identifier.
+     *
+     * @return instance identifier
+     */
+    public int getInstanceId() {
+        return instanceId;
+    }
+
+    /**
+     * Obtains address.
+     *
+     * @return address
+     */
+    public MappingAddress getAddress() {
+        return address;
+    }
+
     @Override
     public ExtensionMappingAddressType type() {
-        return SECURITY_ADDRESS.type();
+        return SEGMENT_ADDRESS.type();
     }
 
     @Override
     public byte[] serialize() {
-        return new byte[0];
+        Map<String, Object> parameterMap = Maps.newHashMap();
+
+        parameterMap.put(INSTANCE_ID, instanceId);
+        parameterMap.put(ADDRESS, address);
+
+        return APP_KRYO.serialize(parameterMap);
     }
 
     @Override
     public void deserialize(byte[] data) {
+        Map<String, Object> parameterMap = APP_KRYO.deserialize(data);
 
+        this.instanceId = (int) parameterMap.get(INSTANCE_ID);
+        this.address = (MappingAddress) parameterMap.get(ADDRESS);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(address, instanceId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj instanceof LispSegmentAddress) {
+            final LispSegmentAddress other = (LispSegmentAddress) obj;
+            return Objects.equals(this.address, other.address) &&
+                    Objects.equals(this.instanceId, other.instanceId);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("address", address)
+                .add("instanceId", instanceId)
+                .toString();
+    }
+
+    /**
+     * A builder for building LispSegmentAddress.
+     */
+    public static final class Builder {
+        private int instanceId;
+        private MappingAddress address;
+
+        /**
+         * Sets instance identifer.
+         *
+         * @param instanceId instance identifier
+         * @return Builder object
+         */
+        public Builder withInstanceId(int instanceId) {
+            this.instanceId = instanceId;
+            return this;
+        }
+
+        /**
+         * Sets address.
+         *
+         * @param address mapping address
+         * @return Builder object
+         */
+        public Builder withAddress(MappingAddress address) {
+            this.address = address;
+            return this;
+        }
+
+        /**
+         * Builds LispSegmentAddress instance.
+         *
+         * @return LispSegmentAddress instance
+         */
+        public LispSegmentAddress build() {
+
+            return new LispSegmentAddress(instanceId, address);
+        }
     }
 }
diff --git a/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/LispNonceAddressTest.java b/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/LispNonceAddressTest.java
new file mode 100644
index 0000000..0f21800
--- /dev/null
+++ b/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/LispNonceAddressTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.drivers.lisp.extensions;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddresses;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Unit tests for LispNonceAddress extension class.
+ */
+public class LispNonceAddressTest {
+
+    private static final IpPrefix IP_ADDRESS_1 = IpPrefix.valueOf("1.2.3.4/24");
+    private static final IpPrefix IP_ADDRESS_2 = IpPrefix.valueOf("5.6.7.8/24");
+
+    private static final int NONCE_1 = 1048576;
+    private static final int NONCE_2 = 1;
+
+    private LispNonceAddress address1;
+    private LispNonceAddress sameAsAddress1;
+    private LispNonceAddress address2;
+
+    @Before
+    public void setUp() {
+
+        MappingAddress ma1 = MappingAddresses.ipv4MappingAddress(IP_ADDRESS_1);
+
+        address1 = new LispNonceAddress.Builder()
+                                .withNonce(NONCE_1)
+                                .withAddress(ma1)
+                                .build();
+
+        sameAsAddress1 = new LispNonceAddress.Builder()
+                                .withNonce(NONCE_1)
+                                .withAddress(ma1)
+                                .build();
+
+        MappingAddress ma2 = MappingAddresses.ipv4MappingAddress(IP_ADDRESS_2);
+
+        address2 = new LispNonceAddress.Builder()
+                                .withNonce(NONCE_2)
+                                .withAddress(ma2)
+                                .build();
+    }
+
+    @Test
+    public void testEquality() {
+        new EqualsTester()
+                .addEqualityGroup(address1, sameAsAddress1)
+                .addEqualityGroup(address2).testEquals();
+    }
+
+    @Test
+    public void testConstruction() {
+        LispNonceAddress address = address1;
+
+        MappingAddress ma = MappingAddresses.ipv4MappingAddress(IP_ADDRESS_1);
+
+        assertThat(address.getNonce(), is(NONCE_1));
+        assertThat(address.getAddress(), is(ma));
+    }
+
+    @Test
+    public void testSerialization() {
+        LispNonceAddress other = new LispNonceAddress();
+        other.deserialize(address1.serialize());
+
+        new EqualsTester()
+                .addEqualityGroup(address1, other)
+                .testEquals();
+    }
+}
diff --git a/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/LispSegmentAddressTest.java b/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/LispSegmentAddressTest.java
new file mode 100644
index 0000000..4b12289
--- /dev/null
+++ b/drivers/lisp/src/test/java/org/onosproject/drivers/lisp/extensions/LispSegmentAddressTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.drivers.lisp.extensions;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.mapping.addresses.MappingAddress;
+import org.onosproject.mapping.addresses.MappingAddresses;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Unit tests for LispSegmentAddress extension class.
+ */
+public class LispSegmentAddressTest {
+
+    private static final IpPrefix IP_ADDRESS_1 = IpPrefix.valueOf("1.2.3.4/24");
+    private static final IpPrefix IP_ADDRESS_2 = IpPrefix.valueOf("5.6.7.8/24");
+
+    private static final int INSTANCE_ID_1 = 1;
+    private static final int INSTANCE_ID_2 = 2;
+
+    private LispSegmentAddress address1;
+    private LispSegmentAddress sameAsAddress1;
+    private LispSegmentAddress address2;
+
+    @Before
+    public void setUp() {
+
+        MappingAddress ma1 = MappingAddresses.ipv4MappingAddress(IP_ADDRESS_1);
+
+        address1 = new LispSegmentAddress.Builder()
+                                    .withInstanceId(INSTANCE_ID_1)
+                                    .withAddress(ma1)
+                                    .build();
+
+        sameAsAddress1 = new LispSegmentAddress.Builder()
+                                    .withInstanceId(INSTANCE_ID_1)
+                                    .withAddress(ma1)
+                                    .build();
+
+        MappingAddress ma2 = MappingAddresses.ipv4MappingAddress(IP_ADDRESS_2);
+
+        address2 = new LispSegmentAddress.Builder()
+                                    .withInstanceId(INSTANCE_ID_2)
+                                    .withAddress(ma2)
+                                    .build();
+    }
+
+    @Test
+    public void testEquality() {
+        new EqualsTester()
+                .addEqualityGroup(address1, sameAsAddress1)
+                .addEqualityGroup(address2).testEquals();
+    }
+
+    @Test
+    public void testConstruction() {
+        LispSegmentAddress address = address1;
+
+        MappingAddress ma = MappingAddresses.ipv4MappingAddress(IP_ADDRESS_1);
+
+        assertThat(address.getInstanceId(), is(INSTANCE_ID_1));
+        assertThat(address.getAddress(), is(ma));
+    }
+
+    @Test
+    public void testSerialization() {
+        LispSegmentAddress other = new LispSegmentAddress();
+        other.deserialize(address1.serialize());
+
+        new EqualsTester()
+                .addEqualityGroup(address1, other)
+                .testEquals();
+    }
+}