/* $Id$ */

package aspectjhw.lambda;

import junit.framework.TestCase;
import java.util.*;

/**
 * @author Gary T. Leavens
 */
public class ApplicationTest extends TestCase {

    /**
     * Constructor for ApplicationTest.
     * @param name this test's name
     */
    public ApplicationTest(String name) {
        super(name);
    }

    /** Run this test */
    public static void main(String[] args) {
        junit.textui.TestRunner.run(ApplicationTest.class);
    }

    /** Test the equals method. */
    public void testEquals() {
        assertEquals(
            new Application(new Variable("x"), new Variable("x")),
            new Application(new Variable("x"), new Variable("x")));
        assertFalse(
            new Application(new Variable("x"), new Variable("x")).equals(
                new Application(new Variable("x"), new Variable("y"))));
        assertFalse(
            new Application(new Variable("x"), new Variable("x")).equals(
                new Application(new Variable("y"), new Variable("x"))));
        assertFalse(
            new Application(new Variable("x"), new Variable("x")).equals(
                new Application(new Variable("y"), new Variable("y"))));
    }

    /** Test hashCode */
    public void testHashCode() {
        assertEquals(
            new Application(new Variable("x"), new Variable("x")).hashCode(),
            new Application(new Variable("x"), new Variable("x")).hashCode());
    }

    /** Test reduce1Step */
    public void testReduce1Step() {
        Term t = new Application(new Variable("x"), new Variable("x"));
        assertEquals(t, t.reduce1Step());
        t = new Application(
                new Lambda("x", new Variable("x")),
                new Variable("z"));
        assertEquals(new Variable("z"), t.reduce1Step());
        t = new Application(
                new Application(
                    new Lambda("x", new Variable("x")),
                    new Lambda("q", new Variable("q"))),
                new Variable("z"));
        assertEquals(
            new Application(new Lambda("q", new Variable("q")),
                            new Variable("z")),
            t.reduce1Step());
    }

    /** Test freeVars */
    public void testFreeVars() {
        assertEquals(
            new HashSet(),
            new Application(
                new Lambda("x", new Variable("x")),
                new Lambda("y", new Variable("y")))
                .freeVars());
        Term t = new Application(new Variable("x"), new Variable("y"));
        Set s = new HashSet();
        s.add("x");
        s.add("y");
        assertEquals(s, t.freeVars());
    }

    /** Test substituteFor */
    public void testSubstituteFor() {
        Term t = new Application(new Variable("x"), new Variable("y"));
        assertEquals(t, t.substituteFor("z", new Variable("q")));
        assertEquals(
            new Application(new Variable("z"), new Variable("y")),
            t.substituteFor("x", new Variable("z")));
    }

}
