/**
 * LOGBack: the reliable, fast and flexible logging library for Java.
 * 
 * Copyright (C) 1999-2006, QOS.ch, LOGBack.com
 * 
 * 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.
 */
package ch.qos.logback.core.pattern.parser;

import junit.framework.*;

import java.util.List;
import java.util.ArrayList;

import ch.qos.logback.core.pattern.parser.ScanException;
import ch.qos.logback.core.pattern.parser.Token;
import ch.qos.logback.core.pattern.parser.TokenStream;

public class TokenStreamTest extends TestCase {

	public TokenStreamTest(String arg0) {
		super(arg0);
	}

	protected void setUp() throws Exception {
		super.setUp();
	}

	protected void tearDown() throws Exception {
		super.tearDown();
	}

	public void testEmpty() throws ScanException {
		List tl = new TokenStream("").tokenize();
		List witness = new ArrayList();
		assertEquals(witness, tl);
	}

	public void testSingleLiteral() throws ScanException {
		List tl = new TokenStream("hello").tokenize();
		List<Token> witness = new ArrayList<Token>();
		witness.add(new Token(Token.LITERAL, "hello"));
		assertEquals(witness, tl);
	}

	public void testLiteralWithPercent() throws ScanException {
		{
			List tl = new TokenStream("hello\\%world").tokenize();

			List<Token> witness = new ArrayList<Token>();
			witness.add(new Token(Token.LITERAL, "hello%world"));
			assertEquals(witness, tl);
		}
		{
			List tl = new TokenStream("hello\\%").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(new Token(Token.LITERAL, "hello%"));
			assertEquals(witness, tl);
		}

		{
			List tl = new TokenStream("\\%").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(new Token(Token.LITERAL, "%"));
			assertEquals(witness, tl);
		}
	}

	public void testBasic() throws ScanException {

		// test "%c"
		{
			List tl = new TokenStream("%c").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "c"));
			assertEquals(witness, tl);
		}

		{
			// test "xyz%-34c"
			List tl = new TokenStream("%a%b").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "a"));
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "b"));
			assertEquals(witness, tl);
		}

		{
			// test "xyz%-34c"
			List tl = new TokenStream("xyz%-34c").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(new Token(Token.LITERAL, "xyz"));
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.FORMAT_MODIFIER, "-34"));
			witness.add(new Token(Token.KEYWORD, "c"));
			assertEquals(witness, tl);
		}
	}

	public void testComplexNR() throws ScanException {
		List tl = new TokenStream("%d{1234} [%34.-67toto] %n").tokenize();
		List<Token> witness = new ArrayList<Token>();
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.KEYWORD, "d"));
		witness.add(new Token(Token.OPTION, "1234"));
		witness.add(new Token(Token.LITERAL, " ["));
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.FORMAT_MODIFIER, "34.-67"));
		witness.add(new Token(Token.KEYWORD, "toto"));
		witness.add(new Token(Token.LITERAL, "] "));
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.KEYWORD, "n"));
		assertEquals(witness, tl);
	}

	public void testEmptyP() throws ScanException {
		List tl = new TokenStream("()").tokenize();
		List<Token> witness = new ArrayList<Token>();
		witness.add(new Token(Token.LITERAL, "("));
		witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
		assertEquals(witness, tl);
	}

	public void testEmptyP2() throws ScanException {
		List tl = new TokenStream("%()").tokenize();
		List<Token> witness = new ArrayList<Token>();
		witness.add(Token.PERCENT_TOKEN);
		witness.add(Token.LEFT_PARENTHESIS_TOKEN);
		witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
		assertEquals(witness, tl);
	}

	public void testEscape() throws ScanException {
		{
			List tl = new TokenStream("\\%").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(new Token(Token.LITERAL, "%"));
			assertEquals(witness, tl);
		}

		{
			List tl = new TokenStream("\\%\\(\\t\\)\\r\\n").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(new Token(Token.LITERAL, "%(\t)\r\n"));
			assertEquals(witness, tl);
		}

		{
			List tl = new TokenStream("\\\\%x").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(new Token(Token.LITERAL, "\\"));
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "x"));
			assertEquals(witness, tl);
		}

		{
			List tl = new TokenStream("%x\\)").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "x"));
			witness.add(new Token(Token.LITERAL, ")"));
			assertEquals(witness, tl);
		}
    
    {
      List tl = new TokenStream("%x\\_a").tokenize();
      List<Token> witness = new ArrayList<Token>();
      witness.add(Token.PERCENT_TOKEN);
      witness.add(new Token(Token.KEYWORD, "x"));
      witness.add(new Token(Token.LITERAL, "a"));
      assertEquals(witness, tl);
    }
    {
      List tl = new TokenStream("%x\\_%b").tokenize();
      List<Token> witness = new ArrayList<Token>();
      witness.add(Token.PERCENT_TOKEN);
      witness.add(new Token(Token.KEYWORD, "x"));
      witness.add(Token.PERCENT_TOKEN);
      witness.add(new Token(Token.KEYWORD, "b"));
      assertEquals(witness, tl);
    }
	}

	public void testOptions() throws ScanException {
		{
			List tl = new TokenStream("%x{t}").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "x"));
			witness.add(new Token(Token.OPTION, "t"));
			assertEquals(witness, tl);
		}

		{
			List tl = new TokenStream("%x{t,y}").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "x"));
			witness.add(new Token(Token.OPTION, "t,y"));
			assertEquals(witness, tl);
		}
		
		{
			List tl = new TokenStream("%x{\"hello world.\", \"12y  \"}").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "x"));
			witness.add(new Token(Token.OPTION, "\"hello world.\", \"12y  \""));
			assertEquals(witness, tl);
		}
		
		{
			List tl = new TokenStream("%x{opt\\}}").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "x"));
			witness.add(new Token(Token.OPTION, "opt}"));
			assertEquals(witness, tl);
		}
	}

	public void testSimpleP() throws ScanException {
		List tl = new TokenStream("%(hello %class{.4?})").tokenize();
		List<Token> witness = new ArrayList<Token>();
		witness.add(Token.PERCENT_TOKEN);
		witness.add(Token.LEFT_PARENTHESIS_TOKEN);
		witness.add(new Token(Token.LITERAL, "hello "));
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.KEYWORD, "class"));
		witness.add(new Token(Token.OPTION, ".4?"));
		witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
		assertEquals(witness, tl);
	}

	public void testSimpleP2() throws ScanException {
		List tl =  new TokenStream("X %a %-12.550(hello %class{.4?})").tokenize();
		List<Token> witness = new ArrayList<Token>();
		witness.add(new Token(Token.LITERAL, "X "));
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.KEYWORD, "a"));
		witness.add(new Token(Token.LITERAL, " "));
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.FORMAT_MODIFIER, "-12.550"));
		witness.add(Token.LEFT_PARENTHESIS_TOKEN);
		witness.add(new Token(Token.LITERAL, "hello "));
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.KEYWORD, "class"));
		witness.add(new Token(Token.OPTION, ".4?"));
		witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
		assertEquals(witness, tl);
	}

	public void testMultipleRecursion() throws ScanException {
		List tl =  new TokenStream("%-1(%d %45(%class %file))").tokenize();
		List<Token> witness = new ArrayList<Token>();
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.FORMAT_MODIFIER, "-1"));
		witness.add(Token.LEFT_PARENTHESIS_TOKEN);
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.KEYWORD, "d"));
		witness.add(new Token(Token.LITERAL, " "));
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.FORMAT_MODIFIER, "45"));
		witness.add(Token.LEFT_PARENTHESIS_TOKEN);
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.KEYWORD, "class"));
		witness.add(new Token(Token.LITERAL, " "));
		witness.add(Token.PERCENT_TOKEN);
		witness.add(new Token(Token.KEYWORD, "file"));
		witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
		witness.add(Token.RIGHT_PARENTHESIS_TOKEN);

		assertEquals(witness, tl);
	}

	public void testNested() throws ScanException {
		{
			List tl = new TokenStream("%(%a%(%b))").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(Token.PERCENT_TOKEN);
			witness.add(Token.LEFT_PARENTHESIS_TOKEN);
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "a"));
			witness.add(Token.PERCENT_TOKEN);
			witness.add(Token.LEFT_PARENTHESIS_TOKEN);
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "b"));
			witness.add(Token.RIGHT_PARENTHESIS_TOKEN);
			witness.add(Token.RIGHT_PARENTHESIS_TOKEN);

			assertEquals(witness, tl);
		}

		{
			List tl = new TokenStream("\\(%h\\)").tokenize();
			List<Token> witness = new ArrayList<Token>();
			witness.add(new Token(Token.LITERAL, "("));
			witness.add(Token.PERCENT_TOKEN);
			witness.add(new Token(Token.KEYWORD, "h"));
			witness.add(new Token(Token.LITERAL, ")"));
            
            assertEquals(witness, tl);
		}

		//
	}

}