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 
17 package android.net.wifi.aware;
18 
19 import static org.hamcrest.core.IsEqual.equalTo;
20 
21 import androidx.test.filters.SmallTest;
22 
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.junit.rules.ErrorCollector;
26 
27 import java.nio.BufferOverflowException;
28 import java.util.ArrayList;
29 import java.util.List;
30 
31 
32 /**
33  * Unit test harness for TlvBufferUtils class.
34  */
35 @SmallTest
36 public class TlvBufferUtilsTest {
37     @Rule
38     public ErrorCollector collector = new ErrorCollector();
39 
40     /*
41      * TlvBufferUtils Tests
42      */
43 
44     @Test
testTlvBuild()45     public void testTlvBuild() {
46         TlvBufferUtils.TlvConstructor tlv11 = new TlvBufferUtils.TlvConstructor(1, 1);
47         tlv11.allocate(15);
48         tlv11.putByte(0, (byte) 2);
49         tlv11.putByteArray(2, new byte[] {
50                 0, 1, 2 });
51 
52         collector.checkThat("tlv11-correct-construction",
53                 tlv11.getArray(), equalTo(new byte[]{0, 1, 2, 2, 3, 0, 1, 2}));
54 
55         TlvBufferUtils.TlvConstructor tlv01 = new TlvBufferUtils.TlvConstructor(0, 1);
56         tlv01.allocate(15);
57         tlv01.putByte(0, (byte) 2);
58         tlv01.putByteArray(2, new byte[] {
59                 0, 1, 2 });
60 
61         collector.checkThat("tlv01-correct-construction",
62                 tlv01.getArray(), equalTo(new byte[] {1, 2, 3, 0, 1, 2 }));
63 
64         collector.checkThat("tlv11-valid",
65                 TlvBufferUtils.isValid(tlv11.getArray(), 1, 1),
66                 equalTo(true));
67         collector.checkThat("tlv01-valid",
68                 TlvBufferUtils.isValid(tlv01.getArray(), 0, 1),
69                 equalTo(true));
70     }
71 
72     /**
73      * Validate that re-using a TLV by any of the reallocation method resets it completely.
74      */
75     @Test
testTlvReuse()76     public void testTlvReuse() {
77         TlvBufferUtils.TlvConstructor tlv = new TlvBufferUtils.TlvConstructor(1, 1);
78 
79         tlv.allocate(10);
80         tlv.putByte(0, (byte) 2);
81         tlv.putByte(1, (byte) 104);
82 
83         collector.checkThat("initial", tlv.getArray(), equalTo(new byte[]{0, 1, 2, 1, 1, 104}));
84 
85         tlv.allocate(8);
86         tlv.putByte(5, (byte) 7);
87         collector.checkThat("re-alloc", tlv.getArray(), equalTo(new byte[]{5, 1, 7}));
88     }
89 
90     /**
91      * Verify that can build a valid TLV from a List of byte[].
92      */
93     @Test
testTlvListOperations()94     public void testTlvListOperations() {
95         byte[] entry1 = { 1, 2, 3 };
96         byte[] entry2 = { 4, 5 };
97         byte[] entry3 = new byte[0];
98         List<byte[]> data = new ArrayList<>();
99         data.add(entry1);
100         data.add(entry2);
101         data.add(entry3);
102         data.add(null); // zero-length should work
103 
104         TlvBufferUtils.TlvConstructor tlv01 = new TlvBufferUtils.TlvConstructor(0, 1);
105         tlv01.allocateAndPut(data);
106         byte[] tlvData = tlv01.getArray();
107         List<byte[]> parsedList = new TlvBufferUtils.TlvIterable(0, 1, tlvData).toList();
108 
109         collector.checkThat("tlvData-correct-length", tlvData.length,
110                 equalTo(entry1.length + 1 + entry2.length + 1 + entry3.length + 1 + 1));
111         collector.checkThat("parsedList-correct-length", parsedList.size(), equalTo(4));
112         collector.checkThat("parsedList-entry1", parsedList.get(0), equalTo(entry1));
113         collector.checkThat("parsedList-entry2", parsedList.get(1), equalTo(entry2));
114         collector.checkThat("parsedList-entry3", parsedList.get(2), equalTo(entry3));
115         collector.checkThat("parsedList-entry4", parsedList.get(3), equalTo(new byte[0]));
116     }
117 
118     /**
119      * Verify that can parse a (correctly formatted) byte array to a list.
120      */
121     @Test
testTlvParseToList()122     public void testTlvParseToList() {
123         byte[] validTlv01 = { 0, 1, 55, 2, 33, 66, 0 };
124 
125         List<byte[]> parsedList = new TlvBufferUtils.TlvIterable(0, 1, validTlv01).toList();
126 
127         collector.checkThat("parsedList-entry1", parsedList.get(0), equalTo(new byte[0]));
128         collector.checkThat("parsedList-entry2", parsedList.get(1), equalTo(new byte[] { 55 }));
129         collector.checkThat("parsedList-entry3", parsedList.get(2), equalTo(new byte[] { 33, 66 }));
130         collector.checkThat("parsedList-entry4", parsedList.get(3), equalTo(new byte[0]));
131     }
132 
133     /**
134      * Verify that an exception is thrown when trying to parse an invalid array.
135      */
136     @Test(expected = BufferOverflowException.class)
testTlvParseToListError()137     public void testTlvParseToListError() {
138         byte[] invalidTlv01 = { 0, 1, 55, 2, 55, 66, 3 }; // bad data
139 
140         List<byte[]> data = new TlvBufferUtils.TlvIterable(0, 1, invalidTlv01).toList();
141     }
142 
143     /**
144      * Validate the API which places raw bytes into the TLV (without a TL structure).
145      */
146     @Test
testRawPuts()147     public void testRawPuts() {
148         TlvBufferUtils.TlvConstructor tlv = new TlvBufferUtils.TlvConstructor(1, 1);
149 
150         tlv.allocate(10);
151         tlv.putByte(0, (byte) 2);
152         tlv.putRawByte((byte) 55);
153         tlv.putByte(1, (byte) 104);
154         tlv.putRawByteArray(new byte[]{66, 77});
155 
156         collector.checkThat("data", tlv.getArray(),
157                 equalTo(new byte[]{0, 1, 2, 55, 1, 1, 104, 66, 77}));
158     }
159 
160     @Test
testTlvIterate()161     public void testTlvIterate() {
162         final String ascii = "ABC";
163         final String nonAscii = "何かもっと複雑な";
164 
165         TlvBufferUtils.TlvConstructor tlv22 = new TlvBufferUtils.TlvConstructor(2, 2);
166         tlv22.allocate(18);
167         tlv22.putInt(0, 2);
168         tlv22.putShort(2, (short) 3);
169         tlv22.putZeroLengthElement(55);
170 
171         TlvBufferUtils.TlvIterable tlv22It = new TlvBufferUtils.TlvIterable(2, 2, tlv22.getArray());
172         int count = 0;
173         for (TlvBufferUtils.TlvElement tlv : tlv22It) {
174             if (count == 0) {
175                 collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(0));
176                 collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(4));
177                 collector.checkThat("tlv22-correct-iteration-DATA", tlv.getInt(), equalTo(2));
178             } else if (count == 1) {
179                 collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(2));
180                 collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(2));
181                 collector.checkThat("tlv22-correct-iteration-DATA", (int) tlv.getShort(),
182                         equalTo(3));
183             } else if (count == 2) {
184                 collector.checkThat("tlv22-correct-iteration-mType", tlv.type, equalTo(55));
185                 collector.checkThat("tlv22-correct-iteration-mLength", tlv.length, equalTo(0));
186             } else {
187                 collector.checkThat("Invalid number of iterations in loop - tlv22", true,
188                         equalTo(false));
189             }
190             ++count;
191         }
192         if (count != 3) {
193             collector.checkThat("Invalid number of iterations outside loop - tlv22", true,
194                     equalTo(false));
195         }
196 
197         TlvBufferUtils.TlvConstructor tlv02 = new TlvBufferUtils.TlvConstructor(0, 2);
198         tlv02.allocate(100);
199         tlv02.putByte(0, (byte) 2);
200         tlv02.putString(0, ascii);
201         tlv02.putString(0, nonAscii);
202         tlv02.putByteArray(0, new byte[]{5, 4, 3, 2, 1});
203 
204         TlvBufferUtils.TlvIterable tlv02It = new TlvBufferUtils.TlvIterable(0, 2, tlv02.getArray());
205         count = 0;
206         for (TlvBufferUtils.TlvElement tlv : tlv02It) {
207             if (count == 0) {
208                 collector.checkThat("tlv02-correct-iteration-mLength", tlv.length, equalTo(1));
209                 collector.checkThat("tlv02-correct-iteration-DATA", (int) tlv.getByte(),
210                         equalTo(2));
211             } else if (count == 1) {
212                 collector.checkThat("tlv02-correct-iteration-mLength", tlv.length,
213                         equalTo(ascii.length()));
214                 collector.checkThat("tlv02-correct-iteration-DATA", tlv.getString().equals(ascii),
215                         equalTo(true));
216             } else if (count == 2) {
217                 collector.checkThat("tlv02-correct-iteration-mLength", tlv.length,
218                         equalTo(nonAscii.getBytes().length));
219                 collector.checkThat("tlv02-correct-iteration-DATA",
220                         tlv.getString().equals(nonAscii), equalTo(true));
221             } else if (count == 3) {
222                 collector.checkThat("tlv02-correct-iteration-mLength", tlv.length,
223                         equalTo(5));
224                 collector.checkThat("tlv02-correct-iteration-DATA", tlv.getRawData(),
225                         equalTo(new byte[]{5, 4, 3, 2, 1}));
226             } else {
227                 collector.checkThat("Invalid number of iterations in loop - tlv02", true,
228                         equalTo(false));
229             }
230             ++count;
231         }
232         collector.checkThat("Invalid number of iterations outside loop - tlv02", count,
233                 equalTo(4));
234 
235         collector.checkThat("tlv22-valid",
236                 TlvBufferUtils.isValid(tlv22.getArray(), 2, 2),
237                 equalTo(true));
238         collector.checkThat("tlv02-valid",
239                 TlvBufferUtils.isValid(tlv02.getArray(), 0, 2),
240                 equalTo(true));
241     }
242 
243     @Test(expected = IllegalArgumentException.class)
testTlvInvalidSizeT1L0()244     public void testTlvInvalidSizeT1L0() {
245         TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, 0);
246     }
247 
248     @Test(expected = IllegalArgumentException.class)
testTlvInvalidSizeTm3L2()249     public void testTlvInvalidSizeTm3L2() {
250         TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(-3, 2);
251     }
252 
253     @Test(expected = IllegalArgumentException.class)
testTlvInvalidSizeT1Lm2()254     public void testTlvInvalidSizeT1Lm2() {
255         TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, -2);
256     }
257 
258     @Test(expected = IllegalArgumentException.class)
testTlvInvalidSizeT1L3()259     public void testTlvInvalidSizeT1L3() {
260         TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(1, 3);
261     }
262 
263     @Test(expected = IllegalArgumentException.class)
testTlvInvalidSizeT3L1()264     public void testTlvInvalidSizeT3L1() {
265         TlvBufferUtils.TlvConstructor tlv10 = new TlvBufferUtils.TlvConstructor(3, 1);
266     }
267 
268     @Test(expected = IllegalArgumentException.class)
testTlvItInvalidSizeT1L0()269     public void testTlvItInvalidSizeT1L0() {
270         final byte[] testTlv = {
271                 0, 1, 2 };
272         final int testLength = 3;
273         TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 0, testTlv);
274     }
275 
276     @Test(expected = IllegalArgumentException.class)
testTlvItInvalidSizeTm3L2()277     public void testTlvItInvalidSizeTm3L2() {
278         final byte[] testTlv = {
279                 0, 1, 2 };
280         final int testLength = 3;
281         TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(-3, 2, testTlv);
282     }
283 
284     @Test(expected = IllegalArgumentException.class)
testTlvItInvalidSizeT1Lm2()285     public void testTlvItInvalidSizeT1Lm2() {
286         final byte[] testTlv = {
287                 0, 1, 2 };
288         final int testLength = 3;
289         TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, -2, testTlv);
290     }
291 
292     @Test(expected = IllegalArgumentException.class)
testTlvItInvalidSizeT1L3()293     public void testTlvItInvalidSizeT1L3() {
294         final byte[] testTlv = {
295                 0, 1, 2 };
296         final int testLength = 3;
297         TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 3, testTlv);
298     }
299 
300     @Test(expected = IllegalArgumentException.class)
testTlvItInvalidSizeT3L1()301     public void testTlvItInvalidSizeT3L1() {
302         final byte[] testTlv = {
303                 0, 1, 2 };
304         final int testLength = 3;
305         TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(3, 1, testTlv);
306     }
307 
308     /**
309      * Validate that a malformed byte array fails the TLV validity test.
310      */
311     @Test
testTlvInvalidByteArray()312     public void testTlvInvalidByteArray() {
313         TlvBufferUtils.TlvConstructor tlv01 = new TlvBufferUtils.TlvConstructor(0, 1);
314         tlv01.allocate(15);
315         tlv01.putByte(0, (byte) 2);
316         tlv01.putByteArray(2, new byte[]{0, 1, 2});
317 
318         byte[] array = tlv01.getArray();
319         array[0] = 10;
320 
321         collector.checkThat("tlv01-invalid",
322                 TlvBufferUtils.isValid(array, 0, 1), equalTo(false));
323     }
324 }
325