1796N/A/*
1796N/A * Copyright 2009 Google, Inc. All Rights Reserved.
1796N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1796N/A *
1796N/A * This code is free software; you can redistribute it and/or modify it
1796N/A * under the terms of the GNU General Public License version 2 only, as
1796N/A * published by the Free Software Foundation.
1796N/A *
1796N/A * This code is distributed in the hope that it will be useful, but WITHOUT
1796N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1796N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1796N/A * version 2 for more details (a copy is included in the LICENSE file that
1796N/A * accompanied this code).
1796N/A *
1796N/A * You should have received a copy of the GNU General Public License version
1796N/A * 2 along with this work; if not, write to the Free Software Foundation,
1796N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1796N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
1796N/A */
1796N/A
1796N/A/**
1796N/A * @test
2398N/A * @bug 4206909 4813885
2398N/A * @summary Test basic functionality of DeflaterOutputStream/InflaterInputStream and GZIPOutputStream/GZIPInputStream, including flush
1796N/A */
1796N/A
1796N/Aimport java.io.*;
1796N/Aimport java.util.*;
1796N/Aimport java.util.zip.*;
1796N/A
1796N/Apublic class InflateIn_DeflateOut {
1796N/A
1796N/A private static class PairedInputStream extends ByteArrayInputStream {
1796N/A private PairedOutputStream out = null;
1796N/A private Random random;
1796N/A
1796N/A public PairedInputStream() {
1796N/A // The ByteArrayInputStream needs to start with a buffer, but we
1796N/A // need to set it to have no data
1796N/A super(new byte[1]);
1796N/A count = 0;
1796N/A pos = 0;
1796N/A random = new Random(new Date().getTime());
1796N/A }
1796N/A
1796N/A public void setPairedOutputStream(PairedOutputStream out) {
1796N/A this.out = out;
1796N/A }
1796N/A
1796N/A private void maybeFlushPair() {
1796N/A if (random.nextInt(100) < 10) {
1796N/A out.flush();
1796N/A }
1796N/A }
1796N/A
1796N/A public int read() {
1796N/A maybeFlushPair();
1796N/A return super.read();
1796N/A }
1796N/A
1796N/A public int read(byte b[], int off, int len) {
1796N/A maybeFlushPair();
1796N/A return super.read(b, off, len);
1796N/A }
1796N/A
1796N/A public void addBytes(byte[] bytes, int len) {
1796N/A int oldavail = count - pos;
1796N/A int newcount = oldavail + len;
1796N/A byte[] newbuf = new byte[newcount];
1796N/A System.arraycopy(buf, pos, newbuf, 0, oldavail);
1796N/A System.arraycopy(bytes, 0, newbuf, oldavail, len);
1796N/A pos = 0;
1796N/A count = newcount;
1796N/A buf = newbuf;
1796N/A }
1796N/A }
1796N/A
1796N/A private static class PairedOutputStream extends ByteArrayOutputStream {
2398N/A private PairedInputStream pairedStream = null;
1796N/A
2398N/A public PairedOutputStream(PairedInputStream inputPair) {
2398N/A super();
2398N/A this.pairedStream = inputPair;
2398N/A }
1796N/A
2398N/A public void flush() {
2398N/A if (count > 0) {
2398N/A pairedStream.addBytes(buf, count);
2398N/A reset();
2398N/A }
1796N/A }
1796N/A
2398N/A public void close() {
2398N/A flush();
2398N/A }
1796N/A }
1796N/A
1796N/A private static boolean readFully(InputStream in, byte[] buf, int length)
1796N/A throws IOException {
1796N/A int pos = 0;
1796N/A int n;
1796N/A while ((n = in.read(buf, pos, length - pos)) > 0) {
1796N/A pos += n;
1796N/A if (pos == length) return true;
1796N/A }
1796N/A return false;
1796N/A }
1796N/A
1796N/A private static boolean readLineIfAvailable(InputStream in, StringBuilder sb)
1796N/A throws IOException {
1796N/A try {
1796N/A while (in.available() > 0) {
1796N/A int i = in.read();
1796N/A if (i < 0) break;
1796N/A char c = (char) (((byte) i) & 0xff);
1796N/A sb.append(c);
1796N/A if (c == '\n') return true;
1796N/A }
1796N/A } catch (EOFException e) {
1796N/A // empty
1796N/A }
1796N/A return false;
1796N/A }
1796N/A
1796N/A /** Check that written, closed and read */
1796N/A private static void WriteCloseRead() throws Throwable {
1796N/A Random random = new Random(new Date().getTime());
1796N/A
1796N/A PairedInputStream pis = new PairedInputStream();
1796N/A InflaterInputStream iis = new InflaterInputStream(pis);
1796N/A
1796N/A PairedOutputStream pos = new PairedOutputStream(pis);
1796N/A pis.setPairedOutputStream(pos);
1796N/A
1796N/A byte[] data = new byte[random.nextInt(1024 * 1024)];
1796N/A byte[] buf = new byte[data.length];
1796N/A random.nextBytes(data);
1796N/A
3656N/A try (DeflaterOutputStream dos = new DeflaterOutputStream(pos, true)) {
3656N/A dos.write(data);
3656N/A }
1796N/A check(readFully(iis, buf, buf.length));
1796N/A check(Arrays.equals(data, buf));
1796N/A }
1796N/A
2398N/A private static void check(InputStream is, OutputStream os)
2398N/A throws Throwable
2398N/A {
1796N/A Random random = new Random(new Date().getTime());
2398N/A // Large writes
1796N/A for (int x = 0; x < 200 ; x++) {
1796N/A // byte[] data = new byte[random.nextInt(1024 * 1024)];
1796N/A byte[] data = new byte[1024];
1796N/A byte[] buf = new byte[data.length];
1796N/A random.nextBytes(data);
1796N/A
2398N/A os.write(data);
2398N/A os.flush();
2398N/A check(readFully(is, buf, buf.length));
1796N/A check(Arrays.equals(data, buf));
1796N/A }
1796N/A
1796N/A // Small writes
1796N/A for (int x = 0; x < 2000 ; x++) {
1796N/A byte[] data = new byte[random.nextInt(20) + 10];
1796N/A byte[] buf = new byte[data.length];
1796N/A random.nextBytes(data);
1796N/A
2398N/A os.write(data);
2398N/A os.flush();
2398N/A if (!readFully(is, buf, buf.length)) {
1796N/A fail("Didn't read full buffer of " + buf.length);
1796N/A }
1796N/A check(Arrays.equals(data, buf));
1796N/A }
1796N/A
1796N/A String quit = "QUIT\r\n";
1796N/A
1796N/A // Close it out
2398N/A os.write(quit.getBytes());
2398N/A os.close();
1796N/A
1796N/A StringBuilder sb = new StringBuilder();
2398N/A check(readLineIfAvailable(is, sb));
1796N/A equal(sb.toString(), quit);
1796N/A }
1796N/A
2398N/A /** Check that written, flushed and read */
2398N/A private static void WriteFlushRead() throws Throwable {
2398N/A PairedInputStream pis = new PairedInputStream();
2398N/A InflaterInputStream iis = new InflaterInputStream(pis);
2398N/A
2398N/A PairedOutputStream pos = new PairedOutputStream(pis);
2398N/A pis.setPairedOutputStream(pos);
2398N/A DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
2398N/A
2398N/A check(iis, dos);
2398N/A }
2398N/A
2398N/A private static void GZWriteFlushRead() throws Throwable {
2398N/A PairedInputStream pis = new PairedInputStream();
2398N/A PairedOutputStream pos = new PairedOutputStream(pis);
2398N/A pis.setPairedOutputStream(pos);
2398N/A
2398N/A GZIPOutputStream gos = new GZIPOutputStream(pos, true);
2398N/A gos.flush(); // flush the head out, so gis can read
2398N/A GZIPInputStream gis = new GZIPInputStream(pis);
2398N/A
2398N/A check(gis, gos);
2398N/A }
2398N/A
2398N/A private static void checkLOP(InputStream is, OutputStream os)
2398N/A throws Throwable
2398N/A {
2398N/A boolean flushed = false;
2398N/A int count = 0;
2398N/A
2398N/A // Do at least a certain number of lines, but too many without a
2398N/A // flush means this test isn't testing anything
2398N/A while ((count < 10 && flushed) || (count < 1000 && !flushed)) {
2398N/A String command = "PING " + count + "\r\n";
2398N/A os.write(command.getBytes());
2398N/A
2398N/A StringBuilder buf = new StringBuilder();
2398N/A if (!readLineIfAvailable(is, buf)) {
2398N/A flushed = true;
2398N/A os.flush();
2398N/A check(readLineIfAvailable(is, buf));
2398N/A }
2398N/A equal(buf.toString(), command);
2398N/A count++;
2398N/A }
2398N/A check(flushed);
2398N/A }
2398N/A
1796N/A /** Validate that we need to use flush at least once on a line
1796N/A * oriented protocol */
1796N/A private static void LineOrientedProtocol() throws Throwable {
1796N/A PairedInputStream pis = new PairedInputStream();
1796N/A InflaterInputStream iis = new InflaterInputStream(pis);
1796N/A
1796N/A PairedOutputStream pos = new PairedOutputStream(pis);
1796N/A pis.setPairedOutputStream(pos);
1796N/A DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
1796N/A
2398N/A checkLOP(iis, dos);
2398N/A }
1796N/A
2398N/A private static void GZLineOrientedProtocol() throws Throwable {
2398N/A PairedInputStream pis = new PairedInputStream();
2398N/A PairedOutputStream pos = new PairedOutputStream(pis);
2398N/A pis.setPairedOutputStream(pos);
2398N/A
2398N/A GZIPOutputStream gos = new GZIPOutputStream(pos, true);
2398N/A gos.flush(); // flush the head out, so gis can read
2398N/A GZIPInputStream gis = new GZIPInputStream(pis);
2398N/A
2398N/A checkLOP(gis, gos);
1796N/A }
1796N/A
1796N/A public static void realMain(String[] args) throws Throwable {
1796N/A WriteCloseRead();
1796N/A WriteFlushRead();
1796N/A LineOrientedProtocol();
2398N/A GZWriteFlushRead();
2398N/A GZLineOrientedProtocol();
1796N/A }
1796N/A
1796N/A //--------------------- Infrastructure ---------------------------
1796N/A static volatile int passed = 0, failed = 0;
1796N/A static void pass() {passed++;}
1796N/A static void fail() {failed++; Thread.dumpStack();}
1796N/A static void fail(String msg) {System.out.println(msg); fail();}
1796N/A static void unexpected(Throwable t) {failed++; t.printStackTrace();}
1796N/A static void check(boolean cond) {if (cond) pass(); else fail();}
1796N/A static void equal(Object x, Object y) {
1796N/A if (x == null ? y == null : x.equals(y)) pass();
1796N/A else fail(x + " not equal to " + y);}
1796N/A public static void main(String[] args) throws Throwable {
1796N/A try {realMain(args);} catch (Throwable t) {unexpected(t);}
1796N/A System.out.println("\nPassed = " + passed + " failed = " + failed);
1796N/A if (failed > 0) throw new AssertionError("Some tests failed");}
1796N/A}