1 /*
2  * Copyright (c) 2015, 2018, 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 package test.java.io.InputStream;
24 
25 import java.io.ByteArrayInputStream;
26 import java.io.FilterInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.util.Arrays;
30 import java.util.Random;
31 import org.testng.annotations.Test;
32 
33 /*
34  * @test
35  * @bug 8080835 8139206
36  * @library /test/lib
37  * @build jdk.test.lib.RandomFactory
38  * @run main ReadNBytes
39  * @summary Basic test for InputStream.readNBytes
40  * @key randomness
41  */
42 
43 public class ReadNBytes {
44 
45     private static Random generator = new Random();
46 
47     @Test
testReadNBytes()48     public void testReadNBytes() throws IOException {
49         test(new byte[]{1, 2, 3});
50         test(createRandomBytes(1024));
51         for (int shift : new int[] {13, 15, 17}) {
52             for (int offset : new int[] {-1, 0, 1}) {
53                 test(createRandomBytes((1 << shift) + offset));
54             }
55         }
56 
57         test(-1);
58         test(0);
59         for (int shift : new int[] {13, 15, 17}) {
60             for (int offset : new int[] {-1, 0, 1}) {
61                 test((1 << shift) + offset);
62             }
63         }
64     }
65 
test(byte[] inputBytes)66     static void test(byte[] inputBytes) throws IOException {
67         int length = inputBytes.length;
68         WrapperInputStream in = new WrapperInputStream(new ByteArrayInputStream(inputBytes));
69         byte[] readBytes = new byte[(length / 2) + 1];
70         int nread = in.readNBytes(readBytes, 0, readBytes.length);
71 
72         int x;
73         byte[] tmp;
74         check(nread == readBytes.length,
75                 "Expected number of bytes read: " + readBytes.length + ", got: " + nread);
76         check(Arrays.equals((tmp = Arrays.copyOf(inputBytes, nread)), readBytes),
77                 "Expected[" + tmp + "], got:[" + readBytes + "]");
78         check(!in.isClosed(), "Stream unexpectedly closed");
79 
80         // Read again
81         nread = in.readNBytes(readBytes, 0, readBytes.length);
82 
83         check(nread == length - readBytes.length,
84                 "Expected number of bytes read: " + (length - readBytes.length) + ", got: " + nread);
85         check(Arrays.equals((tmp = Arrays.copyOfRange(inputBytes, readBytes.length, length)),
86                 Arrays.copyOf(readBytes, nread)),
87                 "Expected[" + tmp + "], got:[" + readBytes + "]");
88         // Expect end of stream
89         check((x = in.read()) == -1,
90                 "Expected end of stream from read(), got " + x);
91         check((x = in.read(tmp)) == -1,
92                 "Expected end of stream from read(byte[]), got " + x);
93         check((x = in.read(tmp, 0, tmp.length)) == -1,
94                 "Expected end of stream from read(byte[], int, int), got " + x);
95         check((x = in.readNBytes(tmp, 0, tmp.length)) == 0,
96                 "Expected end of stream, 0, from readNBytes(byte[], int, int), got " + x);
97         check(!in.isClosed(), "Stream unexpectedly closed");
98     }
99 
test(int max)100     static void test(int max) throws IOException {
101         byte[] inputBytes = max <= 0 ? new byte[0] : createRandomBytes(max);
102         WrapperInputStream in =
103                 new WrapperInputStream(new ByteArrayInputStream(inputBytes));
104 
105         if (max < 0) {
106             try {
107                 in.readNBytes(max);
108                 check(false, "Expected IllegalArgumentException not thrown");
109             } catch (IllegalArgumentException iae) {
110                 return;
111             }
112         } else if (max == 0) {
113             int x;
114             check((x = in.readNBytes(max).length) == 0,
115                     "Expected zero bytes, got " + x);
116             return;
117         }
118 
119         int off = Math.toIntExact(in.skip(generator.nextInt(max/2)));
120         int len = generator.nextInt(max - 1 - off);
121         byte[] readBytes = in.readNBytes(len);
122         check(readBytes.length == len,
123                 "Expected " + len + " bytes, got " + readBytes.length);
124         check(Arrays.equals(Arrays.copyOfRange(inputBytes, off, off + len), readBytes),
125                 "Expected[" + Arrays.copyOfRange(inputBytes, off, off + len) +
126                         "], got:[" + readBytes + "]");
127 
128         int remaining = max - (off + len);
129         readBytes = in.readNBytes(remaining);
130         check(readBytes.length == remaining,
131                 "Expected " + remaining + "bytes, got " + readBytes.length);
132         check(Arrays.equals(Arrays.copyOfRange(inputBytes, off + len, max),
133                 readBytes),
134                 "Expected[" + Arrays.copyOfRange(inputBytes, off + len, max) +
135                         "], got:[" + readBytes + "]");
136 
137         check(!in.isClosed(), "Stream unexpectedly closed");
138     }
139 
createRandomBytes(int size)140     static byte[] createRandomBytes(int size) {
141         byte[] bytes = new byte[size];
142         generator.nextBytes(bytes);
143         return bytes;
144     }
145 
check(boolean cond, Object ... failedArgs)146     static void check(boolean cond, Object ... failedArgs) {
147         if (cond)
148             return;
149         StringBuilder sb = new StringBuilder();
150         for (Object o : failedArgs)
151             sb.append(o);
152         throw new RuntimeException(sb.toString());
153     }
154 
155 
156     static class WrapperInputStream extends FilterInputStream {
157         private boolean closed;
WrapperInputStream(InputStream in)158         WrapperInputStream(InputStream in) { super(in); }
close()159         @Override public void close() throws IOException { closed = true; in.close(); }
isClosed()160         boolean isClosed() { return closed; }
161     }
162 }