Merge "Add SmsHeaderTest" into rvc-dev
diff --git a/src/com/android/cellbroadcastservice/SmsHeader.java b/src/com/android/cellbroadcastservice/SmsHeader.java
index 2449f98..e7e2c44 100644
--- a/src/com/android/cellbroadcastservice/SmsHeader.java
+++ b/src/com/android/cellbroadcastservice/SmsHeader.java
@@ -19,6 +19,8 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * SMS user data header, as specified in TS 23.040 9.2.3.24.
@@ -71,6 +73,25 @@
     /** The maximum number of payload bytes per message */
     public static final int MAX_USER_DATA_BYTES = 140;
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        SmsHeader smsHeader = (SmsHeader) o;
+        return languageTable == smsHeader.languageTable
+                && languageShiftTable == smsHeader.languageShiftTable
+                && Objects.equals(portAddrs, smsHeader.portAddrs)
+                && Objects.equals(concatRef, smsHeader.concatRef)
+                && Objects.equals(specialSmsMsgList, smsHeader.specialSmsMsgList)
+                && Objects.equals(miscEltList, smsHeader.miscEltList);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(portAddrs, concatRef, specialSmsMsgList, miscEltList, languageTable,
+                languageShiftTable);
+    }
+
     /**
      * Port addresses used in creating and parsing SmsHeader.
      */
@@ -81,6 +102,21 @@
         public int destPort;
         public int origPort;
         public boolean areEightBits;
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            PortAddrs portAddrs = (PortAddrs) o;
+            return destPort == portAddrs.destPort
+                    && origPort == portAddrs.origPort
+                    && areEightBits == portAddrs.areEightBits;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(destPort, origPort, areEightBits);
+        }
     }
 
     /**
@@ -94,6 +130,22 @@
         public int seqNumber;
         public int msgCount;
         public boolean isEightBits;
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            ConcatRef concatRef = (ConcatRef) o;
+            return refNumber == concatRef.refNumber
+                    && seqNumber == concatRef.seqNumber
+                    && msgCount == concatRef.msgCount
+                    && isEightBits == concatRef.isEightBits;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(refNumber, seqNumber, msgCount, isEightBits);
+        }
     }
 
     /**
@@ -102,6 +154,20 @@
     public static class SpecialSmsMsg {
         public int msgIndType;
         public int msgCount;
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            SpecialSmsMsg that = (SpecialSmsMsg) o;
+            return msgIndType == that.msgIndType
+                    && msgCount == that.msgCount;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(msgIndType, msgCount);
+        }
     }
 
     /**
@@ -111,6 +177,22 @@
     public static class MiscElt {
         public int id;
         public byte[] data;
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            MiscElt miscElt = (MiscElt) o;
+            return id == miscElt.id
+                    && Arrays.equals(data, miscElt.data);
+        }
+
+        @Override
+        public int hashCode() {
+            int result = Objects.hash(id);
+            result = 31 * result + Arrays.hashCode(data);
+            return result;
+        }
     }
 
     public PortAddrs portAddrs;
diff --git a/tests/src/com/android/cellbroadcastservice/tests/SmsHeaderTest.java b/tests/src/com/android/cellbroadcastservice/tests/SmsHeaderTest.java
new file mode 100644
index 0000000..1545c2d
--- /dev/null
+++ b/tests/src/com/android/cellbroadcastservice/tests/SmsHeaderTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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 com.android.cellbroadcastservice.tests;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.cellbroadcastservice.SmsHeader;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class SmsHeaderTest extends CellBroadcastServiceTestBase {
+
+    private SmsHeader mSmsHeader;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
+        mSmsHeader = new SmsHeader();
+
+        // construct port addresses
+        SmsHeader.PortAddrs portAddresses = new SmsHeader.PortAddrs();
+        portAddresses.areEightBits = true;
+        portAddresses.destPort = 80;
+        portAddresses.origPort = 80;
+
+        // construct concatenated reference
+        SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+        concatRef.isEightBits = true;
+        concatRef.msgCount = 0x03;
+        concatRef.refNumber = 0x02;
+        concatRef.seqNumber = 0x01;
+
+        // construct special SMS message
+        SmsHeader.SpecialSmsMsg specialSmsMessage1 = new SmsHeader.SpecialSmsMsg();
+        specialSmsMessage1.msgIndType = 0x01;
+        specialSmsMessage1.msgCount = 0x02;
+
+        // construct misc elt
+        SmsHeader.MiscElt miscElement1 = new SmsHeader.MiscElt();
+        miscElement1.id = 0x26; // must be != to a defined elt id
+        miscElement1.data = new byte[]{0x00, 0x01, 0x02, 0x03, 0x04};
+
+        mSmsHeader.portAddrs = portAddresses;
+        mSmsHeader.concatRef = concatRef;
+        mSmsHeader.specialSmsMsgList = new ArrayList<>();
+        mSmsHeader.specialSmsMsgList.add(specialSmsMessage1);
+        mSmsHeader.miscEltList = new ArrayList<>();
+        mSmsHeader.miscEltList.add(miscElement1);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    private void assertEquals(SmsHeader a, SmsHeader b) {
+        assertTrue(a.equals(b));
+    }
+
+    @Test
+    public void testConvertToByteArray() {
+        assertNotNull(mSmsHeader);
+
+        // convert to byte array and back
+        SmsHeader convertedSmsHeader = SmsHeader.fromByteArray(SmsHeader.toByteArray(mSmsHeader));
+        assertEquals(mSmsHeader, convertedSmsHeader);
+    }
+
+    /**
+     * Convert to byte array and back when ConcatRef and PortAddrs are 16 bit
+     */
+    @Test
+    public void testConvertToByteArray16bits() {
+        mSmsHeader.concatRef.isEightBits = false;
+        mSmsHeader.portAddrs.areEightBits = false;
+        assertNotNull(mSmsHeader);
+
+        // convert to byte array and back
+        SmsHeader convertedSmsHeader = SmsHeader.fromByteArray(SmsHeader.toByteArray(mSmsHeader));
+        assertEquals(mSmsHeader, convertedSmsHeader);
+    }
+
+    /**
+     * Convert to byte array and back with language table != 0
+     */
+    @Test
+    public void testConvertToByteArrayLanguageTable() {
+        mSmsHeader.languageShiftTable = 0x24;
+        mSmsHeader.languageTable = 0x25;
+        assertNotNull(mSmsHeader);
+
+        // convert to byte array and back
+        SmsHeader convertedSmsHeader = SmsHeader.fromByteArray(SmsHeader.toByteArray(mSmsHeader));
+        assertEquals(mSmsHeader, convertedSmsHeader);
+    }
+}