/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.poifs.storage;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;

import junit.framework.TestCase;

import org.apache.poi.util.DummyPOILogger;
import org.apache.poi.util.POILogger;

/**
 * Class to test RawDataBlock functionality
 *
 * @author Marc Johnson
 */
public final class TestRawDataBlock extends TestCase {
	/**
	 * Test creating a normal RawDataBlock
	 */
	public void testNormalConstructor() throws IOException {
		byte[] data = new byte[ 512 ];

		for (int j = 0; j < 512; j++)
		{
			data[ j ] = ( byte ) j;
		}
		RawDataBlock block = new RawDataBlock(new ByteArrayInputStream(data));

		assertTrue("Should not be at EOF", !block.eof());
		byte[] out_data = block.getData();

		assertEquals("Should be same length", data.length, out_data.length);
		for (int j = 0; j < 512; j++)
		{
			assertEquals("Should be same value at offset " + j, data[ j ],
						 out_data[ j ]);
		}
	}

	/**
	 * Test creating an empty RawDataBlock
	 */
	public void testEmptyConstructor() throws IOException {
		byte[]	   data  = new byte[ 0 ];
		RawDataBlock block = new RawDataBlock(new ByteArrayInputStream(data));

		assertTrue("Should be at EOF", block.eof());
		try
		{
			block.getData();
		}
		catch (IOException ignored)
		{

			// as expected
		}
	}

	/**
	 * Test creating a short RawDataBlock
	 * Will trigger a warning, but no longer an IOException,
	 *  as people seem to have "valid" truncated files
	 */
	public void testShortConstructor() throws Exception {
		// Get the logger to be used
	    POILogger oldLogger = RawDataBlock.log;
		DummyPOILogger logger = new DummyPOILogger();
		try {
    		RawDataBlock.log = logger;
    		assertEquals(0, logger.logged.size());
    
    		// Test for various data sizes
    		for (int k = 1; k <= 512; k++)
    		{
    			byte[] data = new byte[ k ];
    
    			for (int j = 0; j < k; j++)
    			{
    				data[ j ] = ( byte ) j;
    			}
    			RawDataBlock block = null;
    
    			logger.reset();
    			assertEquals(0, logger.logged.size());
    
    			// Have it created
    			block = new RawDataBlock(new ByteArrayInputStream(data));
    			assertNotNull(block);
    
    			// Check for the warning is there for <512
    			if(k < 512) {
    				assertEquals(
    						"Warning on " + k + " byte short block",
    						1, logger.logged.size()
    				);
    
    				// Build the expected warning message, and check
    				String bts = k + " byte";
    				if(k > 1) {
    					bts += "s";
    				}
    
    				assertEquals(
    						"7 - Unable to read entire block; "+bts+" read before EOF; expected 512 bytes. Your document was either written by software that ignores the spec, or has been truncated!",
    						logger.logged.get(0)
    				);
    			} else {
    				assertEquals(0, logger.logged.size());
    			}
    		}
		} finally {
		    RawDataBlock.log = oldLogger;
		}
	}

	/**
	 * Tests that when using a slow input stream, which
	 *  won't return a full block at a time, we don't
	 *  incorrectly think that there's not enough data
	 */
	public void testSlowInputStream() throws Exception {
		// Get the logger to be used
        POILogger oldLogger = RawDataBlock.log;
        DummyPOILogger logger = new DummyPOILogger();
        try {
            RawDataBlock.log = logger;
     		assertEquals(0, logger.logged.size());
    
    		// Test for various ok data sizes
    		for (int k = 1; k < 512; k++) {
    			byte[] data = new byte[ 512 ];
    			for (int j = 0; j < data.length; j++) {
    				data[j] = (byte) j;
    			}
    
    			// Shouldn't complain, as there is enough data,
    			//  even if it dribbles through
    			RawDataBlock block =
    				new RawDataBlock(new SlowInputStream(data, k));
    			assertFalse(block.eof());
    		}
    
    		// But if there wasn't enough data available, will
    		//  complain
    		for (int k = 1; k < 512; k++) {
    			byte[] data = new byte[ 511 ];
    			for (int j = 0; j < data.length; j++) {
    				data[j] = (byte) j;
    			}
    
    			logger.reset();
    			assertEquals(0, logger.logged.size());
    
    			// Should complain, as there isn't enough data
    			RawDataBlock block =
    				new RawDataBlock(new SlowInputStream(data, k));
    			assertNotNull(block);
    			assertEquals(
    					"Warning on " + k + " byte short block",
    					1, logger.logged.size()
    			);
    		}
        } finally {
            RawDataBlock.log = oldLogger;
        }
	}

	/**
	 * An input stream which will return a maximum of
	 *  a given number of bytes to read, and often claims
	 *  not to have any data
	 */
	public static class SlowInputStream extends InputStream {
		private Random rnd = new Random();
		private byte[] data;
		private int chunkSize;
		private int pos = 0;

		public SlowInputStream(byte[] data, int chunkSize) {
			this.chunkSize = chunkSize;
			this.data = data;
		}

		/**
		 * 75% of the time, claim there's no data available
		 */
		private boolean claimNoData() {
			if(rnd.nextFloat() < 0.25f) {
				return false;
			}
			return true;
		}

		public int read() {
			if(pos >= data.length) {
				return -1;
			}
			int ret = data[pos];
			pos++;

			if(ret < 0) ret += 256;
			return ret;
		}

		/**
		 * Reads the requested number of bytes, or the chunk
		 *  size, whichever is lower.
		 * Quite often will simply claim to have no data
		 */
		public int read(byte[] b, int off, int len) {
			// Keep the length within the chunk size
			if(len > chunkSize) {
				len = chunkSize;
			}
			// Don't read off the end of the data
			if(pos + len > data.length) {
				len = data.length - pos;

				// Spot when we're out of data
				if(len == 0) {
					return -1;
				}
			}

			// 75% of the time, claim there's no data
			if(claimNoData()) {
				return 0;
			}

			// Copy, and return what we read
			System.arraycopy(data, pos, b, off, len);
			pos += len;
			return len;
		}

		public int read(byte[] b) {
			return read(b, 0, b.length);
		}
	}
}
