Path: blob/master/test/jdk/java/nio/charset/coders/BashStreams.java
41153 views
/*1* Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @summary Stochastic test of charset-based streams25* @key randomness26*/2728import java.io.*;29import java.util.*;30import java.nio.*;31import java.nio.channels.*;32import java.nio.charset.*;333435public class BashStreams {3637static final PrintStream log = System.err;383940static class CharacterGenerator {4142private final Random rand;43private final int max;44private final int limit;45private int count = 0;4647CharacterGenerator(long seed, String csn, int limit) {48rand = new Random(seed);49this.max = Character.MAX_CODE_POINT + 1;50this.limit = limit;51}5253private char[] saved = new char[10];54private int savedCount = 0;5556void push(char c) {57saved[savedCount++] = c;58count--;59}6061int count() {62return count;63}6465boolean hasNext() {66return count < limit;67}6869char next() {70if (count >= limit)71throw new RuntimeException("EOF");72if (savedCount > 0) {73savedCount--;74count++;75return saved[savedCount];76}77int c;78for (;;) {79c = rand.nextInt(max);80if ((Character.isBmpCodePoint(c)81&& (Character.isSurrogate((char) c)82|| (c == 0xfffe) || (c == 0xffff))))83continue;84if (Character.isSupplementaryCodePoint(c)85&& (count == limit - 1))86continue;87break;88}89count++;90if (Character.isSupplementaryCodePoint(c)) {91count++;92push(Character.lowSurrogate(c));93return Character.highSurrogate(c);94}95return (char)c;96}9798}99100101static void mismatch(String csn, int count, char c, char d) {102throw new RuntimeException(csn + ": Mismatch at count "103+ count104+ ": " + Integer.toHexString(c)105+ " != "106+ Integer.toHexString(d));107}108109static void mismatchedEOF(String csn, int count, int cgCount) {110throw new RuntimeException(csn + ": Mismatched EOFs: "111+ count112+ " != "113+ cgCount);114}115116117static class Sink // One abomination...118extends OutputStream119implements WritableByteChannel120{121122private final String csn;123private final CharacterGenerator cg;124private int count = 0;125126Sink(String csn, long seed) {127this.csn = csn;128this.cg = new CharacterGenerator(seed, csn, Integer.MAX_VALUE);129}130131public void write(int b) throws IOException {132write (new byte[] { (byte)b }, 0, 1);133}134135private int check(byte[] ba, int off, int len) throws IOException {136String s = new String(ba, off, len, csn);137int n = s.length();138for (int i = 0; i < n; i++) {139char c = s.charAt(i);140char d = cg.next();141if (c != d) {142if (c == '?') {143if (Character.isHighSurrogate(d))144cg.next();145continue;146}147mismatch(csn, count + i, c, d);148}149}150count += n;151return len;152}153154public void write(byte[] ba, int off, int len) throws IOException {155check(ba, off, len);156}157158public int write(ByteBuffer bb) throws IOException {159int n = check(bb.array(),160bb.arrayOffset() + bb.position(),161bb.remaining());162bb.position(bb.position() + n);163return n;164}165166public void close() {167count = -1;168}169170public boolean isOpen() {171return count >= 0;172}173174}175176static void testWrite(String csn, int limit, long seed, Writer w)177throws IOException178{179Random rand = new Random(seed);180CharacterGenerator cg = new CharacterGenerator(seed, csn,181Integer.MAX_VALUE);182int count = 0;183char[] ca = new char[16384];184185int n = 0;186while (count < limit) {187n = rand.nextInt(ca.length);188for (int i = 0; i < n; i++)189ca[i] = cg.next();190w.write(ca, 0, n);191count += n;192}193if (Character.isHighSurrogate(ca[n - 1]))194w.write(cg.next());195w.close();196}197198static void testStreamWrite(String csn, int limit, long seed)199throws IOException200{201log.println(" write stream");202testWrite(csn, limit, seed,203new OutputStreamWriter(new Sink(csn, seed), csn));204}205206static void testChannelWrite(String csn, int limit, long seed)207throws IOException208{209log.println(" write channel");210testWrite(csn, limit, seed,211Channels.newWriter(new Sink(csn, seed),212Charset.forName(csn)213.newEncoder()214.onMalformedInput(CodingErrorAction.REPLACE)215.onUnmappableCharacter(CodingErrorAction.REPLACE),2168192));217}218219220static class Source // ... and another221extends InputStream222implements ReadableByteChannel223{224225private final String csn;226private final CharsetEncoder enc;227private final CharacterGenerator cg;228private int count = 0;229230Source(String csn, long seed, int limit) {231this.csn = csn.startsWith("\1") ? csn.substring(1) : csn;232this.enc = Charset.forName(this.csn).newEncoder()233.onMalformedInput(CodingErrorAction.REPLACE)234.onUnmappableCharacter(CodingErrorAction.REPLACE);235this.cg = new CharacterGenerator(seed, csn, limit);236}237238public int read() throws IOException {239byte[] b = new byte[1];240read(b);241return b[0];242}243244private CharBuffer cb = CharBuffer.allocate(8192);245private ByteBuffer bb = null;246247public int read(byte[] ba, int off, int len) throws IOException {248if (!cg.hasNext())249return -1;250int end = off + len;251int i = off;252while (i < end) {253if ((bb == null) || !bb.hasRemaining()) {254cb.clear();255while (cb.hasRemaining()) {256if (!cg.hasNext())257break;258char c = cg.next();259if (Character.isHighSurrogate(c)260&& cb.remaining() == 1) {261cg.push(c);262break;263}264cb.put(c);265}266cb.flip();267if (!cb.hasRemaining())268break;269bb = enc.encode(cb);270}271int d = Math.min(bb.remaining(), end - i);272bb.get(ba, i, d);273i += d;274}275return i - off;276}277278public int read(ByteBuffer bb) throws IOException {279int n = read(bb.array(),280bb.arrayOffset() + bb.position(),281bb.remaining());282if (n >= 0)283bb.position(bb.position() + n);284return n;285}286287public void close() {288count = -1;289}290291public boolean isOpen() {292return count != -1;293}294295}296297static void testRead(String csn, int limit, long seed, int max,298Reader rd)299throws IOException300{301Random rand = new Random(seed);302CharacterGenerator cg = new CharacterGenerator(seed, csn, limit);303int count = 0;304char[] ca = new char[16384];305306int n = 0;307while (count < limit) {308int rn = rand.nextInt(ca.length);309n = rd.read(ca, 0, rn);310if (n < 0)311break;312for (int i = 0; i < n; i++) {313char c = ca[i];314if (!cg.hasNext())315mismatchedEOF(csn, count + i, cg.count());316char d = cg.next();317if (c == '?') {318if (Character.isHighSurrogate(d)) {319cg.next();320continue;321}322if (d > max)323continue;324}325if (c != d)326mismatch(csn, count + i, c, d);327}328count += n;329}330if (cg.hasNext())331mismatchedEOF(csn, count, cg.count());332rd.close();333}334335static void testStreamRead(String csn, int limit, long seed, int max)336throws IOException337{338log.println(" read stream");339testRead(csn, limit, seed, max,340new InputStreamReader(new Source(csn, seed, limit), csn));341}342343static void testChannelRead(String csn, int limit, long seed, int max)344throws IOException345{346log.println(" read channel");347testRead(csn, limit, seed, max,348Channels.newReader(new Source(csn, seed, limit), csn));349}350351352static final int LIMIT = 1 << 21;353354static void test(String csn, int limit, long seed, int max)355throws Exception356{357log.println();358log.println(csn);359360testStreamWrite(csn, limit, seed);361testChannelWrite(csn, limit, seed);362testStreamRead(csn, limit, seed, max);363testChannelRead(csn, limit, seed, max);364}365366public static void main(String[] args) throws Exception {367368if (System.getProperty("os.arch").equals("ia64")) {369// This test requires 54 minutes on an Itanium-1 processor370return;371}372373int ai = 0, an = args.length;374375int limit;376if (ai < an)377limit = 1 << Integer.parseInt(args[ai++]);378else379limit = LIMIT;380log.println("limit = " + limit);381382long seed;383if (ai < an)384seed = Long.parseLong(args[ai++]);385else386seed = System.currentTimeMillis();387log.println("seed = " + seed);388389test("UTF-8", limit, seed, Integer.MAX_VALUE);390test("US-ASCII", limit, seed, 0x7f);391test("ISO-8859-1", limit, seed, 0xff);392393}394395}396397398