/* ====================================================================
   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.hdgf.streams;

import static org.apache.poi.poifs.storage.RawDataUtil.decompress;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.IOException;

import org.apache.poi.hdgf.pointers.Pointer;
import org.junit.BeforeClass;
import org.junit.Test;

public final class TestStreamBasics extends StreamTest {
	private static byte[] compressedStream, uncompressedStream;

	@BeforeClass
	public static void init() throws IOException {
        compressedStream = decompress(
            "H4sIAAAAAAAAAAFTAaz+e8QC6/ABAAC48/BO4PsBAAPr8AoFBOvwFQnr8Gfr8CLc/zQPRg94WA/5/u"+
            "T3hRUALIYB/GgP6PMoniBOZr3//uJAKL2Pt3SeqwJCewltqwKnDsi7rbHe/XhuS/f2FPrn9Bbr8PSv"+
            "QwGAuuvwVOvwRgAX6/BML9hPAdTr8CADEgwR1bwREPgVFv/r8Kz/3U/39mAALuvwLNnXTwF38/CW8/"+
            "BUAH0a6/BE2k8BEQoAnzIKAADWlA92HwD9HevwnOdPAe5h3EwQ6/BWACT7AftPPwGEYgAAHAMU3v19"+
            "IevwZPxPAaSlEOoYEynr8NTFEGxkAOsAR5cSJ1UR/U8BX5RxAABoAxIxMRH/QFUBAHIAAKPc6/BkHw"+
            "AA2OvwpEJ/VQFidwAA0E8S/TLvAUNVAVGBANcADgYEET/BEURVvwEeiAAAKk8SRH7r8LRFVQFmiUgl"+
            "AGEhwtTYaVMBAAA="
        );
	        
        uncompressedStream = decompress(
            "H4sIAAAAAAAAAGNgZGDYAcSogJGBGUjCMAsQcwJxOhAroSulEkB2Qqsogw4I41KrMU/BL23vv0cOGn"+
            "v7t5eAGU7VnLlgBobUibUb0fVX5HnDrROB0mJA/GW9M2MDkA4BYjcGcSDpc8Of8QqQVgCLgkT2AEV+"+
            "wEX+A8k1//3hpiUw6AFJnZv+jOVAsWmMIDVSQBGXW/6MgsCgNOJiYLhGVHjIAvGc5/6M7xKB5gDZYQ"+
            "wqIBf+9mdsSWJgkIG6Eh0oAnHKH3/GJUkwF2oCyStAkZwUBgZ3sDnqIPf89WecUsjAkAFWYwjyhUMo"+
            "I0MRA8NiBuwuvAHES5xCGZPKGRgugP1lBAo951DGwEYGBj42kIg9yHaXUEa5DgYGLbAaF6DIFtdQxr"+
            "ROmAgIAAD6SJPAdAIAAA=="
        );
	}
	        

	@Test
	public void testCompressedStream() {
		// Create a fake pointer
		Pointer ptr = new TestPointer(true, 0, compressedStream.length, -1, (short)-1);
		// Now the stream
		Stream stream = Stream.createStream(ptr, compressedStream, null, null);

		// Check
		assertNotNull(stream.getPointer());
		assertNotNull(stream.getStore());
		assertTrue(stream.getStore() instanceof CompressedStreamStore);
		assertTrue(stream instanceof UnknownStream);

		// Check the stream store
		CompressedStreamStore ss = (CompressedStreamStore)stream.getStore();
		assertEquals(4, ss._getBlockHeader().length);
		assertEquals(compressedStream.length, ss._getCompressedContents().length);
		assertEquals(uncompressedStream.length, ss.getContents().length);

		for(int i=0; i<uncompressedStream.length; i++) {
			assertEquals(uncompressedStream[i], ss.getContents()[i]);
		}
	}

	@Test
    public void testUncompressedStream() {
		// Create a fake pointer
		Pointer ptr = new TestPointer(false, 0, uncompressedStream.length, -1, (short)-1);
		// Now the stream
		Stream stream = Stream.createStream(ptr, uncompressedStream, null, null);

		// Check
		assertNotNull(stream.getPointer());
		assertNotNull(stream.getStore());
		assertFalse(stream.getStore() instanceof CompressedStreamStore);
		assertTrue(stream instanceof UnknownStream);
	}
}
