blob: a1b37ff7b6cf22c3fb113722cf36acb89c2e6ae9 [file] [log] [blame]
/*
* 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.util;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.net.wifi.ScanResult.InformationElement;
import android.support.test.filters.SmallTest;
import com.android.server.wifi.hotspot2.NetworkDetail;
import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.BitSet;
/**
* Unit tests for {@link com.android.server.wifi.util.InformationElementUtil}.
*/
@SmallTest
public class InformationElementUtilTest {
// SSID Information Element tags
private static final byte[] TEST_SSID_BYTES_TAG = new byte[] { (byte) 0x00, (byte) 0x0B };
// SSID Information Element entry used for testing.
private static final byte[] TEST_SSID_BYTES = "GoogleGuest".getBytes();
// Valid zero length tag.
private static final byte[] TEST_VALID_ZERO_LENGTH_TAG =
new byte[] { (byte) 0x0B, (byte) 0x00 };
// BSS_LOAD Information Element entry used for testing.
private static final byte[] TEST_BSS_LOAD_BYTES_IE =
new byte[] { (byte) 0x0B, (byte) 0x01, (byte) 0x08 };
/*
* Function to provide SSID Information Element (SSID = "GoogleGuest").
*
* @return byte[] Byte array representing the test SSID
*/
private byte[] getTestSsidIEBytes() throws IOException {
return concatenateByteArrays(TEST_SSID_BYTES_TAG, TEST_SSID_BYTES);
}
/*
* Function used to set byte arrays used for testing.
*
* @param byteArrays variable number of byte arrays to concatenate
* @return byte[] Byte array resulting from concatenating the arrays passed to the function
*/
private static byte[] concatenateByteArrays(byte[]... byteArrays) throws IOException {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (byte[] b : byteArrays) {
baos.write(b);
}
baos.flush();
return baos.toByteArray();
}
/**
* Test parseInformationElements with an empty byte array.
* Expect parseInformationElement to return an empty InformationElement array.
*/
@Test
public void parseInformationElements_withEmptyByteArray() {
byte[] emptyBytes = new byte[0];
InformationElement[] results =
InformationElementUtil.parseInformationElements(emptyBytes);
assertEquals("parsed results should be empty", 0, results.length);
}
/**
* Test parseInformationElements called with a null parameter.
* Expect parseInfomrationElement to return an empty InformationElement array.
*/
@Test
public void parseInformationElements_withNullBytes() {
byte[] nullBytes = null;
InformationElement[] results =
InformationElementUtil.parseInformationElements(nullBytes);
assertEquals("parsed results should be empty", 0, results.length);
}
/*
* Test parseInformationElements with a single element represented in the byte array.
* Expect a single element to be returned in the InformationElements array. The
* length of this array should be 1 and the contents should be valid.
*
* @throws java.io.IOException
*/
@Test
public void parseInformationElements_withSingleElement() throws IOException {
byte[] ssidBytes = getTestSsidIEBytes();
InformationElement[] results =
InformationElementUtil.parseInformationElements(ssidBytes);
assertEquals("Parsed results should have 1 IE", 1, results.length);
assertEquals("Parsed result should be a ssid", InformationElement.EID_SSID, results[0].id);
assertArrayEquals("parsed SSID does not match input",
TEST_SSID_BYTES, results[0].bytes);
}
/*
* Test parseInformationElement with extra padding in the data to parse.
* Expect the function to return the SSID information element.
*
* Note: Experience shows that APs often pad messages with 0x00. This happens to be the tag for
* EID_SSID. This test checks if padding will be properly discarded.
*
* @throws java.io.IOException
*/
@Test
public void parseInformationElements_withExtraPadding() throws IOException {
byte[] paddingBytes = new byte[10];
Arrays.fill(paddingBytes, (byte) 0x00);
byte[] ssidBytesWithPadding = concatenateByteArrays(getTestSsidIEBytes(), paddingBytes);
InformationElement[] results =
InformationElementUtil.parseInformationElements(ssidBytesWithPadding);
assertEquals("Parsed results should have 1 IE", 1, results.length);
assertEquals("Parsed result should be a ssid", InformationElement.EID_SSID, results[0].id);
assertArrayEquals("parsed SSID does not match input",
TEST_SSID_BYTES, results[0].bytes);
}
/*
* Test parseInformationElement with two elements where the second element has an invalid
* length.
* Expect the function to return the first valid entry and skip the remaining information.
*
* Note: This test partially exposes issues with blindly parsing the data. A higher level
* function to validate the parsed data may be added.
*
* @throws java.io.IOException
* */
@Test
public void parseInformationElements_secondElementInvalidLength() throws IOException {
byte[] invalidTag = new byte[] { (byte) 0x01, (byte) 0x08, (byte) 0x08 };
byte[] twoTagsSecondInvalidBytes = concatenateByteArrays(getTestSsidIEBytes(), invalidTag);
InformationElement[] results =
InformationElementUtil.parseInformationElements(twoTagsSecondInvalidBytes);
assertEquals("Parsed results should have 1 IE", 1, results.length);
assertEquals("Parsed result should be a ssid.", InformationElement.EID_SSID, results[0].id);
assertArrayEquals("parsed SSID does not match input",
TEST_SSID_BYTES, results[0].bytes);
}
/*
* Test parseInformationElements with two valid Information Element entries.
* Expect the function to return an InformationElement array with two entries containing valid
* data.
*
* @throws java.io.IOException
*/
@Test
public void parseInformationElements_twoElements() throws IOException {
byte[] twoValidTagsBytes =
concatenateByteArrays(getTestSsidIEBytes(), TEST_BSS_LOAD_BYTES_IE);
InformationElement[] results =
InformationElementUtil.parseInformationElements(twoValidTagsBytes);
assertEquals("parsed results should have 2 elements", 2, results.length);
assertEquals("First parsed element should be a ssid",
InformationElement.EID_SSID, results[0].id);
assertArrayEquals("parsed SSID does not match input",
TEST_SSID_BYTES, results[0].bytes);
assertEquals("second element should be a BSS_LOAD tag",
InformationElement.EID_BSS_LOAD, results[1].id);
assertEquals("second element should have data of length 1", 1, results[1].bytes.length);
assertEquals("second element data was not parsed correctly.",
(byte) 0x08, results[1].bytes[0]);
}
/*
* Test parseInformationElements with two elements where the first information element has a
* length of zero.
* Expect the function to return an InformationElement array with two entries containing valid
* data.
*
* @throws java.io.IOException
*/
@Test
public void parseInformationElements_firstElementZeroLength() throws IOException {
byte[] zeroLengthTagWithSSIDBytes =
concatenateByteArrays(TEST_VALID_ZERO_LENGTH_TAG, getTestSsidIEBytes());
InformationElement[] results =
InformationElementUtil.parseInformationElements(zeroLengthTagWithSSIDBytes);
assertEquals("Parsed results should have 2 elements.", 2, results.length);
assertEquals("First element tag should be EID_BSS_LOAD",
InformationElement.EID_BSS_LOAD, results[0].id);
assertEquals("First element should be length 0", 0, results[0].bytes.length);
assertEquals("Second element should be a ssid", InformationElement.EID_SSID, results[1].id);
assertArrayEquals("parsed SSID does not match input",
TEST_SSID_BYTES, results[1].bytes);
}
/*
* Test parseInformationElements with two elements where the first element has an invalid
* length. The invalid length in the first element causes us to miss the start of the second
* Infomation Element. This results in a single element in the returned array.
* Expect the function to return a single entry in an InformationElement array. This returned
* entry is not validated at this time and does not contain valid data (since the incorrect
* length was used).
* TODO: attempt to validate the data and recover as much as possible. When the follow-on CL
* is in development, this test will be updated to reflect the change.
*
* @throws java.io.IOException
*/
@Test
public void parseInformationElements_firstElementWrongLength() throws IOException {
byte[] invalidLengthTag = new byte[] {(byte) 0x0B, (byte) 0x01 };
byte[] invalidLengthTagWithSSIDBytes =
concatenateByteArrays(invalidLengthTag, getTestSsidIEBytes());
InformationElement[] results =
InformationElementUtil.parseInformationElements(invalidLengthTagWithSSIDBytes);
assertEquals("Parsed results should have 1 element", 1, results.length);
assertEquals("First result should be a EID_BSS_LOAD tag.",
InformationElement.EID_BSS_LOAD, results[0].id);
assertEquals("First result should have data of 1 byte", 1, results[0].bytes.length);
assertEquals("First result should have data set to 0x00",
invalidLengthTagWithSSIDBytes[2], results[0].bytes[0]);
}
/**
* Test Capabilities.generateCapabilitiesString() with a RSN IE.
* Expect the function to return a string with the proper security information.
*/
@Test
public void buildCapabilities_rsnElement() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_RSN;
ie.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F,
(byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00,
(byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
(byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F,
(byte) 0xAC, (byte) 0x02, (byte) 0x00, (byte) 0x00 };
InformationElement[] ies = new InformationElement[] { ie };
BitSet beaconCap = new BitSet(16);
beaconCap.set(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[WPA2-PSK-CCMP+TKIP]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with a RSN IE which is malformed.
* Expect the function to return a string with empty key management & pairswise cipher security
* information.
*/
@Test
public void buildCapabilities_malformedRsnElement() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_RSN;
ie.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F,
(byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00,
(byte) 0x00, (byte) 0x0F, (byte) 0xAC };
InformationElement[] ies = new InformationElement[] { ie };
BitSet beaconCap = new BitSet(16);
beaconCap.set(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[WPA2]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with a WPA type 1 IE.
* Expect the function to return a string with the proper security information.
*/
@Test
public void buildCapabilities_wpa1Element() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_VSA;
ie.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50,
(byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00,
(byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04,
(byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50,
(byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 };
InformationElement[] ies = new InformationElement[] { ie };
BitSet beaconCap = new BitSet(16);
beaconCap.set(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[WPA-PSK-CCMP+TKIP]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with a WPA type 1 IE which is malformed.
* Expect the function to return a string with empty key management & pairswise cipher security
* information.
*/
@Test
public void buildCapabilities_malformedWpa1Element() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_VSA;
ie.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01,
(byte) 0x01, (byte) 0x00 };
InformationElement[] ies = new InformationElement[] { ie };
BitSet beaconCap = new BitSet(16);
beaconCap.set(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[WPA]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with both RSN and WPA1 IE.
* Expect the function to return a string with the proper security information.
*/
@Test
public void buildCapabilities_rsnAndWpaElement() {
InformationElement ieRsn = new InformationElement();
ieRsn.id = InformationElement.EID_RSN;
ieRsn.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F,
(byte) 0xAC, (byte) 0x02, (byte) 0x02, (byte) 0x00,
(byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
(byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F,
(byte) 0xAC, (byte) 0x02, (byte) 0x00, (byte) 0x00 };
InformationElement ieWpa = new InformationElement();
ieWpa.id = InformationElement.EID_VSA;
ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50,
(byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00,
(byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04,
(byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50,
(byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 };
InformationElement[] ies = new InformationElement[] { ieWpa, ieRsn };
BitSet beaconCap = new BitSet(16);
beaconCap.set(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with both RSN and WPA1 IE which are malformed.
* Expect the function to return a string with empty key management & pairswise cipher security
* information.
*/
@Test
public void buildCapabilities_malformedRsnAndWpaElement() {
InformationElement ieRsn = new InformationElement();
ieRsn.id = InformationElement.EID_RSN;
ieRsn.bytes = new byte[] { (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F,
(byte) 0xAC, (byte) 0x02, (byte) 0x02 };
InformationElement ieWpa = new InformationElement();
ieWpa.id = InformationElement.EID_VSA;
ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50,
(byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00,
(byte) 0x00, (byte) 0x50 };
InformationElement[] ies = new InformationElement[] { ieWpa, ieRsn };
BitSet beaconCap = new BitSet(16);
beaconCap.set(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[WPA][WPA2]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with both WPS and WPA1 IE.
* Expect the function to return a string with the proper security information.
*/
@Test
public void buildCapabilities_wpaAndWpsElement() {
InformationElement ieWpa = new InformationElement();
ieWpa.id = InformationElement.EID_VSA;
ieWpa.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x01,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50,
(byte) 0xF2, (byte) 0x02, (byte) 0x02, (byte) 0x00,
(byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04,
(byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x02,
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x50,
(byte) 0xF2, (byte) 0x02, (byte) 0x00, (byte) 0x00 };
InformationElement ieWps = new InformationElement();
ieWps.id = InformationElement.EID_VSA;
ieWps.bytes = new byte[] { (byte) 0x00, (byte) 0x50, (byte) 0xF2, (byte) 0x04 };
InformationElement[] ies = new InformationElement[] { ieWpa, ieWps };
BitSet beaconCap = new BitSet(16);
beaconCap.set(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[WPA-PSK-CCMP+TKIP][WPS]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with a vendor specific element which
* is not WPA type 1. Beacon Capability Information field has the Privacy
* bit set.
*
* Expect the function to return a string with the proper security information.
*/
@Test
public void buildCapabilities_nonRsnWpa1Element_privacySet() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_VSA;
ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01,
(byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
InformationElement[] ies = new InformationElement[] { ie };
BitSet beaconCap = new BitSet(16);
beaconCap.set(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[WEP]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with a vendor specific element which
* is not WPA type 1. Beacon Capability Information field doesn't have the
* Privacy bit set.
*
* Expect the function to return an empty string.
*/
@Test
public void buildCapabilities_nonRsnWpa1Element_privacyClear() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_VSA;
ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01,
(byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
InformationElement[] ies = new InformationElement[] { ie };
BitSet beaconCap = new BitSet(16);
beaconCap.clear(4);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with a vendor specific element which
* is not WPA type 1. Beacon Capability Information field has the ESS bit set.
*
* Expect the function to return a string with [ESS] there.
*/
@Test
public void buildCapabilities_nonRsnWpa1Element_essSet() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_VSA;
ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01,
(byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
InformationElement[] ies = new InformationElement[] { ie };
BitSet beaconCap = new BitSet(16);
beaconCap.set(0);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("[ESS]", result);
}
/**
* Test Capabilities.generateCapabilitiesString() with a vendor specific element which
* is not WPA type 1. Beacon Capability Information field doesn't have the
* ESS bit set.
*
* Expect the function to return an empty string.
*/
@Test
public void buildCapabilities_nonRsnWpa1Element_essClear() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_VSA;
ie.bytes = new byte[] { (byte) 0x00, (byte) 0x04, (byte) 0x0E, (byte) 0x01,
(byte) 0x01, (byte) 0x02, (byte) 0x01, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };
InformationElement[] ies = new InformationElement[] { ie };
BitSet beaconCap = new BitSet(16);
beaconCap.clear(0);
InformationElementUtil.Capabilities capabilities =
new InformationElementUtil.Capabilities();
capabilities.from(ies, beaconCap);
String result = capabilities.generateCapabilitiesString();
assertEquals("", result);
}
/**
* Verify the expectations when building an ExtendedCapabilites IE from data with no bits set.
* Both ExtendedCapabilities#isStrictUtf8() and ExtendedCapabilites#is80211McRTTResponder()
* should return false.
*/
@Test
public void buildExtendedCapabilities_emptyBitSet() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_EXTENDED_CAPS;
ie.bytes = new byte[8];
InformationElementUtil.ExtendedCapabilities extendedCap =
new InformationElementUtil.ExtendedCapabilities();
extendedCap.from(ie);
assertFalse(extendedCap.isStrictUtf8());
assertFalse(extendedCap.is80211McRTTResponder());
}
/**
* Verify the expectations when building an ExtendedCapabilites IE from data with UTF-8 SSID
* bit set (bit 48). ExtendedCapabilities#isStrictUtf8() should return true.
*/
@Test
public void buildExtendedCapabilites_strictUtf8() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_EXTENDED_CAPS;
ie.bytes = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00 };
InformationElementUtil.ExtendedCapabilities extendedCap =
new InformationElementUtil.ExtendedCapabilities();
extendedCap.from(ie);
assertTrue(extendedCap.isStrictUtf8());
assertFalse(extendedCap.is80211McRTTResponder());
}
/**
* Verify the expectations when building an ExtendedCapabilites IE from data with RTT Response
* Enable bit set (bit 70). ExtendedCapabilities#is80211McRTTResponder() should return true.
*/
@Test
public void buildExtendedCapabilites_80211McRTTResponder() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_EXTENDED_CAPS;
ie.bytes = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x40 };
InformationElementUtil.ExtendedCapabilities extendedCap =
new InformationElementUtil.ExtendedCapabilities();
extendedCap.from(ie);
assertFalse(extendedCap.isStrictUtf8());
assertTrue(extendedCap.is80211McRTTResponder());
}
/**
* Test a that a correctly formed TIM Information Element is decoded into a valid TIM element,
* and the values are captured
*/
@Test
public void parseTrafficIndicationMapInformationElementValid() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_TIM;
ie.bytes = new byte[] { (byte) 0x03, (byte) 0x05, (byte) 0x00, (byte) 0x00};
InformationElementUtil.TrafficIndicationMap trafficIndicationMap =
new InformationElementUtil.TrafficIndicationMap();
trafficIndicationMap.from(ie);
assertEquals(trafficIndicationMap.mLength, 4);
assertEquals(trafficIndicationMap.mDtimCount, 3);
assertEquals(trafficIndicationMap.mDtimPeriod, 5);
assertEquals(trafficIndicationMap.mBitmapControl, 0);
assertEquals(trafficIndicationMap.isValid(), true);
}
/**
* Test that a short invalid Information Element is marked as being an invalid TIM element when
* parsed as Traffic Indication Map.
*/
@Test
public void parseTrafficIndicationMapInformationElementInvalidTooShort() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_TIM;
ie.bytes = new byte[] { (byte) 0x01, (byte) 0x07 };
InformationElementUtil.TrafficIndicationMap trafficIndicationMap =
new InformationElementUtil.TrafficIndicationMap();
trafficIndicationMap.from(ie);
assertEquals(trafficIndicationMap.isValid(), false);
}
/**
* Test that a too-large invalid Information Element is marked as an invalid TIM element when
* parsed as Traffic Indication Map.
*/
@Test
public void parseTrafficIndicationMapInformationElementInvalidTooLong() {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_TIM;
ie.bytes = new byte[255]; // bytes length of upto 254 is valid for TIM
Arrays.fill(ie.bytes, (byte) 7);
InformationElementUtil.TrafficIndicationMap trafficIndicationMap =
new InformationElementUtil.TrafficIndicationMap();
trafficIndicationMap.from(ie);
assertEquals(trafficIndicationMap.isValid(), false);
}
/**
* Verify that the expected Roaming Consortium information element is parsed and retrieved
* from the list of IEs.
*
* @throws Exception
*/
@Test
public void getRoamingConsortiumIE() throws Exception {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_ROAMING_CONSORTIUM;
/**
* Roaming Consortium Format;
* | Number of OIs | OI#1 and OI#2 Lengths | OI #1 | OI #2 (optional) | OI #3 (optional) |
* 1 1 variable variable variable
*/
ie.bytes = new byte[] { (byte) 0x01 /* number of OIs */, (byte) 0x03 /* OI Length */,
(byte) 0x11, (byte) 0x22, (byte) 0x33};
InformationElementUtil.RoamingConsortium roamingConsortium =
InformationElementUtil.getRoamingConsortiumIE(new InformationElement[] {ie});
assertEquals(1, roamingConsortium.anqpOICount);
assertEquals(1, roamingConsortium.getRoamingConsortiums().length);
assertEquals(0x112233, roamingConsortium.getRoamingConsortiums()[0]);
}
/**
* Verify that the expected Hotspot 2.0 Vendor Specific information element is parsed and
* retrieved from the list of IEs.
*
* @throws Exception
*/
@Test
public void getHS2VendorSpecificIE() throws Exception {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_VSA;
/**
* Vendor Specific OI Format:
* | OI | Type | Hotspot Configuration | PPS MO ID (optional) | ANQP Domain ID (optional)
* 3 1 1 2 2
*
* With OI=0x506F9A and Type=0x10 for Hotspot 2.0
*
* The Format of Hotspot Configuration:
* B0 B1 B2 B3 B4 B7
* | DGAF Disabled | PPS MO ID Flag | ANQP Domain ID Flag | reserved | Release Number |
*/
ie.bytes = new byte[] { (byte) 0x50, (byte) 0x6F, (byte) 0x9A, (byte) 0x10,
(byte) 0x14 /* Hotspot Configuration */, (byte) 0x11, (byte) 0x22};
InformationElementUtil.Vsa vsa =
InformationElementUtil.getHS2VendorSpecificIE(new InformationElement[] {ie});
assertEquals(NetworkDetail.HSRelease.R2, vsa.hsRelease);
assertEquals(0x2211, vsa.anqpDomainID);
}
/**
* Verify that the expected Interworking information element is parsed and retrieved from the
* list of IEs. Uses an IE w/o the optional Venue Info.
*
* @throws Exception
*/
@Test
public void getInterworkingElementNoVenueIE() throws Exception {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_INTERWORKING;
/**
* Interworking Format:
* | Access Network Option | Venue Info (optional) | HESSID (optional) |
* 1 2 6
*
* Access Network Option Format:
*
* B0 B3 B4 B5 B6 B7
* | Access Network Type | Internet | ASRA | ESR | UESA |
*/
ie.bytes = new byte[] { (byte) 0x10, (byte) 0x11, (byte) 0x22, (byte) 0x33, (byte) 0x44,
(byte) 0x55, (byte) 0x66 };
InformationElementUtil.Interworking interworking =
InformationElementUtil.getInterworkingIE(new InformationElement[] {ie});
assertTrue(interworking.internet);
assertEquals(NetworkDetail.Ant.Private, interworking.ant);
assertEquals(0x112233445566L, interworking.hessid);
}
/**
* Verify that the expected Interworking information element is parsed and retrieved from the
* list of IEs. Uses an IE with the optional Venue Info.
*
* @throws Exception
*/
@Test
public void getInterworkingElementWithVenueIE() throws Exception {
InformationElement ie = new InformationElement();
ie.id = InformationElement.EID_INTERWORKING;
/**
* Interworking Format:
* | Access Network Option | Venue Info (optional) | HESSID (optional) |
* 1 2 6
*
* Access Network Option Format:
*
* B0 B3 B4 B5 B6 B7
* | Access Network Type | Internet | ASRA | ESR | UESA |
*/
ie.bytes = new byte[]{(byte) 0x10, (byte) 0xAA, (byte) 0xBB, (byte) 0x11, (byte) 0x22,
(byte) 0x33, (byte) 0x44, (byte) 0x55, (byte) 0x66};
InformationElementUtil.Interworking interworking =
InformationElementUtil.getInterworkingIE(new InformationElement[] {ie});
assertTrue(interworking.internet);
assertEquals(NetworkDetail.Ant.Private, interworking.ant);
assertEquals(0x112233445566L, interworking.hessid);
}
}