1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi.hotspot2.anqp; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertTrue; 21 22import android.test.suitebuilder.annotation.SmallTest; 23 24import org.junit.Test; 25 26import java.io.ByteArrayOutputStream; 27import java.io.IOException; 28import java.net.ProtocolException; 29import java.nio.BufferUnderflowException; 30import java.nio.ByteBuffer; 31import java.nio.charset.StandardCharsets; 32import java.util.ArrayList; 33import java.util.Arrays; 34import java.util.List; 35import java.util.Locale; 36 37/** 38 * Unit tests for {@link com.android.server.wifi.hotspot2.anqp.HSFriendlyNameElement}. 39 */ 40@SmallTest 41public class HSFriendlyNameElementTest { 42 private static final String TEST_LANGUAGE = "en"; 43 private static final Locale TEST_LOCALE = Locale.forLanguageTag(TEST_LANGUAGE); 44 private static final String TEST_OPERATOR_NAME1 = "Operator1"; 45 private static final String TEST_OPERATOR_NAME2 = "Operator2"; 46 47 /** 48 * Helper function for appending a Operator Name to an output stream. 49 * 50 * @param stream Stream to write to 51 * @param operator The name of the operator 52 * @throws IOException 53 */ 54 private void appendOperatorName(ByteArrayOutputStream stream, String operator) 55 throws IOException { 56 byte[] nameBytes = operator.getBytes(StandardCharsets.UTF_8); 57 int length = I18Name.LANGUAGE_CODE_LENGTH + operator.length(); 58 stream.write((byte) length); 59 stream.write(TEST_LANGUAGE.getBytes(StandardCharsets.US_ASCII)); 60 stream.write(new byte[]{(byte) 0x0}); // Padding for language code. 61 stream.write(nameBytes); 62 } 63 64 /** 65 * Helper function for generating test data. 66 * 67 * @return byte[] of data 68 * @throws IOException 69 */ 70 private byte[] getTestData(String[] names) throws IOException { 71 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 72 for (String name : names) { 73 appendOperatorName(stream, name); 74 } 75 return stream.toByteArray(); 76 } 77 78 /** 79 * Verify that HSFriendlyNameElement with a empty operator name list will be returned when 80 * parsing an empty buffer. 81 * 82 * @throws Exception 83 */ 84 @Test 85 public void parseBufferWithEmptyBuffer() throws Exception { 86 assertTrue(HSFriendlyNameElement.parse(ByteBuffer.allocate(0)).getNames().isEmpty()); 87 } 88 89 /** 90 * Verify that BufferUnderflowException will be thrown when parsing a truncated buffer 91 * (missing a byte at the end). 92 * 93 * @throws Exception 94 */ 95 @Test(expected = BufferUnderflowException.class) 96 public void parseBufferWithTruncatedByte() throws Exception { 97 byte[] testData = getTestData(new String[] {TEST_OPERATOR_NAME1}); 98 // Truncate a byte at the end. 99 ByteBuffer buffer = ByteBuffer.allocate(testData.length - 1); 100 buffer.put(testData, 0, testData.length - 1); 101 buffer.position(0); 102 HSFriendlyNameElement.parse(buffer); 103 } 104 105 /** 106 * Verify that an expected HSFriendlyNameElement will be returned when parsing a buffer 107 * containing the default test data. 108 * 109 * @throws Exception 110 */ 111 @Test 112 public void parseBufferWithDefaultTestData() throws Exception { 113 byte[] testData = getTestData(new String[] {TEST_OPERATOR_NAME1, TEST_OPERATOR_NAME2}); 114 ByteBuffer buffer = ByteBuffer.allocate(testData.length); 115 buffer.put(testData); 116 buffer.position(0); 117 118 // Setup expected element. 119 List<I18Name> nameList = new ArrayList<>(); 120 nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_OPERATOR_NAME1)); 121 nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_OPERATOR_NAME2)); 122 HSFriendlyNameElement expectedElement = new HSFriendlyNameElement(nameList); 123 124 assertEquals(expectedElement, HSFriendlyNameElement.parse(buffer)); 125 } 126 127 /** 128 * Verify that an expected HSFriendlyNameElement will be returned when parsing a buffer 129 * containing a operator name with the maximum length. 130 * 131 * @throws Exception 132 */ 133 @Test 134 public void parseBufferWithMaxLengthOperatoreName() throws Exception { 135 // Operator name with the maximum length. 136 byte[] textData = new byte[HSFriendlyNameElement.MAXIMUM_OPERATOR_NAME_LENGTH]; 137 Arrays.fill(textData, (byte) 'a'); 138 String text = new String(textData); 139 byte[] testData = getTestData(new String[] {text}); 140 ByteBuffer buffer = ByteBuffer.allocate(testData.length); 141 buffer.put(testData); 142 buffer.position(0); 143 144 // Setup expected element. 145 List<I18Name> nameList = new ArrayList<>(); 146 nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, text)); 147 HSFriendlyNameElement expectedElement = new HSFriendlyNameElement(nameList); 148 149 assertEquals(expectedElement, HSFriendlyNameElement.parse(buffer)); 150 } 151 152 /** 153 * Verify that ProtocolException will be thrown when parsing a buffer containing a 154 * operator name that exceeds the maximum length. 155 * 156 * @throws Exception 157 */ 158 @Test(expected = ProtocolException.class) 159 public void parseBufferWithOperatorNameLengthExceedMax() throws Exception { 160 byte[] textData = new byte[HSFriendlyNameElement.MAXIMUM_OPERATOR_NAME_LENGTH + 1]; 161 Arrays.fill(textData, (byte) 'a'); 162 String text = new String(textData); 163 byte[] testData = getTestData(new String[] {text}); 164 ByteBuffer buffer = ByteBuffer.allocate(testData.length); 165 buffer.put(testData); 166 buffer.position(0); 167 HSFriendlyNameElement.parse(buffer); 168 } 169 170} 171