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 java.io.BufferedInputStream;
21import java.io.ByteArrayInputStream;
22import java.io.File;
23import java.io.FileInputStream;
24import java.io.FileOutputStream;
25import java.io.IOException;
26import java.io.InputStream;
27import java.io.OutputStream;
28
29import junit.framework.TestCase;
30import tests.support.Support_ASimpleInputStream;
31import tests.support.Support_PlatformFile;
32import dalvik.annotation.TestLevel;
33import dalvik.annotation.TestTargetClass;
34import dalvik.annotation.TestTargetNew;
35import dalvik.annotation.TestTargets;
36
37@TestTargetClass(BufferedInputStream.class)
38public class BufferedInputStreamTest extends TestCase {
39
40    public String fileName;
41
42    private BufferedInputStream is;
43
44    private FileInputStream isFile;
45
46    byte[] ibuf = new byte[4096];
47
48    public String fileString = "Test_All_Tests\nTest_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\nTest_java_io_File\nTest_java_io_FileDescriptor\nTest_java_io_FileInputStream\nTest_java_io_FileNotFoundException\nTest_java_io_FileOutputStream\nTest_java_io_FilterInputStream\nTest_java_io_FilterOutputStream\nTest_java_io_InputStream\nTest_java_io_IOException\nTest_java_io_OutputStream\nTest_java_io_PrintStream\nTest_java_io_RandomAccessFile\nTest_java_io_SyncFailedException\nTest_java_lang_AbstractMethodError\nTest_java_lang_ArithmeticException\nTest_java_lang_ArrayIndexOutOfBoundsException\nTest_java_lang_ArrayStoreException\nTest_java_lang_Boolean\nTest_java_lang_Byte\nTest_java_lang_Character\nTest_java_lang_Class\nTest_java_lang_ClassCastException\nTest_java_lang_ClassCircularityError\nTest_java_lang_ClassFormatError\nTest_java_lang_ClassLoader\nTest_java_lang_ClassNotFoundException\nTest_java_lang_CloneNotSupportedException\nTest_java_lang_Double\nTest_java_lang_Error\nTest_java_lang_Exception\nTest_java_lang_ExceptionInInitializerError\nTest_java_lang_Float\nTest_java_lang_IllegalAccessError\nTest_java_lang_IllegalAccessException\nTest_java_lang_IllegalArgumentException\nTest_java_lang_IllegalMonitorStateException\nTest_java_lang_IllegalThreadStateException\nTest_java_lang_IncompatibleClassChangeError\nTest_java_lang_IndexOutOfBoundsException\nTest_java_lang_InstantiationError\nTest_java_lang_InstantiationException\nTest_java_lang_Integer\nTest_java_lang_InternalError\nTest_java_lang_InterruptedException\nTest_java_lang_LinkageError\nTest_java_lang_Long\nTest_java_lang_Math\nTest_java_lang_NegativeArraySizeException\nTest_java_lang_NoClassDefFoundError\nTest_java_lang_NoSuchFieldError\nTest_java_lang_NoSuchMethodError\nTest_java_lang_NullPointerException\nTest_java_lang_Number\nTest_java_lang_NumberFormatException\nTest_java_lang_Object\nTest_java_lang_OutOfMemoryError\nTest_java_lang_RuntimeException\nTest_java_lang_SecurityManager\nTest_java_lang_Short\nTest_java_lang_StackOverflowError\nTest_java_lang_String\nTest_java_lang_StringBuffer\nTest_java_lang_StringIndexOutOfBoundsException\nTest_java_lang_System\nTest_java_lang_Thread\nTest_java_lang_ThreadDeath\nTest_java_lang_ThreadGroup\nTest_java_lang_Throwable\nTest_java_lang_UnknownError\nTest_java_lang_UnsatisfiedLinkError\nTest_java_lang_VerifyError\nTest_java_lang_VirtualMachineError\nTest_java_lang_vm_Image\nTest_java_lang_vm_MemorySegment\nTest_java_lang_vm_ROMStoreException\nTest_java_lang_vm_VM\nTest_java_lang_Void\nTest_java_net_BindException\nTest_java_net_ConnectException\nTest_java_net_DatagramPacket\nTest_java_net_DatagramSocket\nTest_java_net_DatagramSocketImpl\nTest_java_net_InetAddress\nTest_java_net_NoRouteToHostException\nTest_java_net_PlainDatagramSocketImpl\nTest_java_net_PlainSocketImpl\nTest_java_net_Socket\nTest_java_net_SocketException\nTest_java_net_SocketImpl\nTest_java_net_SocketInputStream\nTest_java_net_SocketOutputStream\nTest_java_net_UnknownHostException\nTest_java_util_ArrayEnumerator\nTest_java_util_Date\nTest_java_util_EventObject\nTest_java_util_HashEnumerator\nTest_java_util_Hashtable\nTest_java_util_Properties\nTest_java_util_ResourceBundle\nTest_java_util_tm\nTest_java_util_Vector\n";
49
50    /**
51     * @throws IOException
52     * @tests java.io.BufferedInputStream#BufferedInputStream(java.io.InputStream,
53     *        int)
54     */
55    @TestTargetNew(
56        level = TestLevel.COMPLETE,
57        method = "BufferedInputStream",
58        args = {java.io.InputStream.class}
59    )
60    public void test_ConstructorLjava_io_InputStream() {
61        is = new BufferedInputStream(isFile);
62
63        try {
64            is.read();
65        } catch (Exception e) {
66            fail("Test 1: Read failed on a freshly constructed buffer.");
67        }
68    }
69
70    /**
71     * @throws IOException
72     * @tests java.io.BufferedInputStream#BufferedInputStream(java.io.InputStream,
73     *        int)
74     */
75    @TestTargetNew(
76        level = TestLevel.COMPLETE,
77        method = "BufferedInputStream",
78        args = {java.io.InputStream.class, int.class}
79    )
80    public void test_ConstructorLjava_io_InputStreamI() throws IOException {
81        // Test for method java.io.BufferedInputStream(java.io.InputStream, int)
82        boolean exceptionFired = false;
83
84        try {
85            is = new BufferedInputStream(isFile, -1);
86            fail("IllegalArgumentException expected.");
87        } catch (IllegalArgumentException e) {
88            // Expected.
89        }
90
91        try {
92            // Create buffer with exact size of file
93            is = new BufferedInputStream(isFile, this.fileString
94                    .length());
95            // Ensure buffer gets filled by evaluating one read
96            is.read();
97            // Close underlying FileInputStream, all but 1 buffered bytes should
98            // still be available.
99            isFile.close();
100            // Read the remaining buffered characters, no IOException should
101            // occur.
102            is.skip(this.fileString.length() - 2);
103            is.read();
104            try {
105                // is.read should now throw an exception because it will have to
106                // be filled.
107                is.read();
108            } catch (IOException e) {
109                exceptionFired = true;
110            }
111            assertTrue("Exception should have been triggered by read()",
112                    exceptionFired);
113        } catch (IOException e) {
114            fail("Exception during test_1_Constructor");
115        }
116
117        // regression test for harmony-2407
118        new testBufferedInputStream(null);
119        assertNotNull(testBufferedInputStream.buf);
120        testBufferedInputStream.buf = null;
121        new testBufferedInputStream(null, 100);
122        assertNotNull(testBufferedInputStream.buf);
123    }
124
125    static class testBufferedInputStream extends BufferedInputStream {
126        static byte[] buf;
127        testBufferedInputStream(InputStream is) throws IOException {
128            super(is);
129            buf = super.buf;
130        }
131
132        testBufferedInputStream(InputStream is, int size) throws IOException {
133            super(is, size);
134            buf = super.buf;
135        }
136    }
137
138    /**
139     * @tests java.io.BufferedInputStream#available()
140     */
141    @TestTargetNew(
142        level = TestLevel.COMPLETE,
143        notes = "Verifies the available() method.",
144        method = "available",
145        args = {}
146    )
147    public void test_available() {
148        // Test for method int java.io.BufferedInputStream.available()
149        try {
150            assertTrue("Returned incorrect number of available bytes", is
151                    .available() == fileString.length());
152        } catch (IOException e) {
153            fail("Exception during available test");
154        }
155
156        // Test that a closed stream throws an IOE for available()
157        BufferedInputStream bis = new BufferedInputStream(
158                new ByteArrayInputStream(new byte[] { 'h', 'e', 'l', 'l', 'o',
159                        ' ', 't', 'i', 'm' }));
160        int available = 0;
161        try {
162            available = bis.available();
163            bis.close();
164        } catch (IOException ex) {
165            fail();
166        }
167        assertTrue(available != 0);
168
169        try {
170            bis.available();
171            fail("Expected test to throw IOE.");
172        } catch (IOException ex) {
173            // expected
174        } catch (Throwable ex) {
175            fail("Expected test to throw IOE not "
176                    + ex.getClass().getName());
177        }
178    }
179
180    /**
181     * @throws IOException
182     * @tests java.io.BufferedInputStream#close()
183     */
184    @TestTargetNew(
185        level = TestLevel.COMPLETE,
186        method = "close",
187        args = {}
188    )
189    public void test_close() throws IOException {
190        is.close();
191
192        try {
193            is.read();
194            fail("Test 1: IOException expected when reading after closing " +
195                 "the stream.");
196        } catch (IOException e) {
197            // Expected.
198        }
199
200        Support_ASimpleInputStream sis = new Support_ASimpleInputStream(true);
201        is = new BufferedInputStream(sis);
202        try {
203            is.close();
204            fail("Test 2: IOException expected.");
205        } catch (IOException e) {
206            // Expected.
207        }
208        sis.throwExceptionOnNextUse = false;
209    }
210
211    /**
212     * @tests java.io.BufferedInputStream#mark(int)
213     */
214    @TestTargets({
215        @TestTargetNew(
216                level = TestLevel.COMPLETE,
217                method = "mark",
218                args = {int.class}
219        ),
220        @TestTargetNew(
221                level = TestLevel.COMPLETE,
222                method = "reset",
223                args = {}
224        ) /* ,
225        @TestTargetNew(
226                level = TestLevel.PARTIAL_COMPLETE,
227                notes = "Checks that a marked position is invalidated.",
228                method = "read",
229                args = {}
230        ),
231        @TestTargetNew(
232                level = TestLevel.PARTIAL_COMPLETE,
233                notes = "Checks that a marked position is invalidated.",
234                method = "read",
235                args = {byte[].class, int.class, int.class}
236        ),
237        @TestTargetNew(
238                level = TestLevel.PARTIAL_COMPLETE,
239                notes = "Checks that a marked position is invalidated.",
240                method = "skip",
241                args = {long.class}
242        )    */
243    })
244    public void test_markI_reset() throws IOException {
245        byte[] buf1 = new byte[100];
246        byte[] buf2 = new byte[100];
247
248        // Test 1: Check that reset fails if no mark has been set.
249        try {
250            is.reset();
251            fail("Test 1: IOException expected if no mark has been set.");
252        } catch (IOException e) {
253            // Expected.
254        }
255
256        // Test 2: Check that mark / reset works when the mark is not invalidated.
257        is.skip(10);
258        is.mark(100);
259        is.read(buf1, 0, buf1.length);
260        is.reset();
261        is.read(buf2, 0, buf2.length);
262        is.reset();
263        assertTrue("Test 2: Failed to mark correct position or reset failed.",
264                new String(buf1, 0, buf1.length).equals(new String(buf2, 0, buf2.length)));
265
266        // Tests 3 and 4: Check that skipping less than readlimit bytes does
267        // not invalidate the mark.
268        is.skip(10);
269        try {
270            is.reset();
271        } catch (IOException e) {
272            fail("Test 3: Unexpected IOException " + e.getMessage());
273        }
274        is.read(buf2, 0, buf2.length);
275        is.reset();
276        assertTrue("Test 4: Failed to mark correct position, or reset failed.",
277                new String(buf1, 0, buf1.length).equals(new String(buf2, 0, buf2.length)));
278
279/* Tests disabled because they fail. The specification is ambiguous
280 * regarding the invalidation of a set mark by read and skip operations.
281
282        // Test 5: Check that the mark is invalidated by a sequence of reads.
283        is.skip(200);
284        is.mark(10);
285        for (int i = 0; i < 11; i++) {
286            is.read();
287        }
288        try {
289            is.reset();
290            fail("Test 5: IOException expected because the mark should be invalid.");
291        } catch (IOException e) {
292            // Expected.
293        }
294
295        // Test 6: Check that the mark is invalidated by a buffer read.
296        is.skip(200);
297        is.mark(10);
298        is.read(buf1, 0, buf1.length);
299        try {
300            is.reset();
301            fail("Test 6: IOException expected because the mark should be invalid.");
302        } catch (IOException e) {
303            // Expected.
304        }
305
306        // Test 7: Check that the mark is invalidated by a skip.
307        is.mark(10);
308        is.skip(11);
309        try {
310            is.reset();
311            fail("Test 7: IOException expected because the mark should be invalid.");
312        } catch (IOException e) {
313            // Expected.
314        }
315*/
316
317        // Test 8: Check that reset fails for a closed input stream.
318        is.close();
319        try {
320            is.reset();
321            fail("Test 8: IOException expected because the input stream is closed.");
322        } catch (IOException e) {
323            // Expected.
324        }
325    }
326
327    /**
328     * @tests java.io.BufferedInputStream#markSupported()
329     */
330    @TestTargetNew(
331        level = TestLevel.COMPLETE,
332        notes = "Verifies markSupported() method.",
333        method = "markSupported",
334        args = {}
335    )
336    public void test_markSupported() {
337        // Test for method boolean java.io.BufferedInputStream.markSupported()
338        assertTrue("markSupported returned incorrect value", is.markSupported());
339    }
340
341    /**
342     * @tests java.io.BufferedInputStream#read()
343     */
344    @TestTargetNew(
345        level = TestLevel.COMPLETE,
346        notes = "A partial read test in test_markI_reset() is disabled at " +
347                "the moment because it fails. If this test is ever " +
348                "enabled, then the level here must be changed to " +
349                "PARTIAL_COMPLETE.",
350        method = "read",
351        args = {}
352    )
353    public void test_read() throws IOException {
354        int c = is.read();
355        assertTrue("Test 1: Incorrect character read.",
356                c == fileString.charAt(0));
357
358        byte[] bytes = new byte[256];
359        for (int i = 0; i < 256; i++) {
360            bytes[i] = (byte) i;
361        }
362
363        BufferedInputStream in = new BufferedInputStream(
364                new ByteArrayInputStream(bytes), 5);
365
366        // Read more bytes than are buffered.
367        for (int i = 0; i < 10; i++) {
368            assertEquals("Test 2: Incorrect byte read;", bytes[i], in.read());
369        }
370
371        in.close();
372        try {
373            in.read();
374            fail("Test 3: IOException expected.");
375        } catch (IOException e) {
376            // Expected.
377        }
378    }
379
380    /**
381     * @tests java.io.BufferedInputStream#read(byte[], int, int)
382     */
383    @TestTargetNew(
384        level = TestLevel.PARTIAL_COMPLETE,
385        notes = "Checks exceptions only.",
386        method = "read",
387        args = {byte[].class, int.class, int.class}
388    )
389    public void test_read$BII_Exception() throws IOException {
390        BufferedInputStream bis = new BufferedInputStream(null);
391
392        try {
393            bis.read(null, -1, -1);
394            fail("should throw NullPointerException");
395        } catch (NullPointerException e) {
396            //expected
397        }
398
399        try {
400            bis.read(new byte[0], -1, -1);
401            fail("should throw IndexOutOfBoundsException");
402        } catch (IndexOutOfBoundsException e) {
403            // Expected
404        }
405
406        try {
407            bis.read(new byte[0], 1, -1);
408            fail("should throw IndexOutOfBoundsException");
409        } catch (IndexOutOfBoundsException e) {
410            // Expected
411        }
412
413        try {
414            bis.read(new byte[0], 1, 1);
415            fail("should throw IndexOutOfBoundsException");
416        } catch (IndexOutOfBoundsException e) {
417            // Expected
418        }
419
420        bis.close();
421
422        try {
423            bis.read(null, -1, -1);
424            fail("should throw IOException");
425        } catch (IOException e) {
426            //expected
427        }
428    }
429
430    /**
431     * @tests java.io.BufferedInputStream#read(byte[], int, int)
432     */
433    @TestTargetNew(
434        level = TestLevel.PARTIAL_COMPLETE,
435        notes = "Functional test.",
436        method = "read",
437        args = {byte[].class, int.class, int.class}
438    )
439    public void test_read$BII() {
440        // Test for method int java.io.BufferedInputStream.read(byte [], int,
441        // int)
442        byte[] buf1 = new byte[100];
443        try {
444            is.skip(3000);
445            is.mark(1000);
446            is.read(buf1, 0, buf1.length);
447            assertTrue("Failed to read correct data", new String(buf1, 0,
448                    buf1.length).equals(fileString.substring(3000, 3100)));
449
450        } catch (IOException e) {
451            fail("Exception during read test");
452        }
453
454        BufferedInputStream bufin = new BufferedInputStream(new InputStream() {
455            int size = 2, pos = 0;
456
457            byte[] contents = new byte[size];
458
459            @Override
460            public int read() throws IOException {
461                if (pos >= size) {
462                    throw new IOException("Read past end of data");
463                }
464                return contents[pos++];
465            }
466
467            @Override
468            public int read(byte[] buf, int off, int len) throws IOException {
469                if (pos >= size) {
470                    throw new IOException("Read past end of data");
471                }
472                int toRead = len;
473                if (toRead > available()) {
474                    toRead = available();
475                }
476                System.arraycopy(contents, pos, buf, off, toRead);
477                pos += toRead;
478                return toRead;
479            }
480
481            @Override
482            public int available() {
483                return size - pos;
484            }
485        });
486        try {
487            bufin.read();
488            int result = bufin.read(new byte[2], 0, 2);
489            assertTrue("Incorrect result: " + result, result == 1);
490        } catch (IOException e) {
491            fail("Unexpected: " + e);
492        }
493    }
494
495    /**
496     * @tests java.io.BufferedInputStream#skip(long)
497     */
498    @TestTargetNew(
499        level = TestLevel.COMPLETE,
500        notes = "Verifies skip(long n) method.",
501        method = "skip",
502        args = {long.class}
503    )
504    public void test_skipJ() {
505        // Test for method long java.io.BufferedInputStream.skip(long)
506        byte[] buf1 = new byte[10];
507        try {
508            is.mark(2000);
509            is.skip(1000);
510            is.read(buf1, 0, buf1.length);
511            is.reset();
512            assertTrue("Failed to skip to correct position", new String(buf1,
513                    0, buf1.length).equals(fileString.substring(1000, 1010)));
514        } catch (IOException e) {
515            fail("Exception during skip test");
516        }
517
518        //regression for HARMONY-667
519        BufferedInputStream buf = new BufferedInputStream(null, 5);
520        try {
521            buf.skip(10);
522            fail("Should throw IOException");
523        } catch (IOException e) {
524            //expected
525        }
526    }
527
528    /**
529     * Sets up the fixture, for example, open a network connection. This method
530     * is called before a test is executed.
531     */
532    @Override
533    protected void setUp() {
534
535        try {
536            fileName = System.getProperty("java.io.tmpdir");
537            String separator = System.getProperty("file.separator");
538            if (fileName.charAt(fileName.length() - 1) == separator.charAt(0)) {
539                fileName = Support_PlatformFile.getNewPlatformFile(fileName,
540                        "input.tst");
541            } else {
542                fileName = Support_PlatformFile.getNewPlatformFile(fileName
543                        + separator, "input.tst");
544            }
545            OutputStream fos = new FileOutputStream(fileName);
546            fos.write(fileString.getBytes());
547            fos.close();
548            isFile = new FileInputStream(fileName);
549            is = new BufferedInputStream(isFile, 1000);
550        } catch (IOException e) {
551            System.out.println("Exception during setup");
552            e.printStackTrace();
553        }
554
555    }
556
557    /**
558     * Tears down the fixture, for example, close a network connection. This
559     * method is called after a test is executed.
560     */
561    @Override
562    protected void tearDown() {
563
564        if (is != null) {
565            try {
566                is.close();
567            } catch (Exception e) {
568                System.out.println("Exception 1 during BIS tearDown: " + e.getMessage());
569            }
570        }
571        try {
572            File f = new File(fileName);
573            f.delete();
574        } catch (Exception e) {
575            System.out.println("Exception 2 during BIS tearDown: " + e.getMessage());
576        }
577    }
578}
579