1 /*
2  * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /* @test
25  * @bug 4400571
26  * @summary Verify that ObjectInputStream.available() functions properly when
27  *          called at the beginning of a data block, and that it does not
28  *          attempt any read operations that may potentially block.
29  */
30 
31 import java.io.*;
32 
33 public class Available {
main(String[] args)34     public static void main(String[] args) throws Exception {
35         ObjectOutputStream oout;
36         ByteArrayOutputStream bout;
37         byte[] buf;
38 
39         // write stream containing short data block
40         oout = new ObjectOutputStream(bout = new ByteArrayOutputStream());
41         oout.write(new byte[100]);
42         oout.close();
43         buf = bout.toByteArray();
44 
45         // 4 byte stream header + 2 byte block header + data
46         if ((getAvailable(buf, 4) != 0) || (getAvailable(buf, 5) != 0)) {
47             throw new Error();
48         }
49         for (int i = 0; i < 100; i++) {
50             if (getAvailable(buf, 6 + i) != i) {
51                 throw new Error();
52             }
53         }
54 
55         // write stream containing long data block
56         oout = new ObjectOutputStream(bout = new ByteArrayOutputStream());
57         oout.write(new byte[500]);
58         oout.close();
59         buf = bout.toByteArray();
60 
61         // 4 byte stream header + 5 byte block header + data
62         for (int i = 4; i < 9; i++) {
63             if (getAvailable(buf, i) != 0) {
64                 throw new Error();
65             }
66         }
67         for (int i = 0; i < 500; i++) {
68             if (getAvailable(buf, 9 + i) != i) {
69                 throw new Error();
70             }
71         }
72     }
73 
74     /**
75      * Given a byte array containing a serialized stream, creates a copy of the
76      * given data truncated to the specified length, then returns the result of
77      * a call to available() on an ObjectInputStream created on top of the
78      * truncated data.  As a side effect, a StreamCorrupted or EOFException
79      * will get thrown if the available() call attempts to read past the
80      * underlying stream's available data.
81      */
getAvailable(byte[] data, int truncateLen)82     static int getAvailable(byte[] data, int truncateLen) throws IOException {
83         byte[] trunc = new byte[truncateLen];
84         System.arraycopy(data, 0, trunc, 0, truncateLen);
85         return new ObjectInputStream(
86             new ByteArrayInputStream(trunc)).available();
87     }
88 }
89