/*
 * LpLookaheadLexerTest.java
 * JUnit based test
 *
 * Copyright (C) 2006 - 2007 Martin Slota
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

/*
 * History:
 * v0.1 (???): initial version
 * v0.2 (2007-01-02):
 * - tests from LpLexerTest adapted for LpLookaheadLexer
 * - testExceptions added
 * - documentation added
 * v0.2.1 (2007-01-12):
 * - assertion messages added
 * v0.2.2 (2007-01-28):
 * - unnecessary throws clauses removed
 * - documentation updated
 * v0.2.3 (2007-02-08):
 * - changed because LpLookaheadLexer changed (made reusable...)
 * v1.0.0 (2007-05-05):
 * - promoted to version 1.0.0 :o)
 */

package lp.parse;

import java.util.List;
import java.util.Random;
import junit.framework.*;

import static lp.parse.LpTokenType.*;

/**
 * Contains tests of the {@link LpLookaheadLexer} class.
 * 
 * @author Martin Slota
 * @version 1.0.0
 * @see LpLookaheadLexer
 */
public class LpLookaheadLexerTest extends LpLexerTest {
	/**
	 * A default test case constructor.
	 *
	 * @param testName the name of the test case
	 */
	public LpLookaheadLexerTest(String testName) {
		super(testName);
		lexer = new LpLookaheadLexer();
	}
	
	/**
	 * Calls {@link LpLexerTest#doTest(String, List)} and then makes a more 
	 * advanced test with some lookahead calls (which shouldn't influence the 
	 * results of other methods).
	 * 
	 * @throws java.io.IOException (wrapped in an 
	 * {@link lp.util.ExceptionAdapter}) if an I/O exception occurs while 
	 * parsing the input (should never happen)
	 */
	@Override
	protected void doTest(String source, List<LpToken> expectedTokens) {
		// first the ordinary test
		super.doTest(source, expectedTokens);
		
		// now a more advanced test with lookahead calls
		LpLookaheadLexer lookaheadLexer = (LpLookaheadLexer)lexer;
		lookaheadLexer.setInput(source);
		Random r = new Random();
		for (int i = 0; i < expectedTokens.size(); i++) {
			// the ordinary behaviour should stay unchanged
			LpToken expected = expectedTokens.get(i);
			lookaheadLexer.nextToken();
			testEqual(expected, lookaheadLexer.getTokenType(), 
					lookaheadLexer.getLexem(),
					lookaheadLexer.getLineNumber(), 
					lookaheadLexer.getPosition());
			testEqual(expected, lookaheadLexer.getToken());
			
			// make a lookahead call and check if it is correct
			int laIndex = Math.min(r.nextInt(20),
					expectedTokens.size() - i - 1);
			LpToken lookahead = lookaheadLexer.getToken(laIndex);
			LpToken expectedLookahead = expectedTokens.get(i + laIndex);
			testEqual(expectedLookahead, lookaheadLexer.getTokenType(laIndex),
					lookaheadLexer.getLexem(laIndex), 
					lookaheadLexer.getLineNumber(laIndex),
					lookaheadLexer.getPosition(laIndex));
			testEqual(expectedLookahead, lookahead);
		}
		lookaheadLexer.nextToken();
		assertEquals("End of input expected!", lookaheadLexer.getTokenType(), EOF);
		lookaheadLexer.close();
	}
	
	/**
	 * Tests exceptions that should be thrown when a negative lookahead is 
	 * requested.
	 *
	 * @throws java.io.IOException (wrapped in an 
	 * {@link lp.util.ExceptionAdapter}) if an I/O exception occurs while 
	 * parsing the input (should never happen)
	 */
	public void testException() {
		LpLookaheadLexer lookaheadLexer = (LpLookaheadLexer)lexer;
		lookaheadLexer.setInput("");
		lookaheadLexer.nextToken();
		try {
			lookaheadLexer.getTokenType(-1);
			fail("An IllegalArgumentException expected!");
		} catch (IllegalArgumentException e) {
			// behaves as expected
		}
		try {
			lookaheadLexer.getLexem(-2);
			fail("An IllegalArgumentException expected!");
		} catch (IllegalArgumentException e) {
			// behaves as expected
		}
		try {
			lookaheadLexer.getPosition(-3);
			fail("An IllegalArgumentException expected!");
		} catch (IllegalArgumentException e) {
			// behaves as expected
		}
		try {
			lookaheadLexer.getLineNumber(-4);
			fail("An IllegalArgumentException expected!");
		} catch (IllegalArgumentException e) {
			// behaves as expected
		}
		try {
			lookaheadLexer.getToken(-5);
			fail("An IllegalArgumentException expected!");
		} catch (IllegalArgumentException e) {
			// behaves as expected
		}
	}
}