Change the behaviour on short last blocks to be a warning not an exception, as some...
[poi.git] / src / testcases / org / apache / poi / poifs / storage / TestRawDataBlock.java
blob4c84f04b71a884d710e863f547fd7b8031bc040b
2 /* ====================================================================
3 Licensed to the Apache Software Foundation (ASF) under one or more
4 contributor license agreements. See the NOTICE file distributed with
5 this work for additional information regarding copyright ownership.
6 The ASF licenses this file to You under the Apache License, Version 2.0
7 (the "License"); you may not use this file except in compliance with
8 the License. You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================== */
20 package org.apache.poi.poifs.storage;
22 import java.io.*;
23 import java.util.Random;
25 import org.apache.poi.util.DummyPOILogger;
26 import org.apache.poi.util.POILogFactory;
28 import junit.framework.*;
30 /**
31 * Class to test RawDataBlock functionality
33 * @author Marc Johnson
36 public class TestRawDataBlock
37 extends TestCase
40 /**
41 * Constructor TestRawDataBlock
43 * @param name
46 public TestRawDataBlock(String name)
48 super(name);
50 // We always want to use our own
51 // logger
52 System.setProperty(
53 "org.apache.poi.util.POILogger",
54 "org.apache.poi.util.DummyPOILogger"
58 /**
59 * Test creating a normal RawDataBlock
61 * @exception IOException
64 public void testNormalConstructor()
65 throws IOException
67 byte[] data = new byte[ 512 ];
69 for (int j = 0; j < 512; j++)
71 data[ j ] = ( byte ) j;
73 RawDataBlock block = new RawDataBlock(new ByteArrayInputStream(data));
75 assertTrue("Should not be at EOF", !block.eof());
76 byte[] out_data = block.getData();
78 assertEquals("Should be same length", data.length, out_data.length);
79 for (int j = 0; j < 512; j++)
81 assertEquals("Should be same value at offset " + j, data[ j ],
82 out_data[ j ]);
86 /**
87 * Test creating an empty RawDataBlock
89 * @exception IOException
92 public void testEmptyConstructor()
93 throws IOException
95 byte[] data = new byte[ 0 ];
96 RawDataBlock block = new RawDataBlock(new ByteArrayInputStream(data));
98 assertTrue("Should be at EOF", block.eof());
99 try
101 block.getData();
103 catch (IOException ignored)
106 // as expected
111 * Test creating a short RawDataBlock
112 * Will trigger a warning, but no longer an IOException,
113 * as people seem to have "valid" truncated files
115 public void testShortConstructor() throws Exception
117 // Get the logger to be used
118 DummyPOILogger logger = (DummyPOILogger)POILogFactory.getLogger(
119 RawDataBlock.class
121 assertEquals(0, logger.logged.size());
123 // Test for various data sizes
124 for (int k = 1; k <= 512; k++)
126 byte[] data = new byte[ k ];
128 for (int j = 0; j < k; j++)
130 data[ j ] = ( byte ) j;
132 RawDataBlock block = null;
134 logger.reset();
135 assertEquals(0, logger.logged.size());
137 // Have it created
138 block = new RawDataBlock(new ByteArrayInputStream(data));
139 assertNotNull(block);
141 // Check for the warning is there for <512
142 if(k < 512) {
143 assertEquals(
144 "Warning on " + k + " byte short block",
145 1, logger.logged.size()
148 // Build the expected warning message, and check
149 String bts = k + " byte";
150 if(k > 1) {
151 bts += "s";
154 assertEquals(
155 "7 - Unable to read entire block; "+bts+" read before EOF; expected 512 bytes. Your document has probably been truncated!",
156 (String)(logger.logged.get(0))
158 } else {
159 assertEquals(0, logger.logged.size());
165 * Tests that when using a slow input stream, which
166 * won't return a full block at a time, we don't
167 * incorrectly think that there's not enough data
169 public void testSlowInputStream() throws Exception {
170 // Get the logger to be used
171 DummyPOILogger logger = (DummyPOILogger)POILogFactory.getLogger(
172 RawDataBlock.class
174 assertEquals(0, logger.logged.size());
176 // Test for various ok data sizes
177 for (int k = 1; k < 512; k++) {
178 byte[] data = new byte[ 512 ];
179 for (int j = 0; j < data.length; j++) {
180 data[j] = (byte) j;
183 // Shouldn't complain, as there is enough data,
184 // even if it dribbles through
185 RawDataBlock block =
186 new RawDataBlock(new SlowInputStream(data, k));
187 assertFalse(block.eof());
190 // But if there wasn't enough data available, will
191 // complain
192 for (int k = 1; k < 512; k++) {
193 byte[] data = new byte[ 511 ];
194 for (int j = 0; j < data.length; j++) {
195 data[j] = (byte) j;
198 logger.reset();
199 assertEquals(0, logger.logged.size());
201 // Should complain, as there isn't enough data
202 RawDataBlock block =
203 new RawDataBlock(new SlowInputStream(data, k));
204 assertNotNull(block);
205 assertEquals(
206 "Warning on " + k + " byte short block",
207 1, logger.logged.size()
213 * An input stream which will return a maximum of
214 * a given number of bytes to read, and often claims
215 * not to have any data
217 public static class SlowInputStream extends InputStream {
218 private Random rnd = new Random();
219 private byte[] data;
220 private int chunkSize;
221 private int pos = 0;
223 public SlowInputStream(byte[] data, int chunkSize) {
224 this.chunkSize = chunkSize;
225 this.data = data;
229 * 75% of the time, claim there's no data available
231 private boolean claimNoData() {
232 if(rnd.nextFloat() < 0.25f) {
233 return false;
235 return true;
238 public int read() throws IOException {
239 if(pos >= data.length) {
240 return -1;
242 int ret = data[pos];
243 pos++;
245 if(ret < 0) ret += 256;
246 return ret;
250 * Reads the requested number of bytes, or the chunk
251 * size, whichever is lower.
252 * Quite often will simply claim to have no data
254 public int read(byte[] b, int off, int len) throws IOException {
255 // Keep the length within the chunk size
256 if(len > chunkSize) {
257 len = chunkSize;
259 // Don't read off the end of the data
260 if(pos + len > data.length) {
261 len = data.length - pos;
263 // Spot when we're out of data
264 if(len == 0) {
265 return -1;
269 // 75% of the time, claim there's no data
270 if(claimNoData()) {
271 return 0;
274 // Copy, and return what we read
275 System.arraycopy(data, pos, b, off, len);
276 pos += len;
277 return len;
280 public int read(byte[] b) throws IOException {
281 return read(b, 0, b.length);
287 * main method to run the unit tests
289 * @param ignored_args
292 public static void main(String [] ignored_args)
294 System.out
295 .println("Testing org.apache.poi.poifs.storage.RawDataBlock");
296 junit.textui.TestRunner.run(TestRawDataBlock.class);