ChoiceTest.java revision e98fbf8686c5289bf03fe5c3de7ff82d3a77104d
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Stepan M. Mishura
20*/
21
22package org.apache.harmony.security.tests.asn1.der;
23
24import java.io.IOException;
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.Collection;
28import java.util.List;
29
30import junit.framework.TestCase;
31
32import org.apache.harmony.security.asn1.ASN1Any;
33import org.apache.harmony.security.asn1.ASN1BitString;
34import org.apache.harmony.security.asn1.ASN1Boolean;
35import org.apache.harmony.security.asn1.ASN1Choice;
36import org.apache.harmony.security.asn1.ASN1Explicit;
37import org.apache.harmony.security.asn1.ASN1Integer;
38import org.apache.harmony.security.asn1.ASN1Oid;
39import org.apache.harmony.security.asn1.ASN1SequenceOf;
40import org.apache.harmony.security.asn1.ASN1Type;
41import org.apache.harmony.security.asn1.BerInputStream;
42import org.apache.harmony.security.asn1.DerInputStream;
43import org.apache.harmony.security.asn1.DerOutputStream;
44
45
46/**
47 * ASN.1 DER test for Choice type
48 *
49 * @see http://asn1.elibel.tm.fr/en/standards/index.htm
50 */
51
52public class ChoiceTest extends TestCase {
53
54    private static ASN1SequenceOf sequence = new ASN1SequenceOf(ASN1Boolean
55            .getInstance());
56
57    //
58    // choice ::= CHOICE {
59    //     boolean BOOLEAN,
60    //     sequenceof SEQUENCE OF BOOLEAN,
61    //     int INTEGER
62    // }
63    //
64
65    private static ASN1Choice choice = new ASN1Choice(new ASN1Type[] {
66            ASN1Boolean.getInstance(), sequence, ASN1Integer.getInstance() }) {
67
68        public int getIndex(Object object) {
69            if (object instanceof Boolean) {
70                return 0; // ASN1Boolean
71            } else if (object instanceof Collection) {
72                return 1; // ASN1SequenceOf
73            } else {
74                return 2; // ASN1Integer
75            }
76        }
77
78        public Object getObjectToEncode(Object object) {
79            return object;
80        }
81    };
82
83    //
84    // Test Cases
85    //
86
87    private static Object[][] testcases = {
88            // format: object to encode / byte array
89
90            // choice = Boolean (false)
91            { Boolean.FALSE, new byte[] { 0x01, 0x01, 0x00 } },
92
93            // choice = Boolean (true)
94            { Boolean.TRUE, new byte[] { 0x01, 0x01, (byte) 0xFF } },
95
96            // choice = SequenceOf (empty)
97            { new ArrayList(), new byte[] { 0x30, 0x00 } },
98
99    //TODO add testcase for another ASN.1 type`
100
101    };
102
103    public void testDecode_Valid() throws IOException {
104
105        for (int i = 0; i < testcases.length; i++) {
106            DerInputStream in = new DerInputStream((byte[]) testcases[i][1]);
107            assertEquals("Test case: " + i, testcases[i][0], choice.decode(in));
108        }
109    }
110
111    //FIXME need testcase for decoding invalid encodings
112
113    public void testEncode() throws IOException {
114
115        for (int i = 0; i < testcases.length; i++) {
116            DerOutputStream out = new DerOutputStream(choice, testcases[i][0]);
117            assertTrue("Test case: " + i, Arrays.equals(
118                    (byte[]) testcases[i][1], out.encoded));
119        }
120    }
121
122    public void testChoiceInSequenceOf() throws IOException {
123
124        ASN1Choice choice = new ASN1Choice(new ASN1Type[] {
125                ASN1Boolean.getInstance(), ASN1Integer.getInstance() }) {
126
127            public int getIndex(Object object) {
128                if (object instanceof Boolean) {
129                    return 0; // ASN1Boolean
130                } else {
131                    return 1; // ASN1Integer
132                }
133            }
134
135            public Object getObjectToEncode(Object object) {
136                return object;
137            }
138        };
139
140        ASN1SequenceOf sequenceOf = new ASN1SequenceOf(choice);
141
142        ArrayList list = new ArrayList();
143        list.add(Boolean.FALSE);
144        list.add(new byte[] { 0x09 });
145
146        byte[] encoded = new byte[] {
147        // Sequence Of
148                0x30, 0x06,
149                // Boolean
150                0x01, 0x01, 0x00,
151                // Integer
152                0x02, 0x01, 0x09 };
153
154        assertTrue("Encoded: ", Arrays.equals(encoded, sequenceOf.encode(list)));
155
156        List values = (List) sequenceOf.decode(encoded);
157
158        assertEquals("Size: ", 2, values.size());
159        assertEquals("First: ", Boolean.FALSE, values.get(0));
160        assertTrue("Second: ", Arrays.equals(new byte[] { 0x09 },
161                (byte[]) values.get(1)));
162    }
163
164    //
165    //
166    //
167    //
168    //
169
170    public void test_ExplicitChoice() throws IOException {
171
172        ASN1Choice choice = new ASN1Choice(new ASN1Type[] { ASN1Boolean
173                .getInstance() }) {
174
175            public Object getObjectToEncode(Object obj) {
176                return obj;
177            }
178
179            public int getIndex(Object obj) {
180                return 0;
181            }
182        };
183
184        ASN1Explicit explicit = new ASN1Explicit(0, choice);
185
186        byte[] encoded = new byte[] { (byte) 0xA0, 0x03, 0x01, 0x01, 0x00 };
187
188        assertEquals("False: ", Boolean.FALSE, explicit.decode(encoded));
189
190        encoded[4] = (byte) 0xFF;
191
192        assertEquals("True: ", Boolean.TRUE, explicit.decode(encoded));
193    }
194
195    /**
196     * TODO Put method description here
197     */
198    public void testChoiceOfChoice() throws Exception {
199
200        ASN1Choice choice1 = new ASN1Choice(new ASN1Type[] {
201                ASN1Oid.getInstance(), // first
202                ASN1Boolean.getInstance(),// second: decoded component
203                ASN1Integer.getInstance() // third
204                }) {
205
206            public Object getDecodedObject(BerInputStream in)
207                    throws IOException {
208
209                assertEquals("choice1", 1, in.choiceIndex);
210
211                return in.content;
212            }
213
214            public Object getObjectToEncode(Object obj) {
215                return obj;
216            }
217
218            public int getIndex(Object obj) {
219                return 0;
220            }
221        };
222
223        ASN1Choice choice2 = new ASN1Choice(new ASN1Type[] { choice1, // first: decoded component
224                ASN1BitString.getInstance() // second
225                }) {
226
227            public Object getDecodedObject(BerInputStream in)
228                    throws IOException {
229
230                assertEquals("choice2", 0, in.choiceIndex);
231
232                return in.content;
233            }
234
235            public Object getObjectToEncode(Object obj) {
236                return obj;
237            }
238
239            public int getIndex(Object obj) {
240                return 0;
241            }
242        };
243
244        Boolean b = (Boolean) choice2.decode(new byte[] { 0x01, 0x01, 0x00 });
245
246        assertTrue(b == Boolean.FALSE);
247    }
248
249    /**
250     * TODO Put method description here
251     */
252    public void testDistinctTags() throws Exception {
253
254        ASN1Choice choice1 = new ASN1Choice(new ASN1Type[] {
255                ASN1Boolean.getInstance(),// component to be checked
256                ASN1Oid.getInstance(), ASN1Integer.getInstance() }) {
257
258            public Object getObjectToEncode(Object obj) {
259                return obj;
260            }
261
262            public int getIndex(Object obj) {
263                return 0;
264            }
265        };
266
267        // two ASN.1 booleans
268        try {
269            new ASN1Choice(new ASN1Type[] { choice1, //
270                    ASN1Boolean.getInstance() // component to be checked
271                    }) {
272
273                public Object getObjectToEncode(Object obj) {
274                    return obj;
275                }
276
277                public int getIndex(Object obj) {
278                    return 0;
279                }
280            };
281            fail("No expected IllegalArgumentException");
282        } catch (IllegalArgumentException e) {
283        }
284
285        // ASN.1 ANY
286        try {
287            new ASN1Choice(new ASN1Type[] { choice1,//
288                    ASN1Any.getInstance() // component to be checked
289                    }) {
290
291                public Object getObjectToEncode(Object obj) {
292                    return obj;
293                }
294
295                public int getIndex(Object obj) {
296                    return 0;
297                }
298            };
299            fail("No expected IllegalArgumentException");
300        } catch (IllegalArgumentException e) {
301        }
302
303        // two choices
304        ASN1Choice choice2 = new ASN1Choice(new ASN1Type[] {
305                ASN1BitString.getInstance(), //
306                ASN1Boolean.getInstance() //component to be checked
307                }) {
308
309            public Object getObjectToEncode(Object obj) {
310                return obj;
311            }
312
313            public int getIndex(Object obj) {
314                return 0;
315            }
316        };
317
318        try {
319            new ASN1Choice(new ASN1Type[] { choice1, choice2 }) {
320
321                public Object getObjectToEncode(Object obj) {
322                    return obj;
323                }
324
325                public int getIndex(Object obj) {
326                    return 0;
327                }
328            };
329            fail("No expected IllegalArgumentException");
330        } catch (IllegalArgumentException e) {
331        }
332    }
333}
334