1 /* 2 * Copyright 2009 Google, Inc. 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 /** 25 * @test 26 * @bug 4206909 4813885 27 * @summary Test basic functionality of DeflaterOutputStream/InflaterInputStream and GZIPOutputStream/GZIPInputStream, including flush 28 */ 29 30 import java.io.*; 31 import java.util.*; 32 import java.util.zip.*; 33 34 public class InflateIn_DeflateOut { 35 36 private static class PairedInputStream extends ByteArrayInputStream { 37 private PairedOutputStream out = null; 38 private Random random; 39 40 public PairedInputStream() { 41 // The ByteArrayInputStream needs to start with a buffer, but we 42 // need to set it to have no data 43 super(new byte[1]); 44 count = 0; 45 pos = 0; 46 random = new Random(new Date().getTime()); 47 } 48 49 public void setPairedOutputStream(PairedOutputStream out) { 50 this.out = out; 51 } 52 53 private void maybeFlushPair() { 54 if (random.nextInt(100) < 10) { 55 out.flush(); 56 } 57 } 58 59 public int read() { 60 maybeFlushPair(); 61 return super.read(); 62 } 63 64 public int read(byte b[], int off, int len) { 65 maybeFlushPair(); 66 return super.read(b, off, len); 67 } 68 69 public void addBytes(byte[] bytes, int len) { 70 int oldavail = count - pos; 71 int newcount = oldavail + len; 72 byte[] newbuf = new byte[newcount]; 73 System.arraycopy(buf, pos, newbuf, 0, oldavail); 74 System.arraycopy(bytes, 0, newbuf, oldavail, len); 75 pos = 0; 76 count = newcount; 77 buf = newbuf; 78 } 79 } 80 81 private static class PairedOutputStream extends ByteArrayOutputStream { 82 private PairedInputStream pairedStream = null; 83 84 public PairedOutputStream(PairedInputStream inputPair) { 85 super(); 86 this.pairedStream = inputPair; 87 } 88 89 public void flush() { 90 if (count > 0) { 91 pairedStream.addBytes(buf, count); 92 reset(); 93 } 94 } 95 96 public void close() { 97 flush(); 98 } 99 } 100 101 private static boolean readFully(InputStream in, byte[] buf, int length) 102 throws IOException { 103 int pos = 0; 104 int n; 105 while ((n = in.read(buf, pos, length - pos)) > 0) { 106 pos += n; 107 if (pos == length) return true; 108 } 109 return false; 110 } 111 112 private static boolean readLineIfAvailable(InputStream in, StringBuilder sb) 113 throws IOException { 114 try { 115 while (in.available() > 0) { 116 int i = in.read(); 117 if (i < 0) break; 118 char c = (char) (((byte) i) & 0xff); 119 sb.append(c); 120 if (c == '\n') return true; 121 } 122 } catch (EOFException e) { 123 // empty 124 } 125 return false; 126 } 127 128 /** Check that written, closed and read */ 129 private static void WriteCloseRead() throws Throwable { 130 Random random = new Random(new Date().getTime()); 131 132 PairedInputStream pis = new PairedInputStream(); 133 InflaterInputStream iis = new InflaterInputStream(pis); 134 135 PairedOutputStream pos = new PairedOutputStream(pis); 136 pis.setPairedOutputStream(pos); 137 138 byte[] data = new byte[random.nextInt(1024 * 1024)]; 139 byte[] buf = new byte[data.length]; 140 random.nextBytes(data); 141 142 try (DeflaterOutputStream dos = new DeflaterOutputStream(pos, true)) { 143 dos.write(data); 144 } 145 check(readFully(iis, buf, buf.length)); 146 check(Arrays.equals(data, buf)); 147 } 148 149 private static void check(InputStream is, OutputStream os) 150 throws Throwable 151 { 152 Random random = new Random(new Date().getTime()); 153 // Large writes 154 for (int x = 0; x < 200 ; x++) { 155 // byte[] data = new byte[random.nextInt(1024 * 1024)]; 156 byte[] data = new byte[1024]; 157 byte[] buf = new byte[data.length]; 158 random.nextBytes(data); 159 160 os.write(data); 161 os.flush(); 162 check(readFully(is, buf, buf.length)); 163 check(Arrays.equals(data, buf)); 164 } 165 166 // Small writes 167 for (int x = 0; x < 2000 ; x++) { 168 byte[] data = new byte[random.nextInt(20) + 10]; 169 byte[] buf = new byte[data.length]; 170 random.nextBytes(data); 171 172 os.write(data); 173 os.flush(); 174 if (!readFully(is, buf, buf.length)) { 175 fail("Didn't read full buffer of " + buf.length); 176 } 177 check(Arrays.equals(data, buf)); 178 } 179 180 String quit = "QUIT\r\n"; 181 182 // Close it out 183 os.write(quit.getBytes()); 184 os.close(); 185 186 StringBuilder sb = new StringBuilder(); 187 check(readLineIfAvailable(is, sb)); 188 equal(sb.toString(), quit); 189 } 190 191 /** Check that written, flushed and read */ 192 private static void WriteFlushRead() throws Throwable { 193 PairedInputStream pis = new PairedInputStream(); 194 InflaterInputStream iis = new InflaterInputStream(pis); 195 196 PairedOutputStream pos = new PairedOutputStream(pis); 197 pis.setPairedOutputStream(pos); 198 DeflaterOutputStream dos = new DeflaterOutputStream(pos, true); 199 200 check(iis, dos); 201 } 202 203 private static void GZWriteFlushRead() throws Throwable { 204 PairedInputStream pis = new PairedInputStream(); 205 PairedOutputStream pos = new PairedOutputStream(pis); 206 pis.setPairedOutputStream(pos); 207 208 GZIPOutputStream gos = new GZIPOutputStream(pos, true); 209 gos.flush(); // flush the head out, so gis can read 210 GZIPInputStream gis = new GZIPInputStream(pis); 211 212 check(gis, gos); 213 } 214 215 private static void checkLOP(InputStream is, OutputStream os) 216 throws Throwable 217 { 218 boolean flushed = false; 219 int count = 0; 220 221 // Do at least a certain number of lines, but too many without a 222 // flush means this test isn't testing anything 223 while ((count < 10 && flushed) || (count < 1000 && !flushed)) { 224 String command = "PING " + count + "\r\n"; 225 os.write(command.getBytes()); 226 227 StringBuilder buf = new StringBuilder(); 228 if (!readLineIfAvailable(is, buf)) { 229 flushed = true; 230 os.flush(); 231 check(readLineIfAvailable(is, buf)); 232 } 233 equal(buf.toString(), command); 234 count++; 235 } 236 check(flushed); 237 } 238 239 /** Validate that we need to use flush at least once on a line 240 * oriented protocol */ 241 private static void LineOrientedProtocol() throws Throwable { 242 PairedInputStream pis = new PairedInputStream(); 243 InflaterInputStream iis = new InflaterInputStream(pis); 244 245 PairedOutputStream pos = new PairedOutputStream(pis); 246 pis.setPairedOutputStream(pos); 247 DeflaterOutputStream dos = new DeflaterOutputStream(pos, true); 248 249 checkLOP(iis, dos); 250 } 251 252 private static void GZLineOrientedProtocol() throws Throwable { 253 PairedInputStream pis = new PairedInputStream(); 254 PairedOutputStream pos = new PairedOutputStream(pis); 255 pis.setPairedOutputStream(pos); 256 257 GZIPOutputStream gos = new GZIPOutputStream(pos, true); 258 gos.flush(); // flush the head out, so gis can read 259 GZIPInputStream gis = new GZIPInputStream(pis); 260 261 checkLOP(gis, gos); 262 } 263 264 public static void realMain(String[] args) throws Throwable { 265 WriteCloseRead(); 266 WriteFlushRead(); 267 LineOrientedProtocol(); 268 GZWriteFlushRead(); 269 GZLineOrientedProtocol(); 270 } 271 272 //--------------------- Infrastructure --------------------------- 273 static volatile int passed = 0, failed = 0; 274 static void pass() {passed++;} 275 static void fail() {failed++; Thread.dumpStack();} 276 static void fail(String msg) {System.out.println(msg); fail();} 277 static void unexpected(Throwable t) {failed++; t.printStackTrace();} 278 static void check(boolean cond) {if (cond) pass(); else fail();} 279 static void equal(Object x, Object y) { 280 if (x == null ? y == null : x.equals(y)) pass(); 281 else fail(x + " not equal to " + y);} 282 public static void main(String[] args) throws Throwable { 283 try {realMain(args);} catch (Throwable t) {unexpected(t);} 284 System.out.println("\nPassed = " + passed + " failed = " + failed); 285 if (failed > 0) throw new AssertionError("Some tests failed");} 286 }