/*
 * GeneralizedLogicProgramTest.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 (2007-01-29): initial version
 * v0.2 (2007-02-04):
 * - testIsGround and testEqualsAndHashCode added
 * - documentation added
 * v0.2.1 (2007-02-12):
 * - moved to lp.unit package
 * v0.2.2 (2007-02-12):
 * - changed because of changes in LpParser
 * v0.2.3 (2007-02-12):
 * - renamed to DefaultLogicProgramTest
 * v0.2.4 (2007-02-14):
 * - testEqualsAndHashCode fixed
 * v0.2.5 (2007-03-06):
 * - renamed to GeneralizedLogicProgramTest
 * v1.0.0 (2007-05-05):
 * - promoted to version 1.0.0 :o)
 */

package lp.unit;

import junit.framework.*;
import lp.parse.LpParser;
import lp.struct.LpRule;

/**
 * Contains tests of the {@link GeneralizedLogicProgram} class.
 *
 * @author Martin Slota
 * @version 1.0.0
 * @see GeneralizedLogicProgram
 */
public class GeneralizedLogicProgramTest extends TestCase {
	/**
	 * The {@code LpParser} instance used in tests to convert strings into
	 * {@link LpRule} instances.
	 */
	private final LpParser parser;
	
	/**
	 * A default test case constructor.
	 *
	 * @param testName the name of the test case
	 */
	public GeneralizedLogicProgramTest(String testName) {
		super(testName);
		parser = new LpParser();
	}
	
	/**
	 * Tests the {@link GeneralizedLogicProgram#isGround()} method.
	 */
	public void testIsGround() {
		String source = "p(a, b) :- not q(c, f(a, X), d), r(a, b).\n" +
				"not q(a) :- p(a, f(g(a), c)).\n" +
				"married(john, marry).\n" +
				"u :- not u, son(john, X).";
		parser.setInput(source);
		LpRule r1 = parser.parseRule();
		LpRule r2 = parser.parseRule();
		LpRule r3 = parser.parseRule();
		LpRule r4 = parser.parseRule();
		parser.close();
		
		LogicProgram p1 = new GeneralizedLogicProgram();
		p1.add(r1);
		assertEquals("LogicProgram.isGround() result not as expected",
				false, p1.isGround());
		
		LogicProgram p2 = new GeneralizedLogicProgram();
		p2.add(r2);
		assertEquals("LogicProgram.isGround() result not as expected",
				true, p2.isGround());
		p2.add(r3);
		assertEquals("LogicProgram.isGround() result not as expected",
				true, p2.isGround());
		p2.add(r4);
		assertEquals("LogicProgram.isGround() result not as expected",
				false, p2.isGround());
		
		LogicProgram p3 = new GeneralizedLogicProgram();
		p3.add(r3);
		assertEquals("LogicProgram.isGround() result not as expected",
				true, p3.isGround());
		p3.add(r1);
		assertEquals("LogicProgram.isGround() result not as expected",
				false, p3.isGround());
	}
	
	/**
	 * Tests the {@link GeneralizedLogicProgram#equals(Object)} and
	 * {@link GeneralizedLogicProgram#hashCode()} methods.
	 */
	public void testEqualsAndHashCode() {
		String source = "p(a, b) :- not q(c, f(a, X), d), r(a, b).\n" +
				"not q(a) :- p(a, f(g(a), c)).\n" +
				"married(john, marry).\n" +
				"u :- not u, son(john, X).";
		parser.setInput(source);
		LogicProgram p1 = parser.parseAllRules();
		parser.close();
		
		parser.setInput(source);
		LogicProgram p2 = parser.parseAllRules();
		parser.close();
		
		assertEquals("Logic programs should be equal!", p1, p2);
		assertEquals("Hash codes of equal logic programs should be equal!",
				p1.hashCode(), p2.hashCode());
		
		p2.remove(p2.get(1));
		assertFalse("Logic programs should differ!", p1.equals(p2));
		
		p2.add(p1.get(1));
		assertEquals("Logic programs should be equal!", p1, p2);
		assertEquals("Hash codes of equal logic programs should be equal!",
				p1.hashCode(), p2.hashCode());
	}
}