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.VenueNameElement}. 39 */ 40@SmallTest 41public class VenueNameElementTest { 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_VENUE_NAME1 = "Venue1"; 45 private static final String TEST_VENUE_NAME2 = "Venue2"; 46 47 /** 48 * Helper function for appending a Venue Name to an output stream. 49 * 50 * @param stream Stream to write to 51 * @param venue The venue name string 52 * @throws IOException 53 */ 54 private void appendVenue(ByteArrayOutputStream stream, String venue) throws IOException { 55 byte[] venueBytes = venue.getBytes(StandardCharsets.UTF_8); 56 int length = I18Name.LANGUAGE_CODE_LENGTH + venue.length(); 57 stream.write((byte) length); 58 stream.write(TEST_LANGUAGE.getBytes(StandardCharsets.US_ASCII)); 59 stream.write(new byte[]{(byte) 0x0}); // Padding for language code. 60 stream.write(venueBytes); 61 } 62 63 /** 64 * Helper function for generating test data. 65 * 66 * @return byte[] of data 67 * @throws IOException 68 */ 69 private byte[] getTestData(String[] names) throws IOException { 70 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 71 // Venue info data not currently used. 72 stream.write(new byte[VenueNameElement.VENUE_INFO_LENGTH]); 73 for (String name : names) { 74 appendVenue(stream, name); 75 } 76 return stream.toByteArray(); 77 } 78 79 /** 80 * Verify that BufferUnderflowException will be thrown when parsing an empty buffer. 81 * 82 * @throws Exception 83 */ 84 @Test(expected = BufferUnderflowException.class) 85 public void parseEmptyBuffer() throws Exception { 86 VenueNameElement.parse(ByteBuffer.allocate(0)); 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 parseTruncatedBuffer() throws Exception { 97 ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[] {TEST_VENUE_NAME1})); 98 // Truncate a byte at the end. 99 buffer.limit(buffer.remaining() - 1); 100 VenueNameElement.parse(buffer); 101 } 102 103 /** 104 * Verify that a VenueNameElement with empty name list will be returned when parsing a buffer 105 * contained no venue name (only contained the venue info data). 106 * 107 * @throws Exception 108 */ 109 @Test 110 public void parseBufferWithEmptyVenueName() throws Exception { 111 ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[0])); 112 assertTrue(VenueNameElement.parse(buffer).getNames().isEmpty()); 113 } 114 /** 115 * Verify that an expected VenueNameElement will be returned when parsing a buffer contained 116 * valid Venue Name data. 117 * 118 * @throws Exception 119 */ 120 @Test 121 public void parseBufferWithValidVenueNames() throws Exception { 122 // Setup expected element. 123 List<I18Name> nameList = new ArrayList<>(); 124 nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_VENUE_NAME1)); 125 nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, TEST_VENUE_NAME2)); 126 VenueNameElement expectedElement = new VenueNameElement(nameList); 127 128 ByteBuffer buffer = ByteBuffer.wrap( 129 getTestData(new String[] {TEST_VENUE_NAME1, TEST_VENUE_NAME2})); 130 assertEquals(expectedElement, VenueNameElement.parse(buffer)); 131 } 132 133 /** 134 * Verify that an expected VenueNameElement will be returned when parsing a buffer 135 * contained a venue name with the maximum length. 136 * 137 * @throws Exception 138 */ 139 @Test 140 public void parseBufferWithMaxLengthVenueName() throws Exception { 141 // Venue name with maximum length. 142 byte[] textData = new byte[VenueNameElement.MAXIMUM_VENUE_NAME_LENGTH]; 143 Arrays.fill(textData, (byte) 'a'); 144 String text = new String(textData); 145 ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[] {text})); 146 147 // Setup expected element. 148 List<I18Name> nameList = new ArrayList<>(); 149 nameList.add(new I18Name(TEST_LANGUAGE, TEST_LOCALE, text)); 150 VenueNameElement expectedElement = new VenueNameElement(nameList); 151 152 assertEquals(expectedElement, VenueNameElement.parse(buffer)); 153 } 154 155 /** 156 * Verify that ProtocolException will be thrown when parsing a buffer contained a 157 * venue name that exceeds the maximum length. 158 * 159 * @throws Exception 160 */ 161 @Test(expected = ProtocolException.class) 162 public void parseBufferWithVenueNameLengthExceedMax() throws Exception { 163 byte[] textData = new byte[VenueNameElement.MAXIMUM_VENUE_NAME_LENGTH + 1]; 164 Arrays.fill(textData, (byte) 'a'); 165 String text = new String(textData); 166 ByteBuffer buffer = ByteBuffer.wrap(getTestData(new String[] {text})); 167 VenueNameElement.parse(buffer); 168 } 169} 170