/* 
 * E-XML Library:  For XML, XML-RPC, HTTP, and related.
 * Copyright (C) 2002-2008  Elias Ross
 * 
 * genman@noderunner.net
 * http://noderunner.net/~genman
 * 
 * 1025 NE 73RD ST
 * SEATTLE WA 98115
 * USA
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * $Id$
 */

package net.noderunner.http;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

/**
 * This class is for unit testing {@link DataPoster} classes.
 *
 * @author Elias Ross
 * @version 1.0
 */
public class GeneralDataPosterTest
	extends junit.framework.TestCase
{
	public GeneralDataPosterTest(String name) {
		super(name);
	}

	public static void main(String[] args) {
		junit.textui.TestRunner.run(GeneralDataPosterTest.class);
	}

	/*
	public static junit.framework.TestSuite suite() {
		return new org.hansel.CoverageDecorator(GeneralDataPosterTest.class,
			new Class[] { GeneralDataPoster.class });
	} 
	*/

	/**
	 * Doesn't allow marking.
	 */
	class ByteArrayInputStream2 extends ByteArrayInputStream {
		boolean tested = false;
		ByteArrayInputStream2(byte[] buf) {
			super(buf);
		}
		public boolean markSupported() { 
			tested = true;
			return false;
		}
		public String toString() { return super.toString() + " tested=" + tested; }
	}

	public void testChunkLots()
		throws Exception
	{
		int len = 1024 * 64;
		byte b[] = new byte[len];
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataPoster poster2 = new GeneralDataPoster(bais, -1);
		poster2.sendData(baos);
		InputStream is = new ChunkedInputStream(new ByteArrayInputStream(baos.toByteArray()));
		int total = 0;
		while (true) {
			int got = is.read(b);
			if (got == -1)
				break;
			total += got;
		}
		assertEquals("got back lots of bytes", len, total);
	}


	public void testChunk()
		throws Exception
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ByteArrayInputStream bais = new ByteArrayInputStream(new byte[] { 1, 2, 3 });
		DataPoster poster2 = new GeneralDataPoster(bais, -1);
		poster2.sendData(baos);
		byte b[] = new byte[3];
		InputStream is = new ChunkedInputStream(new ByteArrayInputStream(baos.toByteArray()));
		int got = is.read(b);
		assertEquals("got back 3 bytes", 3, got);
		assertEquals("got back 1 2 3", 1, b[0]);
		assertEquals("got back 1 2 3", 2, b[1]);
		assertEquals("got back 1 2 3", 3, b[2]);
	}

	public void testRepost()
		throws Exception
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ByteArrayInputStream bais = new ByteArrayInputStream(new byte[] { 1, 2, 3 });
		DataPoster poster2 = new GeneralDataPoster(bais, 2);
		poster2.sendData(baos);
		assertEquals("wrote 2 bytes", 2, baos.size());
		poster2.sendData(baos);
		assertEquals("wrote 4 bytes", 4, baos.size());
		poster2.sendData(baos);
		assertEquals("wrote 6 bytes", 6, baos.size());
	}

	public void testCoverage()
		throws Exception
	{
		GeneralDataPoster gdp = new GeneralDataPoster();
		gdp.toString();
		gdp.init(null, 0);
		gdp.init(null, 0);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		gdp.sendData(bos);
		assertEquals(0, bos.size());
	}
	
	public void testRepostChunked()
		throws Exception
	{
		GeneralDataPoster gdp = new GeneralDataPoster();
		// use chunked
		gdp.init(new ByteArrayInputStream(new byte[]{ 'a', 'b' }), -1);
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		gdp.sendData(bos);
		gdp.sendData(bos);
		byte[] a = bos.toByteArray(); 
		ByteArrayInputStream bais = new ByteArrayInputStream(a);
		ChunkedInputStream cis;

		cis = new ChunkedInputStream(bais);
		assertEquals('a', cis.read());
		assertEquals('b', cis.read());
		assertEquals(-1, cis.read());
		cis.close();
		cis = new ChunkedInputStream(bais);
		assertEquals('a', cis.read());
		assertEquals('b', cis.read());
	}

	public void testExceptions()
		throws Exception
	{
		try {
			new GeneralDataPoster(null, 10);
			fail("null InputStream with non-zero length");
		} catch (IllegalArgumentException e) { }
		DataPoster poster = new GeneralDataPoster(null, 0);
		try {
			poster.sendData(null);
			fail("null os");
		} catch (IllegalArgumentException e) { }

		ByteArrayOutputStream baos;
		InputStream bais;
		DataPoster poster2;
		baos = new ByteArrayOutputStream();
		bais = new ByteArrayInputStream2(new byte[] { 1, 2, 3 });
		poster2 = new GeneralDataPoster(bais, 2);
		poster2.sendData(baos);
		try {
			poster2.sendData(baos);
			fail("cannot reset input stream");
		} catch (HttpException e) { }
		assertEquals("only wrote 2 bytes", 2, baos.size());

		baos = new ByteArrayOutputStream();
		bais = new ByteArrayInputStream(new byte[] { 1, 2, 3 });
		poster2 = new GeneralDataPoster(bais, 4);
		try {
			poster2.sendData(baos);
			fail("not enough data");
		} catch (HttpException e) { }
		assertEquals("only wrote 3 bytes", 3, baos.size());


	}

}
