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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 */ 23 24 /** 25 * @test 26 * @bug 4206909 27 * @summary Test basic functionality of DeflaterOutputStream and InflaterInputStream 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 DeflaterOutputStream dos = new DeflaterOutputStream(pos, true); 138 139 byte[] data = new byte[random.nextInt(1024 * 1024)]; 140 byte[] buf = new byte[data.length]; 141 random.nextBytes(data); 142 143 dos.write(data); 144 dos.close(); 145 check(readFully(iis, buf, buf.length)); 146 check(Arrays.equals(data, buf)); 147 } 148 149 /** Check that written, flushed and read */ 150 private static void WriteFlushRead() throws Throwable { 151 Random random = new Random(new Date().getTime()); 152 153 PairedInputStream pis = new PairedInputStream(); 154 InflaterInputStream iis = new InflaterInputStream(pis); 155 156 PairedOutputStream pos = new PairedOutputStream(pis); 157 pis.setPairedOutputStream(pos); 158 DeflaterOutputStream dos = new DeflaterOutputStream(pos, true); 159 160 // Large writes 161 for (int x = 0; x < 200 ; x++) { 162 // byte[] data = new byte[random.nextInt(1024 * 1024)]; 163 byte[] data = new byte[1024]; 164 byte[] buf = new byte[data.length]; 165 random.nextBytes(data); 166 167 dos.write(data); 168 dos.flush(); 169 check(readFully(iis, buf, buf.length)); 170 check(Arrays.equals(data, buf)); 171 } 172 173 // Small writes 174 for (int x = 0; x < 2000 ; x++) { 175 byte[] data = new byte[random.nextInt(20) + 10]; 176 byte[] buf = new byte[data.length]; 177 random.nextBytes(data); 178 179 dos.write(data); 180 dos.flush(); 181 if (!readFully(iis, buf, buf.length)) { 182 fail("Didn't read full buffer of " + buf.length); 183 } 184 check(Arrays.equals(data, buf)); 185 } 186 187 String quit = "QUIT\r\n"; 188 189 // Close it out 190 dos.write(quit.getBytes()); 191 dos.close(); 192 193 StringBuilder sb = new StringBuilder(); 194 check(readLineIfAvailable(iis, sb)); 195 equal(sb.toString(), quit); 196 } 197 198 /** Validate that we need to use flush at least once on a line 199 * oriented protocol */ 200 private static void LineOrientedProtocol() throws Throwable { 201 PairedInputStream pis = new PairedInputStream(); 202 InflaterInputStream iis = new InflaterInputStream(pis); 203 204 PairedOutputStream pos = new PairedOutputStream(pis); 205 pis.setPairedOutputStream(pos); 206 DeflaterOutputStream dos = new DeflaterOutputStream(pos, true); 207 208 boolean flushed = false; 209 int count = 0; 210 211 // Do at least a certain number of lines, but too many without a 212 // flush means this test isn't testing anything 213 while ((count < 10 && flushed) || (count < 1000 && !flushed)) { 214 String command = "PING " + count + "\r\n"; 215 dos.write(command.getBytes()); 216 217 StringBuilder buf = new StringBuilder(); 218 if (!readLineIfAvailable(iis, buf)) { 219 flushed = true; 220 dos.flush(); 221 check(readLineIfAvailable(iis, buf)); 222 } 223 equal(buf.toString(), command); 224 count++; 225 } 226 check(flushed); 227 } 228 229 public static void realMain(String[] args) throws Throwable { 230 WriteCloseRead(); 231 232 WriteFlushRead(); 233 234 LineOrientedProtocol(); 235 } 236 237 //--------------------- Infrastructure --------------------------- 238 static volatile int passed = 0, failed = 0; 239 static void pass() {passed++;} 240 static void fail() {failed++; Thread.dumpStack();} 241 static void fail(String msg) {System.out.println(msg); fail();} 242 static void unexpected(Throwable t) {failed++; t.printStackTrace();} 243 static void check(boolean cond) {if (cond) pass(); else fail();} 244 static void equal(Object x, Object y) { 245 if (x == null ? y == null : x.equals(y)) pass(); 246 else fail(x + " not equal to " + y);} 247 public static void main(String[] args) throws Throwable { 248 try {realMain(args);} catch (Throwable t) {unexpected(t);} 249 System.out.println("\nPassed = " + passed + " failed = " + failed); 250 if (failed > 0) throw new AssertionError("Some tests failed");} 251 }