1 /*
2  * Copyright (c) 2001, 2019, 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 4417152 4481572 6248930 6725399 6884800 8220477
26  * @summary Test Channels basic functionality
27  */
28 
29 import java.io.*;
30 import java.nio.*;
31 import java.nio.charset.*;
32 import java.nio.channels.*;
33 
34 public class Basic {
35 
36     static String message;
37 
38     static String encoding;
39 
40     static File blah;
41 
42     static int ITERATIONS = 500;
43 
main(String[] args)44     public static void main(String[] args) throws Exception {
45         message = "ascii data for a test";
46         encoding = "ISO-8859-1";
47         test();
48         message = "\ucafe\ubabe\ucafe\ubabe\ucafe\ubabe";
49         encoding = "UTF-8";
50         test();
51     }
52 
failNpeExpected()53     static void failNpeExpected() {
54         throw new RuntimeException("Did not get the expected NullPointerException.");
55     }
56 
test()57     private static void test() throws Exception {
58         //Test if methods of Channels throw NPE with null argument(s)
59         try {
60             Channels.newInputStream((ReadableByteChannel)null);
61             failNpeExpected();
62         } catch (NullPointerException npe) {}
63 
64         try {
65             Channels.newOutputStream((WritableByteChannel)null);
66             failNpeExpected();
67         } catch (NullPointerException npe) {}
68 
69         try {
70             ReadableByteChannel channel = Channels.newChannel((InputStream)null);
71             failNpeExpected();
72         } catch (NullPointerException ne) {}  // OK. As expected.
73 
74         try {
75             WritableByteChannel channel = Channels.newChannel((OutputStream)null);
76             failNpeExpected();
77         } catch (NullPointerException ne) {}  // OK. As expected.
78 
79         WritableByteChannel wbc = new WritableByteChannel() {
80             public int write(ByteBuffer src) { return 0; }
81             public void close() throws IOException { }
82             public boolean isOpen() { return true; }
83         };
84 
85         ReadableByteChannel rbc = new ReadableByteChannel() {
86             public int read(ByteBuffer dst) { return 0; }
87             public void close() {}
88             public boolean isOpen() { return true; }
89         };
90 
91         try {
92             Channels.newReader((ReadableByteChannel)null,
93                                Charset.defaultCharset().newDecoder(),
94                                -1);
95             failNpeExpected();
96         } catch (NullPointerException npe) {}
97 
98         try {
99             Channels.newReader(rbc, (CharsetDecoder)null, -1);
100             failNpeExpected();
101         } catch (NullPointerException npe) {}
102 
103         try {
104             Channels.newReader((ReadableByteChannel)null,
105                                Charset.defaultCharset().name());
106             failNpeExpected();
107         } catch (NullPointerException npe) {}
108 
109         try {
110             Channels.newReader(rbc, (String)null);
111             failNpeExpected();
112         } catch (NullPointerException npe) {}
113 
114 
115         try {
116             Channels.newReader(null, (String)null);
117             failNpeExpected();
118         } catch (NullPointerException npe) {}
119 
120         try {
121             Channels.newReader(rbc, (Charset)null);
122             failNpeExpected();
123         } catch (NullPointerException npe) {}
124 
125 
126         try {
127             Channels.newReader(null, (Charset)null);
128             failNpeExpected();
129         } catch (NullPointerException npe) {}
130 
131         try {
132             Channels.newWriter((WritableByteChannel)null,
133                                Charset.defaultCharset().newEncoder(),
134                                -1);
135             failNpeExpected();
136         } catch (NullPointerException npe) {}
137 
138         try {
139             Channels.newWriter(null, null, -1);
140             failNpeExpected();
141         } catch (NullPointerException npe) {}
142 
143         try {
144             Channels.newWriter(wbc, null, -1);
145             failNpeExpected();
146         } catch (NullPointerException npe) {}
147 
148         try {
149             Channels.newWriter((WritableByteChannel)null,
150                                Charset.defaultCharset().name());
151             failNpeExpected();
152         } catch (NullPointerException npe) {}
153 
154         try {
155             Channels.newWriter(wbc, (String)null);
156             failNpeExpected();
157         } catch (NullPointerException npe) {}
158 
159         try {
160             Channels.newWriter(null, (String)null);
161             failNpeExpected();
162         } catch (NullPointerException npe) {}
163 
164         try {
165             Channels.newWriter(wbc, (Charset)null);
166             failNpeExpected();
167         } catch (NullPointerException npe) {}
168 
169         try {
170             Channels.newWriter(null, (Charset)null);
171             failNpeExpected();
172         } catch (NullPointerException npe) {}
173 
174         try {
175             blah = File.createTempFile("blah", null);
176 
177             testNewOutputStream(blah);
178             readAndCheck(blah);
179             blah.delete();
180 
181             writeOut(blah, ITERATIONS);
182             testNewInputStream(blah);
183             blah.delete();
184 
185             testNewChannelOut(blah);
186             readAndCheck(blah);
187             blah.delete();
188 
189             testNewChannelWriteAfterClose(blah);
190 
191             testNewChannelReadAfterClose(blah);
192             blah.delete();
193 
194             writeOut(blah, ITERATIONS);
195             testNewChannelIn(blah);
196             test4481572(blah);
197             blah.delete();
198 
199             testNewWriter(blah);
200             readAndCheck(blah);
201             blah.delete();
202 
203             writeOut(blah, ITERATIONS);
204             testNewReader(blah);
205 
206             testNewWriterClose();
207             testNewReaderClose();
208         } finally {
209             blah.delete();
210         }
211     }
212 
readAndCheck(File blah)213     private static void readAndCheck(File blah) throws Exception {
214         FileInputStream fis = new FileInputStream(blah);
215         int messageSize = message.length() * ITERATIONS * 3 + 1;
216         byte bb[] = new byte[messageSize];
217         int bytesRead = 0;
218         int totalRead = 0;
219         while (bytesRead != -1) {
220             totalRead += bytesRead;
221             bytesRead = fis.read(bb, totalRead, messageSize - totalRead);
222         }
223         String result = new String(bb, 0, totalRead, encoding);
224         int len = message.length();
225         for (int i=0; i<ITERATIONS; i++) {
226             String segment = result.substring(i++ * len, i * len);
227             if (!segment.equals(message))
228                 throw new RuntimeException("Test failed");
229         }
230         fis.close();
231     }
232 
writeOut(File blah, int limit)233     private static void writeOut(File blah, int limit) throws Exception {
234         FileOutputStream fos = new FileOutputStream(blah);
235         for (int i=0; i<limit; i++)
236             fos.write(message.getBytes(encoding));
237         fos.close();
238     }
239 
testNewOutputStream(File blah)240     private static void testNewOutputStream(File blah) throws Exception {
241         FileOutputStream fos = new FileOutputStream(blah);
242         FileChannel fc = fos.getChannel();
243         WritableByteChannel wbc = (WritableByteChannel)fc;
244         OutputStream os = Channels.newOutputStream(wbc);
245         for (int i=0; i<ITERATIONS; i++)
246             os.write(message.getBytes(encoding));
247         os.close();
248         fos.close();
249     }
250 
testNewInputStream(File blah)251     private static void testNewInputStream(File blah) throws Exception {
252         FileInputStream fis = new FileInputStream(blah);
253         FileChannel fc = fis.getChannel();
254         InputStream is = Channels.newInputStream(fc);
255         int messageSize = message.length() * ITERATIONS * 3 + 1;
256         byte bb[] = new byte[messageSize];
257 
258         int bytesRead = 0;
259         int totalRead = 0;
260         while (bytesRead != -1) {
261             totalRead += bytesRead;
262             long rem = Math.min(fc.size() - totalRead, (long)Integer.MAX_VALUE);
263             if (is.available() != (int)rem)
264                 throw new RuntimeException("available not useful or not maximally useful");
265             bytesRead = is.read(bb, totalRead, messageSize - totalRead);
266         }
267         if (is.available() != 0)
268            throw new RuntimeException("available() should return 0 at EOF");
269 
270         String result = new String(bb, 0, totalRead, encoding);
271         int len = message.length();
272         for (int i=0; i<ITERATIONS; i++) {
273             String segment = result.substring(i++ * len, i * len);
274             if (!segment.equals(message))
275                 throw new RuntimeException("Test failed");
276         }
277         is.close();
278         fis.close();
279     }
280 
testNewChannelOut(File blah)281     private static void testNewChannelOut(File blah) throws Exception {
282         ExtendedFileOutputStream fos = new ExtendedFileOutputStream(blah);
283         WritableByteChannel wbc = Channels.newChannel(fos);
284 
285         for (int i=0; i<ITERATIONS; i++)
286             wbc.write(ByteBuffer.wrap(message.getBytes(encoding)));
287         wbc.close();
288         fos.close();
289     }
290 
testNewChannelIn(File blah)291     private static void testNewChannelIn(File blah) throws Exception {
292         ExtendedFileInputStream fis = new ExtendedFileInputStream(blah);
293         ReadableByteChannel rbc = Channels.newChannel(fis);
294 
295         int messageSize = message.length() * ITERATIONS * 3;
296         byte data[] = new byte[messageSize+1];
297         ByteBuffer bb = ByteBuffer.wrap(data);
298 
299         int bytesRead = 0;
300         int totalRead = 0;
301         while (bytesRead != -1) {
302             totalRead += bytesRead;
303             bytesRead = rbc.read(bb);
304         }
305 
306         String result = new String(data, 0, totalRead, encoding);
307         int len = message.length();
308         for (int i=0; i<ITERATIONS; i++) {
309             String segment = result.substring(i++ * len, i * len);
310             if (!segment.equals(message))
311                 throw new RuntimeException("Test failed");
312         }
313         rbc.close();
314         fis.close();
315     }
316 
testNewChannelWriteAfterClose(File blah)317     private static void testNewChannelWriteAfterClose(File blah)
318         throws Exception {
319         try (ExtendedFileOutputStream fos =
320             new ExtendedFileOutputStream(blah)) {
321             WritableByteChannel wbc = Channels.newChannel(fos);
322 
323             wbc.close();
324             try {
325                 wbc.write(ByteBuffer.allocate(0));
326                 throw new RuntimeException
327                     ("No ClosedChannelException on WritableByteChannel::write");
328             } catch (ClosedChannelException expected) {
329             }
330         }
331     }
332 
testNewChannelReadAfterClose(File blah)333     private static void testNewChannelReadAfterClose(File blah)
334         throws Exception {
335         try (ExtendedFileInputStream fis = new ExtendedFileInputStream(blah)) {
336             ReadableByteChannel rbc = Channels.newChannel(fis);
337 
338             rbc.close();
339             try {
340                 rbc.read(ByteBuffer.allocate(0));
341                 throw new RuntimeException
342                     ("No ClosedChannelException on ReadableByteChannel::read");
343             } catch (ClosedChannelException expected) {
344             }
345         }
346     }
347 
348     // Causes BufferOverflowException if bug 4481572 is present.
test4481572(File blah)349     private static void test4481572(File blah) throws Exception {
350         ExtendedFileInputStream fis = new ExtendedFileInputStream(blah);
351         ReadableByteChannel rbc = Channels.newChannel(fis);
352 
353         byte data[] = new byte[9000];
354         ByteBuffer bb = ByteBuffer.wrap(data);
355 
356         int bytesRead = 1;
357         int totalRead = 0;
358         while (bytesRead > 0) {
359             totalRead += bytesRead;
360             bytesRead = rbc.read(bb);
361         }
362         rbc.close();
363         fis.close();
364     }
365 
testNewWriter(File blah)366     private static void testNewWriter(File blah) throws Exception {
367         FileOutputStream fos = new FileOutputStream(blah);
368         WritableByteChannel wbc = (WritableByteChannel)fos.getChannel();
369         Writer w = Channels.newWriter(wbc, encoding);
370         char data[] = new char[40];
371         message.getChars(0, message.length(), data, 0);
372         for (int i=0; i<ITERATIONS; i++)
373             w.write(data, 0, message.length());
374         w.flush();
375         w.close();
376         fos.close();
377     }
378 
testNewReader(File blah)379     private static void testNewReader(File blah) throws Exception {
380         FileInputStream fis = new FileInputStream(blah);
381         ReadableByteChannel rbc = (ReadableByteChannel)fis.getChannel();
382         Reader r = Channels.newReader(rbc, encoding);
383 
384         int messageSize = message.length() * ITERATIONS;
385         char data[] = new char[messageSize];
386 
387         int totalRead = 0;
388         int charsRead = 0;
389         while (totalRead < messageSize) {
390             totalRead += charsRead;
391             charsRead = r.read(data, totalRead, messageSize - totalRead);
392         }
393         String result = new String(data, 0, totalRead);
394         int len = message.length();
395         for (int i=0; i<ITERATIONS; i++) {
396             String segment = result.substring(i++ * len, i * len);
397             if (!segment.equals(message))
398                 throw new RuntimeException("Test failed");
399         }
400         r.close();
401         fis.close();
402     }
403 
testNewWriterClose()404     private static void testNewWriterClose() throws Exception {
405         Writer writer = null;
406         try {
407             WritableByteChannel channel = new WritableByteChannel() {
408                 @Override
409                 public int write(ByteBuffer src) throws IOException {
410                     return 0;
411                 }
412 
413                 @Override
414                 public boolean isOpen() {
415                     return true;
416                 }
417 
418                 @Override
419                 public void close() throws IOException {
420                     throw new IOException();
421                 }
422             };
423             writer = Channels.newWriter(channel,
424                 StandardCharsets.UTF_8.newEncoder(), -1);
425             writer.close();
426         } catch (IOException ioe) {
427             Exception theException = null;
428             try {
429                 writer.write(1);
430                 writer.flush();
431             } catch (Exception e) {
432                 theException = e;
433             } finally {
434                 if (theException == null) {
435                     throw new RuntimeException("IOException not thrown");
436                 } else if (!(theException instanceof IOException)) {
437                     throw new RuntimeException("Exception not an IOException: "
438                         + theException);
439                 } else {
440                     String message = theException.getMessage();
441                     if (!message.equals("Stream closed")) {
442                         throw new RuntimeException("Unexpected message "
443                             + message);
444                     }
445                 }
446             }
447         }
448     }
449 
testNewReaderClose()450     private static void testNewReaderClose() throws Exception {
451         Reader reader = null;
452         try {
453             ReadableByteChannel channel = new ReadableByteChannel() {
454                 @Override
455                 public int read(ByteBuffer dst) throws IOException {
456                     dst.put((byte)7);
457                     return 1;
458                 }
459 
460                 @Override
461                 public boolean isOpen() {
462                     return true;
463                 }
464 
465                 @Override
466                 public void close() throws IOException {
467                     throw new IOException();
468                 }
469             };
470             reader = Channels.newReader(channel,
471                 StandardCharsets.UTF_8.newDecoder(), -1);
472             reader.close();
473         } catch (IOException ioe) {
474             Exception theException = null;
475             try {
476                 reader.read();
477             } catch (Exception e) {
478                 theException = e;
479             } finally {
480                 if (theException == null) {
481                     throw new RuntimeException("IOException not thrown");
482                 } else if (!(theException instanceof IOException)) {
483                     throw new RuntimeException("Exception not an IOException: "
484                         + theException);
485                 } else {
486                     String message = theException.getMessage();
487                     if (!message.equals("Stream closed")) {
488                         throw new RuntimeException("Unexpected message "
489                             + message);
490                     }
491                 }
492             }
493         }
494     }
495 }
496 
497 class ExtendedFileInputStream extends java.io.FileInputStream {
ExtendedFileInputStream(File file)498     ExtendedFileInputStream(File file) throws FileNotFoundException {
499         super(file);
500     }
501 }
502 
503 class ExtendedFileOutputStream extends java.io.FileOutputStream {
ExtendedFileOutputStream(File file)504     ExtendedFileOutputStream(File file) throws FileNotFoundException {
505         super(file);
506     }
507 }
508