View Javadoc
1   package nom.tam.image.compression.hdu;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.ByteArrayOutputStream;
5   import java.io.File;
6   import java.io.IOException;
7   import java.nio.Buffer;
8   import java.nio.ByteBuffer;
9   import java.util.Random;
10  import java.util.zip.GZIPInputStream;
11  
12  import org.junit.Assert;
13  import org.junit.Test;
14  
15  import nom.tam.fits.BinaryTable;
16  import nom.tam.fits.BinaryTableHDU;
17  import nom.tam.fits.Fits;
18  import nom.tam.fits.FitsException;
19  import nom.tam.fits.Header;
20  import nom.tam.fits.HeaderCard;
21  import nom.tam.fits.compression.algorithm.api.ICompressOption;
22  import nom.tam.fits.compression.algorithm.api.ICompressorControl;
23  import nom.tam.fits.header.Compression;
24  import nom.tam.fits.header.IFitsHeader;
25  import nom.tam.fits.header.Standard;
26  import nom.tam.fits.util.BlackBoxImages;
27  import nom.tam.image.compression.bintable.BinaryTableTileCompressor;
28  import nom.tam.image.compression.bintable.BinaryTableTileDecompressor;
29  import nom.tam.image.compression.bintable.BinaryTableTileDescription;
30  import nom.tam.util.ColumnTable;
31  import nom.tam.util.Cursor;
32  import nom.tam.util.SafeClose;
33  
34  /*
35   * #%L
36   * nom.tam FITS library
37   * %%
38   * Copyright (C) 1996 - 2024 nom-tam-fits
39   * %%
40   * This is free and unencumbered software released into the public domain.
41   *
42   * Anyone is free to copy, modify, publish, use, compile, sell, or
43   * distribute this software, either in source code form or as a compiled
44   * binary, for any purpose, commercial or non-commercial, and by any
45   * means.
46   *
47   * In jurisdictions that recognize copyright laws, the author or authors
48   * of this software dedicate any and all copyright interest in the
49   * software to the public domain. We make this dedication for the benefit
50   * of the public at large and to the detriment of our heirs and
51   * successors. We intend this dedication to be an overt act of
52   * relinquishment in perpetuity of all present and future rights to this
53   * software under copyright law.
54   *
55   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
56   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
57   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
58   * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
59   * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
60   * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
61   * OTHER DEALINGS IN THE SOFTWARE.
62   * #L%
63   */
64  
65  import static nom.tam.fits.header.Standard.XTENSION_BINTABLE;
66  import static nom.tam.image.compression.bintable.BinaryTableTileDescription.tile;
67  
68  public class CompressedTableTest {
69  
70      private final double[][][] doubles = new double[50][5][5];
71  
72      public CompressedTableTest() {
73          super();
74          Random random = new Random();
75          for (int i1 = 0; i1 < doubles.length; i1++) {
76              for (int i2 = 0; i2 < doubles[i1].length; i2++) {
77                  for (int i3 = 0; i3 < doubles[i1][i2].length; i3++) {
78                      doubles[i1][i2][i3] = random.nextDouble();
79                  }
80              }
81          }
82      }
83  
84      @Test
85      public void testBasicBinaryTable() throws Exception {
86  
87          Fits fitsComp = new Fits("src/test/resources/nom/tam/table/comp/testBinaryTable.fits.fz");
88          CompressedTableHDU cfitsioTable = (CompressedTableHDU) fitsComp.getHDU(1);
89  
90          cfitsioTable.info(System.out);
91  
92          BinaryTableHDU binaryTable2HDU = cfitsioTable.asBinaryTableHDU();
93  
94          Fits fits = new Fits();
95          fits.addHDU(binaryTable2HDU);
96          fits.write(new File("target/testBinaryTable_uncompressed.fits"));
97          fits.close();
98  
99          CompressedTableHDU compressed = CompressedTableHDU.fromBinaryTableHDU(binaryTable2HDU, 10).compress();
100         compressed.compress();
101         fits = new Fits();
102         fits.addHDU(compressed);
103         fits.write(new File("target/testBinaryTable_recompressed.fits"));
104         fits.close();
105 
106         fits = new Fits("target/testBinaryTable_uncompressed.fits");
107         Header header = fits.getHDU(1).getHeader();
108         Cursor<String, HeaderCard> iter = header.iterator();
109         assertStringCard(Standard.XTENSION, XTENSION_BINTABLE, iter.next());
110         assertIntCard(Standard.BITPIX, 8, iter.next());
111         assertIntCard(Standard.NAXIS, 2, iter.next());
112         assertIntCard(Standard.NAXISn.n(1), 200, iter.next());
113         assertIntCard(Standard.NAXISn.n(2), 50, iter.next());
114         assertIntCard(Standard.PCOUNT, 0, iter.next());
115         assertIntCard(Standard.GCOUNT, 1, iter.next());
116         assertIntCard(Standard.TFIELDS, 1, iter.next());
117         // the order of the next two fields is not fix
118         assertStringCard(Standard.TFORMn.n(1), "25D", header.card(Standard.TFORMn.n(1)).card());
119         assertStringCard(Standard.TDIMn.n(1), "(5,5)", header.card(Standard.TDIMn.n(1)).card());
120         fits.close();
121 
122         fits = new Fits("target/testBinaryTable_recompressed.fits");
123         header = fits.getHDU(1).getHeader();
124         iter = header.iterator();
125         assertStringCard(Standard.XTENSION, XTENSION_BINTABLE, iter.next());
126         assertIntCard(Standard.BITPIX, 8, iter.next());
127         assertIntCard(Standard.NAXIS, 2, iter.next());
128         assertIntCard(Standard.NAXISn.n(1), 8, iter.next());
129         assertIntCard(Standard.NAXISn.n(2), 5, iter.next());
130 
131         HeaderCard hc = iter.next();
132         Assert.assertEquals(Standard.PCOUNT.key(), hc.getKey());
133         Assert.assertNotEquals((long) hc.getValue(Long.class, 0L), 0L);
134 
135         assertIntCard(Standard.GCOUNT, 1, iter.next());
136         assertIntCard(Standard.TFIELDS, 1, iter.next());
137         // the order of the next two fields is not fix
138         assertStringCard(Standard.TFORMn.n(1), "1PB", header.card(Standard.TFORMn.n(1)).card());
139         assertStringCard(Standard.TDIMn.n(1), "(5,5)", header.card(Standard.TDIMn.n(1)).card());
140         fits.close();
141     }
142 
143     @Test
144     public void testCompressedVarTable() throws Exception {
145         String compressedVarTable = BlackBoxImages.getBlackBoxImage("map_one_source_a_level_1_cal.fits.fz");
146         Fits fitsComp = new Fits(compressedVarTable);
147         CompressedTableHDU cfitsioTable = (CompressedTableHDU) fitsComp.getHDU(1);
148 
149         cfitsioTable.info(System.out);
150 
151         BinaryTableHDU binaryTable2HDU = cfitsioTable.asBinaryTableHDU();
152         Fits fits = new Fits();
153         fits.addHDU(binaryTable2HDU);
154         fits.write(new File("target/map_one_source_a_level_1_cal_uncompressed.fits"));
155         fits.close();
156         fitsComp.close();
157 
158         fits = new Fits("target/map_one_source_a_level_1_cal_uncompressed.fits");
159         BinaryTableHDU table = (BinaryTableHDU) fits.getHDU(1);
160 
161         Assert.assertNotNull(table); // table could be read.
162 
163         Assert.assertEquals(21, table.getNCols());
164         Assert.assertEquals(1, table.getNRows());
165 
166         String originalVarTable = BlackBoxImages.getBlackBoxImage("map_one_source_a_level_1_cal.fits");
167         Fits fitsOrg = new Fits(originalVarTable);
168         Header orgHeader = fitsOrg.getHDU(1).getHeader();
169 
170         Assert.assertEquals(orgHeader.getSize(), table.getHeader().getSize());
171         Cursor<String, HeaderCard> iterator = orgHeader.iterator();
172         while (iterator.hasNext()) {
173             HeaderCard headerCard = iterator.next();
174             String uncompressed = table.getHeader().getStringValue(headerCard.getKey());
175             String original = orgHeader.getStringValue(headerCard.getKey());
176             if (uncompressed != null || original != null) {
177                 Assert.assertEquals(original, uncompressed);
178             }
179         }
180         fitsOrg.close();
181     }
182 
183     private void assertIntCard(IFitsHeader expectedKey, int expectedValue, HeaderCard card) {
184         Assert.assertEquals(expectedKey.key(), card.getKey());
185         Assert.assertEquals(Integer.valueOf(expectedValue), card.getValue(Integer.class, -1));
186     }
187 
188     private void assertStringCard(IFitsHeader expectedKey, String expectedValue, HeaderCard card) {
189         Assert.assertEquals(expectedKey.key(), card.getKey());
190         Assert.assertEquals(expectedValue, card.getValue());
191     }
192 
193     @Test
194     public void testB12TableDecompress() throws Exception {
195         Fits fitsComp = null;
196         Fits fitsOrg = null;
197         try {
198             fitsOrg = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
199             fitsComp = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits.fz");
200             CompressedTableHDU cfitsioTable = (CompressedTableHDU) fitsComp.getHDU(1);
201             BinaryTableHDU orgTable = (BinaryTableHDU) fitsOrg.getHDU(1);
202             BinaryTableHDU decompressedTable = cfitsioTable.asBinaryTableHDU();
203 
204             for (int row = 0; row < 50; row++) {
205                 Object decompressedElement = decompressedTable.getElement(row, 0);
206                 Object orgElement = orgTable.getElement(row, 0);
207                 Assert.assertEquals(orgElement, decompressedElement);
208                 decompressedElement = decompressedTable.getElement(row, 1);
209                 orgElement = orgTable.getElement(row, 1);
210                 Assert.assertArrayEquals((short[]) orgElement, (short[]) decompressedElement);
211                 decompressedElement = decompressedTable.getElement(row, 2);
212                 orgElement = orgTable.getElement(row, 2);
213                 Assert.assertArrayEquals((float[][]) orgElement, (float[][]) decompressedElement);
214                 decompressedElement = decompressedTable.getElement(row, 3);
215                 orgElement = orgTable.getElement(row, 3);
216                 Assert.assertArrayEquals((double[]) orgElement, (double[]) decompressedElement, 0.000000001d);
217                 decompressedElement = decompressedTable.getElement(row, 4);
218                 orgElement = orgTable.getElement(row, 4);
219                 Assert.assertArrayEquals((String[]) orgElement, (String[]) decompressedElement);
220             }
221 
222         } finally {
223             SafeClose.close(fitsComp);
224         }
225     }
226 
227     @Test
228     public void testB12TableCompress() throws Exception {
229         Fits fitsComp = null;
230         Fits fitsUncompressed = null;
231         Fits fitsOrg = null;
232         try {
233             fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
234 
235             CompressedTableHDU compressedTable = CompressedTableHDU
236                     .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), 0).compress();
237             compressedTable.compress();
238 
239             fitsOrg = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits.fz");
240             BinaryTableHDU orgTable = (BinaryTableHDU) fitsOrg.getHDU(1);
241 
242             for (int column = 0; column < 5; column++) {
243                 Object decompressedElement = compressedTable.getElement(0, column);
244                 Object orgElement = orgTable.getElement(0, column);
245                 byte[] decompressed = decompress(decompressedElement);
246                 byte[] org = decompress(orgElement);
247                 if (column == 3) {
248                     org = unshuffle(org, 8);
249                     decompressed = unshuffle(decompressed, 8);
250                 }
251                 Assert.assertArrayEquals("column " + column, org, decompressed);
252             }
253 
254         } finally {
255             SafeClose.close(fitsComp);
256         }
257     }
258 
259     private int[] calculateOffsets(byte[] byteArray, int primitiveSize) {
260         int[] offset = new int[primitiveSize];
261         offset[0] = 0;
262         for (int primitivIndex = 1; primitivIndex < primitiveSize; primitivIndex++) {
263             offset[primitivIndex] = offset[primitivIndex - 1] + byteArray.length / primitiveSize;
264         }
265         return offset;
266     }
267 
268     public byte[] unshuffle(byte[] byteArray, int primitiveSize) {
269         byte[] result = new byte[byteArray.length];
270         int resultIndex = 0;
271         int[] offset = calculateOffsets(byteArray, primitiveSize);
272         for (int index = 0; index < byteArray.length; index += primitiveSize) {
273             for (int primitiveIndex = 0; primitiveIndex < primitiveSize; primitiveIndex++) {
274                 result[index + primitiveIndex] = byteArray[resultIndex + offset[primitiveIndex]];
275             }
276             resultIndex++;
277         }
278         return result;
279     }
280 
281     private byte[] decompress(Object decompressedElement) throws IOException {
282         if (decompressedElement instanceof byte[]) {
283             if (((byte[]) decompressedElement)[0] != 31 && ((byte[]) decompressedElement)[1] != -117) {
284                 return (byte[]) decompressedElement;
285             }
286         }
287         ByteArrayOutputStream decompressed = new ByteArrayOutputStream();
288         byte[] buffer = new byte[1024];
289         GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream((byte[]) decompressedElement));
290         int count;
291         while ((count = gzipInputStream.read(buffer)) >= 0) {
292             decompressed.write(buffer, 0, count);
293         }
294         return decompressed.toByteArray();
295     }
296 
297     @Test
298     public void testB12TableTileDecompress() throws Exception {
299         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
300         int tileSize = 5;
301 
302         CompressedTableHDU compressedTable = CompressedTableHDU
303                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
304         compressedTable.compress();
305 
306         BinaryTableHDU hdu = compressedTable.asBinaryTableHDU(1);
307 
308         Assert.assertEquals(tileSize, hdu.getNRows());
309 
310         BinaryTableHDU hdu0 = (BinaryTableHDU) fitsUncompressed.getHDU(1);
311 
312         BinaryTable tab0 = hdu0.getData();
313         BinaryTable tab = hdu.getData();
314 
315         for (int row = 0; row < hdu.getNRows(); row++) {
316             int row0 = tileSize + row;
317             Assert.assertEquals("row " + row, tab0.getElement(row0, 0), tab.getElement(row, 0));
318             Assert.assertArrayEquals("row " + row, (short[]) tab0.getElement(row0, 1), (short[]) tab.getElement(row, 1));
319 
320             float[][] f0 = (float[][]) tab0.getElement(row0, 2);
321             float[][] f = (float[][]) tab.getElement(row, 2);
322             Assert.assertEquals(f0.length, f.length);
323             for (int j = 0; j < f0.length; j++) {
324                 Assert.assertArrayEquals(f0[j], f[j], 1e-4f);
325             }
326 
327             Assert.assertArrayEquals("row " + row, (double[]) tab0.getElement(row0, 3), (double[]) tab.getElement(row, 3),
328                     1e-8);
329 
330             String[] s0 = (String[]) tab0.getElement(row0, 4);
331             String[] s = (String[]) tab.getElement(row, 4);
332             Assert.assertEquals(s0.length, s.length);
333             for (int j = 0; j < s0.length; j++) {
334                 Assert.assertEquals(s0[j], s[j]);
335             }
336         }
337 
338         fitsUncompressed.close();
339     }
340 
341     @Test
342     public void testB12TableDecompressColumn() throws Exception {
343         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
344         int tileSize = 5;
345 
346         CompressedTableHDU compressedTable = CompressedTableHDU
347                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
348         compressedTable.compress();
349 
350         String[] s = (String[]) compressedTable.getColumnData(0, 1, 3);
351 
352         Assert.assertEquals(2 * tileSize, s.length);
353 
354         BinaryTableHDU hdu0 = (BinaryTableHDU) fitsUncompressed.getHDU(1);
355 
356         BinaryTable tab0 = hdu0.getData();
357 
358         for (int row = 0; row < s.length; row++) {
359             int row0 = tileSize + row;
360             Assert.assertEquals("row " + row, tab0.getElement(row0, 0), s[row]);
361         }
362 
363         fitsUncompressed.close();
364     }
365 
366     @Test
367     public void testB12TableDecompressFullColumn() throws Exception {
368         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
369         int tileSize = 6; // Non-divisor tile size...
370 
371         BinaryTableHDU hdu0 = (BinaryTableHDU) fitsUncompressed.getHDU(1);
372         CompressedTableHDU compressedTable = CompressedTableHDU.fromBinaryTableHDU(hdu0, tileSize).compress();
373         compressedTable.compress();
374 
375         String[] s = (String[]) compressedTable.getColumnData(0);
376 
377         Assert.assertEquals(hdu0.getNRows(), s.length);
378 
379         BinaryTable tab0 = hdu0.getData();
380 
381         for (int row = 0; row < s.length; row++) {
382             Assert.assertEquals("row " + row, tab0.getElement(row, 0), s[row]);
383         }
384 
385         fitsUncompressed.close();
386     }
387 
388     @Test(expected = IllegalArgumentException.class)
389     public void testB12TableDecompressNegativeTileStart() throws Exception {
390         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
391         int tileSize = 5;
392 
393         CompressedTableHDU compressedTable = CompressedTableHDU
394                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
395         compressedTable.compress();
396         compressedTable.getColumnData(0, -1, 3);
397     }
398 
399     @Test(expected = IllegalArgumentException.class)
400     public void testB12TableDecompressOutOfBoundsTileStart() throws Exception {
401         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
402         int tileSize = 5;
403 
404         CompressedTableHDU compressedTable = CompressedTableHDU
405                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
406         compressedTable.compress();
407         compressedTable.getColumnData(0, compressedTable.getNRows(), 3);
408     }
409 
410     @Test(expected = IllegalArgumentException.class)
411     public void testB12TableDecompressOutOfBoundsTileEnd() throws Exception {
412         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
413         int tileSize = 5;
414 
415         CompressedTableHDU compressedTable = CompressedTableHDU
416                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
417         compressedTable.compress();
418         compressedTable.getColumnData(0, 1, compressedTable.getNRows() + 1);
419     }
420 
421     @Test(expected = FitsException.class)
422     public void testB12TableDecompressNoZTILELEN() throws Exception {
423         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
424         int tileSize = 5;
425 
426         CompressedTableHDU compressedTable = CompressedTableHDU
427                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
428         compressedTable.compress();
429         compressedTable.getHeader().deleteKey(Compression.ZTILELEN);
430         compressedTable.getTileRows(); // Throws exception...
431     }
432 
433     @Test(expected = FitsException.class)
434     public void testB12TableDecompressInvalidZTILELEN() throws Exception {
435         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
436         int tileSize = 5;
437 
438         CompressedTableHDU compressedTable = CompressedTableHDU
439                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
440         compressedTable.compress();
441         compressedTable.addValue(Compression.ZTILELEN, 0);
442         compressedTable.getTileRows(); // Throws exception...
443     }
444 
445     @Test
446     public void testB12TableDecompressEmptyRange() throws Exception {
447         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
448         int tileSize = 5;
449 
450         CompressedTableHDU compressedTable = CompressedTableHDU
451                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
452         compressedTable.compress();
453         Assert.assertNull(compressedTable.getColumnData(0, 1, 1));
454     }
455 
456     @Test(expected = IllegalArgumentException.class)
457     public void testB12TableDecompressInvalidTileFrom() throws Exception {
458         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
459         int tileSize = 5;
460 
461         CompressedTableHDU compressedTable = CompressedTableHDU
462                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
463         compressedTable.compress();
464         compressedTable.asBinaryTableHDU(-1);
465     }
466 
467     @Test(expected = IllegalArgumentException.class)
468     public void testB12TableDecompressInvalidTileTo() throws Exception {
469         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
470         int tileSize = 5;
471 
472         CompressedTableHDU compressedTable = CompressedTableHDU
473                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
474         compressedTable.compress();
475         compressedTable.asBinaryTableHDU(0, compressedTable.getTileCount() + 1);
476     }
477 
478     @Test(expected = IllegalArgumentException.class)
479     public void testB12TableDecompressEmptyTileRange() throws Exception {
480         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
481         int tileSize = 5;
482 
483         CompressedTableHDU compressedTable = CompressedTableHDU
484                 .fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), tileSize).compress();
485         compressedTable.compress();
486         compressedTable.asBinaryTableHDU(0, 0);
487     }
488 
489     @Test(expected = IllegalArgumentException.class)
490     public void testB12TableCompressIllegalAlgo() throws Exception {
491         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
492         CompressedTableHDU.fromBinaryTableHDU((BinaryTableHDU) fitsUncompressed.getHDU(1), 0, "BLAH");
493     }
494 
495     @Test
496     public void testB12TableCompressPrepTwice() throws Exception {
497         Fits fitsUncompressed = new Fits("src/test/resources/nom/tam/table/comp/bt12.fits");
498         BinaryTableHDU hdu = (BinaryTableHDU) fitsUncompressed.getHDU(1);
499         CompressedTableHDU cHDU = CompressedTableHDU.fromBinaryTableHDU(hdu, 0);
500         cHDU.getData().prepareUncompressedData(hdu.getData().getData());
501         cHDU.getData().prepareUncompressedData(hdu.getData().getData());
502         // No exception.
503     }
504 
505     @Test
506     public void testFixedTableCompressDefragment() throws Exception {
507         BinaryTable btab = new BinaryTable();
508         btab.addColumn(BinaryTable.ColumnDesc.createForFixedArrays(int.class, 6));
509         for (int i = 0; i < 100; i++) {
510             btab.addRowEntries(new int[] {i, i + 1, i + 2, i + 3, i + 4, i + 5});
511         }
512 
513         CompressedTableHDU chdu = CompressedTableHDU.fromBinaryTableHDU(btab.toHDU(), 0);
514         chdu.getData().defragment(); // No exception.
515     }
516 
517     @Test
518     public void testVLACompressDefragment() throws Exception {
519         BinaryTable btab = new BinaryTable();
520         btab.addColumn(BinaryTable.ColumnDesc.createForVariableSize(int.class));
521         for (int i = 0; i < 100; i++) {
522             btab.addRowEntries(new int[] {i, i + 1, i + 2, i + 3, i + 4, i + 5});
523         }
524 
525         CompressedTableHDU chdu = CompressedTableHDU.fromBinaryTableHDU(btab.toHDU(), 0);
526         Assert.assertEquals(0, chdu.getData().defragment());
527     }
528 
529     @Test
530     public void testSetReversedVLAIndices() throws Exception {
531         try {
532             Assert.assertFalse(CompressedTableHDU.hasOldStandardVLAIndexing());
533             CompressedTableHDU.useOldStandardVLAIndexing(true);
534             Assert.assertTrue(CompressedTableHDU.hasOldStandardVLAIndexing());
535             CompressedTableHDU.useOldStandardVLAIndexing(false);
536             Assert.assertFalse(CompressedTableHDU.hasOldStandardVLAIndexing());
537         } finally {
538             CompressedTableHDU.useOldStandardVLAIndexing(false);
539         }
540     }
541 
542     @Test
543     public void testBinaryTableTileFillHeader() throws Exception {
544         ColumnTable<?> tab = new ColumnTable<>();
545         tab.addColumn(int.class, 10);
546         BinaryTableTileDecompressor tile = new BinaryTableTileDecompressor(new CompressedTableData(), tab, tile()//
547                 .rowStart(0)//
548                 .rowEnd(10)//
549                 .column(0)//
550                 .tileIndex(1)//
551                 .compressionAlgorithm("BLAH"));
552 
553         Header h = new Header();
554         tile.fillHeader(h);
555         Assert.assertEquals("BLAH", h.getStringValue(Compression.ZCTYPn.n(1)));
556     }
557 
558     @Test(expected = IllegalStateException.class)
559     public void testBinaryTableTileCompressorError() throws Exception {
560         class MyCompressor extends BinaryTableTileCompressor {
561             public MyCompressor(CompressedTableData compressedTable, ColumnTable<?> table,
562                     BinaryTableTileDescription description) {
563 
564                 super(compressedTable, table, description);
565                 // TODO Auto-generated constructor stub
566             }
567 
568             public ICompressorControl getCompressorControl() {
569                 return new ICompressorControl() {
570 
571                     @Override
572                     public boolean compress(Buffer in, ByteBuffer out, ICompressOption option) {
573                         return false;
574                     }
575 
576                     @Override
577                     public void decompress(ByteBuffer in, Buffer out, ICompressOption option) {
578                     }
579 
580                     @Override
581                     public ICompressOption option() {
582                         return null;
583                     }
584                 };
585             }
586         }
587 
588         MyCompressor tile = null;
589 
590         try {
591             ColumnTable<?> tab = new ColumnTable<>();
592             tab.addColumn(new int[100], 10);
593 
594             tile = new MyCompressor(new CompressedTableData(), tab, tile()//
595                     .rowStart(0)//
596                     .rowEnd(10)//
597                     .column(0)//
598                     .tileIndex(1));
599         } catch (Exception e) {
600             throw new Exception(e.getMessage(), e);
601         }
602 
603         tile.run();
604     }
605 
606 }