1 /*
2  * Copyright (c) 2010, 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 6227608
26  * @summary Test proper handling of flush()
27  * @modules jdk.charsets
28  * @author Martin Buchholz
29  */
30 
31 import java.util.*;
32 import java.io.*;
33 import java.nio.*;
34 import java.nio.charset.*;
35 
36 public class Flush {
contents(ByteBuffer bb)37     private static byte[] contents(ByteBuffer bb) {
38         byte[] contents = new byte[bb.position()];
39         bb.duplicate().flip().get(contents);
40         return contents;
41     }
42 
extend(ByteBuffer bb)43     private static ByteBuffer extend(ByteBuffer bb) {
44         ByteBuffer x = ByteBuffer.allocate(2*bb.capacity()+10);
45         bb.flip();
46         x.put(bb);
47         return x;
48     }
49 
realMain(String[] args)50     private static void realMain(String[] args) throws Throwable {
51         // A japanese character should decode as a 3-byte
52         // switch-to-japanese escape sequence, followed by a 2-byte
53         // encoding of the char itself, followed by a 3-byte return to
54         // ASCII escape sequence.
55         char[] jis0208 = {'\u3001'};
56         CharBuffer cb = CharBuffer.wrap(jis0208);
57         ByteBuffer bb = ByteBuffer.allocate(6);
58         CharsetEncoder enc = Charset.forName("ISO-2022-JP").newEncoder();
59 
60         check(enc.encode(cb, bb, true).isUnderflow());
61 
62         System.out.println(Arrays.toString(contents(bb)));
63         check(! cb.hasRemaining());
64         equal(contents(bb).length, 3 + 2);
65         equal(bb.get(0), (byte)0x1b);
66 
67         //----------------------------------------------------------------
68         // We must be able to recover if flush() returns OVERFLOW
69         //----------------------------------------------------------------
70         check(enc.flush(bb).isOverflow());
71         check(enc.flush(bb).isOverflow());
72         equal(contents(bb).length, 3 + 2);
73 
74         bb = extend(bb);
75 
76         check(enc.flush(bb).isUnderflow());
77         equal(bb.get(3 + 2), (byte)0x1b);
78         System.out.println(Arrays.toString(contents(bb)));
79         equal(contents(bb).length, 3 + 2 + 3);
80 
81         //----------------------------------------------------------------
82         // A final redundant flush() is a no-op
83         //----------------------------------------------------------------
84         check(enc.flush(bb).isUnderflow());
85         check(enc.flush(bb).isUnderflow());
86         equal(contents(bb).length, 3 + 2 + 3);
87 
88         //----------------------------------------------------------------
89         // CharsetEncoder.encode(ByteBuffer) must call flush(ByteBuffer)
90         //----------------------------------------------------------------
91         bb = enc.encode(CharBuffer.wrap(jis0208));
92         byte[] expected = "\u001b$B!\"\u001b(B".getBytes("ASCII");
93         byte[] contents = new byte[bb.limit()]; bb.get(contents);
94         check(Arrays.equals(contents, expected));
95     }
96 
97     //--------------------- Infrastructure ---------------------------
98     static volatile int passed = 0, failed = 0;
pass()99     static void pass() { passed++; }
fail()100     static void fail() { failed++; Thread.dumpStack(); }
fail(String msg)101     static void fail(String msg) { System.out.println(msg); fail(); }
unexpected(Throwable t)102     static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
check(boolean cond)103     static void check(boolean cond) { if (cond) pass(); else fail(); }
equal(Object x, Object y)104     static void equal(Object x, Object y) {
105         if (x == null ? y == null : x.equals(y)) pass();
106         else {System.out.println(x + " not equal to " + y); fail(); }}
107 
main(String[] args)108     public static void main(String[] args) throws Throwable {
109         try { realMain(args); } catch (Throwable t) { unexpected(t); }
110 
111         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
112         if (failed > 0) throw new Exception("Some tests failed");
113     }
114 }
115