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
20
21import java.io.ByteArrayInputStream;
22import java.io.IOException;
23import java.io.InputStream;
24import java.io.SequenceInputStream;
25import java.util.Enumeration;
26
27import tests.support.Support_ASimpleInputStream;
28import dalvik.annotation.TestLevel;
29import dalvik.annotation.TestTargetClass;
30import dalvik.annotation.TestTargetNew;
31
32@TestTargetClass(SequenceInputStream.class)
33public class SequenceInputStreamTest extends junit.framework.TestCase {
34
35    Support_ASimpleInputStream simple1, simple2;
36    SequenceInputStream si;
37    String s1 = "Hello";
38    String s2 = "World";
39
40    /**
41     * @tests SequenceInputStream#SequenceInputStream(java.io.InputStream,
42     *        java.io.InputStream)
43     */
44    @TestTargetNew(
45        level = TestLevel.SUFFICIENT,
46        notes = "Checks NullPointerException. A positive test of this " +
47                "constructor is implicitely done in setUp(); if it would " +
48                "fail, all other tests will also fail.",
49        method = "SequenceInputStream",
50        args = {java.io.InputStream.class, java.io.InputStream.class}
51    )
52    public void test_Constructor_LInputStreamLInputStream_Null() {
53        try {
54            si = new SequenceInputStream(null , null);
55            fail("Test 1: NullPointerException expected.");
56        } catch (NullPointerException e) {
57            // Expected.
58        }
59
60        //will not throw NullPointerException if the first InputStream is not null
61        InputStream is = new ByteArrayInputStream(s1.getBytes());
62        si = new SequenceInputStream(is , null);
63    }
64
65    /**
66     * @tests java.io.SequenceInputStream#SequenceInputStream(java.util.Enumeration)
67     */
68    @TestTargetNew(
69        level = TestLevel.COMPLETE,
70        notes = "",
71        method = "SequenceInputStream",
72        args = {java.util.Enumeration.class}
73    )
74    public void test_ConstructorLjava_util_Enumeration() {
75        // Test for method java.io.SequenceInputStream(java.util.Enumeration)
76        class StreamEnumerator implements Enumeration<InputStream> {
77            InputStream streams[] = new InputStream[2];
78
79            int count = 0;
80
81            public StreamEnumerator() {
82                streams[0] = new ByteArrayInputStream(s1.getBytes());
83                streams[1] = new ByteArrayInputStream(s2.getBytes());
84            }
85
86            public boolean hasMoreElements() {
87                return count < streams.length;
88            }
89
90            public InputStream nextElement() {
91                return streams[count++];
92            }
93        }
94
95        try {
96            si = new SequenceInputStream(new StreamEnumerator());
97            byte buf[] = new byte[s1.length() + s2.length()];
98            si.read(buf, 0, s1.length());
99            si.read(buf, s1.length(), s2.length());
100            assertTrue("Read incorrect bytes: " + new String(buf), new String(
101                    buf).equals(s1 + s2));
102        } catch (IOException e) {
103            fail("IOException during read test : " + e.getMessage());
104        }
105
106    }
107
108    /**
109     * @throws IOException
110     * @tests java.io.SequenceInputStream#available()
111     */
112    @TestTargetNew(
113        level = TestLevel.COMPLETE,
114        notes = "",
115        method = "available",
116        args = {}
117    )
118    public void test_available() throws IOException {
119        assertEquals("Returned incorrect number of bytes!", s1.length(), si.available());
120        simple2.throwExceptionOnNextUse = true;
121        assertTrue("IOException on second stream should not affect at this time!",
122                si.available() == s1.length());
123        simple1.throwExceptionOnNextUse = true;
124        try {
125            si.available();
126            fail("IOException not thrown!");
127        } catch (IOException e) {
128            // expected
129        }
130    }
131
132    /**
133     * @tests java.io.SequenceInputStream#close()
134     */
135    @TestTargetNew(
136        level = TestLevel.PARTIAL_COMPLETE,
137        notes = "",
138        method = "close",
139        args = {}
140    )
141    public void test_close() throws IOException {
142        assertTrue("Something is available!", si.available() > 0);
143        si.close();
144        //will not throw IOException to close a stream which is closed already
145        si.close();
146        assertTrue("Nothing is available, now!", si.available() <= 0);
147//        assertEquals("And not on the underlying streams either!", 0, simple1.available());
148//        assertTrue("And not on the underlying streams either!", simple1.available() <= 0);
149//        assertTrue("And not on the underlying streams either!", simple2.available() <= 0);
150    }
151
152    /**
153     * @tests java.io.SequenceInputStream#close()
154     */
155    @TestTargetNew(
156        level = TestLevel.PARTIAL_COMPLETE,
157        notes = "",
158        method = "close",
159        args = {}
160    )
161    public void test_close2() throws IOException {
162        simple1.throwExceptionOnNextUse = true;
163        try {
164            si.close();
165            fail("IOException not thrown!");
166        } catch (IOException e) {
167            // expected
168        }
169    }
170
171    /**
172     * @tests java.io.SequenceInputStream#read()
173     */
174    @TestTargetNew(
175        level = TestLevel.COMPLETE,
176        notes = "",
177        method = "read",
178        args = {}
179    )
180    public void test_read() throws IOException {
181        si.read();
182        assertEquals("Test 1: Incorrect char read;",
183                s1.charAt(1), (char) si.read());
184
185        // We are still reading from the first input stream, should be ok.
186        simple2.throwExceptionOnNextUse = true;
187        try {
188            assertEquals("Test 2: Incorrect char read;",
189                    s1.charAt(2), (char) si.read());
190        } catch (IOException e) {
191            fail("Test 3: Unexpected IOException.");
192        }
193
194        simple1.throwExceptionOnNextUse = true;
195        try {
196            si.read();
197            fail("Test 4: IOException expected.");
198        } catch (IOException e) {
199            // Expected.
200        }
201        simple1.throwExceptionOnNextUse = false;
202
203        // Reading bytes 4 and 5 of the first input stream should be ok again.
204        si.read();
205        si.read();
206
207        // Reading the first byte of the second input stream should fail.
208        try {
209            si.read();
210            fail("Test 5: IOException expected.");
211        } catch (IOException e) {
212            // Expected.
213        }
214
215        // Reading from the second input stream should be ok now.
216        simple2.throwExceptionOnNextUse = false;
217        try {
218            assertEquals("Test 6: Incorrect char read;",
219                    s2.charAt(0), (char) si.read());
220        } catch (IOException e) {
221            fail("Test 7: Unexpected IOException.");
222        }
223
224        si.close();
225        assertTrue("Test 8: -1 expected when reading from a closed " +
226                   "sequence input stream.", si.read() == -1);
227    }
228
229    @TestTargetNew(
230        level = TestLevel.PARTIAL_COMPLETE,
231        notes = "",
232        method = "read",
233        args = {byte[].class, int.class, int.class}
234    )
235    public void test_read_exc() throws IOException {
236        simple2.throwExceptionOnNextUse = true;
237        assertEquals("IOException on second stream should not affect at this time!", 72, si.read());
238        simple1.throwExceptionOnNextUse = true;
239        try {
240            si.read();
241            fail("IOException not thrown!");
242        } catch (IOException e) {
243            // expected
244        }
245    }
246
247    /**
248     * @tests java.io.SequenceInputStream#read(byte[], int, int)
249     */
250    @TestTargetNew(
251        level = TestLevel.PARTIAL_COMPLETE,
252        notes = "",
253        method = "read",
254        args = {byte[].class, int.class, int.class}
255    )
256    public void test_read$BII() throws IOException {
257        // Test for method int java.io.SequenceInputStream.read(byte [], int,
258        // int)
259        try {
260            byte buf[] = new byte[s1.length() + s2.length()];
261            si.read(buf, 0, s1.length());
262            si.read(buf, s1.length(), s2.length());
263            assertTrue("Read incorrect bytes: " + new String(buf), new String(
264                    buf).equals(s1 + s2));
265        } catch (IOException e) {
266            fail("IOException during read test : " + e.getMessage());
267        }
268
269        ByteArrayInputStream bis1 = new ByteArrayInputStream(
270                new byte[] { 1, 2, 3, 4 });
271        ByteArrayInputStream bis2 = new ByteArrayInputStream(
272                new byte[] { 5, 6, 7, 8 });
273        SequenceInputStream sis = new SequenceInputStream(bis1, bis2);
274
275        try {
276            sis.read(null, 0, 2);
277            fail("Expected NullPointerException exception");
278        } catch (NullPointerException e) {
279            // expected
280        }
281
282        assertEquals(4, sis.read(new byte[10], 0, 8));
283        // The call to read will return after the end of the first substream is
284        // reached. So the next call to read will close the first substream
285        // because the read call to that substream will return -1, and
286        // it will continue reading from the second substream.
287        assertEquals(5, sis.read());
288
289        //returns -1 if the stream is closed , do not throw IOException
290        byte[] array = new byte[] { 1 , 2 , 3 ,4 };
291        sis.close();
292        int result = sis.read(array , 0 , 5);
293        assertEquals(-1 , result);
294    }
295
296    @TestTargetNew(
297        level = TestLevel.PARTIAL_COMPLETE,
298        notes = "",
299        method = "read",
300        args = {byte[].class, int.class, int.class}
301    )
302    public void test_read$BII_Excpetion() throws IOException {
303        byte[] buf = new byte[4];
304        si.read(buf, 0, 2);
305        si.read(buf, 2, 1);
306        simple2.throwExceptionOnNextUse = true;
307        si.read(buf, 3, 1);
308        assertEquals("Wrong stuff read!", "Hell", new String(buf));
309        simple1.throwExceptionOnNextUse = true;
310        try {
311            si.read(buf, 3, 1);
312            fail("IOException not thrown!");
313        } catch (IOException e) {
314            // expected
315        }
316
317        buf = new byte[10];
318        simple1 = new Support_ASimpleInputStream(s1);
319        simple2 = new Support_ASimpleInputStream(s2);
320        si = new SequenceInputStream(simple1, simple2);
321        try {
322            si.read(buf, -1, 1);
323            fail("IndexOutOfBoundsException was not thrown");
324        } catch (IndexOutOfBoundsException e) {
325            // Expected
326        }
327        try {
328            si.read(buf, 0, -1);
329            fail("IndexOutOfBoundsException was not thrown");
330        } catch (IndexOutOfBoundsException e) {
331            // Expected
332        }
333        try {
334            si.read(buf, 1, 10);
335            fail("IndexOutOfBoundsException was not thrown");
336        } catch (IndexOutOfBoundsException e) {
337            // Expected
338        }
339    }
340
341    /**
342     * Sets up the fixture, for example, open a network connection. This method
343     * is called before a test is executed.
344     */
345    protected void setUp() {
346        simple1 = new Support_ASimpleInputStream(s1);
347        simple2 = new Support_ASimpleInputStream(s2);
348        si = new SequenceInputStream(simple1, simple2);
349    }
350
351    /**
352     * Tears down the fixture, for example, close a network connection. This
353     * method is called after a test is executed.
354     */
355    protected void tearDown() {
356    }
357}
358