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.internal.telephony.uicc.euicc.asn1;
18
19import static org.junit.Assert.assertArrayEquals;
20import static org.junit.Assert.assertEquals;
21import static org.junit.Assert.assertFalse;
22import static org.junit.Assert.assertTrue;
23import static org.junit.Assert.fail;
24
25import android.test.suitebuilder.annotation.SmallTest;
26
27import com.android.internal.telephony.uicc.IccUtils;
28import com.android.internal.telephony.uicc.asn1.Asn1Decoder;
29import com.android.internal.telephony.uicc.asn1.Asn1Node;
30import com.android.internal.telephony.uicc.asn1.InvalidAsn1DataException;
31import com.android.internal.telephony.uicc.asn1.TagNotFoundException;
32
33import org.junit.Test;
34
35public class Asn1NodeTest {
36
37    @SmallTest
38    @Test
39    public void testCreateConstructedNodeWithShortTag() {
40        Asn1Node node = Asn1Node.newBuilder(0x65).build();
41        assertEquals(0x65, node.getTag());
42        assertTrue(node.isConstructed());
43        assertEquals(2, node.getEncodedLength());
44        assertEquals(0, node.getDataLength());
45        assertArrayEquals(new byte[] {0x65, 0x00}, node.toBytes());
46    }
47
48    @SmallTest
49    @Test
50    public void testCreateConstructedNodeWithLongTag() {
51        Asn1Node node = Asn1Node.newBuilder(0x3F34).build();
52        assertEquals(0x3F34, node.getTag());
53        assertTrue(node.isConstructed());
54        assertEquals(3, node.getEncodedLength());
55        assertEquals(0, node.getDataLength());
56        assertArrayEquals(new byte[] {0x3F, 0x34, 0x00}, node.toBytes());
57    }
58
59    @SmallTest
60    @Test
61    public void testChildren() throws TagNotFoundException, InvalidAsn1DataException {
62        Asn1Node node =
63                Asn1Node.newBuilder(0x3F34)
64                        .addChild(Asn1Node.newBuilder(0x35).addChild(Asn1Node.newBuilder(0x36)))
65                        .addChild(Asn1Node.newBuilder(0x35))
66                        .addChild(Asn1Node.newBuilder(0x37))
67                        .build();
68
69        assertEquals(0x3F34, node.getTag());
70        assertEquals(3, node.getChildren().size());
71        assertEquals(0x35, node.getChildren().get(0).getTag());
72        assertEquals(0x35, node.getChildren().get(1).getTag());
73        assertEquals(0x37, node.getChildren().get(2).getTag());
74        assertEquals(2, node.getChildren(0x35).size());
75        assertEquals(0x35, node.getChildren(0x35).get(0).getTag());
76        assertEquals(0x35, node.getChildren(0x35).get(1).getTag());
77        assertEquals(1, node.getChild(0x35).getChildren().size());
78        assertEquals(0, node.getChildren().get(1).getChildren().size());
79        assertEquals(0x36, node.getChild(0x35).getChildren().get(0).getTag());
80
81        assertTrue(node.hasChild(0x35, 0x36));
82        assertFalse(node.hasChild(0x38, 0x39));
83        assertTrue(node.getChild(0x35).hasChild(0x36));
84        assertFalse(node.getChild(0x35).hasChild(0x39));
85    }
86
87    @SmallTest
88    @Test
89    public void testNonExitingChildren() throws TagNotFoundException, InvalidAsn1DataException {
90        Asn1Node node =
91                Asn1Node.newBuilder(0x3F34)
92                        .addChild(Asn1Node.newBuilder(0x34))
93                        .addChild(Asn1Node.newBuilder(0x35).addChild(Asn1Node.newBuilder(0x36)))
94                        .addChildAsInteger(0x11, 123)
95                        .build();
96
97        assertEquals(0, node.getChild(0x34).getChildren(0x37).size());
98        assertEquals(0, node.getChildren(0x37).size());
99        assertEquals(0, node.getChild(0x11).getChildren(0x37).size());
100        assertEquals(0, node.getChild(0x11).getChildren().size());
101        try {
102            node.getChild(0x35).getChild(0x37);
103            fail("0x37 should not exist.");
104        } catch (TagNotFoundException e) {
105            assertEquals(0x37, e.getTag());
106        }
107        try {
108            node.getChild(0x35, 0x37);
109            fail("0x37 should not exist.");
110        } catch (TagNotFoundException e) {
111            assertEquals(0x37, e.getTag());
112        }
113        try {
114            node.getChild(0x11).getChild(0x37);
115            fail("0x37 should not exist.");
116        } catch (TagNotFoundException e) {
117            assertEquals(0x37, e.getTag());
118        }
119    }
120
121    @SmallTest
122    @Test
123    public void testBuilderAndGetters() throws TagNotFoundException, InvalidAsn1DataException {
124        Asn1Node node =
125                Asn1Node.newBuilder(0x30)
126                        .addChildAsInteger(0x11, 1234567)
127                        .addChildAsString(0x12, "This is a test.")
128                        .addChild(
129                                Asn1Node.newBuilder(0x31)
130                                        .addChildAsBits(0x13, 0xF2344)
131                                        .addChildAsBytes(0x14, new byte[] {-1, 0, -1}))
132                        .addChildAsBoolean(0x15, true)
133                        .addChildAsBoolean(0x16, false)
134                        .addChildren(IccUtils.hexStringToBytes("13040422C4F01403FF00FF"))
135                        .build();
136
137        assertEquals(54, node.getEncodedLength());
138        assertEquals(52, node.getDataLength());
139
140        final String nodeHex =
141                "3034110312D687120F54686973206973206120746573742E310B13040422C4F0"
142                        + "1403FF00FF1501FF16010013040422C4F01403FF00FF";
143        assertEquals(nodeHex, node.toHex());
144        assertEquals("3034", node.getHeadAsHex());
145        assertEquals(1234567, node.getChild(0x11).asInteger());
146        assertEquals("This is a test.", node.getChild(0x12).asString());
147        assertEquals(0xF2344, node.getChild(0x31).getChild(0x13).asBits());
148        assertArrayEquals(new byte[] {-1, 0, -1}, node.getChild(0x31).getChild(0x14).asBytes());
149        assertTrue(node.getChild(0x15).asBoolean());
150        assertFalse(node.getChild(0x16).asBoolean());
151        assertEquals(0xF2344, node.getChild(0x13).asBits());
152        assertArrayEquals(new byte[] {-1, 0, -1}, node.getChild(0x14).asBytes());
153    }
154
155    @SmallTest
156    @Test
157    public void testGettersInvalidData() throws TagNotFoundException, InvalidAsn1DataException {
158        Asn1Node node = Asn1Node.newBuilder(0x30).addChildAsString(0x12, "string").build();
159        try {
160            node.getChild(0x12).asInteger();
161            fail("Should not be parsed.");
162        } catch (InvalidAsn1DataException e) {
163            assertEquals(0x12, e.getTag());
164        }
165        try {
166            node.getChild(0x12).asBits();
167            fail("Should not be parsed.");
168        } catch (InvalidAsn1DataException e) {
169            assertEquals(0x12, e.getTag());
170        }
171        try {
172            node.getChild(0x12).asBoolean();
173            fail("Should not be parsed.");
174        } catch (InvalidAsn1DataException e) {
175            assertEquals(0x12, e.getTag());
176        }
177    }
178
179    @SmallTest
180    @Test
181    public void testWriteToBytes() throws InvalidAsn1DataException {
182        final String nodeHex =
183                "3031110312D687120F54686973206973206120746573742E310B13040422C4F0"
184                        + "1403FF00FF1501FF13040422C4F01403FF00FF";
185
186        Asn1Node node = new Asn1Decoder(nodeHex).nextNode();
187        // Writes the bytes before children accessed.
188        assertEquals(nodeHex, node.toHex());
189        // Writes the bytes after children accessed.
190        node.getChildren();
191        assertEquals(nodeHex, node.toHex());
192    }
193
194    @SmallTest
195    @Test
196    public void testLongFormLength() throws TagNotFoundException, InvalidAsn1DataException {
197        Asn1Node node = Asn1Node.newBuilder(0xBF37).addChildAsBytes(0x5A, new byte[257]).build();
198        assertEquals(266, node.getEncodedLength());
199        assertEquals(261, node.getDataLength());
200        assertEquals(257, node.getChild(0x5A).getDataLength());
201        assertEquals("BF37820105", node.getHeadAsHex());
202
203        byte[] expected = new byte[266];
204        System.arraycopy(IccUtils.hexStringToBytes("BF378201055A820101"), 0, expected, 0, 9);
205        byte[] actual = new byte[266];
206        node.writeToBytes(actual, 0);
207        assertArrayEquals(expected, actual);
208    }
209
210    @SmallTest
211    @Test(expected = IllegalArgumentException.class)
212    public void testBuilder_NonConstructedTag() {
213        Asn1Node.newBuilder(0x87);
214    }
215
216    @SmallTest
217    @Test(expected = IllegalStateException.class)
218    public void testBuilderAddChildAsInteger_ConstructedTag() {
219        Asn1Node.newBuilder(0xBF37).addChildAsInteger(0xBF37, 1);
220    }
221
222    @SmallTest
223    @Test(expected = IllegalStateException.class)
224    public void testBuilderAddChildAsString_ConstructedTag() {
225        Asn1Node.newBuilder(0xBF37).addChildAsString(0xBF37, "");
226    }
227
228    @SmallTest
229    @Test(expected = IllegalStateException.class)
230    public void testBuilderAddChildAsBytes_ConstructedTag() {
231        Asn1Node.newBuilder(0xBF37).addChildAsBytesFromHex(0xBF37, "00");
232    }
233
234    @SmallTest
235    @Test(expected = IllegalStateException.class)
236    public void testBuilderAddChildAsBits_ConstructedTag() {
237        Asn1Node.newBuilder(0xBF37).addChildAsBits(0xBF37, 1);
238    }
239
240    @SmallTest
241    @Test(expected = IllegalStateException.class)
242    public void testBuilderAddChildAsBoolean_ConstructedTag() {
243        Asn1Node.newBuilder(0xBF37).addChildAsBoolean(0xBF37, true);
244    }
245
246    @SmallTest
247    @Test(expected = IllegalStateException.class)
248    public void testAsInteger_ConstructedTag() throws InvalidAsn1DataException {
249        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
250        node.asInteger();
251    }
252
253    @SmallTest
254    @Test(expected = IllegalStateException.class)
255    public void testAsLong_ConstructedTag() throws InvalidAsn1DataException {
256        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
257        node.asRawLong();
258    }
259
260    @SmallTest
261    @Test(expected = IllegalStateException.class)
262    public void testAsString_ConstructedTag() throws InvalidAsn1DataException {
263        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
264        node.asString();
265    }
266
267    @SmallTest
268    @Test(expected = IllegalStateException.class)
269    public void testAsBytes_ConstructedTag() throws InvalidAsn1DataException {
270        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
271        node.asBytes();
272    }
273
274    @SmallTest
275    @Test(expected = IllegalStateException.class)
276    public void testAsBits_ConstructedTag() throws InvalidAsn1DataException {
277        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
278        node.asBits();
279    }
280
281    @SmallTest
282    @Test(expected = IllegalStateException.class)
283    public void testAsBoolean_ConstructedTag() throws InvalidAsn1DataException {
284        Asn1Node node = Asn1Node.newBuilder(0xBF37).build();
285        node.asBoolean();
286    }
287
288    @SmallTest
289    @Test(expected = InvalidAsn1DataException.class)
290    public void testAsBoolean_InvalidData() throws TagNotFoundException, InvalidAsn1DataException {
291        Asn1Node node = Asn1Node.newBuilder(0xBF37).addChildAsString(1, "1").build();
292        node.getChild(1).asBoolean();
293    }
294
295    @SmallTest
296    @Test(expected = IndexOutOfBoundsException.class)
297    public void testWriteToBytes_IndexOutOfBounds()
298            throws TagNotFoundException, InvalidAsn1DataException {
299        Asn1Node node = Asn1Node.newBuilder(0xBF37).addChildAsString(1, "1").build();
300        byte[] bytes = new byte[1];
301        node.writeToBytes(bytes, 0);
302    }
303}
304