From e95e05b8758b3856c569d59906abcc8c9613d0c8 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Thu, 24 Apr 2014 21:08:34 +0000 Subject: [PATCH] Correct NPOIFS mini stream first write bug, and add more NPOIFS stream write tests git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1589881 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/poifs/filesystem/NPOIFSMiniStore.java | 8 +- .../filesystem/TestNPOIFSFileSystem.java | 136 +++++++++++++++++- 2 files changed, 140 insertions(+), 4 deletions(-) diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java index 33d0b25418..4339fdcd1f 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java @@ -27,9 +27,9 @@ import java.util.List; import org.apache.poi.poifs.common.POIFSConstants; import org.apache.poi.poifs.property.RootProperty; import org.apache.poi.poifs.storage.BATBlock; +import org.apache.poi.poifs.storage.BATBlock.BATBlockAndIndex; import org.apache.poi.poifs.storage.BlockAllocationTableWriter; import org.apache.poi.poifs.storage.HeaderBlock; -import org.apache.poi.poifs.storage.BATBlock.BATBlockAndIndex; /** * This class handles the MiniStream (small block store) @@ -86,6 +86,11 @@ public class NPOIFSMiniStore extends BlockStore * Load the block, extending the underlying stream if needed */ protected ByteBuffer createBlockIfNeeded(final int offset) throws IOException { + // Ensure we have our first block at this point + if (_mini_stream.getStartBlock() == POIFSConstants.END_OF_CHAIN) { + getFreeBlock(); + } + // Try to get it without extending the stream try { return getBlockAt(offset); @@ -186,6 +191,7 @@ public class NPOIFSMiniStore extends BlockStore if(_header.getSBATCount() == 0) { _header.setSBATStart(batForSBAT); _header.setSBATBlockCount(1); + _mini_stream = new NPOIFSStream(_filesystem, batForSBAT); } else { // Find the end of the SBAT stream, and add the sbat in there ChainLoopDetector loopDetector = _filesystem.getChainLoopDetector(); diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java index b23feb29d1..a5617ef279 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java @@ -681,10 +681,140 @@ public final class TestNPOIFSFileSystem { assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(3)); assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); - // Now add a normal stream and a mini stream - // TODO - // TODO The rest of the test + // Put everything within a new directory + DirectoryEntry testDir = fs.createDirectory("Test Directory"); + + // Add a new Normal Stream (Normal Streams minimum 4096 bytes) + byte[] main4096 = new byte[4096]; + main4096[0] = -10; + main4096[4095] = -11; + testDir.createDocument("Normal4096", new ByteArrayInputStream(main4096)); + + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); + if (fs.getBigBlockSize() == POIFSConstants.SMALLER_BIG_BLOCK_SIZE) { + assertEquals(4, fs.getNextBlock(3)); + assertEquals(5, fs.getNextBlock(4)); + assertEquals(6, fs.getNextBlock(5)); + assertEquals(7, fs.getNextBlock(6)); + assertEquals(8, fs.getNextBlock(7)); + assertEquals(9, fs.getNextBlock(8)); + assertEquals(10, fs.getNextBlock(9)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(10)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(11)); + } else { + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(4)); + } + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); + + + // Add a bigger Normal Stream + byte[] main5124 = new byte[5124]; + main5124[0] = -22; + main5124[5123] = -33; + testDir.createDocument("Normal5124", new ByteArrayInputStream(main5124)); + + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); + if (fs.getBigBlockSize() == POIFSConstants.SMALLER_BIG_BLOCK_SIZE) { + assertEquals(4, fs.getNextBlock(3)); + assertEquals(5, fs.getNextBlock(4)); + assertEquals(6, fs.getNextBlock(5)); + assertEquals(7, fs.getNextBlock(6)); + assertEquals(8, fs.getNextBlock(7)); + assertEquals(9, fs.getNextBlock(8)); + assertEquals(10, fs.getNextBlock(9)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(10)); + + assertEquals(12, fs.getNextBlock(11)); + assertEquals(13, fs.getNextBlock(12)); + assertEquals(14, fs.getNextBlock(13)); + assertEquals(15, fs.getNextBlock(14)); + assertEquals(16, fs.getNextBlock(15)); + assertEquals(17, fs.getNextBlock(16)); + assertEquals(18, fs.getNextBlock(17)); + assertEquals(19, fs.getNextBlock(18)); + assertEquals(20, fs.getNextBlock(19)); + assertEquals(21, fs.getNextBlock(20)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(21)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(22)); + } else { + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); + assertEquals(5, fs.getNextBlock(4)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(5)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(6)); + } + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); + + + // Now Add a mini stream + byte[] mini = new byte[] { 0, 1, 2, 3, 4 }; + testDir.createDocument("Mini", new ByteArrayInputStream(mini)); + + // Mini stream will get one block for fat + one block for data + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); + if (fs.getBigBlockSize() == POIFSConstants.SMALLER_BIG_BLOCK_SIZE) { + assertEquals(4, fs.getNextBlock(3)); + assertEquals(5, fs.getNextBlock(4)); + assertEquals(6, fs.getNextBlock(5)); + assertEquals(7, fs.getNextBlock(6)); + assertEquals(8, fs.getNextBlock(7)); + assertEquals(9, fs.getNextBlock(8)); + assertEquals(10, fs.getNextBlock(9)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(10)); + + assertEquals(12, fs.getNextBlock(11)); + assertEquals(13, fs.getNextBlock(12)); + assertEquals(14, fs.getNextBlock(13)); + assertEquals(15, fs.getNextBlock(14)); + assertEquals(16, fs.getNextBlock(15)); + assertEquals(17, fs.getNextBlock(16)); + assertEquals(18, fs.getNextBlock(17)); + assertEquals(19, fs.getNextBlock(18)); + assertEquals(20, fs.getNextBlock(19)); + assertEquals(21, fs.getNextBlock(20)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(21)); + assertEquals(23, fs.getNextBlock(22)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(23)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(24)); + } else { + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); + assertEquals(5, fs.getNextBlock(4)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(5)); + assertEquals(7, fs.getNextBlock(6)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(7)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(8)); + } + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getRoot().getProperty().getStartBlock()); + + + // Write and read back + // TODO + } + + @Test + public void addBeforeWrite() throws Exception { + NPOIFSFileSystem fs = new NPOIFSFileSystem(); + + // Initially has BAT + Properties but nothing else + assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); + assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(1)); + assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(2)); + + // Add to the mini stream + // TODO + + // Add to the main stream + // TODO + + // Write, read, check + // TODO } /** -- 2.39.5