/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


package npanday.executable.execution;


import npanday.executable.CommandExecutor
import npanday.executable.ExecutionException
import npanday.executable.execution.quoting.CustomSwitchAwareQuotingStrategy
import npanday.executable.execution.quoting.PlexusNativeQuotingStrategy
import org.codehaus.plexus.logging.Logger
import org.codehaus.plexus.logging.console.ConsoleLogger
import org.codehaus.plexus.util.Os
import org.junit.Test
import org.junit.internal.AssumptionViolatedException
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import org.junit.runners.Parameterized.Parameters
import static org.junit.Assert.*

@RunWith(value = Parameterized.class)
public class CommandExecutorTest
{
    private static final String MKDIR = "mkdir";

    private String parentPath;

    private List<String> params = new ArrayList<String>();

    private CommandExecutor cmd;
    private String cmdHint;

    @Parameters
    public static Collection<Object[]> data()
    {
        def osKey = isWindows() ? "win_" : "x_";
        Object[][] data = [
                [osKey + "unified_simple_quoting",
                        new UnifiedShellCommandExecutor(new PlexusNativeQuotingStrategy())],
                [osKey + "unified_custom_quoting",
                        new UnifiedShellCommandExecutor(new CustomSwitchAwareQuotingStrategy())]
        ];
        return Arrays.asList(data);
    }

    public CommandExecutorTest(String hint, CommandExecutor cmd)
    {
        cmdHint = hint;
        println "Executing with " + hint
        File f = new File("test");
        parentPath = System.getProperty("user.dir") + File.separator + "target" + File.separator +
                "test-resources";

        File parentPathFile = new File(parentPath);
        if ( !parentPathFile.exists() )
        {
            parentPathFile.mkdir();
        }

        this.cmd = cmd;
        cmd.setLogger(new ConsoleLogger(Logger.LEVEL_DEBUG, "Command Executor"));
    }

    @Test
    public void testSimpleCommandArg()
    throws ExecutionException
    {
        testArgExpansion(["x"], "x");
    }

    @Test
    public void testCommandArgWithSpaces()
    throws ExecutionException
    {
        testArgExpansion(["a b"], stripQuotes('"a b\"'));
    }

    @Test
    public void testCommandArgWithEmbeddedSingleQuotes_middle()
    throws ExecutionException
    {
        // Not supported by *nix single quoting
      if (!isWindows()) return;

        testArgExpansion(["a ' b"], '"a \' b"');
    }

    @Test
    public void testCommandArgWithEmbeddedSingleQuotes_trailing()
    throws ExecutionException
    {
        testArgExpansion(["a '"], [
                         win_unified_simple_quoting: '"a \'"',
                         win_unified_custom_quoting: '"a \'"'
                         ]);
    }

    @Test
    public void testCommandArgWithEmbeddedSingleQuotes_leading()
    throws ExecutionException
    {
        testArgExpansion(["' a"], [
                         win_unified_simple_quoting: '"\' a"',
                         win_unified_custom_quoting: '"\' a"'
                         ]);
    }

    @Test
    public void testCommandArgWithEmbeddedSingleQuotes_surrounding()
    throws ExecutionException
    {
        testArgExpansion(["' a '"], [
                         win_unified_simple_quoting: '"\' a \'"',
                         win_unified_custom_quoting: '"\' a \'"'
                         ]);
    }

    @Test
    public void testCommandArgWithEmbeddedDoubleQuotes_middle()
    throws ExecutionException
    {
        testArgExpansion(['a " b'], [
                         win_unified_simple_quoting: '"a \\" b"',
                         win_unified_custom_quoting: '"a \\" b"'
                         ]);
    }

    @Test
    public void testCommandArgWithEmbeddedDoubleQuotes_trailing()
    throws ExecutionException
    {
        testArgExpansion(['a "'], [
                         win_unified_simple_quoting: '"a \\""',
                         win_unified_custom_quoting: '"a \\""'
                         ]);
    }

    @Test
    public void testCommandArgWithEmbeddedDoubleQuotes_leading()
    throws ExecutionException
    {
        testArgExpansion(['" a'], [
                         win_unified_simple_quoting: '"\\" a"',
                         win_unified_custom_quoting: '"\\" a"'
                         ]);
    }

    @Test
    public void testCommandArgWithEmbeddedDoubleQuotes_surrounding()
    throws ExecutionException
    {
        testArgExpansion(['" a "'], [
                         win_unified_simple_quoting: '" a "', // if it yet is quoted, it wont quote again
                         win_unified_custom_quoting: '"\\" a \\""' // but we want it escaped and quoted again
                         ]);
    }

    @Test
    public void testCommandArgSwitchWithSpaceInValue_slashColon()
    throws ExecutionException
    {
        testArgExpansion(['/test:a b'], [
                         win_unified_simple_quoting: '"/test:a b"',
                         win_unified_custom_quoting: '/test:"a b"'
                         ]);
    }

    @Test
    public void testCommandArgSwitchWithSpaceInValue_slashEquals()
    throws ExecutionException
    {
        testArgExpansion(['/test=a b'], [
                         win_unified_simple_quoting: '"/test=a b"',
                         win_unified_custom_quoting: '/test="a b"'
                         ]);
    }

    @Test
    public void testCommandArgSwitchWithSpaceInValue_minusColon()
    throws ExecutionException
    {
        testArgExpansion(['-test:a b'], [
                         win_unified_simple_quoting: '"-test:a b"',
                         win_unified_custom_quoting: '-test:"a b"'
                         ]);
    }

    @Test
    public void testCommandArgSwitchWithSpaceInValue_minusEquals()
    throws ExecutionException
    {
        testArgExpansion(['-test=a b'], [
                         win_unified_simple_quoting: '"-test=a b"',
                         win_unified_custom_quoting: '-test="a b"'
                         ]);
    }

    @Test
    public void testCommandArgSwitchWithSpaceInValue_prequotedDouble()
    throws ExecutionException
    {
        testArgExpansion(['/test:"a b"'], [
                         win_unified_simple_quoting: '"/test:\\"a b\\""',
                         win_unified_custom_quoting: '/test:"\\"a b\\""'
                         ]);
    }

    @Test
    public void testCommandArgSwitchWithSpaceInValue_prequotedSingle()
    throws ExecutionException
    {
        testArgExpansion(["/test:'a b'"], [
                         win_unified_simple_quoting: '"/test:\'a b\'"',
                         win_unified_custom_quoting: '/test:"\'a b\'"'
                         ]);
    }

    @Test
    public void testCscDefineSwitch()
    throws ExecutionException
    {
        def raw = '/define:"CONFIG="Debug",DEBUG=-1,TRACE=-1,_MyType="Windows",PLATFORM="AnyCPU"'
        def quoted = '/define:"\\"CONFIG=\\"Debug\\",DEBUG=-1,TRACE=-1,_MyType=\\"Windows\\",PLATFORM=\\"AnyCPU\\""'
        testArgExpansion([raw], [win_unified_custom_quoting: quoted]);
    }

    private def testArgExpansion(ArrayList<String> args, String expected)
    {
        cmd.executeCommand("echo", args)
        assert cmd.result == 0
        assert cmd.standardOut == expected
    }

    private def testArgExpansion(ArrayList<String> args, Map<String, String> expectedPerHint)
    {
        if (!isWindows()){
          return;
        }

        if ( !expectedPerHint.containsKey(cmdHint) )
        {
            cmd.executeCommand("echo", args)
            throw new AssumptionViolatedException("Quoting behaviour undefined for '" + cmdHint + "'.\n"
                                                          + args + " -> " + cmd.standardOut)
        }

        testArgExpansion(args, expectedPerHint[cmdHint])
    }

    @Test
    public void testErrorWithReturnValue()
    throws ExecutionException
    {
        // hopefully an executable named asdfasdf doesnt exist
        try
        {
            cmd.executeCommand("asdfasdf", [])
            fail("expected command to fail")
        }
        catch (ExecutionException)
        {

        }
        println "Result is $cmd.result"
        assert cmd.result != 0
    }

    @Test
    public void testParamWithNoSpaces()
    throws ExecutionException
    {
        String path = parentPath + File.separator + "sampledirectory";

        File dir = new File(path)
        if ( dir.exists() ) dir.deleteDir()

        params.clear();
        params.add(path);

        cmd.executeCommand(MKDIR, params);

        assertTrue(dir.exists());

        if ( dir.exists() )
        {
            dir.delete();
        }
    }

    @Test
    public void testParamWithSpaces()
    throws ExecutionException
    {
        String path = parentPath + File.separator + "sample directory";

        params.clear();
        params.add(path);

        cmd.executeCommand(MKDIR, params);
        File dir = new File(path);

        assertTrue(dir.exists());

        if ( dir.exists() )
        {
            dir.delete();
        }
    }

    @Test
    /**
     test is related to NPANDAY-366
     */
    public void testTooLongCommandName()
    throws ExecutionException
    {
        // we are only interested in exectuing this test
        // on Windows, to catch the "Command line to long" issue for cmd.exe.
        if ( !isWindows() ) return;

        params.clear();

        cmd.setLogger(new ConsoleLogger(0, null));

        try
        {
            cmd.executeCommand(repeat('x', 260), params, null, false);
            fail("Expected the command to fail!");
        }
        catch (ExecutionException e)
        {
            System.out.println(cmd.toString());
            // the message is language-specific, but better to ensure an error than
            // ignoring the test
            // assertEquals( "The input line is too long.", cmdExecutor.getStandardError() );
            assertEquals(1, cmd.getResult());
        }
    }

    @Test
    /**
     test is related to NPANDAY-366
     */
    public void testTooLongCommandName_withSpace()
    throws ExecutionException
    {
        // we are only interested in exectuing this test
        // on Windows, to catch the "Command line to long" issue for cmd.exe.
        if ( !isWindows() ) return;

        params.clear();

        cmd.setLogger(new ConsoleLogger(0, null));

        try
        {
            cmd.executeCommand("echo " + repeat('x', 255), params, null, false);
            fail("Expected the command to fail!");
        }
        catch (ExecutionException e)
        {
            System.out.println(cmd.toString());
            // the message is language-specific, but better to ensure an error than
            // ignoring the test
            // assertEquals( "The input line is too long.", cmdExecutor.getStandardError() );
            assertEquals(1, cmd.getResult());
        }
    }


    @Test
    /**
     test is related to NPANDAY-366
     */
    public void testLongCommand()
    throws ExecutionException
    {
        params.clear();

        cmd.setLogger(new ConsoleLogger(0, null));
        params.add(repeat('a', 260));

        cmd.executeCommand("echo", params, null, false);
        System.out.println(cmd.toString());

        assertEquals(repeat('a', 260), cmd.getStandardOut());
    }

    private static String repeat(String c, int i)
    {
        String tst = "";
        for ( int j = 0; j < i; j++ )
        {
            tst = tst + c;
        }
        return tst;
    }

    /**
     * Simple check if the test is executed on Windows...
     */
    private static boolean isWindows()
    {
       return Os.isFamily(Os.FAMILY_WINDOWS);
    }

  private static String stripQuotes(String s) {
    // On bash, surrounding quotes are not shown by echo
    if (!isWindows()) {
      s = s.substring( 1, s.length() - 1 );
    }
    return s;
  }
}