diff options
6 files changed, 567 insertions, 63 deletions
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java b/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java index 8ef75a600..bc724ceaf 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/ANQPFactory.java @@ -96,7 +96,7 @@ public class ANQPFactory { case ANQPNAIRealm: return new NAIRealmElement(infoID, payload); case ANQP3GPPNetwork: - return new ThreeGPPNetworkElement(infoID, payload); + return ThreeGPPNetworkElement.parse(payload); case ANQPDomName: return DomainNameElement.parse(payload); case ANQPVendorSpec: diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/CellularNetwork.java b/service/java/com/android/server/wifi/hotspot2/anqp/CellularNetwork.java index f8573e6ac..cc39b3f2b 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/CellularNetwork.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/CellularNetwork.java @@ -1,70 +1,167 @@ +/* + * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; + import java.net.ProtocolException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Iterator; +import java.util.Collections; import java.util.List; -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK; +/** + * The IEI (Information Element Identity) contained in the Generic Container for the + * 3GPP Cellular Network ANQP element. + * + * Refer to Annex A of 3GPP TS 24.234 version 11.3.0 for information on the data format: + * (http://www.etsi.org/deliver/etsi_ts/124200_124299/124234/11.03.00_60/ts_124234v110300p.pdf) + */ +public class CellularNetwork { + private static final String TAG = "CellularNetwork"; -public class CellularNetwork implements Iterable<String> { - private static final int PLMNListType = 0; + /** + * IEI type for PLMN (Public Land Mobile Network) list. + */ + @VisibleForTesting + public static final int IEI_TYPE_PLMN_LIST = 0; - private final List<String> mMccMnc; + @VisibleForTesting + public static final int IEI_CONTENT_LENGTH_MASK = 0x7F; - private CellularNetwork(int plmnCount, ByteBuffer payload) throws ProtocolException { - mMccMnc = new ArrayList<>(plmnCount); + /** + * Number of bytes for each PLMN (Public Land Mobile Network). + */ + @VisibleForTesting + public static final int PLMN_DATA_BYTES = 3; - while (plmnCount > 0) { - if (payload.remaining() < 3) { - throw new ProtocolException("Truncated PLMN info"); - } - byte[] plmn = new byte[3]; - payload.get(plmn); + /** + * The value for comparing the third digit of MNC data with to determine if the MNC is + * two or three digits. + */ + private static final int MNC_2DIGIT_VALUE = 0xF; + + /** + * List of PLMN (Public Land Mobile Network) information. + */ + private final List<String> mPlmnList; + + @VisibleForTesting + public CellularNetwork(List<String> plmnList) { + mPlmnList = plmnList; + } + + /** + * Parse a CellularNetwork from the given buffer. + * + * @param payload The byte buffer to read from + * @return {@link CellularNetwork} + * @throws ProtocolException + * @throws BufferUnderflowException + */ + public static CellularNetwork parse(ByteBuffer payload) throws ProtocolException { + int ieiType = payload.get() & 0xFF; + int ieiSize = payload.get() & IEI_CONTENT_LENGTH_MASK; - int mcc = ((plmn[0] << 8) & 0xf00) | - (plmn[0] & 0x0f0) | - (plmn[1] & 0x00f); + // Skip this IEI if it is an unsupported type. + if (ieiType != IEI_TYPE_PLMN_LIST) { + Log.e(TAG, "Ignore unsupported IEI Type: " + ieiType); + // Advance the buffer position to the next IEI. + payload.position(payload.position() + ieiSize); + return null; + } - int mnc = ((plmn[2] << 4) & 0xf0) | - ((plmn[2] >> 4) & 0x0f); + // Get PLMN count. + int plmnCount = payload.get() & 0xFF; - int n2 = (plmn[1] >> 4) & 0x0f; - String mccMnc = n2 != 0xf ? - String.format("%03x%03x", mcc, (mnc << 4) | n2) : - String.format("%03x%02x", mcc, mnc); + // Verify IEI size with PLMN count. The IEI size contained the PLMN count field plus + // the bytes for the PLMNs. + if (ieiSize != (plmnCount * PLMN_DATA_BYTES + 1)) { + throw new ProtocolException("IEI size and PLMN count mismatched: IEI Size=" + ieiSize + + " PLMN Count=" + plmnCount); + } - mMccMnc.add(mccMnc); + // Process each PLMN. + List<String> plmnList = new ArrayList<>(); + while (plmnCount > 0) { + plmnList.add(parsePlmn(payload)); plmnCount--; } + return new CellularNetwork(plmnList); } - public static CellularNetwork buildCellularNetwork(ByteBuffer payload) - throws ProtocolException { - int iei = payload.get() & BYTE_MASK; - int plmnLen = payload.get() & 0x7f; + public List<String> getPlmns() { + return Collections.unmodifiableList(mPlmnList); + } - if (iei != PLMNListType) { - payload.position(payload.position() + plmnLen); - return null; + @Override + public boolean equals(Object thatObject) { + if (this == thatObject) { + return true; } - - int plmnCount = payload.get() & BYTE_MASK; - return new CellularNetwork(plmnCount, payload); + if (!(thatObject instanceof CellularNetwork)) { + return false; + } + CellularNetwork that = (CellularNetwork) thatObject; + return mPlmnList.equals(that.mPlmnList); } @Override - public Iterator<String> iterator() { - return mMccMnc.iterator(); + public int hashCode() { + return mPlmnList.hashCode(); } @Override public String toString() { - StringBuilder sb = new StringBuilder("PLMN:"); - for (String mccMnc : mMccMnc) { - sb.append(' ').append(mccMnc); - } - return sb.toString(); + return "CellularNetwork{mPlmnList=" + mPlmnList + "}"; + } + + /** + * Parse the PLMN information from the given buffer. A string representing a hex value + * of |MCC|MNC| will be returned. + * + * PLMN Coding Format: + * b7 b0 + * | MCC Digit 2 | MCC Digit 1 | + * | MNC Digit 3 | MCC Digit 3 | + * | MNC Digit 2 | MNC Digit 1 | + * + * @param payload The buffer to read from. + * @return {@Link String} + * @throws BufferUnderflowException + */ + private static String parsePlmn(ByteBuffer payload) { + byte[] plmn = new byte[PLMN_DATA_BYTES]; + payload.get(plmn); + + // Formatted as | MCC Digit 1 | MCC Digit 2 | MCC Digit 3 | + int mcc = ((plmn[0] << 8) & 0xF00) | (plmn[0] & 0x0F0) | (plmn[1] & 0x00F); + + // Formated as |MNC Digit 1 | MNC Digit 2 | + int mnc = ((plmn[2] << 4) & 0xF0) | ((plmn[2] >> 4) & 0x0F); + + // The digit 3 of MNC decides if the MNC is 2 or 3 digits number. When it is equal to + // 0xF, MNC is a 2 digit value. Otherwise, it is a 3 digit number. + int mncDigit3 = (plmn[1] >> 4) & 0x0F; + return (mncDigit3 != MNC_2DIGIT_VALUE) + ? String.format("%03x%03x", mcc, (mnc << 4) | mncDigit3) + : String.format("%03x%02x", mcc, mnc); } } diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElement.java index 8436ae3ee..d9795c63d 100644 --- a/service/java/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElement.java +++ b/service/java/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElement.java @@ -1,53 +1,115 @@ +/* + * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; +import com.android.internal.annotations.VisibleForTesting; + import java.net.ProtocolException; +import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK; - /** - * The 3GPP Cellular Network ANQP Element, IEEE802.11-2012 section 8.4.4.11 + * The 3GPP Cellular Network ANQP Element, IEEE802.11-2012 section 8.4.4.11. + * The value is embedded in a Generic container User Data (GUD). + * Refer to Annex A of 3GPP TS 24.234 version 11.3.0 for more info: + * (http://www.etsi.org/deliver/etsi_ts/124200_124299/124234/11.03.00_60/ts_124234v110300p.pdf). + * + * Format: + * | GUD Version | Length | IEI 1 | ... | IEI N| + * 1 1 variable + * */ public class ThreeGPPNetworkElement extends ANQPElement { - private final int mUserData; - private final List<CellularNetwork> mPlmns; + /** + * The expected protocol version number of the Generic container User Data (GUD). + */ + @VisibleForTesting + public static final int GUD_VERSION_1 = 0; - public ThreeGPPNetworkElement(Constants.ANQPElementType infoID, ByteBuffer payload) + private final List<CellularNetwork> mNetworks; + + @VisibleForTesting + public ThreeGPPNetworkElement(List<CellularNetwork> networks) { + super(Constants.ANQPElementType.ANQP3GPPNetwork); + mNetworks = networks; + } + + /** + * Parse a ThreeGPPNetworkElement from the given buffer. + * + * @param payload The byte buffer to read from + * @return {@link ThreeGPPNetworkElement} + * @throws BufferUnderflowException + * @throws ProtocolException + */ + public static ThreeGPPNetworkElement parse(ByteBuffer payload) throws ProtocolException { - super(infoID); + // Verify version. + int gudVersion = payload.get() & 0xFF; + if (gudVersion != GUD_VERSION_1) { + throw new ProtocolException("Unsupported GUD version: " + gudVersion); + } - mPlmns = new ArrayList<CellularNetwork>(); - mUserData = payload.get() & BYTE_MASK; - int length = payload.get() & BYTE_MASK; - if (length > payload.remaining()) { - throw new ProtocolException("Runt payload"); + // Verify length. + int length = payload.get() & 0xFF; + if (length != payload.remaining()) { + throw new ProtocolException("Mismatch length and buffer size: length=" + length + + " bufferSize=" + payload.remaining()); } + // Parse each IEI (Information Element Identity) content. + List<CellularNetwork> networks = new ArrayList<>(); while (payload.hasRemaining()) { - CellularNetwork network = CellularNetwork.buildCellularNetwork(payload); + CellularNetwork network = CellularNetwork.parse(payload); if (network != null) { - mPlmns.add(network); + networks.add(network); } } + return new ThreeGPPNetworkElement(networks); } - public int getUserData() { - return mUserData; + public List<CellularNetwork> getNetworks() { + return Collections.unmodifiableList(mNetworks); } - public List<CellularNetwork> getPlmns() { - return Collections.unmodifiableList(mPlmns); + @Override + public boolean equals(Object thatObject) { + if (this == thatObject) { + return true; + } + if (!(thatObject instanceof ThreeGPPNetworkElement)) { + return false; + } + ThreeGPPNetworkElement that = (ThreeGPPNetworkElement) thatObject; + return mNetworks.equals(that.mNetworks); + + } + + @Override + public int hashCode() { + return mNetworks.hashCode(); } @Override public String toString() { - return "ThreeGPPNetwork{" + - "mUserData=" + mUserData + - ", mPlmns=" + mPlmns + - '}'; + return "ThreeGPPNetwork{mNetworks=" + mNetworks + "}"; } } diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTest.java new file mode 100644 index 000000000..50ab18935 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import android.test.suitebuilder.annotation.SmallTest; + +import org.junit.Test; + +import java.net.ProtocolException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.CellularNetwork}. + */ +@SmallTest +public class CellularNetworkTest { + private static final byte[] TEST_PLMN_BYTES_1 = new byte[] {0x12, 0x34, 0x56}; + private static final String TEST_PLMN_STRING_1 = "214653"; + private static final byte[] TEST_PLMN_BYTES_2 = new byte[] {0x13, (byte) 0xF9, 0x32}; + private static final String TEST_PLMN_STRING_2 = "31923"; + + /** + * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. + * + * @throws Exception + */ + @Test(expected = BufferUnderflowException.class) + public void parseBufferWithEmptyBuffer() throws Exception { + CellularNetwork.parse(ByteBuffer.allocate(0)); + } + + /** + * Verify that a null will be returned when parsing a buffer contained an unsupported IEI type. + * + * @throws Exception + */ + @Test + public void parseBufferWithInvalidIEIType() throws Exception { + byte[][] plmnsData = new byte[][] {TEST_PLMN_BYTES_1, TEST_PLMN_BYTES_2}; + byte[] testData = CellularNetworkTestUtil.formatPLMNListIEI(1, plmnsData); + assertNull(CellularNetwork.parse(ByteBuffer.wrap(testData))); + } + + /** + * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer + * (missing a byte at the end). + * + * @throws Exception + */ + @Test(expected = BufferUnderflowException.class) + public void parseBufferWithIncompleteData() throws Exception { + byte[][] plmnsData = new byte[][] {TEST_PLMN_BYTES_1, TEST_PLMN_BYTES_2}; + byte[] testData = CellularNetworkTestUtil.formatPLMNListIEI(plmnsData); + CellularNetwork.parse(ByteBuffer.wrap(testData, 0, testData.length - 1)); + } + + /** + * Verify that ProtocolException will be thrown when IEI size and the PLMN count doesn't + * match. + * + * @throws Exception + */ + @Test(expected = ProtocolException.class) + public void parseBufferWithMismatchIEISizeAndPLMNCount() throws Exception { + byte[][] plmnsData = new byte[][] {TEST_PLMN_BYTES_1, TEST_PLMN_BYTES_2}; + // Get test data with IEI size set to incorrect value. + byte[] testData = CellularNetworkTestUtil.formatPLMNListIEI( + CellularNetwork.IEI_TYPE_PLMN_LIST, plmnsData, true); + CellularNetwork.parse(ByteBuffer.wrap(testData)); + } + + /** + * Verify that the expected ProtocolPortTuple is returned when parsing a buffer contained + * the test data. + * + * @throws Exception + */ + @Test + public void parseBufferWithTestData() throws Exception { + byte[][] plmnsData = new byte[][] {TEST_PLMN_BYTES_1, TEST_PLMN_BYTES_2}; + byte[] testData = CellularNetworkTestUtil.formatPLMNListIEI(plmnsData); + + // Setup the expected CellularNetwork. + List<String> plmnList = new ArrayList<>(); + plmnList.add(TEST_PLMN_STRING_1); + plmnList.add(TEST_PLMN_STRING_2); + CellularNetwork expected = new CellularNetwork(plmnList); + + assertEquals(expected, CellularNetwork.parse(ByteBuffer.wrap(testData))); + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTestUtil.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTestUtil.java new file mode 100644 index 000000000..dad2919f0 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/CellularNetworkTestUtil.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +/** + * Utility class for formatting IEI (Information Element Identity) data for testing. + */ +public class CellularNetworkTestUtil { + /** + * Format and return PLMN List IEI with the given PLMN list data. + * + * @param plmnList The array of PLMN data + * @return byte[] + * @throws IOException + */ + public static byte[] formatPLMNListIEI(byte[][] plmnList) throws IOException { + return formatPLMNListIEI(CellularNetwork.IEI_TYPE_PLMN_LIST, plmnList); + } + + /** + * Format and return PLMN List IEI with the given IEI type and PLMN list data. This + * allows the test to use an invalid IEI type for testing purpose. + * + * @param ieiType The IEI type + * @param plmnList The array of PLMN data + * @return byte[] + * @throws IOException + */ + public static byte[] formatPLMNListIEI(int ieiType, byte[][] plmnList) throws IOException { + return formatPLMNListIEI(ieiType, plmnList, false); + } + + /** + * Format and return PLMN List IEI with the given IEI type and PLMN list data. This also + * allows the test to intentionally setting an incorrect size value. + * + * @param ieiType The IEI type + * @param plmnList The array of PLMN data + * @param setWrongSize Flag for setting incorrect IEI size + * @return byte[] + * @throws IOException + */ + public static byte[] formatPLMNListIEI(int ieiType, byte[][] plmnList, boolean setWrongSize) + throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + + // Calculate the total bytes for all the PLMNs. + int plmnsSize = getDataSize(plmnList); + + // Use incorrect size intentionally. + if (setWrongSize) plmnsSize -= 1; + + stream.write((byte) ieiType); + // One extra byte for the PLMN count field. + stream.write((byte) ((plmnsSize + 1) & CellularNetwork.IEI_CONTENT_LENGTH_MASK)); + stream.write((byte) plmnList.length); + for (byte[] plmn : plmnList) { + stream.write(plmn); + } + + return stream.toByteArray(); + } + + /** + * Return the number of bytes in a 2D array. + * + * @param dataArray The 2D array + * @return The number of bytes in the 2D array + */ + public static int getDataSize(byte[][] dataArray) { + int size = 0; + for (byte[] data : dataArray) { + size += data.length; + } + return size; + } +} diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElementTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElementTest.java new file mode 100644 index 000000000..02d45ef46 --- /dev/null +++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/anqp/ThreeGPPNetworkElementTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2016 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.server.wifi.hotspot2.anqp; + +import static org.junit.Assert.assertEquals; + +import android.test.suitebuilder.annotation.SmallTest; + +import org.junit.Test; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.ProtocolException; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +/** + * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.ThreeGPPNetworkElement}. + */ +@SmallTest +public class ThreeGPPNetworkElementTest { + private static final byte[][] TEST_NETWORK1_PLMN_BYTES = + new byte[][] { new byte[] {0x21, 0x63, 0x54}, + new byte[] {0x43, (byte) 0x85, 0x76} }; + private static final List<String> TEST_NETWORK1_PLMN_LIST = new ArrayList<>(); + static { + TEST_NETWORK1_PLMN_LIST.add("123456"); + TEST_NETWORK1_PLMN_LIST.add("345678"); + } + private static final CellularNetwork TEST_NETWORK1 = + new CellularNetwork(TEST_NETWORK1_PLMN_LIST); + + private static final byte[][] TEST_NETWORK2_PLMN_BYTES = + new byte[][] { new byte[] {(byte) 0x87, 0x29, 0x10}, + new byte[] {0x62, (byte) 0xF5, 0x73} }; + private static final List<String> TEST_NETWORK2_PLMN_LIST = new ArrayList<>(); + static { + TEST_NETWORK2_PLMN_LIST.add("789012"); + TEST_NETWORK2_PLMN_LIST.add("26537"); + } + private static final CellularNetwork TEST_NETWORK2 = + new CellularNetwork(TEST_NETWORK2_PLMN_LIST); + + /** + * Helper function for generating test data. + * + * @param version The GUD version number + * @param ieiList The array containing IEI data + * @return byte[] + * @throws IOException + */ + private static byte[] getTestData(int version, byte[][] ieiList) + throws IOException { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + int totalIeiSize = CellularNetworkTestUtil.getDataSize(ieiList); + stream.write((byte) version); + stream.write((byte) totalIeiSize); + for (byte[] iei : ieiList) { + stream.write(iei); + } + return stream.toByteArray(); + } + + /** + * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. + * + * @throws Exception + */ + @Test(expected = BufferUnderflowException.class) + public void parseBufferWithEmptyBuffer() throws Exception { + ThreeGPPNetworkElement.parse(ByteBuffer.allocate(0)); + } + + /** + * Verify that ProtocolException will be thrown when parsing an buffer contained + * an unsupported version number. + * + * @throws Exception + */ + @Test(expected = ProtocolException.class) + public void parseBufferWithUnsupportedVersionNumber() throws Exception { + byte[][] testIeiList = new byte[][] { + CellularNetworkTestUtil.formatPLMNListIEI(TEST_NETWORK1_PLMN_BYTES) }; + byte[] testData = getTestData(1, testIeiList); + ThreeGPPNetworkElement.parse(ByteBuffer.wrap(testData)); + } + + /** + * Verify that Protocol will be thrown when parsing a truncated buffer (missing a + * byte at the end), which will cause a inconsistency between the length value and + * the buffer size. + * + * @throws Exception + */ + @Test(expected = ProtocolException.class) + public void parseBufferWithIncompleteData() throws Exception { + byte[][] testIeiList = new byte[][] { + CellularNetworkTestUtil.formatPLMNListIEI(TEST_NETWORK1_PLMN_BYTES) }; + byte[] testData = getTestData(ThreeGPPNetworkElement.GUD_VERSION_1, testIeiList); + ThreeGPPNetworkElement.parse(ByteBuffer.wrap(testData, 0, testData.length - 1)); + } + + /** + * Verify that the expected ThreeGPPNetworkElement is returned when parsing a buffer contained + * the test data. + * + * @throws Exception + */ + @Test + public void parseBufferWithTestData() throws Exception { + byte[][] testIeiList = new byte[][] { + CellularNetworkTestUtil.formatPLMNListIEI(TEST_NETWORK1_PLMN_BYTES), + CellularNetworkTestUtil.formatPLMNListIEI(TEST_NETWORK2_PLMN_BYTES) }; + byte[] testData = getTestData(ThreeGPPNetworkElement.GUD_VERSION_1, testIeiList); + + // Setup the expected ThreeGPPNetworkElement. + List<CellularNetwork> networkList = new ArrayList<>(); + networkList.add(TEST_NETWORK1); + networkList.add(TEST_NETWORK2); + ThreeGPPNetworkElement expected = new ThreeGPPNetworkElement(networkList); + + assertEquals(expected, ThreeGPPNetworkElement.parse(ByteBuffer.wrap(testData))); + } +} |