1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. 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 package test.java.util.zip; 25 26 import org.testng.Assert; 27 import org.testng.annotations.DataProvider; 28 import org.testng.annotations.Test; 29 30 import java.nio.ByteBuffer; 31 import java.util.Arrays; 32 import java.util.zip.Deflater; 33 import java.util.zip.Inflater; 34 35 import static java.nio.charset.StandardCharsets.UTF_8; 36 import static org.testng.Assert.assertThrows; 37 38 /** 39 * @test 40 * @bug 8252739 41 * @summary Verify Deflater.setDictionary(dictionary, offset, length) uses the offset 42 * @run testng/othervm DeflaterDictionaryTests 43 */ 44 public class DeflaterDictionaryTests { 45 // Output buffer size 46 private static final int RESULT_SIZE = 1024; 47 // Data to compress 48 private static final String SRC_DATA = "Welcome to the US Open;".repeat(6); 49 // Dictionary to be used 50 private static final String DICTIONARY = "US Open"; 51 private static final int DICTIONARY_OFFSET = 1; 52 private static final int DICTIONARY_LENGTH = 3; 53 54 /** 55 * DataProvider with offsets which should be valid for setDictionary 56 * 57 * @return valid offset values 58 */ 59 @DataProvider(name = "validDictionaryOffsets") validDictionaryOffsets()60 protected Object[][] validDictionaryOffsets() { 61 return new Object[][]{ 62 {0}, 63 {DICTIONARY_OFFSET}, 64 {DICTIONARY_LENGTH} 65 }; 66 } 67 68 /** 69 * DataProvider with invalid offsets for setDictionary 70 * 71 * @return invalid offset values 72 */ 73 @DataProvider(name = "invalidDictionaryOffsets") invalidDictionaryOffsets()74 protected Object[][] invalidDictionaryOffsets() { 75 return new Object[][]{ 76 {-1}, 77 {DICTIONARY_LENGTH + 2}, 78 {DICTIONARY.length()} 79 }; 80 } 81 82 /** 83 * Validate that an offset can be used with Deflater::setDictionary 84 * 85 * @param dictionary_offset offset value to be used 86 * @throws Exception if an error occurs 87 */ 88 @Test(dataProvider = "validDictionaryOffsets") testByteArray(int dictionary_offset)89 public void testByteArray(int dictionary_offset) throws Exception { 90 byte[] input = SRC_DATA.getBytes(UTF_8); 91 byte[] output = new byte[RESULT_SIZE]; 92 Deflater deflater = new Deflater(); 93 Inflater inflater = new Inflater(); 94 try { 95 // Compress the bytes 96 deflater.setDictionary(DICTIONARY.getBytes(UTF_8), dictionary_offset, DICTIONARY_LENGTH); 97 deflater.setInput(input); 98 deflater.finish(); 99 int compressedDataLength = deflater.deflate(output, 0, output.length, Deflater.NO_FLUSH); 100 System.out.printf("Deflater::getTotalOut:%s, Deflater::getAdler: %s," + 101 " compressed length: %s%n", deflater.getTotalOut(), 102 deflater.getTotalOut(), compressedDataLength); 103 deflater.finished(); 104 105 // Decompress the bytes 106 inflater.setInput(output, 0, compressedDataLength); 107 byte[] result = new byte[RESULT_SIZE]; 108 int resultLength = inflater.inflate(result); 109 if (inflater.needsDictionary()) { 110 System.out.println("Specifying Dictionary"); 111 inflater.setDictionary(DICTIONARY.getBytes(UTF_8), dictionary_offset, DICTIONARY_LENGTH); 112 resultLength = inflater.inflate(result); 113 } else { 114 System.out.println("Did not need to use a Dictionary"); 115 } 116 inflater.finished(); 117 System.out.printf("Inflater::getAdler:%s, length: %s%n", 118 inflater.getAdler(), resultLength); 119 120 Assert.assertEquals(SRC_DATA.length(), resultLength); 121 Assert.assertEquals(input, Arrays.copyOf(result, resultLength)); 122 } finally { 123 // Release Resources 124 deflater.end(); 125 inflater.end(); 126 } 127 } 128 129 /** 130 * Validate that a ByteBuffer can be used with Deflater::setDictionary 131 * 132 * @throws Exception if an error occurs 133 */ 134 @Test testHeapByteBuffer()135 public void testHeapByteBuffer() throws Exception { 136 byte[] input = SRC_DATA.getBytes(UTF_8); 137 byte[] output = new byte[RESULT_SIZE]; 138 ByteBuffer dictDef = ByteBuffer.wrap(DICTIONARY.getBytes(UTF_8), DICTIONARY_OFFSET, DICTIONARY_LENGTH); 139 ByteBuffer dictInf = ByteBuffer.wrap(DICTIONARY.getBytes(UTF_8), DICTIONARY_OFFSET, DICTIONARY_LENGTH); 140 Deflater deflater = new Deflater(); 141 Inflater inflater = new Inflater(); 142 try { 143 // Compress the bytes 144 deflater.setDictionary(dictDef); 145 deflater.setInput(input); 146 deflater.finish(); 147 int compressedDataLength = deflater.deflate(output, 0, output.length, Deflater.NO_FLUSH); 148 System.out.printf("Deflater::getTotalOut:%s, Deflater::getAdler: %s," + 149 " compressed length: %s%n", deflater.getTotalOut(), 150 deflater.getTotalOut(), compressedDataLength); 151 deflater.finished(); 152 153 // Decompress the bytes 154 inflater.setInput(output, 0, compressedDataLength); 155 byte[] result = new byte[RESULT_SIZE]; 156 int resultLength = inflater.inflate(result); 157 if (inflater.needsDictionary()) { 158 System.out.println("Specifying Dictionary"); 159 inflater.setDictionary(dictInf); 160 resultLength = inflater.inflate(result); 161 } else { 162 System.out.println("Did not need to use a Dictionary"); 163 } 164 inflater.finished(); 165 System.out.printf("Inflater::getAdler:%s, length: %s%n", 166 inflater.getAdler(), resultLength); 167 168 Assert.assertEquals(SRC_DATA.length(), resultLength); 169 Assert.assertEquals(input, Arrays.copyOf(result, resultLength)); 170 } finally { 171 // Release Resources 172 deflater.end(); 173 inflater.end(); 174 } 175 } 176 177 /** 178 * Validate that ByteBuffer::allocateDirect can be used with Deflater::setDictionary 179 * 180 * @throws Exception if an error occurs 181 */ 182 @Test testByteBufferDirect()183 public void testByteBufferDirect() throws Exception { 184 byte[] input = SRC_DATA.getBytes(UTF_8); 185 byte[] output = new byte[RESULT_SIZE]; 186 ByteBuffer dictDef = ByteBuffer.allocateDirect(DICTIONARY.length()); 187 ByteBuffer dictInf = ByteBuffer.allocateDirect(DICTIONARY.length()); 188 dictDef.put(DICTIONARY.getBytes(UTF_8)); 189 dictInf.put(DICTIONARY.getBytes(UTF_8)); 190 dictDef.position(DICTIONARY_OFFSET); 191 dictDef.limit(DICTIONARY_LENGTH); 192 dictInf.position(DICTIONARY_OFFSET); 193 dictInf.limit(DICTIONARY_LENGTH); 194 Deflater deflater = new Deflater(); 195 Inflater inflater = new Inflater(); 196 try { 197 // Compress the bytes 198 deflater.setDictionary(dictDef.slice()); 199 deflater.setInput(input); 200 deflater.finish(); 201 int compressedDataLength = deflater.deflate(output, 0, output.length, Deflater.NO_FLUSH); 202 System.out.printf("Deflater::getTotalOut:%s, Deflater::getAdler: %s," + 203 " compressed length: %s%n", deflater.getTotalOut(), 204 deflater.getTotalOut(), compressedDataLength); 205 deflater.finished(); 206 207 // Decompress the bytes 208 inflater.setInput(output, 0, compressedDataLength); 209 byte[] result = new byte[RESULT_SIZE]; 210 int resultLength = inflater.inflate(result); 211 if (inflater.needsDictionary()) { 212 System.out.println("Specifying Dictionary"); 213 inflater.setDictionary(dictInf.slice()); 214 resultLength = inflater.inflate(result); 215 } else { 216 System.out.println("Did not need to use a Dictionary"); 217 } 218 inflater.finished(); 219 System.out.printf("Inflater::getAdler:%s, length: %s%n", 220 inflater.getAdler(), resultLength); 221 222 Assert.assertEquals(SRC_DATA.length(), resultLength); 223 Assert.assertEquals(input, Arrays.copyOf(result, resultLength)); 224 } finally { 225 // Release Resources 226 deflater.end(); 227 inflater.end(); 228 } 229 } 230 231 /** 232 * Validate that an invalid offset used with setDictionary will 233 * throw an Exception 234 * 235 * @param dictionary_offset offset value to be used 236 */ 237 @Test(dataProvider = "invalidDictionaryOffsets") testInvalidOffsets(int dictionary_offset)238 public void testInvalidOffsets(int dictionary_offset) { 239 byte[] dictionary = DICTIONARY.getBytes(UTF_8); 240 241 Deflater deflater = new Deflater(); 242 Inflater inflater = new Inflater(); 243 try { 244 assertThrows(ArrayIndexOutOfBoundsException.class, () -> 245 deflater.setDictionary(dictionary, dictionary_offset, DICTIONARY_LENGTH)); 246 assertThrows(ArrayIndexOutOfBoundsException.class, () -> 247 inflater.setDictionary(dictionary, dictionary_offset, DICTIONARY_LENGTH)); 248 } finally { 249 // Release Resources 250 deflater.end(); 251 inflater.end(); 252 } 253 } 254 }