package parboiled;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.parboiled.Parboiled;
import org.parboiled.parserunners.AbstractParseRunner;
import org.parboiled.parserunners.ReportingParseRunner;
import org.parboiled.support.ParsingResult;

@RunWith(Parameterized.class)
public class SimpleXMLParserTreeTest {
	private static AbstractParseRunner<XmlNode> runner;

	@Before
	public void setup() {
		SimpleXMLParser parser = Parboiled.createParser(SimpleXMLParser.class);
		runner = new ReportingParseRunner<XmlNode>(parser.Document());
//		runner = new TracingParseRunner<XmlElement>(parser.Document());		
	}
		
	@Parameters(name = "{index}: {0}")
	public static Iterable<Object[]> inputs() {
		// Desperate attempt at finding a shorthand notation for test specifications.
		return new ArrayList<Object[]>() {{
				_("<a><b/></a>", 2);
				_("<a><b></b></a>", 2);
				_( "<c> This is content </c>", 2 );
				_( "<c> This is content <b /></c>", 3 );
				_( "<c> This is content <b></b> </c>", 4 );
				_( "<c> This is content <b /> </c>", 4 );
				_( "<a><b><c><d /></c></b></a>", 4 );				
			}
		
			void _(Object ... args) {
				this.add(args);
			}
		};	
	}
	
	final String input;
	final int nodeCount;
	
	public SimpleXMLParserTreeTest(String input, int nodeCount) {
		this.input = input;
		this.nodeCount = nodeCount;
	}
		
	@Test
	public void test() {
		XmlNode resultValue = null;
		try {			
			ParsingResult<XmlNode> result = runner.run(input);
			assertTrue(result.matched);
			resultValue = result.resultValue;
			assertNotNull(resultValue);
			
			assertTrue(resultValue instanceof XmlDocument);
			assertEquals(1, resultValue.children.size());
			
			resultValue = resultValue.children.get(0); // Ignore document wrapper when counting nodes.
			assertEquals(nodeCount, countNodesInTree(resultValue));		
		} catch(AssertionError e) {
			if (resultValue != null) {
				System.out.println("- Error report for input :" + input);
				System.out.println(resultValue.toStringTree());
			}
			throw e;
		}
	}	
	
	private static int countNodesInTree(XmlNode el) {
		int count = 1;
		
		for (XmlNode child : el.children) {
			count += countNodesInTree(child);
		} 
		
		return count;
	}
		
}

@@ -1106,24 +1106,25 @@
 %5D%3E() %7B%7B%0A%09%09%09%09
+_
 _(%22%3Ca%3E%3Cb/%3E%3C/
@@ -1136,16 +1136,17 @@
 2);%0A%09%09%09%09
+_
 _(%22%3Ca%3E%3Cb
@@ -1161,24 +1161,25 @@
 %3E%22, 2);%0A%09%09%09%09
+_
 _( %22%3Cc%3E This
@@ -1198,32 +1198,33 @@
 %3C/c%3E%22, 2 );%0A%09%09%09%09
+_
 _( %22%3Cc%3E This is 
@@ -1244,32 +1244,33 @@
 %3C/c%3E%22, 3 );%0A%09%09%09%09
+_
 _( %22%3Cc%3E This is 
@@ -1297,24 +1297,25 @@
 %22, 4 );%0A%09%09%09%09
+_
 _( %22%3Cc%3E This
@@ -1348,16 +1348,17 @@
  );%0A%09%09%09%09
+_
 _( %22%3Ca%3E%3C
@@ -1386,20 +1386,16 @@
 %3E%22, 4 );
-%09%09%09%09
 %0A%09%09%09%7D%0A%09%09
@@ -1403,16 +1403,17 @@
 %09%09%09void 
+_
 _(Object

Handle warning from compiler regarding identifier _.