Skip to content

Commit 328eae9

Browse files
authored
HADOOP-16768. SnappyCompressor test cases wrongly assume that the compressed data is always smaller than the input data. (#2003)
1 parent aab9e0b commit 328eae9

File tree

2 files changed

+105
-69
lines changed

2 files changed

+105
-69
lines changed

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/compress/CompressDecompressTester.java

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ private void addPair(T compressor, E decompressor, String name) {
126126
builder.add(new TesterPair<T, E>(name, compressor, decompressor));
127127
}
128128

129-
public void test() throws InstantiationException, IllegalAccessException {
129+
public void test() throws Exception {
130130
pairs = builder.build();
131131
pairs = assertionDelegate.filterOnAssumeWhat(pairs);
132132

@@ -287,47 +287,45 @@ private boolean checkSetInputArrayIndexOutOfBoundsException(
287287

288288
@Override
289289
public void assertCompression(String name, Compressor compressor,
290-
Decompressor decompressor, byte[] rawData) {
290+
Decompressor decompressor, byte[] rawData) throws Exception {
291291

292292
int cSize = 0;
293293
int decompressedSize = 0;
294-
byte[] compressedResult = new byte[rawData.length];
294+
// Snappy compression can increase data size
295+
int maxCompressedLength = 32 + rawData.length + rawData.length/6;
296+
byte[] compressedResult = new byte[maxCompressedLength];
295297
byte[] decompressedBytes = new byte[rawData.length];
296-
try {
297-
assertTrue(
298-
joiner.join(name, "compressor.needsInput before error !!!"),
299-
compressor.needsInput());
300-
assertTrue(
298+
assertTrue(
299+
joiner.join(name, "compressor.needsInput before error !!!"),
300+
compressor.needsInput());
301+
assertEquals(
301302
joiner.join(name, "compressor.getBytesWritten before error !!!"),
302-
compressor.getBytesWritten() == 0);
303-
compressor.setInput(rawData, 0, rawData.length);
304-
compressor.finish();
305-
while (!compressor.finished()) {
306-
cSize += compressor.compress(compressedResult, 0,
307-
compressedResult.length);
308-
}
309-
compressor.reset();
310-
311-
assertTrue(
312-
joiner.join(name, "decompressor.needsInput() before error !!!"),
313-
decompressor.needsInput());
314-
decompressor.setInput(compressedResult, 0, cSize);
315-
assertFalse(
316-
joiner.join(name, "decompressor.needsInput() after error !!!"),
317-
decompressor.needsInput());
318-
while (!decompressor.finished()) {
319-
decompressedSize = decompressor.decompress(decompressedBytes, 0,
320-
decompressedBytes.length);
321-
}
322-
decompressor.reset();
323-
assertTrue(joiner.join(name, " byte size not equals error !!!"),
324-
decompressedSize == rawData.length);
325-
assertArrayEquals(
326-
joiner.join(name, " byte arrays not equals error !!!"), rawData,
327-
decompressedBytes);
328-
} catch (Exception ex) {
329-
fail(joiner.join(name, ex.getMessage()));
303+
0, compressor.getBytesWritten());
304+
compressor.setInput(rawData, 0, rawData.length);
305+
compressor.finish();
306+
while (!compressor.finished()) {
307+
cSize += compressor.compress(compressedResult, 0,
308+
compressedResult.length);
309+
}
310+
compressor.reset();
311+
312+
assertTrue(
313+
joiner.join(name, "decompressor.needsInput() before error !!!"),
314+
decompressor.needsInput());
315+
decompressor.setInput(compressedResult, 0, cSize);
316+
assertFalse(
317+
joiner.join(name, "decompressor.needsInput() after error !!!"),
318+
decompressor.needsInput());
319+
while (!decompressor.finished()) {
320+
decompressedSize = decompressor.decompress(decompressedBytes, 0,
321+
decompressedBytes.length);
330322
}
323+
decompressor.reset();
324+
assertEquals(joiner.join(name, " byte size not equals error !!!"),
325+
rawData.length, decompressedSize);
326+
assertArrayEquals(
327+
joiner.join(name, " byte arrays not equals error !!!"), rawData,
328+
decompressedBytes);
331329
}
332330
}),
333331

@@ -519,6 +517,6 @@ abstract static class TesterCompressionStrategy {
519517
protected final Logger logger = Logger.getLogger(getClass());
520518

521519
abstract void assertCompression(String name, Compressor compressor,
522-
Decompressor decompressor, byte[] originalRawData);
520+
Decompressor decompressor, byte[] originalRawData) throws Exception;
523521
}
524522
}

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/io/compress/snappy/TestSnappyCompressorDecompressor.java

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
package org.apache.hadoop.io.compress.snappy;
1919

20+
import static org.assertj.core.api.Assertions.assertThat;
2021
import static org.junit.Assert.assertEquals;
2122
import static org.junit.Assert.assertTrue;
2223
import static org.junit.Assert.fail;
@@ -44,11 +45,16 @@
4445
import org.junit.Assert;
4546
import org.junit.Before;
4647
import org.junit.Test;
48+
import org.slf4j.Logger;
49+
import org.slf4j.LoggerFactory;
4750

4851
import static org.junit.Assume.*;
4952

5053
public class TestSnappyCompressorDecompressor {
5154

55+
public static final Logger LOG =
56+
LoggerFactory.getLogger(TestSnappyCompressorDecompressor.class);
57+
5258
@Before
5359
public void before() {
5460
assumeTrue(SnappyCodec.isNativeCodeLoaded());
@@ -167,40 +173,41 @@ public void testSnappyDecompressorCompressAIOBException() {
167173
}
168174

169175
@Test
170-
public void testSnappyCompressDecompress() {
176+
public void testSnappyCompressDecompress() throws Exception {
171177
int BYTE_SIZE = 1024 * 54;
172178
byte[] bytes = BytesGenerator.get(BYTE_SIZE);
173179
SnappyCompressor compressor = new SnappyCompressor();
174-
try {
175-
compressor.setInput(bytes, 0, bytes.length);
176-
assertTrue("SnappyCompressDecompress getBytesRead error !!!",
177-
compressor.getBytesRead() > 0);
178-
assertTrue(
179-
"SnappyCompressDecompress getBytesWritten before compress error !!!",
180-
compressor.getBytesWritten() == 0);
181-
182-
byte[] compressed = new byte[BYTE_SIZE];
183-
int cSize = compressor.compress(compressed, 0, compressed.length);
184-
assertTrue(
185-
"SnappyCompressDecompress getBytesWritten after compress error !!!",
186-
compressor.getBytesWritten() > 0);
187-
188-
SnappyDecompressor decompressor = new SnappyDecompressor(BYTE_SIZE);
189-
// set as input for decompressor only compressed data indicated with cSize
190-
decompressor.setInput(compressed, 0, cSize);
191-
byte[] decompressed = new byte[BYTE_SIZE];
192-
decompressor.decompress(decompressed, 0, decompressed.length);
193-
194-
assertTrue("testSnappyCompressDecompress finished error !!!",
195-
decompressor.finished());
196-
Assert.assertArrayEquals(bytes, decompressed);
197-
compressor.reset();
198-
decompressor.reset();
199-
assertTrue("decompressor getRemaining error !!!",
200-
decompressor.getRemaining() == 0);
201-
} catch (Exception e) {
202-
fail("testSnappyCompressDecompress ex error!!!");
203-
}
180+
compressor.setInput(bytes, 0, bytes.length);
181+
assertTrue("SnappyCompressDecompress getBytesRead error !!!",
182+
compressor.getBytesRead() > 0);
183+
assertEquals(
184+
"SnappyCompressDecompress getBytesWritten before compress error !!!",
185+
0, compressor.getBytesWritten());
186+
187+
// snappy compression may increase data size.
188+
// This calculation comes from "Snappy::MaxCompressedLength(size_t)"
189+
int maxSize = 32 + BYTE_SIZE + BYTE_SIZE / 6;
190+
byte[] compressed = new byte[maxSize];
191+
int cSize = compressor.compress(compressed, 0, compressed.length);
192+
LOG.info("input size: {}", BYTE_SIZE);
193+
LOG.info("compressed size: {}", cSize);
194+
assertTrue(
195+
"SnappyCompressDecompress getBytesWritten after compress error !!!",
196+
compressor.getBytesWritten() > 0);
197+
198+
SnappyDecompressor decompressor = new SnappyDecompressor();
199+
// set as input for decompressor only compressed data indicated with cSize
200+
decompressor.setInput(compressed, 0, cSize);
201+
byte[] decompressed = new byte[BYTE_SIZE];
202+
decompressor.decompress(decompressed, 0, decompressed.length);
203+
204+
assertTrue("testSnappyCompressDecompress finished error !!!",
205+
decompressor.finished());
206+
Assert.assertArrayEquals(bytes, decompressed);
207+
compressor.reset();
208+
decompressor.reset();
209+
assertEquals("decompressor getRemaining error !!!",
210+
0, decompressor.getRemaining());
204211
}
205212

206213
@Test
@@ -278,7 +285,38 @@ public void testSnappyBlockCompression() {
278285
fail("testSnappyBlockCompression ex error !!!");
279286
}
280287
}
281-
288+
289+
@Test
290+
// The buffer size is smaller than the input.
291+
public void testSnappyCompressDecompressWithSmallBuffer() throws Exception {
292+
int inputSize = 1024 * 50;
293+
int bufferSize = 512;
294+
ByteArrayOutputStream out = new ByteArrayOutputStream();
295+
byte[] buffer = new byte[bufferSize];
296+
byte[] input = BytesGenerator.get(inputSize);
297+
298+
SnappyCompressor compressor = new SnappyCompressor();
299+
compressor.setInput(input, 0, inputSize);
300+
compressor.finish();
301+
while (!compressor.finished()) {
302+
int len = compressor.compress(buffer, 0, buffer.length);
303+
out.write(buffer, 0, len);
304+
}
305+
byte[] compressed = out.toByteArray();
306+
assertThat(compressed).hasSizeGreaterThan(0);
307+
out.reset();
308+
309+
SnappyDecompressor decompressor = new SnappyDecompressor();
310+
decompressor.setInput(compressed, 0, compressed.length);
311+
while (!decompressor.finished()) {
312+
int len = decompressor.decompress(buffer, 0, buffer.length);
313+
out.write(buffer, 0, len);
314+
}
315+
byte[] decompressed = out.toByteArray();
316+
317+
assertThat(decompressed).isEqualTo(input);
318+
}
319+
282320
private void compressDecompressLoop(int rawDataSize) throws IOException {
283321
byte[] rawData = BytesGenerator.get(rawDataSize);
284322
byte[] compressedResult = new byte[rawDataSize+20];

0 commit comments

Comments
 (0)