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
18package tests.api.java.io;
19
20import dalvik.annotation.TestTargets;
21import dalvik.annotation.TestLevel;
22import dalvik.annotation.TestTargetNew;
23import dalvik.annotation.TestTargetClass;
24
25import java.io.ObjectInputStream;
26
27import tests.support.Support_GetPutFields;
28import tests.support.Support_GetPutFieldsDefaulted;
29
30
31/**
32 * Tests the methods of {@code ObjectInputStream.GetField}. Three things make
33 * this class somewhat difficult to test:
34 * <ol>
35 * <li>It is a completely abstract class; none of the methods is implemented in
36 * {@code ObjectInputStream.GetField}.</li>
37 * <li>There is no public class that implements
38 * {@code ObjectInputStream.GetField}. The only way to get an implementation is
39 * by calling {@code ObjectInputStream.getFields()}.</li>
40 * <li>Invoking {@code ObjectOutputStream.getFields()} only works from within
41 * the private {@code readObject(ObjectInputStream)} method of a class that
42 * implements {@code Serializable}; an exception is thrown otherwise.</li>
43 * </ol>
44 * <p>
45 * Given these restrictions, an indirect approach is used to test
46 * {@code ObjectInputStream.GetField}: Three serializable helper classes in
47 * package {@code tests.support} ({@code Support_GetPutFields},
48 * {@code Support_GetPutFieldsDeprecated} and
49 * {@code Support_GetPutFieldsDefaulted}) implement
50 * {@code readObject(ObjectInputStream)} to read data from an input stream.
51 * This input stream in turn reads from one of the corresponding files
52 * ({@code testFields.ser}, {@code testFieldsDeprecated.ser} and
53 * {@code testFieldsDefaulted.ser}) that have been created with
54 * {@code tests.util.FieldTestFileGenerator} on a reference platform.
55 * </p>
56 * <p>
57 * The test method in this class expects to find the reference files as a
58 * resource stored at {@code tests/api/java/io}.
59 * </p>
60 */
61@TestTargetClass(ObjectInputStream.GetField.class)
62public class ObjectInputStreamGetFieldTest extends junit.framework.TestCase {
63
64    private ObjectInputStream ois = null;
65
66    private final String FILENAME =
67            "/tests/api/java/io/testFields.ser";
68    private final String DEFAULTED_FILENAME =
69            "/tests/api/java/io/testFieldsDefaulted.ser";
70
71    public boolean booleanValue;
72    public byte byteValue;
73    public char charValue;
74    public int intValue;
75
76
77    @TestTargets({
78        @TestTargetNew(
79            level = TestLevel.PARTIAL_COMPLETE,
80            notes = "Verifies the get(String, X) methods with valid arguments.",
81            method = "get",
82            args = {java.lang.String.class, boolean.class}
83        ),
84        @TestTargetNew(
85            level = TestLevel.PARTIAL_COMPLETE,
86            notes = "Verifies the get(String, X) methods with valid arguments.",
87            method = "get",
88            args = {java.lang.String.class, byte.class}
89        ),
90        @TestTargetNew(
91            level = TestLevel.PARTIAL_COMPLETE,
92            notes = "Verifies the get(String, X) methods with valid arguments.",
93            method = "get",
94            args = {java.lang.String.class, char.class}
95        ),
96        @TestTargetNew(
97            level = TestLevel.PARTIAL_COMPLETE,
98            notes = "Verifies the get(String, X) methods with valid arguments.",
99            method = "get",
100            args = {java.lang.String.class, double.class}
101        ),
102        @TestTargetNew(
103            level = TestLevel.PARTIAL_COMPLETE,
104            notes = "Verifies the get(String, X) methods with valid arguments.",
105            method = "get",
106            args = {java.lang.String.class, float.class}
107        ),
108        @TestTargetNew(
109            level = TestLevel.PARTIAL_COMPLETE,
110            notes = "Verifies the get(String, X) methods with valid arguments.",
111            method = "get",
112            args = {java.lang.String.class, int.class}
113        ),
114        @TestTargetNew(
115            level = TestLevel.PARTIAL_COMPLETE,
116            notes = "Verifies the get(String, X) methods with valid arguments.",
117            method = "get",
118            args = {java.lang.String.class, long.class}
119        ),
120        @TestTargetNew(
121            level = TestLevel.PARTIAL_COMPLETE,
122            notes = "Verifies the get(String, X) methods with valid arguments.",
123            method = "get",
124            args = {java.lang.String.class, java.lang.Object.class}
125        ),
126        @TestTargetNew(
127            level = TestLevel.PARTIAL_COMPLETE,
128            notes = "Verifies the get(String, X) methods with valid arguments.",
129            method = "get",
130            args = {java.lang.String.class, short.class}
131        )
132    })
133    public void test_get() throws Exception {
134
135        initOis(FILENAME);
136        Support_GetPutFields object = (Support_GetPutFields) ois.readObject();
137        Support_GetPutFields newObject = new Support_GetPutFields();
138        newObject.initTestValues();
139
140        assertTrue("Test 1: The object read from the reference file does " +
141                   "not match a locally created instance of the same class.",
142                   object.equals(newObject));
143
144        initOis(DEFAULTED_FILENAME);
145        Support_GetPutFieldsDefaulted defaulted =
146                (Support_GetPutFieldsDefaulted) ois.readObject();
147        Support_GetPutFieldsDefaulted newDefaulted =
148                new Support_GetPutFieldsDefaulted();
149        newDefaulted.initTestValues();
150
151        assertTrue("Test 2: The object read from the reference file does " +
152                   "not match a locally created instance of the same class.",
153                   defaulted.equals(newDefaulted));
154
155        // Executing the same procedure against the file created with the
156        // deprecated ObjectOutputStream.PutFields.write(ObjectOutput) method
157        // is not possible since there is no corresponding read(ObjectInput)
158        // method. When trying to do it as in tests 1 and 2, a
159        // NullPointerException is thrown.
160    }
161
162
163    @TestTargetNew(
164        level = TestLevel.COMPLETE,
165        notes = "Verifies defaulted(String).",
166        method = "defaulted",
167        args = {java.lang.String.class}
168    )
169    public void test_defaultedLjava_lang_String() throws Exception {
170
171        initOis(FILENAME);
172        Support_GetPutFields object = (Support_GetPutFields) ois.readObject();
173        ObjectInputStream.GetField fields = object.getField;
174
175        try {
176            fields.defaulted("noField");
177            fail("IllegalArgumentException expected.");
178        } catch (IllegalArgumentException e) {}
179
180        assertFalse("The field longValue should not be defaulted.",
181                   fields.defaulted("longValue"));
182
183        // Now the same with defaulted fields.
184        initOis(DEFAULTED_FILENAME);
185        Support_GetPutFieldsDefaulted defaultedObject =
186            (Support_GetPutFieldsDefaulted) ois.readObject();
187        fields = defaultedObject.getField;
188
189        assertTrue("The field longValue should be defaulted.",
190                   fields.defaulted("longValue"));
191
192    }
193
194
195    @TestTargets({
196        @TestTargetNew(
197            level = TestLevel.PARTIAL_COMPLETE,
198            notes = "Verifies the get(String, X) methods with invalid arguments.",
199            method = "get",
200            args = {java.lang.String.class, boolean.class}
201        ),
202        @TestTargetNew(
203            level = TestLevel.PARTIAL_COMPLETE,
204            notes = "Verifies the get(String, X) methods with invalid arguments.",
205            method = "get",
206            args = {java.lang.String.class, byte.class}
207        ),
208        @TestTargetNew(
209            level = TestLevel.PARTIAL_COMPLETE,
210            notes = "Verifies the get(String, X) methods with invalid arguments.",
211            method = "get",
212            args = {java.lang.String.class, char.class}
213        ),
214        @TestTargetNew(
215            level = TestLevel.PARTIAL_COMPLETE,
216            notes = "Verifies the get(String, X) methods with invalid arguments.",
217            method = "get",
218            args = {java.lang.String.class, double.class}
219        ),
220        @TestTargetNew(
221            level = TestLevel.PARTIAL_COMPLETE,
222            notes = "Verifies the get(String, X) methods with invalid arguments.",
223            method = "get",
224            args = {java.lang.String.class, float.class}
225        ),
226        @TestTargetNew(
227            level = TestLevel.PARTIAL_COMPLETE,
228            notes = "Verifies the get(String, X) methods with invalid arguments.",
229            method = "get",
230            args = {java.lang.String.class, int.class}
231        ),
232        @TestTargetNew(
233            level = TestLevel.PARTIAL_COMPLETE,
234            notes = "Verifies the get(String, X) methods with invalid arguments.",
235            method = "get",
236            args = {java.lang.String.class, long.class}
237        ),
238        @TestTargetNew(
239            level = TestLevel.PARTIAL_COMPLETE,
240            notes = "Verifies the get(String, X) methods with invalid arguments.",
241            method = "get",
242            args = {java.lang.String.class, java.lang.Object.class}
243        ),
244        @TestTargetNew(
245            level = TestLevel.PARTIAL_COMPLETE,
246            notes = "Verifies the get(String, X) methods with invalid arguments.",
247            method = "get",
248            args = {java.lang.String.class, short.class}
249        )
250    })
251    public void test_getException() throws Exception {
252
253        initOis(FILENAME);
254        Support_GetPutFields object = (Support_GetPutFields) ois.readObject();
255        ObjectInputStream.GetField fields = object.getField;
256
257        // Methods called with invalid field name.
258        try {
259            fields.get("noValue", false);
260            fail("IllegalArgumentException expected for not existing name " +
261                 "argument in get(String, boolean).");
262        } catch (IllegalArgumentException e) {}
263
264        try {
265            fields.get("noValue", (byte) 0);
266            fail("IllegalArgumentException expected for not existing name " +
267                 "argument in get(String, byte).");
268        } catch (IllegalArgumentException e) {}
269
270        try {
271            fields.get("noValue", (char) 0);
272            fail("IllegalArgumentException expected for not existing name " +
273                 "argument in get(String, char).");
274        } catch (IllegalArgumentException e) {}
275
276        try {
277            fields.get("noValue", 0.0);
278            fail("IllegalArgumentException expected for not existing name " +
279                 "argument in get(String, double).");
280        } catch (IllegalArgumentException e) {}
281
282        try {
283            fields.get("noValue", 0.0f);
284            fail("IllegalArgumentException expected for not existing name " +
285                 "argument in get(String, float).");
286        } catch (IllegalArgumentException e) {}
287
288        try {
289            fields.get("noValue", (long) 0);
290            fail("IllegalArgumentException expected for not existing name " +
291                 "argument in get(String, long).");
292        } catch (IllegalArgumentException e) {}
293
294        try {
295            fields.get("noValue", 0);
296            fail("IllegalArgumentException expected for not existing name " +
297                 "argument in get(String, int).");
298        } catch (IllegalArgumentException e) {}
299
300        try {
301            fields.get("noValue", new Object());
302            fail("IllegalArgumentException expected for not existing name " +
303                 "argument in get(String, Object).");
304        } catch (IllegalArgumentException e) {}
305
306        try {
307            fields.get("noValue", (short) 0);
308            fail("IllegalArgumentException expected for not existing name " +
309                 "argument in get(String, short).");
310        } catch (IllegalArgumentException e) {}
311
312        // Methods called with correct field name but non-matching type.
313        try {
314            fields.get("byteValue", false);
315            fail("IllegalArgumentException expected for non-matching name " +
316                 "and type arguments in get(String, boolean).");
317        } catch (IllegalArgumentException e) {}
318
319        try {
320            fields.get("booleanValue", (byte) 0);
321            fail("IllegalArgumentException expected for non-matching name " +
322                 "and type arguments in get(String, byte).");
323        } catch (IllegalArgumentException e) {}
324
325        try {
326            fields.get("intValue", (char) 0);
327            fail("IllegalArgumentException expected for non-matching name " +
328                 "and type arguments in get(String, char).");
329        } catch (IllegalArgumentException e) {}
330
331        try {
332            fields.get("floatValue", 0.0);
333            fail("IllegalArgumentException expected for non-matching name " +
334                 "and type arguments in get(String, double).");
335        } catch (IllegalArgumentException e) {}
336
337        try {
338            fields.get("doubleValue", 0.0f);
339            fail("IllegalArgumentException expected for non-matching name " +
340                 "and type arguments in get(String, float).");
341        } catch (IllegalArgumentException e) {}
342
343        try {
344            fields.get("intValue", (long) 0);
345            fail("IllegalArgumentException expected for non-matching name " +
346                 "and type arguments in get(String, long).");
347        } catch (IllegalArgumentException e) {}
348
349        try {
350            fields.get("shortValue", 0);
351            fail("IllegalArgumentException expected for non-matching name " +
352                 "and type arguments in get(String, int).");
353        } catch (IllegalArgumentException e) {}
354
355        try {
356            fields.get("booleanValue", new Object());
357            fail("IllegalArgumentException expected for non-matching name " +
358                 "and type arguments in get(String, Object).");
359        } catch (IllegalArgumentException e) {}
360
361        try {
362            fields.get("longValue", (short) 0);
363            fail("IllegalArgumentException expected for non-matching name " +
364                 "and type arguments in get(String, short).");
365        } catch (IllegalArgumentException e) {}
366    }
367
368
369    @TestTargetNew(
370        level = TestLevel.COMPLETE,
371        notes = "Verifies that getObjectStreamClass() does not return null.",
372        method = "getObjectStreamClass",
373        args = {}
374    )
375    public void test_getObjectStreamClass() throws Exception {
376
377        initOis(FILENAME);
378        Support_GetPutFields object = (Support_GetPutFields) ois.readObject();
379        assertNotNull("Return value of getObjectStreamClass() should not be null.",
380                      object.getField.getObjectStreamClass());
381    }
382
383
384    private void initOis(String fileName) throws Exception {
385        if (ois != null) {
386            ois.close();
387        }
388        ois = new ObjectInputStream(
389                    getClass().getResourceAsStream(fileName));
390    }
391
392    protected void tearDown() throws Exception {
393
394        if (ois != null) {
395            ois.close();
396        }
397        super.tearDown();
398    }
399
400}
401