summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Qiu <zqiu@google.com>2016-12-02 10:47:24 -0800
committerPeter Qiu <zqiu@google.com>2016-12-15 15:37:19 -0800
commitfa04a81daf829e6e5c099c9a249b8dd8dd112102 (patch)
tree3873a014d906c85d2ca98251e1d250580924d471
parent3d42402e0d282dc75f9c65f29d0f9e0eea753100 (diff)
downloadandroid_frameworks_opt_net_wifi-fa04a81daf829e6e5c099c9a249b8dd8dd112102.tar.gz
android_frameworks_opt_net_wifi-fa04a81daf829e6e5c099c9a249b8dd8dd112102.tar.bz2
android_frameworks_opt_net_wifi-fa04a81daf829e6e5c099c9a249b8dd8dd112102.zip
Cleanup support for parsing various length integer and string from ByteBuffer
Move and cleanup the parsing functions from com.android.server.wifi.hotspot2.anqp.Constants to the newly created ByteBufferReader, since these are generic parsing functions (not specific to ANQP). An unchecked runtime exception will be thrown when an error is encountered. The possible exceptions are documented for each API. It is the caller's responsibility to handle those exceptions appropriately (e.g. propagate the exceptions upwards with appropriate documentation or catch the exception). The handling of unchecked runtime exceptions for ANQP elements parsing will be added in the follow-on CL as part of the ANQP cleanup. b/33296974 is filed for tracking handling of unchecked runtime exceptions for parsing information elements. Bug: 33000864 Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: I6964520e7cc86071b2096408d6cb0503e0f618ff
-rw-r--r--service/java/com/android/server/wifi/ByteBufferReader.java98
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/Constants.java62
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java5
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/I18Name.java9
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/IconInfo.java10
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java6
-rw-r--r--service/java/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElement.java5
-rw-r--r--service/java/com/android/server/wifi/util/InformationElementUtil.java15
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ByteBufferReaderTest.java170
9 files changed, 296 insertions, 84 deletions
diff --git a/service/java/com/android/server/wifi/ByteBufferReader.java b/service/java/com/android/server/wifi/ByteBufferReader.java
new file mode 100644
index 000000000..91598af5f
--- /dev/null
+++ b/service/java/com/android/server/wifi/ByteBufferReader.java
@@ -0,0 +1,98 @@
+/*
+ * 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.Wifi
+ */
+
+package com.android.server.wifi;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.Charset;
+
+/**
+ * Utility class for reading generic data (e.g. various length integer, string) from ByteBuffer.
+ */
+public class ByteBufferReader {
+ @VisibleForTesting
+ public static final int MINIMUM_INTEGER_SIZE = Byte.BYTES;
+
+ @VisibleForTesting
+ public static final int MAXIMUM_INTEGER_SIZE = Long.BYTES;
+
+ /**
+ * Read an integer value from a buffer.
+ *
+ * @param payload The buffer to read from
+ * @param byteOrder Byte order of the buffer
+ * @param size The number of bytes to read from the buffer
+ * @return The integer value
+ * @throws BufferUnderflowException
+ * @throws IllegalArgumentException
+ */
+ public static long readInteger(ByteBuffer payload, ByteOrder byteOrder, int size) {
+ if (size < MINIMUM_INTEGER_SIZE || size > MAXIMUM_INTEGER_SIZE) {
+ throw new IllegalArgumentException("Invalid size " + size);
+ }
+
+ // Read the necessary bytes.
+ byte[] octets = new byte[size];
+ payload.get(octets);
+
+ // Format the value based on byte order.
+ long value = 0;
+ if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
+ for (int n = octets.length - 1; n >= 0; n--) {
+ value = (value << Byte.SIZE) | (octets[n] & 0xFF);
+ }
+ } else {
+ for (byte octet : octets) {
+ value = (value << Byte.SIZE) | (octet & 0xFF);
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Read a string from a buffer. An empty String will be returned for a String with 0 length.
+ *
+ * @param payload The buffer to read from
+ * @param length Number of bytes to read from the buffer
+ * @param charset The character set of the string
+ * @return {@link String}
+ * @throws BufferUnderflowException
+ * @throws NegativeArraySizeException
+ */
+ public static String readString(ByteBuffer payload, int length, Charset charset) {
+ byte[] octets = new byte[length];
+ payload.get(octets);
+ return new String(octets, charset);
+ }
+
+ /**
+ * Read a string from a buffer where the string value is preceded by the length of the string
+ * (1 byte) in the buffer.
+ *
+ * @param payload The buffer to read from
+ * @param charset The character set of the string
+ * @return {@link String}
+ * @throws BufferUnderflowException
+ */
+ public static String readStringWithByteLength(ByteBuffer payload, Charset charset) {
+ int length = payload.get() & 0xFF;
+ return readString(payload, length, charset);
+ }
+}
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/Constants.java b/service/java/com/android/server/wifi/hotspot2/anqp/Constants.java
index 08b5563b9..7cf34c75d 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/Constants.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/Constants.java
@@ -131,66 +131,4 @@ public class Constants {
public static boolean hasR2Elements(List<ANQPElementType> elements) {
return elements.contains(ANQPElementType.HSOSUProviders);
}
-
- public static long getInteger(ByteBuffer payload, ByteOrder bo, int size) {
- byte[] octets = new byte[size];
- payload.get(octets);
- long value = 0;
- if (bo == ByteOrder.LITTLE_ENDIAN) {
- for (int n = octets.length - 1; n >= 0; n--) {
- value = (value << Byte.SIZE) | (octets[n] & BYTE_MASK);
- }
- }
- else {
- for (byte octet : octets) {
- value = (value << Byte.SIZE) | (octet & BYTE_MASK);
- }
- }
- return value;
- }
-
- public static String getPrefixedString(ByteBuffer payload, int lengthLength, Charset charset)
- throws ProtocolException {
- return getPrefixedString(payload, lengthLength, charset, false);
- }
-
- public static String getPrefixedString(ByteBuffer payload, int lengthLength, Charset charset,
- boolean useNull) throws ProtocolException {
- if (payload.remaining() < lengthLength) {
- throw new ProtocolException("Runt string: " + payload.remaining());
- }
- return getString(payload, (int) getInteger(payload, ByteOrder.LITTLE_ENDIAN,
- lengthLength), charset, useNull);
- }
-
- public static String getTrimmedString(ByteBuffer payload, int length, Charset charset)
- throws ProtocolException {
- String s = getString(payload, length, charset, false);
- int zero = length - 1;
- while (zero >= 0) {
- if (s.charAt(zero) != 0) {
- break;
- }
- zero--;
- }
- return zero < length - 1 ? s.substring(0, zero + 1) : s;
- }
-
- public static String getString(ByteBuffer payload, int length, Charset charset)
- throws ProtocolException {
- return getString(payload, length, charset, false);
- }
-
- public static String getString(ByteBuffer payload, int length, Charset charset, boolean useNull)
- throws ProtocolException {
- if (length > payload.remaining()) {
- throw new ProtocolException("Bad string length: " + length);
- }
- if (useNull && length == 0) {
- return null;
- }
- byte[] octets = new byte[length];
- payload.get(octets);
- return new String(octets, charset);
- }
}
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java
index cb0872e73..0b5352eb8 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/DomainNameElement.java
@@ -1,5 +1,7 @@
package com.android.server.wifi.hotspot2.anqp;
+import com.android.server.wifi.ByteBufferReader;
+
import java.net.ProtocolException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@@ -20,7 +22,8 @@ public class DomainNameElement extends ANQPElement {
while (payload.hasRemaining()) {
// Use latin-1 to decode for now - safe for ASCII and retains encoding
- mDomains.add(Constants.getPrefixedString(payload, 1, StandardCharsets.ISO_8859_1));
+ mDomains.add(ByteBufferReader.readStringWithByteLength(
+ payload, StandardCharsets.ISO_8859_1));
}
}
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/I18Name.java b/service/java/com/android/server/wifi/hotspot2/anqp/I18Name.java
index f97610fbc..81ebdfa2a 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/I18Name.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/I18Name.java
@@ -19,6 +19,7 @@ package com.android.server.wifi.hotspot2.anqp;
import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.wifi.ByteBufferReader;
import java.net.ProtocolException;
import java.nio.ByteBuffer;
@@ -48,11 +49,11 @@ public class I18Name {
if (length < Constants.LANG_CODE_LENGTH || length > payload.remaining()) {
throw new ProtocolException("Invalid I18Name length field value " + length);
}
- mLanguage = Constants.getTrimmedString(payload,
- Constants.LANG_CODE_LENGTH, StandardCharsets.US_ASCII);
+ mLanguage = ByteBufferReader.readString(
+ payload, Constants.LANG_CODE_LENGTH, StandardCharsets.US_ASCII).trim();
mLocale = Locale.forLanguageTag(mLanguage);
- mText = Constants.getString(payload, length
- - Constants.LANG_CODE_LENGTH, StandardCharsets.UTF_8);
+ mText = ByteBufferReader.readString(payload, length - Constants.LANG_CODE_LENGTH,
+ StandardCharsets.UTF_8);
}
@VisibleForTesting
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/IconInfo.java b/service/java/com/android/server/wifi/hotspot2/anqp/IconInfo.java
index c89c4429c..c961bbe79 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/IconInfo.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/IconInfo.java
@@ -7,6 +7,8 @@ import java.util.Locale;
import static com.android.server.wifi.hotspot2.anqp.Constants.SHORT_MASK;
+import com.android.server.wifi.ByteBufferReader;
+
/**
* The Icons available OSU Providers sub field, as specified in
* Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00,
@@ -26,10 +28,10 @@ public class IconInfo {
mWidth = payload.getShort() & SHORT_MASK;
mHeight = payload.getShort() & SHORT_MASK;
- mLanguage = Constants.getTrimmedString(payload,
- Constants.LANG_CODE_LENGTH, StandardCharsets.US_ASCII);
- mIconType = Constants.getPrefixedString(payload, 1, StandardCharsets.US_ASCII);
- mFileName = Constants.getPrefixedString(payload, 1, StandardCharsets.UTF_8);
+ mLanguage = ByteBufferReader.readString(
+ payload, Constants.LANG_CODE_LENGTH, StandardCharsets.US_ASCII).trim();
+ mIconType = ByteBufferReader.readStringWithByteLength(payload, StandardCharsets.US_ASCII);
+ mFileName = ByteBufferReader.readStringWithByteLength(payload, StandardCharsets.UTF_8);
}
public int getWidth() {
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java
index 95fbc893c..6acdbc535 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/NAIRealmData.java
@@ -1,6 +1,7 @@
package com.android.server.wifi.hotspot2.anqp;
import com.android.server.wifi.hotspot2.anqp.eap.EAPMethod;
+import com.android.server.wifi.ByteBufferReader;
import com.android.server.wifi.hotspot2.AuthMatch;
import com.android.server.wifi.hotspot2.DomainMatcher;
import com.android.server.wifi.hotspot2.Utils;
@@ -30,9 +31,8 @@ public class NAIRealmData {
}
boolean utf8 = (payload.get() & 1) == Constants.UTF8_INDICATOR;
- String realm = Constants.getPrefixedString(payload, 1, utf8 ?
- StandardCharsets.UTF_8 :
- StandardCharsets.US_ASCII);
+ String realm = ByteBufferReader.readStringWithByteLength(
+ payload, utf8 ? StandardCharsets.UTF_8 : StandardCharsets.US_ASCII);
String[] realms = realm.split(";");
mRealms = new ArrayList<>();
for (String realmElement : realms) {
diff --git a/service/java/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElement.java b/service/java/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElement.java
index 7230c910d..430126070 100644
--- a/service/java/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElement.java
+++ b/service/java/com/android/server/wifi/hotspot2/anqp/RoamingConsortiumElement.java
@@ -10,7 +10,8 @@ import java.util.Collections;
import java.util.List;
import static com.android.server.wifi.hotspot2.anqp.Constants.BYTE_MASK;
-import static com.android.server.wifi.hotspot2.anqp.Constants.getInteger;
+
+import com.android.server.wifi.ByteBufferReader;
/**
* The Roaming Consortium ANQP Element, IEEE802.11-2012 section 8.4.4.7
@@ -30,7 +31,7 @@ public class RoamingConsortiumElement extends ANQPElement {
if (length > payload.remaining()) {
throw new ProtocolException("Bad OI length: " + length);
}
- mOis.add(getInteger(payload, ByteOrder.BIG_ENDIAN, length));
+ mOis.add(ByteBufferReader.readInteger(payload, ByteOrder.BIG_ENDIAN, length));
}
}
diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java
index 5bb116e3b..268ddce23 100644
--- a/service/java/com/android/server/wifi/util/InformationElementUtil.java
+++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java
@@ -15,14 +15,13 @@
*/
package com.android.server.wifi.util;
-import static com.android.server.wifi.hotspot2.anqp.Constants.getInteger;
-
import android.net.wifi.ScanResult;
import android.net.wifi.ScanResult.InformationElement;
import android.util.Log;
-import com.android.server.wifi.hotspot2.anqp.Constants;
+import com.android.server.wifi.ByteBufferReader;
import com.android.server.wifi.hotspot2.NetworkDetail;
+import com.android.server.wifi.hotspot2.anqp.Constants;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
@@ -183,7 +182,7 @@ public class InformationElementUtil {
}
if (ie.bytes.length == 7 || ie.bytes.length == 9) {
- hessid = getInteger(data, ByteOrder.BIG_ENDIAN, 6);
+ hessid = ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, 6);
}
}
}
@@ -217,15 +216,15 @@ public class InformationElementUtil {
roamingConsortiums = new long[oiCount];
if (oi1Length > 0 && roamingConsortiums.length > 0) {
roamingConsortiums[0] =
- getInteger(data, ByteOrder.BIG_ENDIAN, oi1Length);
+ ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, oi1Length);
}
if (oi2Length > 0 && roamingConsortiums.length > 1) {
roamingConsortiums[1] =
- getInteger(data, ByteOrder.BIG_ENDIAN, oi2Length);
+ ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, oi2Length);
}
if (oi3Length > 0 && roamingConsortiums.length > 2) {
roamingConsortiums[2] =
- getInteger(data, ByteOrder.BIG_ENDIAN, oi3Length);
+ ByteBufferReader.readInteger(data, ByteOrder.BIG_ENDIAN, oi3Length);
}
}
}
@@ -284,7 +283,7 @@ public class InformationElementUtil {
public void from(InformationElement ie) {
ByteBuffer data = ByteBuffer.wrap(ie.bytes).order(ByteOrder.LITTLE_ENDIAN);
extendedCapabilities =
- Constants.getInteger(data, ByteOrder.LITTLE_ENDIAN, ie.bytes.length);
+ ByteBufferReader.readInteger(data, ByteOrder.LITTLE_ENDIAN, ie.bytes.length);
int index = RTT_RESP_ENABLE_BIT / 8;
byte offset = RTT_RESP_ENABLE_BIT % 8;
diff --git a/tests/wifitests/src/com/android/server/wifi/ByteBufferReaderTest.java b/tests/wifitests/src/com/android/server/wifi/ByteBufferReaderTest.java
new file mode 100644
index 000000000..16cd648c2
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/ByteBufferReaderTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.junit.Test;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.ByteBufferReader}.
+ */
+@SmallTest
+public class ByteBufferReaderTest {
+ /**
+ * Verify that BufferUnderflowException will be thrown when reading an integer from a buffer
+ * that contained less data than needed.
+ *
+ * @throws Exception
+ */
+ @Test(expected = BufferUnderflowException.class)
+ public void readIntegerWithBufferUnderflow() throws Exception {
+ byte[] data = new byte[1];
+ ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ ByteBufferReader.readInteger(buffer, buffer.order(), 2);
+ }
+
+ /**
+ * Verify that IllegalArgumentException will be thrown when reading an integer that exceeds
+ * the maximum integer size.
+ *
+ * @throws Exception
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void readIntegerExceedingMaximumLength() throws Exception {
+ int length = ByteBufferReader.MAXIMUM_INTEGER_SIZE + 1;
+ byte[] data = new byte[length];
+ ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ ByteBufferReader.readInteger(buffer, buffer.order(), length);
+ }
+
+ /**
+ * Verify that IllegalArgumentException will be thrown when reading an integer with size
+ * less than the minimum.
+ *
+ * @throws Exception
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void readIntegerLessThanMinimumLength() throws Exception {
+ int length = ByteBufferReader.MINIMUM_INTEGER_SIZE - 1;
+ byte[] data = new byte[length];
+ ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ ByteBufferReader.readInteger(buffer, buffer.order(), length);
+ }
+
+ /**
+ * Verify that the expected integer value is returned when reading an integer with minimum
+ * integer size.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void readIntegerWithMinimumSize() throws Exception {
+ byte[] data = new byte[] {0x1};
+ ByteBuffer buffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ assertEquals(1, ByteBufferReader.readInteger(buffer, buffer.order(),
+ ByteBufferReader.MINIMUM_INTEGER_SIZE));
+ }
+
+ /**
+ * Verify that the expected integer value is returned when reading an integer with maximum
+ * integer size.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void readIntegerWithMaximumSize() throws Exception {
+ byte[] data = new byte[] {0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11};
+
+ // Little Endian parsing.
+ ByteBuffer leBuffer = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
+ long leValue = 0x110000000000001fL;
+ assertEquals(leValue, ByteBufferReader.readInteger(leBuffer, leBuffer.order(),
+ ByteBufferReader.MAXIMUM_INTEGER_SIZE));
+
+ // Big Endian parsing.
+ ByteBuffer beBuffer = ByteBuffer.wrap(data).order(ByteOrder.BIG_ENDIAN);
+ long beValue = 0x1f00000000000011L;
+ assertEquals(beValue, ByteBufferReader.readInteger(beBuffer, beBuffer.order(),
+ ByteBufferReader.MAXIMUM_INTEGER_SIZE));
+ }
+
+ /**
+ * Verify that NegativeArraySizeException will be thrown when attempting to read a string with
+ * negative size.
+ *
+ * @throws Exception
+ */
+ @Test(expected = NegativeArraySizeException.class)
+ public void readStringWithNegativeSize() throws Exception {
+ ByteBufferReader.readString(ByteBuffer.wrap(new byte[10]), -1, StandardCharsets.US_ASCII);
+ }
+
+ /**
+ * Verify that an empty String will be returned when reading a string with zero size.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void readStringWithZeroSize() throws Exception {
+ String str = ByteBufferReader.readString(
+ ByteBuffer.wrap(new byte[10]), 0, StandardCharsets.US_ASCII);
+ assertTrue(str.isEmpty());
+ }
+
+ /**
+ * Verify that the expected string value is returned when reading a string from a buffer that
+ * contained a valid string.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void readString() throws Exception {
+ String expectedValue = "Hello World";
+ ByteBuffer buffer = ByteBuffer.wrap(expectedValue.getBytes(StandardCharsets.US_ASCII));
+ String actualValue = ByteBufferReader.readString(
+ buffer, buffer.remaining(), StandardCharsets.US_ASCII);
+ assertEquals(expectedValue, actualValue);
+ }
+
+ /**
+ * Verify that the expected string value is returned when reading a buffer that contained the
+ * size of the string and the string value.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void readStringWithByteLength() throws Exception {
+ String expectedValue = "Hello World";
+ ByteBuffer buffer = ByteBuffer.allocate(expectedValue.length() + 1);
+ buffer.put((byte) expectedValue.length());
+ buffer.put(expectedValue.getBytes(StandardCharsets.US_ASCII));
+ // Rewind the buffer's position to the beginning for reading.
+ buffer.position(0);
+ String actualValue =
+ ByteBufferReader.readStringWithByteLength(buffer, StandardCharsets.US_ASCII);
+ assertEquals(expectedValue, actualValue);
+ }
+}