1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package libcore.java.util.zip; 18 19import java.io.ByteArrayOutputStream; 20import java.util.zip.Adler32; 21import java.util.zip.Deflater; 22import java.util.zip.Inflater; 23import junit.framework.TestCase; 24 25public class InflaterTest extends TestCase { 26 public void testDefaultDictionary() throws Exception { 27 assertRoundTrip(null); 28 } 29 30 public void testPresetCustomDictionary() throws Exception { 31 assertRoundTrip("dictionary".getBytes("UTF-8")); 32 } 33 34 private static void assertRoundTrip(byte[] dictionary) throws Exception { 35 // Construct a nice long input byte sequence. 36 String expected = makeString(); 37 byte[] expectedBytes = expected.getBytes("UTF-8"); 38 39 // Compress the bytes, using the passed-in dictionary (or no dictionary). 40 byte[] deflatedBytes = deflate(expectedBytes, dictionary); 41 42 // Get ready to decompress deflatedBytes back to the original bytes ... 43 Inflater inflater = new Inflater(); 44 // We'll only supply the input a little bit at a time, so that zlib has to ask for more. 45 final int CHUNK_SIZE = 16; 46 int offset = 0; 47 inflater.setInput(deflatedBytes, offset, CHUNK_SIZE); 48 offset += CHUNK_SIZE; 49 // If we used a dictionary to compress, check that we're asked for that same dictionary. 50 if (dictionary != null) { 51 // 1. there's no data available immediately... 52 assertEquals(0, inflater.inflate(new byte[8])); 53 // 2. ...because you need a dictionary. 54 assertTrue(inflater.needsDictionary()); 55 // 3. ...and that dictionary has the same Adler32 as the dictionary we used. 56 assertEquals(adler32(dictionary), inflater.getAdler()); 57 inflater.setDictionary(dictionary); 58 } 59 // Do the actual decompression, now the dictionary's set up appropriately... 60 // We use a tiny output buffer to ensure that we call inflate multiple times, and 61 // a tiny input buffer to ensure that zlib has to ask for more input. 62 ByteArrayOutputStream inflatedBytes = new ByteArrayOutputStream(); 63 byte[] buf = new byte[8]; 64 while (inflatedBytes.size() != expectedBytes.length) { 65 if (inflater.needsInput()) { 66 int nextChunkByteCount = Math.min(CHUNK_SIZE, deflatedBytes.length - offset); 67 inflater.setInput(deflatedBytes, offset, nextChunkByteCount); 68 offset += nextChunkByteCount; 69 } else { 70 int inflatedByteCount = inflater.inflate(buf); 71 if (inflatedByteCount > 0) { 72 inflatedBytes.write(buf, 0, inflatedByteCount); 73 } 74 } 75 } 76 inflater.end(); 77 78 assertEquals(expected, new String(inflatedBytes.toByteArray(), "UTF-8")); 79 } 80 81 private static String makeString() { 82 StringBuilder sb = new StringBuilder(); 83 for (int i = 0; i < 1024; ++i) { 84 // This is arbitrary but convenient in that it gives our string 85 // an easily-recognizable beginning and end. 86 sb.append(i + 1024); 87 } 88 return sb.toString(); 89 } 90 91 /** 92 * http://code.google.com/p/android/issues/detail?id=11755 93 */ 94 public void testEmptyFileAndEmptyBuffer() throws Exception { 95 byte[] emptyInput = deflate(new byte[0], null); 96 Inflater inflater = new Inflater(); 97 inflater.setInput(emptyInput); 98 assertFalse(inflater.finished()); 99 assertEquals(0, inflater.inflate(new byte[0], 0, 0)); 100 assertTrue(inflater.finished()); 101 } 102 103 private static byte[] deflate(byte[] input, byte[] dictionary) { 104 Deflater deflater = new Deflater(); 105 if (dictionary != null) { 106 deflater.setDictionary(dictionary); 107 } 108 deflater.setInput(input); 109 deflater.finish(); 110 ByteArrayOutputStream deflatedBytes = new ByteArrayOutputStream(); 111 byte[] buf = new byte[8]; 112 while (!deflater.finished()) { 113 int byteCount = deflater.deflate(buf); 114 deflatedBytes.write(buf, 0, byteCount); 115 } 116 deflater.end(); 117 return deflatedBytes.toByteArray(); 118 } 119 120 private static int adler32(byte[] bytes) { 121 Adler32 adler32 = new Adler32(); 122 adler32.update(bytes); 123 return (int) adler32.getValue(); 124 } 125 126 public void testInflaterCounts() throws Exception { 127 Inflater inflater = new Inflater(); 128 129 byte[] decompressed = new byte[32]; 130 byte[] compressed = deflate(new byte[] { 1, 2, 3}, null); 131 assertEquals(11, compressed.length); 132 133 // Feed in bytes [0, 5) to the first iteration. 134 inflater.setInput(compressed, 0, 5); 135 inflater.inflate(decompressed, 0, decompressed.length); 136 assertEquals(5, inflater.getBytesRead()); 137 assertEquals(5, inflater.getTotalIn()); 138 assertEquals(2, inflater.getBytesWritten()); 139 assertEquals(2, inflater.getTotalOut()); 140 141 // Feed in bytes [5, 11) to the second iteration. 142 assertEquals(true, inflater.needsInput()); 143 inflater.setInput(compressed, 5, 6); 144 assertEquals(1, inflater.inflate(decompressed, 0, decompressed.length)); 145 assertEquals(11, inflater.getBytesRead()); 146 assertEquals(11, inflater.getTotalIn()); 147 assertEquals(3, inflater.getBytesWritten()); 148 assertEquals(3, inflater.getTotalOut()); 149 150 inflater.reset(); 151 assertEquals(0, inflater.getBytesRead()); 152 assertEquals(0, inflater.getTotalIn()); 153 assertEquals(0, inflater.getBytesWritten()); 154 assertEquals(0, inflater.getTotalOut()); 155 } 156} 157