|
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; |
|
91 | 94 | import org.junit.Assume; |
92 | 95 | import org.junit.Before; |
93 | 96 | import org.junit.ClassRule; |
| 97 | +import org.junit.Ignore; |
94 | 98 | import org.junit.Rule; |
95 | 99 | import org.junit.Test; |
96 | 100 | import org.junit.experimental.categories.Category; |
@@ -153,7 +157,10 @@ public void setUp() throws Exception { |
153 | 157 | hcd.setMaxVersions(65536); |
154 | 158 | this.htd.addFamily(hcd); |
155 | 159 | } |
156 | | - if (name.getMethodName().equals("testCompactionWithCorruptBlock")) { |
| 160 | + if ( |
| 161 | + name.getMethodName().equals("testCompactionWithCorruptBlock") |
| 162 | + || name.getMethodName().equals("generateHFileForCorruptBlockTest") |
| 163 | + ) { |
157 | 164 | UTIL.getConfiguration().setBoolean("hbase.hstore.validate.read_fully", true); |
158 | 165 | HColumnDescriptor hcd = new HColumnDescriptor(FAMILY); |
159 | 166 | hcd.setCompressionType(Compression.Algorithm.GZ); |
@@ -378,9 +385,38 @@ public void testCompactionWithCorruptResult() throws Exception { |
378 | 385 | assertTrue(fs.exists(tmpPath)); |
379 | 386 | } |
380 | 387 |
|
| 388 | + /** |
| 389 | + * Generates the HFile used by {@link #testCompactionWithCorruptBlock()}. Run this method to |
| 390 | + * regenerate the test resource file after changes to the HFile format. The output file must then |
| 391 | + * be hand-edited to corrupt the first data block (zero out the GZip magic bytes at offset 33) |
| 392 | + * before being placed into the test resources directory. |
| 393 | + */ |
| 394 | + @Ignore("Not a test; utility for regenerating testCompactionWithCorruptBlock resource file") |
| 395 | + @Test |
| 396 | + public void generateHFileForCorruptBlockTest() throws Exception { |
| 397 | + createStoreFile(r, Bytes.toString(FAMILY)); |
| 398 | + createStoreFile(r, Bytes.toString(FAMILY)); |
| 399 | + HStore store = r.getStore(FAMILY); |
| 400 | + |
| 401 | + Collection<HStoreFile> storeFiles = store.getStorefiles(); |
| 402 | + DefaultCompactor tool = (DefaultCompactor) store.storeEngine.getCompactor(); |
| 403 | + CompactionRequestImpl request = new CompactionRequestImpl(storeFiles); |
| 404 | + List<Path> paths = tool.compact(request, NoLimitThroughputController.INSTANCE, null); |
| 405 | + |
| 406 | + FileSystem fs = store.getFileSystem(); |
| 407 | + Path hfilePath = paths.get(0); |
| 408 | + File outFile = new File("/tmp/TestCompaction_HFileWithCorruptBlock.gz"); |
| 409 | + try (InputStream in = fs.open(hfilePath); |
| 410 | + GZIPOutputStream gzOut = new GZIPOutputStream(new FileOutputStream(outFile))) { |
| 411 | + IOUtils.copyBytes(in, gzOut, 4096); |
| 412 | + } |
| 413 | + LoggerFactory.getLogger(TestCompaction.class) |
| 414 | + .info("Wrote HFile to {}. Now hex-edit offset 33 (0x21): zero out bytes 1f 8b.", outFile); |
| 415 | + } |
| 416 | + |
381 | 417 | /** |
382 | 418 | * This test uses a hand-modified HFile, which is loaded in from the resources' path. That file |
383 | | - * was generated from the test support code in this class and then edited to corrupt the |
| 419 | + * was generated from {@link #generateHFileForCorruptBlockTest()} and then edited to corrupt the |
384 | 420 | * GZ-encoded block by zeroing-out the first two bytes of the GZip header, the "standard |
385 | 421 | * declaration" of {@code 1f 8b}, found at offset 33 in the file. I'm not sure why, but it seems |
386 | 422 | * that in this test context we do not enforce CRC checksums. Thus, this corruption manifests in |
|
0 commit comments