
package tests.jibx;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;

//import org.hansel.CoverageDecorator;

import junit.framework.*;

import com.sosnoski.site.HTMLParseBuffer;

public class ParseBufferTest extends TestCase
{
	private static final String TEST_TEXT =
		"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Frameset//EN\"" +
		"\"http://www.w3.org/TR/REC-html40/frameset.dtd\"><!--NewPage-->" +
		"<HTML><HEAD><!-- Generated by javadoc on Fri Mar 16 00:22:04 PST " +
		"2001 --><TITLE>Type-safe Collections Library: Class  CharBuffer" +
		"</TITLE><LINK REL =\"stylesheet\" TYPE=\"text/css\" " +
		"HREF=\"../../../stylesheet.css\" TITLE=\"Style\"></HEAD>" +
		"<BODY BGCOLOR=white FGCOLOR=\"black\"><H2><FONT SIZE=\"-1\">com.sosnoski.util" +
		"</FONT><BR>Class  CharBuffer</H2><PRE>\njava.lang.Object\n  |\n" +
		"  +--<A HREF=\"../../../com/sosnoski/util/GrowableBase.html\">" +
		"com.sosnoski.util.GrowableBase</A>\n        |\n" +
		"        +--<A HREF=\"../../../com/sosnoski/util/array/" +
		"ArrayBase.html\">com.sosnoski.util.array.ArrayBase</A>\n" +
		"              |\n              +--<A HREF=\"../../../com/sosnoski" +
		"/util/array/CharArray.html\">com.sosnoski.util.array.CharArray</A>\n" +
		"                    |\n                    +--<B>com.sosnoski." +
		"util.CharBuffer</B>\n</PRE><HR><DL><DT>public class <B>CharBuffer" +
		"</B><DT>extends <A HREF=\"../../../com/sosnoski/util/array/" +
		"CharArray.html\">CharArray</A></DL><P>Growable <code>char</code> " +
		"array with added <code>StringBuffer</code>-like functionality. This " +
		"implementation differs from <code>StringBuffer</code> in that it is " +
		"unsynchronized so as to provide the best possible performance for " +
		"typical usage scenarios. Explicit synchronization must be " +
		"implemented by a wrapper class or directly by the application in " +
		"cases where instances are modified in a multithreaded environment. " +
		"See the base classes for other details of the implementation.<p>" +
		"This class defines a number of convenience methods for working with " +
		"character data (including simple arrays and <code>String</code>s). " +
		"Besides allowing character data to be appended/inserted/replaced in " +
		"the growable array, other methods support comparisons between the " +
		"several forms of character sequences and calculations of hash codes " +
		"independent of the form of the sequence.<P></BODY></HTML>";
	public static final int TEXT_LENGTH = TEST_TEXT.length();
	
	private HTMLParseBuffer m_buffer;
	
	public ParseBufferTest(String name) {
		super(name);
	}
	
	public void setUp() {
		StringReader reader = new StringReader(TEST_TEXT);
		m_buffer = new HTMLParseBuffer(reader, 100);
	}
	
	public void tearDown() {
		m_buffer = null;
	}
	
	public void testRead() throws IOException {
		assertEquals("Basic character read error", TEST_TEXT.charAt(0),
			m_buffer.read());
		assertEquals("Basic character read error", TEST_TEXT.charAt(1),
			m_buffer.read());
		assertEquals("String read position error", TEST_TEXT.substring(2, 102),
			m_buffer.read(100));
		char[] data = new char[100];
		m_buffer.read(data, 10, 40);
		String text = new String(data, 10, 40);
		assertEquals("Data read to array offset mismatch", text,
			TEST_TEXT.substring(102, 142));
		m_buffer.read(data, 0, 100);
		assertEquals("Data read to array mismatch", new String(data),
			TEST_TEXT.substring(142, 242));
	}
	
	public void testPosition() throws IOException {
		assertEquals("Initial position error", 0, m_buffer.position());
		m_buffer.skip(100);
		assertEquals("Position after skip forward error", 100,
			m_buffer.position());
		m_buffer.skip(-100);
		assertEquals("Position after skip backward to start error", 0,
			m_buffer.position());
		boolean except = false;
		try {
			m_buffer.skip(-1);
		} catch (IllegalArgumentException ex) {
			except = true;
		}
		assertTrue("Exception not thrown on skip before start of file", except);
		m_buffer.skip(100);
		assertEquals("Read after skip forward error", TEST_TEXT.charAt(100),
			m_buffer.read());
		assertEquals("Position after read error", 101, m_buffer.position());
		m_buffer.setPosition(150);
		assertEquals("Position after set error", 150, m_buffer.position());
		// depends on buffer size of 100
		m_buffer.skip(-20);
		assertEquals("Position after skip backward error", 130,
			m_buffer.position());
		assertEquals("Read after skip backward error",
			TEST_TEXT.substring(130, 150), m_buffer.read(20));
		m_buffer.skip(-50);
		except = false;
		try {
			m_buffer.skip(-1);
		} catch (IllegalArgumentException ex) {
			except = true;
		}
		assertTrue("Exception not thrown on skip before start of data", except);
		m_buffer.setPosition(TEXT_LENGTH - 10);
		assertEquals("Read near end", TEST_TEXT.substring(TEXT_LENGTH-10),
			m_buffer.read(10));
		assertTrue("Not at end after reading to end", m_buffer.isEnd());
		except = false;
		try {
			m_buffer.read(1);
		} catch (IOException ex) {
			except = true;
		}
		assertTrue("Exception not thrown on read past end", except);
	}
	
	public void testMark() throws IOException {
		boolean except = false;
		try {
			m_buffer.pushMark(-10);
		} catch (IllegalArgumentException ex) {
			except = true;
		}
		assertTrue("Exception not thrown on mark before start", except);
		m_buffer.skip(100);
		m_buffer.pushMark();
		except = false;
		try {
			m_buffer.pushMark(-10);
		} catch (IllegalArgumentException ex) {
			except = true;
		}
		assertTrue("Exception not thrown on mark before prior mark", except);
		assertEquals("Read after mark", TEST_TEXT.substring(100, 110),
			m_buffer.read(10));
		m_buffer.popMark();
		assertEquals("Read after pop mark", TEST_TEXT.substring(100, 110),
			m_buffer.read(10));
		int chr = m_buffer.read();
		m_buffer.pushMark(-1);
		m_buffer.popMark();
		assertEquals("Mark -1 for last character error", chr, m_buffer.read());
		m_buffer.skip(-11);
		m_buffer.pushMark();
		m_buffer.pushMark(10);
		assertEquals("Wrong data after pushing mark error",
			TEST_TEXT.substring(100, 105), m_buffer.read(5));
		assertEquals("Wrong position after mark and read", 105,
			m_buffer.position());
		assertEquals("Wrong position popped", 5, m_buffer.popMark());
		assertEquals(110, m_buffer.position());
		m_buffer.skip(10);
		m_buffer.pushMark(-10);
		assertEquals(TEST_TEXT.substring(120, 130), m_buffer.read(10));
		assertEquals(-20, m_buffer.clearMark());
		assertEquals(TEST_TEXT.substring(130, 140), m_buffer.read(10));
		assertEquals(-40, m_buffer.popMark());
		assertEquals(TEST_TEXT.substring(100, 110), m_buffer.read(10));
		except = false;
		try {
			m_buffer.clearMark();
		} catch (IllegalStateException ex) {
			except = true;
		}
		assertTrue("Exception not thrown on no mark to clear", except);
		m_buffer.setPosition(TEST_TEXT.length());
		m_buffer.pushMark();
	}
	
	public void testSkips() throws IOException {
		m_buffer.pushMark();
		m_buffer.skipPastChar('<');
		assertEquals('!', m_buffer.read());
		assertTrue(m_buffer.skipToWhitespace());
		assertTrue(m_buffer.skipWhitespace());
		m_buffer.skipPastChar('<');
		m_buffer.skipPastChar('<');
		assertTrue(m_buffer.matchString("HTML"));
		m_buffer.skipPastChar('<');
		assertTrue(!m_buffer.matchString("HTML"));
		assertTrue(m_buffer.matchString("HEAD"));
		m_buffer.skipPastString("LINK");
		assertTrue(HTMLParseBuffer.isWhitespaceChar(m_buffer.read()));
		assertTrue(m_buffer.skipPastName());
		assertTrue(HTMLParseBuffer.isWhitespaceChar(m_buffer.read()));
		m_buffer.skipPastCharQuotes('/');
		assertTrue(m_buffer.matchString("HEAD"));
		m_buffer.skipToWhitespace();
		assertEquals(' ', m_buffer.read());
		assertTrue(m_buffer.matchString("BGCOLOR="));
		m_buffer.popMark();
		m_buffer.skipPastString("PUBLIC ");
		assertTrue(m_buffer.skipToWhitespaceQuotes());
		assertEquals(' ', m_buffer.read());
		assertTrue(m_buffer.matchString("Generated"));
	}
	
	public void testHTML() throws IOException {
		assertEquals("Tag mismatch", "html", m_buffer.nextTag(true));
		assertEquals("Tag mismatch", "head", m_buffer.nextTag(true));
		assertEquals("Tag mismatch", "title", m_buffer.nextTag(true));
		assertEquals("Tag mismatch", "/title", m_buffer.nextTag(true));
		assertEquals("Tag mismatch", "link", m_buffer.nextTag(true));
		assertEquals("Tag mismatch", "/head", m_buffer.nextTag(true));
		assertEquals("Tag mismatch", "body", m_buffer.nextTag(false));
        HashMap attrs = m_buffer.attributes();
        assertEquals("Attribute mismatch", "white", attrs.get("bgcolor"));
        assertEquals("Attribute mismatch", "black", attrs.get("fgcolor"));
		assertEquals("Tag mismatch", "h2", m_buffer.nextTag(false));
        attrs = m_buffer.attributes();
        assertEquals("Attribute count", 0, attrs.size());
		assertEquals("Tag mismatch", "font", m_buffer.nextTag(false));
        m_buffer.dropTag();
		m_buffer.pushMark();
		m_buffer.skipToCloseTag("font");
		assertEquals("Skip to close mismatch", "com.sosnoski.util",
			m_buffer.read(-m_buffer.popMark()));
		assertEquals("Tag mismatch", "/font", m_buffer.nextTag(true));
		assertEquals("Tag mismatch", "br", m_buffer.nextTag(true));
		m_buffer.skipPastCharQuotes('G');
		assertEquals("Skip past char quotes", "rowableBase<",
			m_buffer.read(12));
		m_buffer.skipToWhitespace();
		assertEquals("Skip to whitespace", '\n', m_buffer.read());
		m_buffer.skipWhitespace();
		assertEquals("Skip whitespace", '|', m_buffer.read());
		assertEquals("Tag mismatch", "a", m_buffer.nextTag(true));
		m_buffer.skipToCloseTag("pre");
		assertEquals("Skip to close mismatch", "</PRE>", m_buffer.read(6));
	}
	
/*	public static Test suite() {
        return new CoverageDecorator(ParseBufferTest.class,
            new Class[] { HTMLParseBuffer.class });
	}    */
	
	public static void main(String[] args) {
		String[] names = { ParseBufferTest.class.getName() };
		junit.textui.TestRunner.main(names);
	}
}