Modified: poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSStream.java URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSStream.java?rev=1884783&r1=1884782&r2=1884783&view=diff ============================================================================== --- poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSStream.java (original) +++ poi/trunk/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSStream.java Thu Dec 24 18:42:29 2020 @@ -20,12 +20,14 @@ package org.apache.poi.poifs.filesystem; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -52,2803 +54,2740 @@ import org.apache.poi.poifs.storage.BATB import org.apache.poi.poifs.storage.HeaderBlock; import org.apache.poi.util.IOUtils; import org.apache.poi.util.TempFile; -import org.junit.Assume; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; /** * Tests {@link POIFSStream} */ public final class TestPOIFSStream { - private static final POIDataSamples _inst = POIDataSamples.getPOIFSInstance(); + private static final POIDataSamples _inst = POIDataSamples.getPOIFSInstance(); - /** - * Read a single block stream - */ - @Test - public void testReadTinyStream() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - - // 98 is actually the last block in a two block stream... - POIFSStream stream = new POIFSStream(fs, 98); - Iterator<ByteBuffer> i = stream.getBlockIterator(); - assertTrue(i.hasNext()); - ByteBuffer b = i.next(); - assertFalse(i.hasNext()); - - // Check the contents - assertEquals((byte)0x81, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x82, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - - fs.close(); - } - - /** - * Read a stream with only two blocks in it - */ - @Test - public void testReadShortStream() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - - // 97 -> 98 -> end - POIFSStream stream = new POIFSStream(fs, 97); - Iterator<ByteBuffer> i = stream.getBlockIterator(); - assertTrue(i.hasNext()); - ByteBuffer b97 = i.next(); - assertTrue(i.hasNext()); - ByteBuffer b98 = i.next(); - assertFalse(i.hasNext()); - - // Check the contents of the 1st block - assertEquals((byte)0x01, b97.get()); - assertEquals((byte)0x00, b97.get()); - assertEquals((byte)0x00, b97.get()); - assertEquals((byte)0x00, b97.get()); - assertEquals((byte)0x02, b97.get()); - assertEquals((byte)0x00, b97.get()); - assertEquals((byte)0x00, b97.get()); - assertEquals((byte)0x00, b97.get()); - - // Check the contents of the 2nd block - assertEquals((byte)0x81, b98.get()); - assertEquals((byte)0x00, b98.get()); - assertEquals((byte)0x00, b98.get()); - assertEquals((byte)0x00, b98.get()); - assertEquals((byte)0x82, b98.get()); - assertEquals((byte)0x00, b98.get()); - assertEquals((byte)0x00, b98.get()); - assertEquals((byte)0x00, b98.get()); - - fs.close(); - } - - /** - * Read a stream with many blocks - */ - @Test - public void testReadLongerStream() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - - ByteBuffer b0 = null; - ByteBuffer b1 = null; - ByteBuffer b22 = null; - - // The stream at 0 has 23 blocks in it - POIFSStream stream = new POIFSStream(fs, 0); - Iterator<ByteBuffer> i = stream.getBlockIterator(); - int count = 0; - while(i.hasNext()) { - ByteBuffer b = i.next(); - if(count == 0) { - b0 = b; - } - if(count == 1) { - b1 = b; - } - if(count == 22) { - b22 = b; - } - - count++; - } - assertEquals(23, count); - - // Check the contents - // 1st block is at 0 - assertNotNull(b0); - assertEquals((byte)0x9e, b0.get()); - assertEquals((byte)0x75, b0.get()); - assertEquals((byte)0x97, b0.get()); - assertEquals((byte)0xf6, b0.get()); - - // 2nd block is at 1 - assertNotNull(b1); - assertEquals((byte)0x86, b1.get()); - assertEquals((byte)0x09, b1.get()); - assertEquals((byte)0x22, b1.get()); - assertEquals((byte)0xfb, b1.get()); - - // last block is at 89 - assertNotNull(b22); - assertEquals((byte)0xfe, b22.get()); - assertEquals((byte)0xff, b22.get()); - assertEquals((byte)0x00, b22.get()); - assertEquals((byte)0x00, b22.get()); - assertEquals((byte)0x05, b22.get()); - assertEquals((byte)0x01, b22.get()); - assertEquals((byte)0x02, b22.get()); - assertEquals((byte)0x00, b22.get()); - - fs.close(); - } - - /** - * Read a stream with several blocks in a 4096 byte block file - */ - @Test - public void testReadStream4096() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize4096.zvi")); - - // 0 -> 1 -> 2 -> end - POIFSStream stream = new POIFSStream(fs, 0); - Iterator<ByteBuffer> i = stream.getBlockIterator(); - assertTrue(i.hasNext()); - ByteBuffer b0 = i.next(); - assertTrue(i.hasNext()); - ByteBuffer b1 = i.next(); - assertTrue(i.hasNext()); - ByteBuffer b2 = i.next(); - assertFalse(i.hasNext()); - - // Check the contents of the 1st block - assertEquals((byte)0x9E, b0.get()); - assertEquals((byte)0x75, b0.get()); - assertEquals((byte)0x97, b0.get()); - assertEquals((byte)0xF6, b0.get()); - assertEquals((byte)0xFF, b0.get()); - assertEquals((byte)0x21, b0.get()); - assertEquals((byte)0xD2, b0.get()); - assertEquals((byte)0x11, b0.get()); - - // Check the contents of the 2nd block - assertEquals((byte)0x00, b1.get()); - assertEquals((byte)0x00, b1.get()); - assertEquals((byte)0x03, b1.get()); - assertEquals((byte)0x00, b1.get()); - assertEquals((byte)0x00, b1.get()); - assertEquals((byte)0x00, b1.get()); - assertEquals((byte)0x00, b1.get()); - assertEquals((byte)0x00, b1.get()); - - // Check the contents of the 3rd block - assertEquals((byte)0x6D, b2.get()); - assertEquals((byte)0x00, b2.get()); - assertEquals((byte)0x00, b2.get()); - assertEquals((byte)0x00, b2.get()); - assertEquals((byte)0x03, b2.get()); - assertEquals((byte)0x00, b2.get()); - assertEquals((byte)0x46, b2.get()); - assertEquals((byte)0x00, b2.get()); - - fs.close(); - } - - /** - * Craft a nasty file with a loop, and ensure we don't get stuck - */ - @Test - public void testReadFailsOnLoop() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - - // Hack the FAT so that it goes 0->1->2->0 - fs.setNextBlock(0, 1); - fs.setNextBlock(1, 2); - fs.setNextBlock(2, 0); - - // Now try to read - POIFSStream stream = new POIFSStream(fs, 0); - Iterator<ByteBuffer> i = stream.getBlockIterator(); - assertTrue(i.hasNext()); - - // 1st read works - i.next(); - assertTrue(i.hasNext()); - - // 2nd read works - i.next(); - assertTrue(i.hasNext()); - - // 3rd read works - i.next(); - assertTrue(i.hasNext()); - - // 4th read blows up as it loops back to 0 - try { - i.next(); - fail("Loop should have been detected but wasn't!"); - } catch(RuntimeException e) { - // Good, it was detected - } - assertTrue(i.hasNext()); - - fs.close(); - } - - /** - * Tests that we can load some streams that are - * stored in the mini stream. - */ - @Test - public void testReadMiniStreams() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - POIFSMiniStore ministore = fs.getMiniStore(); - - // 178 -> 179 -> 180 -> end - POIFSStream stream = new POIFSStream(ministore, 178); - Iterator<ByteBuffer> i = stream.getBlockIterator(); - assertTrue(i.hasNext()); - ByteBuffer b178 = i.next(); - assertTrue(i.hasNext()); - ByteBuffer b179 = i.next(); - assertTrue(i.hasNext()); - ByteBuffer b180 = i.next(); - assertFalse(i.hasNext()); - - // Check the contents of the 1st block - assertEquals((byte)0xfe, b178.get()); - assertEquals((byte)0xff, b178.get()); - assertEquals((byte)0x00, b178.get()); - assertEquals((byte)0x00, b178.get()); - assertEquals((byte)0x05, b178.get()); - assertEquals((byte)0x01, b178.get()); - assertEquals((byte)0x02, b178.get()); - assertEquals((byte)0x00, b178.get()); - - // And the 2nd - assertEquals((byte)0x6c, b179.get()); - assertEquals((byte)0x00, b179.get()); - assertEquals((byte)0x00, b179.get()); - assertEquals((byte)0x00, b179.get()); - assertEquals((byte)0x28, b179.get()); - assertEquals((byte)0x00, b179.get()); - assertEquals((byte)0x00, b179.get()); - assertEquals((byte)0x00, b179.get()); - - // And the 3rd - assertEquals((byte)0x30, b180.get()); - assertEquals((byte)0x00, b180.get()); - assertEquals((byte)0x00, b180.get()); - assertEquals((byte)0x00, b180.get()); - assertEquals((byte)0x00, b180.get()); - assertEquals((byte)0x00, b180.get()); - assertEquals((byte)0x00, b180.get()); - assertEquals((byte)0x80, b180.get()); - - fs.close(); - } - - /** - * Writing the same amount of data as before - */ - @Test - public void testReplaceStream() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - - byte[] data = new byte[512]; - for(int i=0; i<data.length; i++) { - data[i] = (byte)(i%256); - } - - // 98 is actually the last block in a two block stream... - POIFSStream stream = new POIFSStream(fs, 98); - stream.updateContents(data); - - // Check the reading of blocks - Iterator<ByteBuffer> it = stream.getBlockIterator(); - assertTrue(it.hasNext()); - ByteBuffer b = it.next(); - assertFalse(it.hasNext()); - - // Now check the contents - data = new byte[512]; - b.get(data); - for(int i=0; i<data.length; i++) { - byte exp = (byte)(i%256); - assertEquals(exp, data[i]); - } - - fs.close(); - } - - /** - * Writes less data than before, some blocks will need - * to be freed - */ - @Test - public void testReplaceStreamWithLess() throws Exception { - try (InputStream is = _inst.openResourceAsStream("BlockSize512.zvi"); - POIFSFileSystem fs = new POIFSFileSystem(is)) { - - byte[] data = new byte[512]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) (i % 256); - } - - // 97 -> 98 -> end - assertEquals(98, fs.getNextBlock(97)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(98)); - - // Create a 2 block stream, will become a 1 block one - POIFSStream stream = new POIFSStream(fs, 97); - stream.updateContents(data); - - // 97 should now be the end, and 98 free - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(97)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(98)); - - // Check the reading of blocks - Iterator<ByteBuffer> it = stream.getBlockIterator(); - assertTrue(it.hasNext()); - ByteBuffer b = it.next(); - assertFalse(it.hasNext()); - - // Now check the contents - data = new byte[512]; - b.get(data); - for (int i = 0; i < data.length; i++) { - byte exp = (byte) (i % 256); - assertEquals(exp, data[i]); - } - } - } - - /** - * Writes more data than before, new blocks will be needed - */ - @Test - public void testReplaceStreamWithMore() throws Exception { - try (InputStream is = _inst.openResourceAsStream("BlockSize512.zvi"); - POIFSFileSystem fs = new POIFSFileSystem(is)) { - - byte[] data = new byte[512 * 3]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) (i % 256); - } - - // 97 -> 98 -> end - assertEquals(98, fs.getNextBlock(97)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(98)); - - // 100 is our first free one - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(100)); - - // Create a 2 block stream, will become a 3 block one - POIFSStream stream = new POIFSStream(fs, 97); - stream.updateContents(data); - - // 97 -> 98 -> 100 -> end - assertEquals(98, fs.getNextBlock(97)); - assertEquals(100, fs.getNextBlock(98)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(100)); - - // Check the reading of blocks - Iterator<ByteBuffer> it = stream.getBlockIterator(); - int count = 0; - while (it.hasNext()) { - ByteBuffer b = it.next(); - data = new byte[512]; - b.get(data); - for (int i = 0; i < data.length; i++) { - byte exp = (byte) (i % 256); - assertEquals(exp, data[i]); - } - count++; - } - assertEquals(3, count); - } - } - - /** - * Writes to a new stream in the file - */ - @Test - public void testWriteNewStream() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - - // 100 is our first free one - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(100)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(101)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(102)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(103)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(104)); - - - // Add a single block one - byte[] data = new byte[512]; - for(int i=0; i<data.length; i++) { - data[i] = (byte)(i%256); - } - - POIFSStream stream = new POIFSStream(fs); - stream.updateContents(data); - - // Check it was allocated properly - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(100)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(101)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(102)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(103)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(104)); - - // And check the contents - Iterator<ByteBuffer> it = stream.getBlockIterator(); - int count = 0; - while(it.hasNext()) { - ByteBuffer b = it.next(); - data = new byte[512]; - b.get(data); - for(int i=0; i<data.length; i++) { - byte exp = (byte)(i%256); - assertEquals(exp, data[i]); - } - count++; - } - assertEquals(1, count); - - - // And a multi block one - data = new byte[512*3]; - for(int i=0; i<data.length; i++) { - data[i] = (byte)(i%256); - } - - stream = new POIFSStream(fs); - stream.updateContents(data); - - // Check it was allocated properly - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(100)); - assertEquals(102, fs.getNextBlock(101)); - assertEquals(103, fs.getNextBlock(102)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(103)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(104)); - - // And check the contents - it = stream.getBlockIterator(); - count = 0; - while(it.hasNext()) { - ByteBuffer b = it.next(); - data = new byte[512]; - b.get(data); - for(int i=0; i<data.length; i++) { - byte exp = (byte)(i%256); - assertEquals(exp, data[i]); - } - count++; - } - assertEquals(3, count); - - // Free it - stream.free(); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(100)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(101)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(102)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(103)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(104)); - - fs.close(); - } - - /** - * Writes to a new stream in the file, where we've not enough - * free blocks so new FAT segments will need to be allocated - * to support this - */ - @Test - public void testWriteNewStreamExtraFATs() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - - // Allocate almost all the blocks - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(100)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(127)); - for(int i=100; i<127; i++) { - fs.setNextBlock(i, POIFSConstants.END_OF_CHAIN); - } - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(127)); - assertTrue(fs.getBATBlockAndIndex(0).getBlock().hasFreeSectors()); - - - // Write a 3 block stream - byte[] data = new byte[512*3]; - for(int i=0; i<data.length; i++) { - data[i] = (byte)(i%256); - } - POIFSStream stream = new POIFSStream(fs); - stream.updateContents(data); - - // Check we got another BAT - assertFalse(fs.getBATBlockAndIndex(0).getBlock().hasFreeSectors()); - assertTrue(fs.getBATBlockAndIndex(128).getBlock().hasFreeSectors()); - - // the BAT will be in the first spot of the new block - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(126)); - assertEquals(129, fs.getNextBlock(127)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(128)); - assertEquals(130, fs.getNextBlock(129)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(130)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(131)); - - fs.close(); - } - - /** - * Replaces data in an existing stream, with a bit - * more data than before, in a 4096 byte block file - */ - @Test - public void testWriteStream4096() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize4096.zvi")); - - // 0 -> 1 -> 2 -> end - assertEquals(1, fs.getNextBlock(0)); - assertEquals(2, fs.getNextBlock(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); - assertEquals(4, fs.getNextBlock(3)); - - // First free one is at 15 - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(14)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(15)); - - - // Write a 5 block file - byte[] data = new byte[4096*5]; - for(int i=0; i<data.length; i++) { - data[i] = (byte)(i%256); - } - POIFSStream stream = new POIFSStream(fs, 0); - stream.updateContents(data); - - - // Check it - assertEquals(1, fs.getNextBlock(0)); - assertEquals(2, fs.getNextBlock(1)); - assertEquals(15, fs.getNextBlock(2)); // Jumps - assertEquals(4, fs.getNextBlock(3)); // Next stream - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(14)); - assertEquals(16, fs.getNextBlock(15)); // Continues - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(16)); // Ends - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(17)); // Free - - // Check the contents too - Iterator<ByteBuffer> it = stream.getBlockIterator(); - int count = 0; - while(it.hasNext()) { - ByteBuffer b = it.next(); - data = new byte[512]; - b.get(data); - for(int i=0; i<data.length; i++) { - byte exp = (byte)(i%256); + /** + * Read a single block stream + */ + @Test + public void testReadTinyStream() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); + + // 98 is actually the last block in a two block stream... + POIFSStream stream = new POIFSStream(fs, 98); + Iterator<ByteBuffer> i = stream.getBlockIterator(); + assertTrue(i.hasNext()); + ByteBuffer b = i.next(); + assertFalse(i.hasNext()); + + // Check the contents + assertEquals((byte) 0x81, b.get()); + assertEquals((byte) 0x00, b.get()); + assertEquals((byte) 0x00, b.get()); + assertEquals((byte) 0x00, b.get()); + assertEquals((byte) 0x82, b.get()); + assertEquals((byte) 0x00, b.get()); + assertEquals((byte) 0x00, b.get()); + assertEquals((byte) 0x00, b.get()); + + fs.close(); + } + + /** + * Read a stream with only two blocks in it + */ + @Test + public void testReadShortStream() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); + + // 97 -> 98 -> end + POIFSStream stream = new POIFSStream(fs, 97); + Iterator<ByteBuffer> i = stream.getBlockIterator(); + assertTrue(i.hasNext()); + ByteBuffer b97 = i.next(); + assertTrue(i.hasNext()); + ByteBuffer b98 = i.next(); + assertFalse(i.hasNext()); + + // Check the contents of the 1st block + assertEquals((byte) 0x01, b97.get()); + assertEquals((byte) 0x00, b97.get()); + assertEquals((byte) 0x00, b97.get()); + assertEquals((byte) 0x00, b97.get()); + assertEquals((byte) 0x02, b97.get()); + assertEquals((byte) 0x00, b97.get()); + assertEquals((byte) 0x00, b97.get()); + assertEquals((byte) 0x00, b97.get()); + + // Check the contents of the 2nd block + assertEquals((byte) 0x81, b98.get()); + assertEquals((byte) 0x00, b98.get()); + assertEquals((byte) 0x00, b98.get()); + assertEquals((byte) 0x00, b98.get()); + assertEquals((byte) 0x82, b98.get()); + assertEquals((byte) 0x00, b98.get()); + assertEquals((byte) 0x00, b98.get()); + assertEquals((byte) 0x00, b98.get()); + + fs.close(); + } + + /** + * Read a stream with many blocks + */ + @Test + public void testReadLongerStream() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); + + ByteBuffer b0 = null; + ByteBuffer b1 = null; + ByteBuffer b22 = null; + + // The stream at 0 has 23 blocks in it + POIFSStream stream = new POIFSStream(fs, 0); + Iterator<ByteBuffer> i = stream.getBlockIterator(); + int count = 0; + while (i.hasNext()) { + ByteBuffer b = i.next(); + if (count == 0) { + b0 = b; + } + if (count == 1) { + b1 = b; + } + if (count == 22) { + b22 = b; + } + + count++; + } + assertEquals(23, count); + + // Check the contents + // 1st block is at 0 + assertNotNull(b0); + assertEquals((byte) 0x9e, b0.get()); + assertEquals((byte) 0x75, b0.get()); + assertEquals((byte) 0x97, b0.get()); + assertEquals((byte) 0xf6, b0.get()); + + // 2nd block is at 1 + assertNotNull(b1); + assertEquals((byte) 0x86, b1.get()); + assertEquals((byte) 0x09, b1.get()); + assertEquals((byte) 0x22, b1.get()); + assertEquals((byte) 0xfb, b1.get()); + + // last block is at 89 + assertNotNull(b22); + assertEquals((byte) 0xfe, b22.get()); + assertEquals((byte) 0xff, b22.get()); + assertEquals((byte) 0x00, b22.get()); + assertEquals((byte) 0x00, b22.get()); + assertEquals((byte) 0x05, b22.get()); + assertEquals((byte) 0x01, b22.get()); + assertEquals((byte) 0x02, b22.get()); + assertEquals((byte) 0x00, b22.get()); + + fs.close(); + } + + /** + * Read a stream with several blocks in a 4096 byte block file + */ + @Test + public void testReadStream4096() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize4096.zvi")); + + // 0 -> 1 -> 2 -> end + POIFSStream stream = new POIFSStream(fs, 0); + Iterator<ByteBuffer> i = stream.getBlockIterator(); + assertTrue(i.hasNext()); + ByteBuffer b0 = i.next(); + assertTrue(i.hasNext()); + ByteBuffer b1 = i.next(); + assertTrue(i.hasNext()); + ByteBuffer b2 = i.next(); + assertFalse(i.hasNext()); + + // Check the contents of the 1st block + assertEquals((byte) 0x9E, b0.get()); + assertEquals((byte) 0x75, b0.get()); + assertEquals((byte) 0x97, b0.get()); + assertEquals((byte) 0xF6, b0.get()); + assertEquals((byte) 0xFF, b0.get()); + assertEquals((byte) 0x21, b0.get()); + assertEquals((byte) 0xD2, b0.get()); + assertEquals((byte) 0x11, b0.get()); + + // Check the contents of the 2nd block + assertEquals((byte) 0x00, b1.get()); + assertEquals((byte) 0x00, b1.get()); + assertEquals((byte) 0x03, b1.get()); + assertEquals((byte) 0x00, b1.get()); + assertEquals((byte) 0x00, b1.get()); + assertEquals((byte) 0x00, b1.get()); + assertEquals((byte) 0x00, b1.get()); + assertEquals((byte) 0x00, b1.get()); + + // Check the contents of the 3rd block + assertEquals((byte) 0x6D, b2.get()); + assertEquals((byte) 0x00, b2.get()); + assertEquals((byte) 0x00, b2.get()); + assertEquals((byte) 0x00, b2.get()); + assertEquals((byte) 0x03, b2.get()); + assertEquals((byte) 0x00, b2.get()); + assertEquals((byte) 0x46, b2.get()); + assertEquals((byte) 0x00, b2.get()); + + fs.close(); + } + + /** + * Craft a nasty file with a loop, and ensure we don't get stuck + */ + @Test + public void testReadFailsOnLoop() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); + + // Hack the FAT so that it goes 0->1->2->0 + fs.setNextBlock(0, 1); + fs.setNextBlock(1, 2); + fs.setNextBlock(2, 0); + + // Now try to read + POIFSStream stream = new POIFSStream(fs, 0); + Iterator<ByteBuffer> i = stream.getBlockIterator(); + assertTrue(i.hasNext()); + + // 1st read works + i.next(); + assertTrue(i.hasNext()); + + // 2nd read works + i.next(); + assertTrue(i.hasNext()); + + // 3rd read works + i.next(); + assertTrue(i.hasNext()); + + // 4th read blows up as it loops back to 0 + assertThrows(RuntimeException.class, i::next, "Loop should have been detected but wasn't!"); + assertTrue(i.hasNext()); + + fs.close(); + } + + /** + * Tests that we can load some streams that are + * stored in the mini stream. + */ + @Test + public void testReadMiniStreams() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); + POIFSMiniStore ministore = fs.getMiniStore(); + + // 178 -> 179 -> 180 -> end + POIFSStream stream = new POIFSStream(ministore, 178); + Iterator<ByteBuffer> i = stream.getBlockIterator(); + assertTrue(i.hasNext()); + ByteBuffer b178 = i.next(); + assertTrue(i.hasNext()); + ByteBuffer b179 = i.next(); + assertTrue(i.hasNext()); + ByteBuffer b180 = i.next(); + assertFalse(i.hasNext()); + + // Check the contents of the 1st block + assertEquals((byte) 0xfe, b178.get()); + assertEquals((byte) 0xff, b178.get()); + assertEquals((byte) 0x00, b178.get()); + assertEquals((byte) 0x00, b178.get()); + assertEquals((byte) 0x05, b178.get()); + assertEquals((byte) 0x01, b178.get()); + assertEquals((byte) 0x02, b178.get()); + assertEquals((byte) 0x00, b178.get()); + + // And the 2nd + assertEquals((byte) 0x6c, b179.get()); + assertEquals((byte) 0x00, b179.get()); + assertEquals((byte) 0x00, b179.get()); + assertEquals((byte) 0x00, b179.get()); + assertEquals((byte) 0x28, b179.get()); + assertEquals((byte) 0x00, b179.get()); + assertEquals((byte) 0x00, b179.get()); + assertEquals((byte) 0x00, b179.get()); + + // And the 3rd + assertEquals((byte) 0x30, b180.get()); + assertEquals((byte) 0x00, b180.get()); + assertEquals((byte) 0x00, b180.get()); + assertEquals((byte) 0x00, b180.get()); + assertEquals((byte) 0x00, b180.get()); + assertEquals((byte) 0x00, b180.get()); + assertEquals((byte) 0x00, b180.get()); + assertEquals((byte) 0x80, b180.get()); + + fs.close(); + } + + /** + * Writing the same amount of data as before + */ + @Test + public void testReplaceStream() throws Exception { + POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); + + byte[] data = new byte[512]; + for (int i = 0; i < data.length; i++) { + data[i] = (byte) (i % 256); + } + + // 98 is actually the last block in a two block stream... + POIFSStream stream = new POIFSStream(fs, 98); + stream.updateContents(data); + + // Check the reading of blocks + Iterator<ByteBuffer> it = stream.getBlockIterator(); + assertTrue(it.hasNext()); + ByteBuffer b = it.next(); + assertFalse(it.hasNext()); + + // Now check the contents + data = new byte[512]; + b.get(data); + for (int i = 0; i < data.length; i++) { + byte exp = (byte) (i % 256); assertEquals(exp, data[i]); - } - count++; - } - assertEquals(5, count); - - fs.close(); - } - - /** - * Tests that we can write into the mini stream - */ - @Test - public void testWriteMiniStreams() throws Exception { - try (InputStream is = _inst.openResourceAsStream("BlockSize512.zvi"); - POIFSFileSystem fs = new POIFSFileSystem(is)) { - - POIFSMiniStore ministore = fs.getMiniStore(); - - // 178 -> 179 -> 180 -> end - assertEquals(179, ministore.getNextBlock(178)); - assertEquals(180, ministore.getNextBlock(179)); - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(180)); - - - // Try writing 3 full blocks worth - byte[] data = new byte[64 * 3]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) i; - } - POIFSStream stream = new POIFSStream(ministore, 178); - stream.updateContents(data); - - // Check - assertEquals(179, ministore.getNextBlock(178)); - assertEquals(180, ministore.getNextBlock(179)); - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(180)); - - stream = new POIFSStream(ministore, 178); - Iterator<ByteBuffer> it = stream.getBlockIterator(); - ByteBuffer b178 = it.next(); - ByteBuffer b179 = it.next(); - ByteBuffer b180 = it.next(); - assertFalse(it.hasNext()); - - assertEquals((byte) 0x00, b178.get()); - assertEquals((byte) 0x01, b178.get()); - assertEquals((byte) 0x40, b179.get()); - assertEquals((byte) 0x41, b179.get()); - assertEquals((byte) 0x80, b180.get()); - assertEquals((byte) 0x81, b180.get()); - - - // Try writing just into 3 blocks worth - data = new byte[64 * 2 + 12]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) (i + 4); - } - stream = new POIFSStream(ministore, 178); - stream.updateContents(data); - - // Check - assertEquals(179, ministore.getNextBlock(178)); - assertEquals(180, ministore.getNextBlock(179)); - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(180)); - - stream = new POIFSStream(ministore, 178); - it = stream.getBlockIterator(); - b178 = it.next(); - b179 = it.next(); - b180 = it.next(); - assertFalse(it.hasNext()); - - assertEquals((byte) 0x04, b178.get(0)); - assertEquals((byte) 0x05, b178.get(1)); - assertEquals((byte) 0x44, b179.get(0)); - assertEquals((byte) 0x45, b179.get(1)); - assertEquals((byte) 0x84, b180.get(0)); - assertEquals((byte) 0x85, b180.get(1)); - - - // Try writing 1, should truncate - data = new byte[12]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) (i + 9); - } - stream = new POIFSStream(ministore, 178); - stream.updateContents(data); - - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(178)); - assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(179)); - assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(180)); - - stream = new POIFSStream(ministore, 178); - it = stream.getBlockIterator(); - b178 = it.next(); - assertFalse(it.hasNext()); - - assertEquals((byte) 0x09, b178.get(0)); - assertEquals((byte) 0x0a, b178.get(1)); - - - // Try writing 5, should extend - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(178)); - assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(179)); - assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(180)); - assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(181)); - assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(182)); - assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(183)); - - data = new byte[64 * 4 + 12]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) (i + 3); - } - stream = new POIFSStream(ministore, 178); - stream.updateContents(data); - - assertEquals(179, ministore.getNextBlock(178)); - assertEquals(180, ministore.getNextBlock(179)); - assertEquals(181, ministore.getNextBlock(180)); - assertEquals(182, ministore.getNextBlock(181)); - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(182)); - - stream = new POIFSStream(ministore, 178); - it = stream.getBlockIterator(); - b178 = it.next(); - b179 = it.next(); - b180 = it.next(); - ByteBuffer b181 = it.next(); - ByteBuffer b182 = it.next(); - assertFalse(it.hasNext()); - - assertEquals((byte) 0x03, b178.get(0)); - assertEquals((byte) 0x04, b178.get(1)); - assertEquals((byte) 0x43, b179.get(0)); - assertEquals((byte) 0x44, b179.get(1)); - assertEquals((byte) 0x83, b180.get(0)); - assertEquals((byte) 0x84, b180.get(1)); - assertEquals((byte) 0xc3, b181.get(0)); - assertEquals((byte) 0xc4, b181.get(1)); - assertEquals((byte) 0x03, b182.get(0)); - assertEquals((byte) 0x04, b182.get(1)); - - - // Write lots, so it needs another big block - ministore.getBlockAt(183); - try { - ministore.getBlockAt(184); - fail("Block 184 should be off the end of the list"); - } catch (NoSuchElementException e) { - } - - data = new byte[64 * 6 + 12]; - for (int i = 0; i < data.length; i++) { - data[i] = (byte) (i + 1); - } - stream = new POIFSStream(ministore, 178); - stream.updateContents(data); - - // Should have added 2 more blocks to the chain - assertEquals(179, ministore.getNextBlock(178)); - assertEquals(180, ministore.getNextBlock(179)); - assertEquals(181, ministore.getNextBlock(180)); - assertEquals(182, ministore.getNextBlock(181)); - assertEquals(183, ministore.getNextBlock(182)); - assertEquals(184, ministore.getNextBlock(183)); - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(184)); - assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(185)); - - // Block 184 should exist - ministore.getBlockAt(183); - ministore.getBlockAt(184); - ministore.getBlockAt(185); - - // Check contents - stream = new POIFSStream(ministore, 178); - it = stream.getBlockIterator(); - b178 = it.next(); - b179 = it.next(); - b180 = it.next(); - b181 = it.next(); - b182 = it.next(); - ByteBuffer b183 = it.next(); - ByteBuffer b184 = it.next(); - assertFalse(it.hasNext()); - - assertEquals((byte) 0x01, b178.get(0)); - assertEquals((byte) 0x02, b178.get(1)); - assertEquals((byte) 0x41, b179.get(0)); - assertEquals((byte) 0x42, b179.get(1)); - assertEquals((byte) 0x81, b180.get(0)); - assertEquals((byte) 0x82, b180.get(1)); - assertEquals((byte) 0xc1, b181.get(0)); - assertEquals((byte) 0xc2, b181.get(1)); - assertEquals((byte) 0x01, b182.get(0)); - assertEquals((byte) 0x02, b182.get(1)); - assertEquals((byte) 0x41, b183.get(0)); - assertEquals((byte) 0x42, b183.get(1)); - assertEquals((byte) 0x81, b184.get(0)); - assertEquals((byte) 0x82, b184.get(1)); - - } - } - - /** - * Craft a nasty file with a loop, and ensure we don't get stuck - */ - @Test - public void testWriteFailsOnLoop() throws Exception { - try (POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi"))) { - - // Hack the FAT so that it goes 0->1->2->0 - fs.setNextBlock(0, 1); - fs.setNextBlock(1, 2); - fs.setNextBlock(2, 0); - - // Try to write a large amount, should fail on the write - byte[] data = new byte[512 * 4]; - POIFSStream stream = new POIFSStream(fs, 0); - try { - stream.updateContents(data); - fail("Loop should have been detected but wasn't!"); - } catch (IllegalStateException e) { - } - - // Now reset, and try on a small bit - // Should fail during the freeing set - fs.setNextBlock(0, 1); - fs.setNextBlock(1, 2); - fs.setNextBlock(2, 0); - - data = new byte[512]; - stream = new POIFSStream(fs, 0); - try { - stream.updateContents(data); - fail("Loop should have been detected but wasn't!"); - } catch (IllegalStateException e) { - } - } - } - - /** - * Tests adding a new stream, writing and reading it. - */ - @Test - public void testReadWriteNewStream() throws Exception { - try (POIFSFileSystem fs = new POIFSFileSystem()) { - POIFSStream stream = new POIFSStream(fs); - - // Check our filesystem has Properties then BAT - assertEquals(2, fs.getFreeBlock()); - BATBlock bat = fs.getBATBlockAndIndex(0).getBlock(); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(1)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(2)); - - // Check the stream as-is - assertEquals(POIFSConstants.END_OF_CHAIN, stream.getStartBlock()); - try { - stream.getBlockIterator(); - fail("Shouldn't be able to get an iterator before writing"); - } catch (IllegalStateException e) { - } - - // Write in two blocks - byte[] data = new byte[512 + 20]; - for (int i = 0; i < 512; i++) { - data[i] = (byte) (i % 256); - } - for (int i = 512; i < data.length; i++) { - data[i] = (byte) (i % 256 + 100); - } - stream.updateContents(data); - - // Check now - assertEquals(4, fs.getFreeBlock()); - bat = fs.getBATBlockAndIndex(0).getBlock(); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(1)); - assertEquals(3, bat.getValueAt(2)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(3)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(4)); - - - Iterator<ByteBuffer> it = stream.getBlockIterator(); - assertTrue(it.hasNext()); - ByteBuffer b = it.next(); - - byte[] read = new byte[512]; - b.get(read); - for (int i = 0; i < read.length; i++) { - assertEquals("Wrong value at " + i, data[i], read[i]); - } - - assertTrue(it.hasNext()); - b = it.next(); - - read = new byte[512]; - b.get(read); - for (int i = 0; i < 20; i++) { - assertEquals(data[i + 512], read[i]); - } - for (int i = 20; i < read.length; i++) { - assertEquals(0, read[i]); - } - - assertFalse(it.hasNext()); - } - } - - /** - * Writes a stream, then replaces it - */ - @Test - public void testWriteThenReplace() throws Exception { - POIFSFileSystem fs = new POIFSFileSystem(); - - // Starts empty, other that Properties and BAT - BATBlock bat = fs.getBATBlockAndIndex(0).getBlock(); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(2)); - - // Write something that uses a main stream - byte[] main4106 = new byte[4106]; - main4106[0] = -10; - main4106[4105] = -11; - fs.getRoot().createDocument("Normal", new ByteArrayInputStream(main4106)); - - // Should have used 9 blocks - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); - assertEquals(3, bat.getValueAt(2)); - assertEquals(4, bat.getValueAt(3)); - assertEquals(5, bat.getValueAt(4)); - assertEquals(6, bat.getValueAt(5)); - assertEquals(7, bat.getValueAt(6)); - assertEquals(8, bat.getValueAt(7)); - assertEquals(9, bat.getValueAt(8)); - assertEquals(10, bat.getValueAt(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); - - DocumentEntry normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - assertEquals(4106, normal.getSize()); - assertEquals(4106, ((DocumentNode)normal).getProperty().getSize()); - - - // Replace with one still big enough for a main stream, but one block smaller - byte[] main4096 = new byte[4096]; - main4096[0] = -10; - main4096[4095] = -11; - - DocumentOutputStream nout = new DocumentOutputStream(normal); - nout.write(main4096); - nout.close(); - - // Will have dropped to 8 - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); - assertEquals(3, bat.getValueAt(2)); - assertEquals(4, bat.getValueAt(3)); - assertEquals(5, bat.getValueAt(4)); - assertEquals(6, bat.getValueAt(5)); - assertEquals(7, bat.getValueAt(6)); - assertEquals(8, bat.getValueAt(7)); - assertEquals(9, bat.getValueAt(8)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(9)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(10)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); - - normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - assertEquals(4096, normal.getSize()); - assertEquals(4096, ((DocumentNode)normal).getProperty().getSize()); - - - // Write and check - fs = writeOutAndReadBack(fs); - bat = fs.getBATBlockAndIndex(0).getBlock(); - - // No change after write - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); // Properties - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); - assertEquals(3, bat.getValueAt(2)); - assertEquals(4, bat.getValueAt(3)); - assertEquals(5, bat.getValueAt(4)); - assertEquals(6, bat.getValueAt(5)); - assertEquals(7, bat.getValueAt(6)); - assertEquals(8, bat.getValueAt(7)); - assertEquals(9, bat.getValueAt(8)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(9)); // End of Normal - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(10)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); - - normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - assertEquals(4096, normal.getSize()); - assertEquals(4096, ((DocumentNode)normal).getProperty().getSize()); - - - // Make longer, take 1 block at the end - normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - nout = new DocumentOutputStream(normal); - nout.write(main4106); - nout.close(); - - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,bat.getValueAt(1)); - assertEquals(3, bat.getValueAt(2)); - assertEquals(4, bat.getValueAt(3)); - assertEquals(5, bat.getValueAt(4)); - assertEquals(6, bat.getValueAt(5)); - assertEquals(7, bat.getValueAt(6)); - assertEquals(8, bat.getValueAt(7)); - assertEquals(9, bat.getValueAt(8)); - assertEquals(10, bat.getValueAt(9)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(10)); // Normal - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); - - normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - assertEquals(4106, normal.getSize()); - assertEquals(4106, ((DocumentNode)normal).getProperty().getSize()); - - - // Make it small, will trigger the SBAT stream and free lots up - byte[] mini = new byte[] { 42, 0, 1, 2, 3, 4, 42 }; - normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - nout = new DocumentOutputStream(normal); - nout.write(mini); - nout.close(); - - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(2)); // SBAT - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(3)); // Mini Stream - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(4)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(5)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(6)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(7)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(8)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(9)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(10)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(11)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); - - normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - assertEquals(7, normal.getSize()); - assertEquals(7, ((DocumentNode)normal).getProperty().getSize()); - - - // Finally back to big again - nout = new DocumentOutputStream(normal); - nout.write(main4096); - nout.close(); - - // Will keep the mini stream, now empty - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(2)); // SBAT - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(3)); // Mini Stream - assertEquals(5, bat.getValueAt(4)); - assertEquals(6, bat.getValueAt(5)); - assertEquals(7, bat.getValueAt(6)); - assertEquals(8, bat.getValueAt(7)); - assertEquals(9, bat.getValueAt(8)); - assertEquals(10, bat.getValueAt(9)); - assertEquals(11, bat.getValueAt(10)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(11)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(13)); - - normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - assertEquals(4096, normal.getSize()); - assertEquals(4096, ((DocumentNode)normal).getProperty().getSize()); - - - // Save, re-load, re-check - fs = writeOutAndReadBack(fs); - bat = fs.getBATBlockAndIndex(0).getBlock(); - - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(0)); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, bat.getValueAt(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(2)); // SBAT - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(3)); // Mini Stream - assertEquals(5, bat.getValueAt(4)); - assertEquals(6, bat.getValueAt(5)); - assertEquals(7, bat.getValueAt(6)); - assertEquals(8, bat.getValueAt(7)); - assertEquals(9, bat.getValueAt(8)); - assertEquals(10, bat.getValueAt(9)); - assertEquals(11, bat.getValueAt(10)); - assertEquals(POIFSConstants.END_OF_CHAIN, bat.getValueAt(11)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(12)); - assertEquals(POIFSConstants.UNUSED_BLOCK, bat.getValueAt(13)); - - normal = (DocumentEntry)fs.getRoot().getEntry("Normal"); - assertEquals(4096, normal.getSize()); - assertEquals(4096, ((DocumentNode)normal).getProperty().getSize()); - - fs.close(); - } - - - /** - * Returns test files with 512 byte and 4k block sizes, loaded - * both from InputStreams and Files - */ - private POIFSFileSystem[] get512and4kFileAndInput() throws IOException { - POIFSFileSystem fsA = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - POIFSFileSystem fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - POIFSFileSystem fsC = new POIFSFileSystem(_inst.getFile("BlockSize4096.zvi")); - POIFSFileSystem fsD = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize4096.zvi")); - return new POIFSFileSystem[] {fsA,fsB,fsC,fsD}; - } - - private static void assertBATCount(POIFSFileSystem fs, int expectedBAT, int expectedXBAT) throws IOException { - int foundBAT = 0; - int foundXBAT = 0; - int sz = (int)(fs.size() / fs.getBigBlockSize()); - for (int i=0; i<sz; i++) { - if(fs.getNextBlock(i) == POIFSConstants.FAT_SECTOR_BLOCK) { - foundBAT++; - } - if(fs.getNextBlock(i) == POIFSConstants.DIFAT_SECTOR_BLOCK) { - foundXBAT++; - } - } - assertEquals("Wrong number of BATs", expectedBAT, foundBAT); - assertEquals("Wrong number of XBATs with " + expectedBAT + " BATs", expectedXBAT, foundXBAT); - } - private void assertContentsMatches(byte[] expected, DocumentEntry doc) throws IOException { - DocumentInputStream inp = new DocumentInputStream(doc); - byte[] contents = new byte[doc.getSize()]; - assertEquals(doc.getSize(), inp.read(contents)); - inp.close(); - - if (expected != null) { - assertThat(expected, equalTo(contents)); - } - } - - private static HeaderBlock writeOutAndReadHeader(POIFSFileSystem fs) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - fs.writeFilesystem(baos); - - return new HeaderBlock(new ByteArrayInputStream(baos.toByteArray())); - } - - private static POIFSFileSystem writeOutAndReadBack(POIFSFileSystem original) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - original.writeFilesystem(baos); - return new POIFSFileSystem(new ByteArrayInputStream(baos.toByteArray())); - } - - private static POIFSFileSystem writeOutFileAndReadBack(POIFSFileSystem original) throws IOException { - final File file = TempFile.createTempFile("TestPOIFS", ".ole2"); - try (OutputStream fout = new FileOutputStream(file)) { - original.writeFilesystem(fout); - } - return new POIFSFileSystem(file, false); - } - - @Test - public void basicOpen() throws IOException { - POIFSFileSystem fsA, fsB; - - // With a simple 512 block file - fsA = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB}) { - assertEquals(512, fs.getBigBlockSize()); - } - fsA.close(); - fsB.close(); - - // Now with a simple 4096 block file - fsA = new POIFSFileSystem(_inst.getFile("BlockSize4096.zvi")); - fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize4096.zvi")); - for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB}) { - assertEquals(4096, fs.getBigBlockSize()); - } - fsA.close(); - fsB.close(); - } - - @Test - public void propertiesAndFatOnRead() throws IOException { - POIFSFileSystem fsA, fsB; - - // With a simple 512 block file - fsA = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB}) { - // Check the FAT was properly processed: - // Verify we only got one block - fs.getBATBlockAndIndex(0); - fs.getBATBlockAndIndex(1); - try { - fs.getBATBlockAndIndex(140); - fail("Should only be one BAT, but a 2nd was found"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - - // Verify a few next offsets - // 97 -> 98 -> END - assertEquals(98, fs.getNextBlock(97)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(98)); - - - // Check the properties - PropertyTable props = fs._get_property_table(); - assertEquals(90, props.getStartBlock()); - assertEquals(7, props.countBlocks()); - - // Root property tells us about the Mini Stream - RootProperty root = props.getRoot(); - assertEquals("Root Entry", root.getName()); - assertEquals(11564, root.getSize()); - assertEquals(0, root.getStartBlock()); - - // Check its children too - Property prop; - Iterator<Property> pi = root.getChildren(); - prop = pi.next(); - assertEquals("Thumbnail", prop.getName()); - prop = pi.next(); - assertEquals("\u0005DocumentSummaryInformation", prop.getName()); - prop = pi.next(); - assertEquals("\u0005SummaryInformation", prop.getName()); - prop = pi.next(); - assertEquals("Image", prop.getName()); - prop = pi.next(); - assertEquals("Tags", prop.getName()); - assertFalse(pi.hasNext()); - - - // Check the SBAT (Small Blocks FAT) was properly processed - POIFSMiniStore ministore = fs.getMiniStore(); - - // Verify we only got two SBAT blocks - ministore.getBATBlockAndIndex(0); - ministore.getBATBlockAndIndex(128); - try { - ministore.getBATBlockAndIndex(256); - fail("Should only be two SBATs, but a 3rd was found"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - - // Verify a few offsets: 0->50 is a stream - for(int i=0; i<50; i++) { - assertEquals(i+1, ministore.getNextBlock(i)); - } - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(50)); - - fs.close(); - } - - // Now with a simple 4096 block file - fsA = new POIFSFileSystem(_inst.getFile("BlockSize4096.zvi")); - fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize4096.zvi")); - for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB}) { - // Check the FAT was properly processed - // Verify we only got one block - fs.getBATBlockAndIndex(0); - fs.getBATBlockAndIndex(1); - try { - fs.getBATBlockAndIndex(1040); - fail("Should only be one BAT, but a 2nd was found"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - - // Verify a few next offsets - // 0 -> 1 -> 2 -> END - assertEquals(1, fs.getNextBlock(0)); - assertEquals(2, fs.getNextBlock(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); - - - // Check the properties - PropertyTable props = fs._get_property_table(); - assertEquals(12, props.getStartBlock()); - assertEquals(1, props.countBlocks()); - - // Root property tells us about the Mini Stream - RootProperty root = props.getRoot(); - assertEquals("Root Entry", root.getName()); - assertEquals(11564, root.getSize()); - assertEquals(0, root.getStartBlock()); - - // Check its children too - Property prop; - Iterator<Property> pi = root.getChildren(); - prop = pi.next(); - assertEquals("Thumbnail", prop.getName()); - prop = pi.next(); - assertEquals("\u0005DocumentSummaryInformation", prop.getName()); - prop = pi.next(); - assertEquals("\u0005SummaryInformation", prop.getName()); - prop = pi.next(); - assertEquals("Image", prop.getName()); - prop = pi.next(); - assertEquals("Tags", prop.getName()); - assertFalse(pi.hasNext()); - - - // Check the SBAT (Small Blocks FAT) was properly processed - POIFSMiniStore ministore = fs.getMiniStore(); - - // Verify we only got one SBAT block - ministore.getBATBlockAndIndex(0); - ministore.getBATBlockAndIndex(128); - ministore.getBATBlockAndIndex(1023); - try { - ministore.getBATBlockAndIndex(1024); - fail("Should only be one SBAT, but a 2nd was found"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - - // Verify a few offsets: 0->50 is a stream - for(int i=0; i<50; i++) { - assertEquals(i+1, ministore.getNextBlock(i)); - } - assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(50)); - - fs.close(); - } - } - - /** - * Check that for a given block, we can correctly figure - * out what the next one is - */ - @Test - public void nextBlock() throws IOException { - POIFSFileSystem fsA = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - POIFSFileSystem fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB}) { - // 0 -> 21 are simple - for(int i=0; i<21; i++) { - assertEquals(i+1, fs.getNextBlock(i)); - } - // 21 jumps to 89, then ends - assertEquals(89, fs.getNextBlock(21)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(89)); - - // 22 -> 88 simple sequential stream - for(int i=22; i<88; i++) { - assertEquals(i+1, fs.getNextBlock(i)); - } - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(88)); - - // 90 -> 96 is another stream - for(int i=90; i<96; i++) { - assertEquals(i+1, fs.getNextBlock(i)); - } - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(96)); - - // 97+98 is another - assertEquals(98, fs.getNextBlock(97)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(98)); - - // 99 is our FAT block - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); - - // 100 onwards is free - for(int i=100; i<fs.getBigBlockSizeDetails().getBATEntriesPerBlock(); i++) { - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(i)); - } - - fs.close(); - } - - // Quick check on 4096 byte blocks too - fsA = new POIFSFileSystem(_inst.getFile("BlockSize4096.zvi")); - fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize4096.zvi")); - for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB}) { - // 0 -> 1 -> 2 -> end - assertEquals(1, fs.getNextBlock(0)); - assertEquals(2, fs.getNextBlock(1)); - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); - - // 4 -> 11 then end - for(int i=4; i<11; i++) { - assertEquals(i+1, fs.getNextBlock(i)); - } - assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(11)); - - fs.close(); - } - } - - /** - * Check we get the right data back for each block - */ - @Test - public void getBlock() throws IOException { - POIFSFileSystem fsA = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - POIFSFileSystem fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB}) { - ByteBuffer b; - - // The 0th block is the first data block - b = fs.getBlockAt(0); - assertEquals((byte)0x9e, b.get()); - assertEquals((byte)0x75, b.get()); - assertEquals((byte)0x97, b.get()); - assertEquals((byte)0xf6, b.get()); - - // And the next block - b = fs.getBlockAt(1); - assertEquals((byte)0x86, b.get()); - assertEquals((byte)0x09, b.get()); - assertEquals((byte)0x22, b.get()); - assertEquals((byte)0xfb, b.get()); - - // Check the final block too - b = fs.getBlockAt(99); - assertEquals((byte)0x01, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x02, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - - fs.close(); - } - - // Quick check on 4096 byte blocks too - fsA = new POIFSFileSystem(_inst.getFile("BlockSize4096.zvi")); - fsB = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize4096.zvi")); - for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB}) { - ByteBuffer b; - - // The 0th block is the first data block - b = fs.getBlockAt(0); - assertEquals((byte)0x9e, b.get()); - assertEquals((byte)0x75, b.get()); - assertEquals((byte)0x97, b.get()); - assertEquals((byte)0xf6, b.get()); - - // And the next block - b = fs.getBlockAt(1); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x03, b.get()); - assertEquals((byte)0x00, b.get()); - - // The 14th block is the FAT - b = fs.getBlockAt(14); - assertEquals((byte)0x01, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x02, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - assertEquals((byte)0x00, b.get()); - - fs.close(); - } - } - - /** - * Ask for free blocks where there are some already - * to be had from the FAT - */ - @Test - public void getFreeBlockWithSpare() throws IOException { - POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi")); - - // Our first BAT block has spares - assertTrue(fs.getBATBlockAndIndex(0).getBlock().hasFreeSectors()); - - // First free one is 100 - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(100)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(101)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(102)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(103)); - - // Ask, will get 100 - assertEquals(100, fs.getFreeBlock()); - - // Ask again, will still get 100 as not written to - assertEquals(100, fs.getFreeBlock()); - - // Allocate it, then ask again - fs.setNextBlock(100, POIFSConstants.END_OF_CHAIN); - assertEquals(101, fs.getFreeBlock()); - - // All done - fs.close(); - } - - /** - * Ask for free blocks where no free ones exist, and so the - * file needs to be extended and another BAT/XBAT added - */ - @Test - public void getFreeBlockWithNoneSpare() throws IOException { - POIFSFileSystem fs1 = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi")); - int free; - - // We have one BAT at block 99 - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs1.getNextBlock(99)); - assertBATCount(fs1, 1, 0); - - // We've spare ones from 100 to 128 - for(int i=100; i<128; i++) { - assertEquals(POIFSConstants.UNUSED_BLOCK, fs1.getNextBlock(i)); - } - - // Check our BAT knows it's free - assertTrue(fs1.getBATBlockAndIndex(0).getBlock().hasFreeSectors()); - - // Allocate all the spare ones - for(int i=100; i<128; i++) { - fs1.setNextBlock(i, POIFSConstants.END_OF_CHAIN); - } - - // BAT is now full, but there's only the one - assertFalse(fs1.getBATBlockAndIndex(0).getBlock().hasFreeSectors()); - try { - assertFalse(fs1.getBATBlockAndIndex(128).getBlock().hasFreeSectors()); - fail("Should only be one BAT"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - assertBATCount(fs1, 1, 0); - - - // Now ask for a free one, will need to extend the file - assertEquals(129, fs1.getFreeBlock()); - - assertFalse(fs1.getBATBlockAndIndex(0).getBlock().hasFreeSectors()); - assertTrue(fs1.getBATBlockAndIndex(128).getBlock().hasFreeSectors()); - assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs1.getNextBlock(128)); - assertEquals(POIFSConstants.UNUSED_BLOCK, fs1.getNextBlock(129)); - - // We now have 2 BATs, but no XBATs - assertBATCount(fs1, 2, 0); - - - // Fill up to hold 109 BAT blocks - for(int i=0; i<109; i++) { - fs1.getFreeBlock(); - int startOffset = i*128; - while( fs1.getBATBlockAndIndex(startOffset).getBlock().hasFreeSectors() ) { - free = fs1.getFreeBlock(); - fs1.setNextBlock(free, POIFSConstants.END_OF_CHAIN); - } - } - - assertFalse(fs1.getBATBlockAndIndex(109 * 128 - 1).getBlock().hasFreeSectors()); - try { - assertFalse(fs1.getBATBlockAndIndex(109 * 128).getBlock().hasFreeSectors()); - fail("Should only be 109 BATs"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - - // We now have 109 BATs, but no XBATs - assertBATCount(fs1, 109, 0); - - - // Ask for it to be written out, and check the header - HeaderBlock header = writeOutAndReadHeader(fs1); - assertEquals(109, header.getBATCount()); - assertEquals(0, header.getXBATCount()); - - - // Ask for another, will get our first XBAT - free = fs1.getFreeBlock(); - assertTrue("Had: " + free, free > 0); - - assertFalse(fs1.getBATBlockAndIndex(109 * 128 - 1).getBlock().hasFreeSectors()); - assertTrue(fs1.getBATBlockAndIndex(110 * 128 - 1).getBlock().hasFreeSectors()); - try { - assertFalse(fs1.getBATBlockAndIndex(110 * 128).getBlock().hasFreeSectors()); - fail("Should only be 110 BATs"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - assertBATCount(fs1, 110, 1); - - header = writeOutAndReadHeader(fs1); - assertEquals(110, header.getBATCount()); - assertEquals(1, header.getXBATCount()); - - - // Fill the XBAT, which means filling 127 BATs - for(int i=109; i<109+127; i++) { - fs1.getFreeBlock(); - int startOffset = i*128; - while( fs1.getBATBlockAndIndex(startOffset).getBlock().hasFreeSectors() ) { - free = fs1.getFreeBlock(); - fs1.setNextBlock(free, POIFSConstants.END_OF_CHAIN); - } - assertBATCount(fs1, i+1, 1); - } - - // Should now have 109+127 = 236 BATs - assertFalse(fs1.getBATBlockAndIndex(236 * 128 - 1).getBlock().hasFreeSectors()); - try { - assertFalse(fs1.getBATBlockAndIndex(236 * 128).getBlock().hasFreeSectors()); - fail("Should only be 236 BATs"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - assertBATCount(fs1, 236, 1); - - - // Ask for another, will get our 2nd XBAT - free = fs1.getFreeBlock(); - assertTrue("Had: " + free, free > 0); - - assertFalse(fs1.getBATBlockAndIndex(236 * 128 - 1).getBlock().hasFreeSectors()); - assertTrue(fs1.getBATBlockAndIndex(237 * 128 - 1).getBlock().hasFreeSectors()); - try { - assertFalse(fs1.getBATBlockAndIndex(237 * 128).getBlock().hasFreeSectors()); - fail("Should only be 237 BATs"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - - - // Check the counts now - assertBATCount(fs1, 237, 2); - - // Check the header - header = writeOutAndReadHeader(fs1); - assertNotNull(header); - - // Now, write it out, and read it back in again fully - POIFSFileSystem fs2 = writeOutAndReadBack(fs1); - fs1.close(); - - // Check that it is seen correctly - assertBATCount(fs2, 237, 2); - - assertFalse(fs2.getBATBlockAndIndex(236 * 128 - 1).getBlock().hasFreeSectors()); - assertTrue(fs2.getBATBlockAndIndex(237 * 128 - 1).getBlock().hasFreeSectors()); - try { - assertFalse(fs2.getBATBlockAndIndex(237 * 128).getBlock().hasFreeSectors()); - fail("Should only be 237 BATs"); - } catch(IndexOutOfBoundsException e) { - // expected here - } - - - // All done - fs2.close(); - } - - /** - * Test that we can correctly get the list of directory - * entries, and the details on the files in them - */ - @Test - public void listEntries() throws IOException { - for(POIFSFileSystem fs : get512and4kFileAndInput()) { - DirectoryEntry root = fs.getRoot(); - assertEquals(5, root.getEntryCount()); - - // Check by the names - Entry thumbnail = root.getEntry("Thumbnail"); - Entry dsi = root.getEntry("\u0005DocumentSummaryInformation"); - Entry si = root.getEntry("\u0005SummaryInformation"); - Entry image = root.getEntry("Image"); - Entry tags = root.getEntry("Tags"); - - assertFalse(thumbnail.isDirectoryEntry()); - assertFalse(dsi.isDirectoryEntry()); - assertFalse(si.isDirectoryEntry()); - assertTrue(image.isDirectoryEntry()); - assertFalse(tags.isDirectoryEntry()); - - // Check via the iterator - Iterator<Entry> it = root.getEntries(); - assertEquals(thumbnail.getName(), it.next().getName()); - assertEquals(dsi.getName(), it.next().getName()); - assertEquals(si.getName(), it.next().getName()); - assertEquals(image.getName(), it.next().getName()); - assertEquals(tags.getName(), it.next().getName()); - - // Look inside another - DirectoryEntry imageD = (DirectoryEntry)image; - assertEquals(7, imageD.getEntryCount()); - - fs.close(); - } - } - - /** - * Tests that we can get the correct contents for - * a document in the filesystem - */ - @Test - public void getDocumentEntry() throws Exception { - for(POIFSFileSystem fs : get512and4kFileAndInput()) { - DirectoryEntry root = fs.getRoot(); - Entry si = root.getEntry("\u0005SummaryInformation"); - - assertTrue(si.isDocumentEntry()); - DocumentNode doc = (DocumentNode)si; - - // Check we can read it - assertContentsMatches(null, doc); - - // Now try to build the property set - DocumentInputStream inp = new DocumentInputStream(doc); - PropertySet ps = PropertySetFactory.create(inp); - SummaryInformation inf = (SummaryInformation)ps; - - // Check some bits in it - assertNull(inf.getApplicationName()); - assertNull(inf.getAuthor()); - assertNull(inf.getSubject()); - assertEquals(131333, inf.getOSVersion()); - - // Finish with this one - inp.close(); - - - // Try the other summary information - si = root.getEntry("\u0005DocumentSummaryInformation"); - assertTrue(si.isDocumentEntry()); - doc = (DocumentNode)si; - assertContentsMatches(null, doc); - - inp = new DocumentInputStream(doc); - ps = PropertySetFactory.create(inp); - DocumentSummaryInformation dinf = (DocumentSummaryInformation)ps; - assertEquals(131333, dinf.getOSVersion()); - - fs.close(); - } - } - - /** - * Read a file, write it and read it again. - * Then, alter+add some streams, write and read - */ - @Test - public void readWriteRead() throws Exception { - SummaryInformation sinf; - DocumentSummaryInformation dinf; - DirectoryEntry root, testDir; - - for(POIFSFileSystem fs1 : get512and4kFileAndInput()) { - // Check we can find the entries we expect - root = fs1.getRoot(); - assertEquals(5, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Tags")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - - // Write out, re-load - POIFSFileSystem fs2 = writeOutAndReadBack(fs1); - fs1.close(); - - // Check they're still there - root = fs2.getRoot(); - assertEquals(5, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Tags")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - - // Check the contents of them - parse the summary block and check - sinf = (SummaryInformation)PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME))); - assertEquals(131333, sinf.getOSVersion()); - - dinf = (DocumentSummaryInformation)PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); - assertEquals(131333, dinf.getOSVersion()); - - - // Add a test mini stream - testDir = root.createDirectory("Testing 123"); - testDir.createDirectory("Testing 456"); - testDir.createDirectory("Testing 789"); - byte[] mini = new byte[] { 42, 0, 1, 2, 3, 4, 42 }; - testDir.createDocument("Mini", new ByteArrayInputStream(mini)); - - - // Write out, re-load - POIFSFileSystem fs3 = writeOutAndReadBack(fs2); - fs2.close(); - - root = fs3.getRoot(); - testDir = (DirectoryEntry)root.getEntry("Testing 123"); - assertEquals(6, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Tags")); - assertThat(root.getEntryNames(), hasItem("Testing 123")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - - // Check old and new are there - sinf = (SummaryInformation)PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME))); - assertEquals(131333, sinf.getOSVersion()); - - dinf = (DocumentSummaryInformation)PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); - assertEquals(131333, dinf.getOSVersion()); - - assertContentsMatches(mini, (DocumentEntry)testDir.getEntry("Mini")); - - - // Write out and read once more, just to be sure - POIFSFileSystem fs4 = writeOutAndReadBack(fs3); - fs3.close(); - - root = fs4.getRoot(); - testDir = (DirectoryEntry)root.getEntry("Testing 123"); - assertEquals(6, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Tags")); - assertThat(root.getEntryNames(), hasItem("Testing 123")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - sinf = (SummaryInformation)PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME))); - assertEquals(131333, sinf.getOSVersion()); - - dinf = (DocumentSummaryInformation)PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); - assertEquals(131333, dinf.getOSVersion()); - - assertContentsMatches(mini, (DocumentEntry)testDir.getEntry("Mini")); - - - // Add a full stream, delete a full stream - byte[] main4096 = new byte[4096]; - main4096[0] = -10; - main4096[4095] = -11; - testDir.createDocument("Normal4096", new ByteArrayInputStream(main4096)); - - root.getEntry("Tags").delete(); - - - // Write out, re-load - POIFSFileSystem fs5 = writeOutAndReadBack(fs4); - fs4.close(); - - // Check it's all there - root = fs5.getRoot(); - testDir = (DirectoryEntry)root.getEntry("Testing 123"); - assertEquals(5, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Testing 123")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - - // Check old and new are there - sinf = (SummaryInformation)PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME))); - assertEquals(131333, sinf.getOSVersion()); - - dinf = (DocumentSummaryInformation)PropertySetFactory.create(new DocumentInputStream( - (DocumentEntry)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME))); - assertEquals(131333, dinf.getOSVersion()); - - assertContentsMatches(mini, (DocumentEntry)testDir.getEntry("Mini")); - assertContentsMatches(main4096, (DocumentEntry)testDir.getEntry("Normal4096")); - - - // Delete a directory, and add one more - testDir.getEntry("Testing 456").delete(); - testDir.createDirectory("Testing ABC"); - - - // Save - POIFSFileSystem fs6 = writeOutAndReadBack(fs5); - fs5.close(); - - // Check - root = fs6.getRoot(); - testDir = (DirectoryEntry)root.getEntry("Testing 123"); - - assertEquals(5, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Testing 123")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - assertEquals(4, testDir.getEntryCount()); - assertThat(testDir.getEntryNames(), hasItem("Mini")); - assertThat(testDir.getEntryNames(), hasItem("Normal4096")); - assertThat(testDir.getEntryNames(), hasItem("Testing 789")); - assertThat(testDir.getEntryNames(), hasItem("Testing ABC")); - - - // Add another mini stream - byte[] mini2 = new byte[] { -42, 0, -1, -2, -3, -4, -42 }; - testDir.createDocument("Mini2", new ByteArrayInputStream(mini2)); - - // Save, load, check - POIFSFileSystem fs7 = writeOutAndReadBack(fs6); - fs6.close(); - - root = fs7.getRoot(); - testDir = (DirectoryEntry)root.getEntry("Testing 123"); - - assertEquals(5, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Testing 123")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - assertEquals(5, testDir.getEntryCount()); - assertThat(testDir.getEntryNames(), hasItem("Mini")); - assertThat(testDir.getEntryNames(), hasItem("Mini2")); - assertThat(testDir.getEntryNames(), hasItem("Normal4096")); - assertThat(testDir.getEntryNames(), hasItem("Testing 789")); - assertThat(testDir.getEntryNames(), hasItem("Testing ABC")); - - assertContentsMatches(mini, (DocumentEntry)testDir.getEntry("Mini")); - assertContentsMatches(mini2, (DocumentEntry)testDir.getEntry("Mini2")); - assertContentsMatches(main4096, (DocumentEntry)testDir.getEntry("Normal4096")); - - - // Delete a mini stream, add one more - testDir.getEntry("Mini").delete(); - - byte[] mini3 = new byte[] { 42, 0, 42, 0, 42, 0, 42 }; - testDir.createDocument("Mini3", new ByteArrayInputStream(mini3)); - - - // Save, load, check - POIFSFileSystem fs8 = writeOutAndReadBack(fs7); - fs7.close(); - - root = fs8.getRoot(); - testDir = (DirectoryEntry)root.getEntry("Testing 123"); - - assertEquals(5, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Testing 123")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - assertEquals(5, testDir.getEntryCount()); - assertThat(testDir.getEntryNames(), hasItem("Mini2")); - assertThat(testDir.getEntryNames(), hasItem("Mini3")); - assertThat(testDir.getEntryNames(), hasItem("Normal4096")); - assertThat(testDir.getEntryNames(), hasItem("Testing 789")); - assertThat(testDir.getEntryNames(), hasItem("Testing ABC")); - - assertContentsMatches(mini2, (DocumentEntry)testDir.getEntry("Mini2")); - assertContentsMatches(mini3, (DocumentEntry)testDir.getEntry("Mini3")); - assertContentsMatches(main4096, (DocumentEntry)testDir.getEntry("Normal4096")); - - - // Change some existing streams - POIFSDocument mini2Doc = new POIFSDocument((DocumentNode)testDir.getEntry("Mini2")); - mini2Doc.replaceContents(new ByteArrayInputStream(mini)); - - byte[] main4106 = new byte[4106]; - main4106[0] = 41; - main4106[4105] = 42; - POIFSDocument mainDoc = new POIFSDocument((DocumentNode)testDir.getEntry("Normal4096")); - mainDoc.replaceContents(new ByteArrayInputStream(main4106)); - - - // Re-check - POIFSFileSystem fs9 = writeOutAndReadBack(fs8); - fs8.close(); - - root = fs9.getRoot(); - testDir = (DirectoryEntry)root.getEntry("Testing 123"); - - assertEquals(5, root.getEntryCount()); - assertThat(root.getEntryNames(), hasItem("Thumbnail")); - assertThat(root.getEntryNames(), hasItem("Image")); - assertThat(root.getEntryNames(), hasItem("Testing 123")); - assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation")); - assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation")); - - assertEquals(5, testDir.getEntryCount()); - assertThat(testDir.getEntryNames(), hasItem("Mini2")); - assertThat(testDir.getEntryNames(), hasItem("Mini3")); - assertThat(testDir.getEntryNames(), hasItem("Normal4096")); - assertThat(testDir.getEntryNames(), hasItem("Testing 789")); - assertThat(testDir.getEntryNames(), hasItem("Testing ABC")); - - assertContentsMatches(mini, (DocumentEntry)testDir.getEntry("Mini2")); - assertContentsMatches(mini3, (DocumentEntry)testDir.getEntry("Mini3"));
[... 3237 lines stripped ...] --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@poi.apache.org For additional commands, e-mail: commits-h...@poi.apache.org