/* *******************************************************************
 * Copyright (c) 1999-2001 Xerox Corporation, 
 *               2002 Palo Alto Research Center, Incorporated (PARC).
 * All rights reserved. 
 * This program and the accompanying materials are made available 
 * under the terms of the Common Public License v1.0 
 * which accompanies this distribution and is available at 
 * http://www.eclipse.org/legal/cpl-v10.html 
 *  
 * Contributors: 
 *     Xerox/PARC     initial implementation 
 * ******************************************************************/

package org.aspectj.util;

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

import junit.framework.TestCase;

/**
 * 
 */
public class LangUtilTest extends TestCase {

	public LangUtilTest(String name) {
		super(name);
	}
    
    /** @see LangUtil.extractOptions(String[], String[], int[], List) */
    public void testExtractOptions() {
        ArrayList extracted = new ArrayList();
        String[] args = new String[] { "-d", "classes", "-classpath", "foo.jar", "-verbose", "Bar.java" };
        String[] validOptions = new String[] { "-classpath", "-d", "-verbose", "-help" };
        int[] optionArgs = new int[] { 1, 1, 0, 0 };
        String[] result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
        String resultString = "" + Arrays.asList(result);
        String EXP = "[Bar.java]";
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        EXP = "[-d, classes, -classpath, foo.jar, -verbose]";
        resultString = "" + extracted;
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        
        // no input, no output
        extracted.clear();
        args = new String[] {};
        result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
        resultString = "" + Arrays.asList(result);
        EXP = "[]";
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        resultString = "" + extracted;
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        
        // one input, nothing extracted
        extracted.clear();
        args = new String[] {"Bar.java"};
        result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
        resultString = "" + Arrays.asList(result);
        EXP = "[Bar.java]";
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        EXP = "[]";
        resultString = "" + extracted;
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        
        // one input, extracted
        extracted.clear();
        args = new String[] {"-verbose"};
        result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
        resultString = "" + Arrays.asList(result);
        EXP = "[]";
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        EXP = "[-verbose]";
        resultString = "" + extracted;
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));

        // ------- booleans
        validOptions = new String[] { "-help", "-verbose" };
        optionArgs = null;

        // one input, extracted
        extracted.clear();
        args = new String[] {"-verbose"};
        result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
        resultString = "" + Arrays.asList(result);
        EXP = "[]";
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        EXP = "[-verbose]";
        resultString = "" + extracted;
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        
        // one input, not extracted
        extracted.clear();
        args = new String[] {"Bar.java"};
        result = LangUtil.extractOptions(args, validOptions, optionArgs, extracted);
        resultString = "" + Arrays.asList(result);
        EXP = "[Bar.java]";
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        EXP = "[]";
        resultString = "" + extracted;
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
    }
        
    /** @see LangUtil.extractOptions(String[], String[][]) */
    public void testExtractOptionsArrayCollector() {
        String[] args = new String[] { "-d", "classes", "-classpath", "foo.jar", "-verbose", "Bar.java" };
        String[][] OPTIONS = new String[][] { 
                new String[] {"-classpath", null },
                new String[] {"-d", null},
                new String[] {"-verbose"},
                new String[] { "-help" }};
                
        String[][] options = LangUtil.copyStrings(OPTIONS);
        
        String[] result = LangUtil.extractOptions(args, options);
        String resultString = "" + Arrays.asList(result);
        String EXP = "[Bar.java]";
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        assertTrue("-verbose".equals(options[2][0]));
        assertTrue("foo.jar".equals(options[0][1]));
        assertTrue("classes".equals(options[1][1]));
        assertTrue("-classpath".equals(options[0][0]));
        assertTrue("-d".equals(options[1][0]));
        assertTrue(null == options[3][0]);

        // get args back, no options set
        args = new String[] { "Bar.java" };
        options = LangUtil.copyStrings(OPTIONS);
        
        result = LangUtil.extractOptions(args, options);
        resultString = "" + Arrays.asList(result);
        EXP = "[Bar.java]";
        assertTrue(resultString + " != " + EXP, resultString.equals(EXP));
        assertTrue(null == options[0][0]);
        assertTrue(null == options[1][0]);
        assertTrue(null == options[2][0]);
        assertTrue(null == options[3][0]);
    }

    public void testOptionVariants() {
        String[] NONE = new String[0];
        String[] one = new String[] {"-1"};
        String[] two = new String[] {"-2"};
        String[] three= new String[] {"-3"};
        String[] both = new String[] {"-1", "-2" };
        String[] oneB = new String[] {"-1-"};
        String[] bothB = new String[] {"-1-", "-2-" };
        String[] onetwoB = new String[] {"-1", "-2-" };
        String[] oneBtwo = new String[] {"-1-", "-2" };
        String[] threeB = new String[] {"-1-", "-2-", "-3-"};
        String[] athreeB = new String[] {"a", "-1-", "-2-", "-3-"};
        String[] threeaB = new String[] {"-1-", "a", "-2-", "-3-"};
        
        checkOptionVariants(NONE, new String[][] { NONE });
        checkOptionVariants(one, new String[][] { one });
        checkOptionVariants(both, new String[][] { both });
        checkOptionVariants(oneB, new String[][] { NONE, one });
        checkOptionVariants(bothB, new String[][] { NONE, one, new String[] {"-2"}, both });
        checkOptionVariants(onetwoB, new String[][] { one, new String[] {"-1", "-2"}});
        checkOptionVariants(oneBtwo, new String[][] { two, new String[] {"-1", "-2"}});
        checkOptionVariants(threeB, new String[][] 
            { 
                NONE,
                one,
                two,
                new String[] {"-1", "-2"}, 
                three,
                new String[] {"-1", "-3"}, 
                new String[] {"-2", "-3"}, 
                new String[] {"-1", "-2", "-3"} 
             });
        checkOptionVariants(athreeB, new String[][] 
            { 
                new String[] {"a"},
                new String[] {"a", "-1"},
                new String[] {"a", "-2"},
                new String[] {"a", "-1", "-2"}, 
                new String[] {"a", "-3"},
                new String[] {"a", "-1", "-3"}, 
                new String[] {"a", "-2", "-3"}, 
                new String[] {"a", "-1", "-2", "-3"} 
             });
        checkOptionVariants(threeaB, new String[][] 
            { 
                new String[] {"a"},
                new String[] {"-1", "a"},
                new String[] {"a", "-2"},
                new String[] {"-1", "a", "-2"}, 
                new String[] {"a", "-3"},
                new String[] {"-1", "a", "-3"}, 
                new String[] {"a", "-2", "-3"}, 
                new String[] {"-1", "a", "-2", "-3"} 
             });
    }
    
    void checkOptionVariants(String[] options, String[][] expected) {
        String[][] result = LangUtil.optionVariants(options);
        if (expected.length != result.length) {
            assertTrue("exp=" + expected.length + " actual=" + result.length, false);
        }
        for (int i = 0; i < expected.length; i++) {
            assertEquals(""+i, 
                "" + Arrays.asList(expected[i]), 
                "" + Arrays.asList(result[i])); 
        }
    }
    
    /** @see XMLWriterTest#testUnflattenList() */
    public void testCommaSplit() {
        checkCommaSplit("", new String[] {""});
        checkCommaSplit("1", new String[] {"1"});
        checkCommaSplit(" 1 2 ", new String[] {"1 2"});
        checkCommaSplit(" 1 , 2 ", new String[] {"1", "2"});
        checkCommaSplit("1,2,3,4", new String[] {"1", "2", "3", "4"});
    }
    
    void checkCommaSplit(String input, String[] expected) {
        List actual = LangUtil.commaSplit(input);
        String a = "" + actual;
        String e = "" + Arrays.asList(expected);
        assertTrue(e + "==" + a, e.equals(a));
    }   
    
    public void testElideEndingLines() {
        StringBuffer stackBuffer = LangUtil.stackToString(new RuntimeException(""), true);
        LangUtil.elideEndingLines(LangUtil.StringChecker.TEST_PACKAGES, stackBuffer, 100);
        String result = stackBuffer.toString();
        if (-1 == result.indexOf("(... ")) {
            // brittle - will fail under different top-level drivers
            String m = "when running under eclipse or Ant, expecting (... in trace: "; 
            assertTrue( m + result, false);            
        }
        
        stackBuffer = new StringBuffer("java.lang.RuntimeException: unimplemented"
           + "\n at org.aspectj.ajdt.internal.core.builder.EclipseUnwovenClassFile.writeWovenBytes(EclipseUnwovenClassFile.java:59)"
           + "\n at org.aspectj.weaver.bcel.BcelWeaver.dump(BcelWeaver.java:271)"
           + "\n at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:233)"
           + "\n at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:198)"
           + "\n at org.aspectj.ajdt.internal.core.builder.AjBuildManager.weaveAndGenerateClassFiles(AjBuildanager.java:230)"
           + "\n at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:50)"
           + "\n at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:42)"
           + "\n at org.aspectj.testing.harness.bridge.CompilerRun.run(CompilerRun.java:222)"
           + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
           + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:167)"
           + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:126)"
           + "\n at org.aspectj.testing.run.Runner$IteratorWrapper.run(Runner.java:441)"
           + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
           + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:167)"
           + "\n at org.aspectj.testing.run.Runner.runChild(Runner.java:126)"
           + "\n at org.aspectj.testing.run.Runner$IteratorWrapper.run(Runner.java:441)"
           + "\n at org.aspectj.testing.run.Runner.runPrivate(Runner.java:363)"
           + "\n at org.aspectj.testing.run.Runner.run(Runner.java:114)"
           + "\n at org.aspectj.testing.run.Runner.run(Runner.java:105)"
           + "\n at org.aspectj.testing.run.Runner.runIterator(Runner.java:228)"
           + "\n at org.aspectj.testing.drivers.Harness.run(Harness.java:254)"
           + "\n at org.aspectj.testing.drivers.Harness.runMain(Harness.java:217)"
           + "\n at org.aspectj.testing.drivers.Harness.main(Harness.java:99)"
           + "\n at org.aspectj.testing.Harness.main(Harness.java:37)"
           + "\n clip me");

        LangUtil.elideEndingLines(LangUtil.StringChecker.TEST_PACKAGES, stackBuffer, 25);
        result = stackBuffer.toString();
        assertTrue(result, -1 != result.indexOf("(... ")); 
        assertTrue(result, -1 == result.indexOf("org.aspectj.testing"));
    }
}
