|
40 | 40 | import static org.mockito.Mockito.spy; |
41 | 41 | import static org.mockito.Mockito.when; |
42 | 42 |
|
| 43 | +import java.io.File; |
| 44 | +import java.io.FileOutputStream; |
43 | 45 | import java.io.IOException; |
44 | 46 | import java.io.InputStream; |
45 | 47 | import java.io.OutputStream; |
|
52 | 54 | import java.util.concurrent.CountDownLatch; |
53 | 55 | import java.util.concurrent.TimeUnit; |
54 | 56 | import java.util.zip.GZIPInputStream; |
| 57 | +import java.util.zip.GZIPOutputStream; |
55 | 58 | import org.apache.hadoop.conf.Configuration; |
56 | 59 | import org.apache.hadoop.fs.FSDataOutputStream; |
57 | 60 | import org.apache.hadoop.fs.FileStatus; |
|
93 | 96 | import org.junit.Assume; |
94 | 97 | import org.junit.Before; |
95 | 98 | import org.junit.ClassRule; |
| 99 | +import org.junit.Ignore; |
96 | 100 | import org.junit.Rule; |
97 | 101 | import org.junit.Test; |
98 | 102 | import org.junit.experimental.categories.Category; |
@@ -156,7 +160,10 @@ public void setUp() throws Exception { |
156 | 160 | ColumnFamilyDescriptorBuilder.newBuilder(FAMILY).setMaxVersions(65536).build(); |
157 | 161 | builder.setColumnFamily(familyDescriptor); |
158 | 162 | } |
159 | | - if (name.getMethodName().equals("testCompactionWithCorruptBlock")) { |
| 163 | + if ( |
| 164 | + name.getMethodName().equals("testCompactionWithCorruptBlock") |
| 165 | + || name.getMethodName().equals("generateHFileForCorruptBlockTest") |
| 166 | + ) { |
160 | 167 | UTIL.getConfiguration().setBoolean("hbase.hstore.validate.read_fully", true); |
161 | 168 | ColumnFamilyDescriptor familyDescriptor = ColumnFamilyDescriptorBuilder.newBuilder(FAMILY) |
162 | 169 | .setCompressionType(Compression.Algorithm.GZ).build(); |
@@ -382,9 +389,38 @@ public void testCompactionWithCorruptResult() throws Exception { |
382 | 389 | assertTrue(fs.exists(tmpPath)); |
383 | 390 | } |
384 | 391 |
|
| 392 | + /** |
| 393 | + * Generates the HFile used by {@link #testCompactionWithCorruptBlock()}. Run this method to |
| 394 | + * regenerate the test resource file after changes to the HFile format. The output file must then |
| 395 | + * be hand-edited to corrupt the first data block (zero out the GZip magic bytes at offset 33) |
| 396 | + * before being placed into the test resources directory. |
| 397 | + */ |
| 398 | + @Ignore("Not a test; utility for regenerating testCompactionWithCorruptBlock resource file") |
| 399 | + @Test |
| 400 | + public void generateHFileForCorruptBlockTest() throws Exception { |
| 401 | + createStoreFile(r, Bytes.toString(FAMILY)); |
| 402 | + createStoreFile(r, Bytes.toString(FAMILY)); |
| 403 | + HStore store = r.getStore(FAMILY); |
| 404 | + |
| 405 | + Collection<HStoreFile> storeFiles = store.getStorefiles(); |
| 406 | + DefaultCompactor tool = (DefaultCompactor) store.storeEngine.getCompactor(); |
| 407 | + CompactionRequestImpl request = new CompactionRequestImpl(storeFiles); |
| 408 | + List<Path> paths = tool.compact(request, NoLimitThroughputController.INSTANCE, null); |
| 409 | + |
| 410 | + FileSystem fs = store.getFileSystem(); |
| 411 | + Path hfilePath = paths.get(0); |
| 412 | + File outFile = new File("/tmp/TestCompaction_HFileWithCorruptBlock.gz"); |
| 413 | + try (InputStream in = fs.open(hfilePath); |
| 414 | + GZIPOutputStream gzOut = new GZIPOutputStream(new FileOutputStream(outFile))) { |
| 415 | + IOUtils.copyBytes(in, gzOut, 4096); |
| 416 | + } |
| 417 | + LoggerFactory.getLogger(TestCompaction.class) |
| 418 | + .info("Wrote HFile to {}. Now hex-edit offset 33 (0x21): zero out bytes 1f 8b.", outFile); |
| 419 | + } |
| 420 | + |
385 | 421 | /** |
386 | 422 | * This test uses a hand-modified HFile, which is loaded in from the resources' path. That file |
387 | | - * was generated from the test support code in this class and then edited to corrupt the |
| 423 | + * was generated from {@link #generateHFileForCorruptBlockTest()} and then edited to corrupt the |
388 | 424 | * GZ-encoded block by zeroing-out the first two bytes of the GZip header, the "standard |
389 | 425 | * declaration" of {@code 1f 8b}, found at offset 33 in the file. I'm not sure why, but it seems |
390 | 426 | * that in this test context we do not enforce CRC checksums. Thus, this corruption manifests in |
|
0 commit comments