< prev index next >

test/java/util/zip/InflateIn_DeflateOut.java

Print this page

        

*** 21,31 **** * questions. */ /** * @test ! * @bug 4206909 4813885 * @summary Test basic functionality of DeflaterOutputStream/InflaterInputStream and GZIPOutputStream/GZIPInputStream, including flush */ import java.io.*; import java.util.*; --- 21,31 ---- * questions. */ /** * @test ! * @bug 4206909 4813885 8189789 * @summary Test basic functionality of DeflaterOutputStream/InflaterInputStream and GZIPOutputStream/GZIPInputStream, including flush */ import java.io.*; import java.util.*;
*** 144,153 **** --- 144,194 ---- } check(readFully(iis, buf, buf.length)); check(Arrays.equals(data, buf)); } + private static void TestFlushableGZIPOutputStream() throws Throwable { + Random random = new Random(new Date().getTime()); + + ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream(); + OutputStream output = new FlushableGZIPOutputStream(byteOutStream); + + byte[] data = new byte[random.nextInt(1024 * 1024)]; + byte[] buf = new byte[data.length]; + random.nextBytes(data); + + output.write(data); + for (int i=0; i<data.length; i++) { + output.write(data[i]); + } + output.flush(); + for (int i=0; i<data.length; i++) { + output.write(data[i]); + } + output.write(data); + output.close(); + + ByteArrayInputStream byteInStream = + new ByteArrayInputStream(byteOutStream.toByteArray()); + + GZIPInputStream gzis = new GZIPInputStream(byteInStream); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int numRead; + byte[] b = new byte[4 * 1024]; + try { + while ((numRead = gzis.read(buf)) >= 0) { + baos.write(b, 0, numRead); + } + } finally { + baos.close(); + } + + byte[] decompressedBytes = baos.toByteArray(); + + check(decompressedBytes.length == data.length * 4); + } + private static void check(InputStream is, OutputStream os) throws Throwable { Random random = new Random(new Date().getTime()); // Large writes
*** 265,274 **** --- 306,316 ---- WriteCloseRead(); WriteFlushRead(); LineOrientedProtocol(); GZWriteFlushRead(); GZLineOrientedProtocol(); + TestFlushableGZIPOutputStream(); } //--------------------- Infrastructure --------------------------- static volatile int passed = 0, failed = 0; static void pass() {passed++;}
*** 281,286 **** --- 323,405 ---- else fail(x + " not equal to " + y);} public static void main(String[] args) throws Throwable { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.println("\nPassed = " + passed + " failed = " + failed); if (failed > 0) throw new AssertionError("Some tests failed");} + } + + class FlushableGZIPOutputStream extends GZIPOutputStream { + public FlushableGZIPOutputStream(OutputStream os) throws IOException { + super(os); + } + + private static final byte[] EMPTYBYTEARRAY = new byte[0]; + private boolean hasData = false; + + /** + * Here we make sure we have received data, so that the header has been for + * sure written to the output stream already. + */ + @Override + public synchronized void write(byte[] bytes, int i, int i1) + throws IOException { + super.write(bytes, i, i1); + hasData = true; + } + + @Override + public synchronized void write(int i) throws IOException { + super.write(i); + hasData = true; + } + + @Override + public synchronized void write(byte[] bytes) throws IOException { + super.write(bytes); + hasData = true; + } + + @Override + public synchronized void flush() throws IOException { + if (!hasData) { + return; // do not allow the gzip header to be flushed on its own + } + + // trick the deflater to flush + /** + * Now this is tricky: We force the Deflater to flush its data by + * switching compression level. As yet, a perplexingly simple workaround + * for + * http://developer.java.sun.com/developer/bugParade/bugs/4255743.html + */ + if (!def.finished()) { + def.setInput(EMPTYBYTEARRAY, 0, 0); + + def.setLevel(Deflater.NO_COMPRESSION); + deflate(); + + def.setLevel(Deflater.DEFAULT_COMPRESSION); + deflate(); + + out.flush(); + } + + hasData = false; // no more data to flush + } + + /* + * Keep on calling deflate until it runs dry. The default implementation + * only does it once and can therefore hold onto data when they need to be + * flushed out. + */ + @Override + protected void deflate() throws IOException { + int len; + do { + len = def.deflate(buf, 0, buf.length); + if (len > 0) { + out.write(buf, 0, len); + } + } while (len != 0); + } + }
< prev index next >