/**
 * Copyright (c) 2013-2015 Linagora
 * 
 * This program/library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This program/library 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 Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program/library; If not, see <http://www.gnu.org/licenses/>
 * for the GNU Lesser General Public License version 2.1.
 */
package org.ow2.petals.launcher;

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

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.ow2.petals.jmx.api.api.PetalsJmxApiFactory;
import org.ow2.petals.jmx.api.mock.PetalsJmxApiFactoryMock;
import org.ow2.petals.launcher.api.server.PetalsServerFactory;
import org.ow2.petals.launcher.utest.PetalsServerUTest;

/**
 * Unit tests of {@link PetalsLauncher}
 * 
 * @author Christophe DENEUX - Linagora
 * 
 */
public class PetalsLauncherTest {

    @Before
    public void setUp() throws Exception {
        // The Petals JMX API Mock is required by unit test
        System.setProperty(PetalsJmxApiFactory.PROPERTY_NAME,
                PetalsJmxApiFactoryMock.class.getName());
    }

    @After
    public void tearDown() throws Exception {
        System.clearProperty(PetalsJmxApiFactory.PROPERTY_NAME);
    }

    /**
     * <p>
     * Check the argument parsing against a command line containing:
     * <ul>
     * <li>the option to specify a configuration but without the url,</li>
     * <li>no help flag,</li>
     * <li>no version flag,</li>
     * <li>no error flag,</li>
     * <li>no extra parameters.</li>
     * </ul>
     * </p>
     * <p>
     * Expected results:
     * <ul>
     * <li>an error occurs about the missing URL.</li>
     * </ul>
     * </p>
     */
    @Test
    public final void testRun_Start_Error_00() {

        final PrintStream standardConsoleOutput = System.out;
        final PrintStream standardConsoleError = System.err;

        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));
            final ByteArrayOutputStream outBAIS = new ByteArrayOutputStream();
            System.setOut(new PrintStream(outBAIS));
            
            System.setProperty(PetalsServerFactory.PROPERTY_NAME, PetalsServerUTest.class.getName());

            PetalsLauncher.run(new String[] { "-" + PetalsLauncher.URL_SHORT_OPTION });

            final String error = errBAIS.toString();
            final String output = outBAIS.toString();
            assertFalse("No error message print", error.isEmpty());
            assertTrue("It's not the expected error message.", error.contains("Missing argument")
                    && error.trim().endsWith(PetalsLauncher.URL_SHORT_OPTION));
            assertFalse("Stack trace is present in error message",
                    error.contains(PetalsLauncher.class.getName()));
            assertFalse("Stack trace is present in error message", error.contains("Caused by"));
            assertTrue("Usage header is missing", output.contains(PetalsLauncher.NAME));
            assertTrue("Usage footer is missing", output.contains(PetalsLauncher.USAGE_FOOTER));
        } finally {
            System.setOut(standardConsoleOutput);
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsServerFactory.PROPERTY_NAME);
        }
    }

    /**
     * <p>
     * Check the argument parsing against a command line containing:
     * <ul>
     * <li>the option to specify a configuration but with an unexisting url,</li>
     * <li>no help flag,</li>
     * <li>no version flag,</li>
     * <li>no error flag,</li>
     * <li>no extra parameters.</li>
     * </ul>
     * </p>
     * <p>
     * Expected results:
     * <ul>
     * <li>an error occurs about the missing URL.</li>
     * </ul>
     * </p>
     */
    @Test
    public final void testRun_Start_Error_01() {

        final PrintStream standardConsoleOutput = System.out;
        final PrintStream standardConsoleError = System.err;

        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));
            final ByteArrayOutputStream outBAIS = new ByteArrayOutputStream();
            System.setOut(new PrintStream(outBAIS));

            System.setProperty(PetalsServerFactory.PROPERTY_NAME, PetalsServerUTest.class.getName());

            final String fileName = "unexisting-server.properties";
            PetalsLauncher.run(new String[] { "-" + PetalsLauncher.URL_SHORT_OPTION,
                    "file:///" + fileName });

            final String error = errBAIS.toString();
            final String output = outBAIS.toString();
            assertFalse("No error message print", error.isEmpty());
            assertTrue("It's not the expected error message.", error.contains(fileName));
            assertFalse("Stack trace is present in error message",
                    error.contains(PetalsLauncher.class.getName()));
            assertFalse("Stack trace is present in error message", error.contains("Caused by"));
            assertFalse("Usage header is present", output.contains(PetalsLauncher.NAME));
            assertFalse("Usage footer is present", output.contains(PetalsLauncher.USAGE_FOOTER));
        } finally {
            System.setOut(standardConsoleOutput);
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsServerFactory.PROPERTY_NAME);
        }
    }

    /**
     * <p>
     * Check the argument parsing against a command line containing:
     * <ul>
     * <li>the option to specify a configuration but with an unexisting url,</li>
     * <li>no help flag,</li>
     * <li>no version flag,</li>
     * <li>error flag enabled,</li>
     * <li>no extra parameters.</li>
     * </ul>
     * </p>
     * <p>
     * Expected results:
     * <ul>
     * <li>an error occurs about the missing URL.</li>
     * </ul>
     * </p>
     */
    @Test
    public final void testRun_Start_Error_02() {

        final PrintStream standardConsoleOutput = System.out;
        final PrintStream standardConsoleError = System.err;

        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));
            final ByteArrayOutputStream outBAIS = new ByteArrayOutputStream();
            System.setOut(new PrintStream(outBAIS));

            System.setProperty(PetalsServerFactory.PROPERTY_NAME, PetalsServerUTest.class.getName());

            final String fileName = "unexisting-server.properties";
            PetalsLauncher.run(new String[] { "-" + PetalsLauncher.URL_SHORT_OPTION,
                    "file:///" + fileName, "-" + PetalsLauncher.ERROR_SHORT_OPTION });

            final String error = errBAIS.toString();
            final String output = outBAIS.toString();
            assertFalse("No error message print", error.isEmpty());
            assertTrue("It's not the expected error message.", error.contains(fileName));
            assertTrue("Stack trace is not present in error message",
                    error.contains(PetalsLauncher.class.getName()));
            assertTrue("Stack trace is not present in error message", error.contains("Caused by"));
            assertFalse("Usage header is present", output.contains(PetalsLauncher.NAME));
            assertFalse("Usage footer is present", output.contains(PetalsLauncher.USAGE_FOOTER));
        } finally {
            System.setOut(standardConsoleOutput);
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsServerFactory.PROPERTY_NAME);
        }
    }

    /**
     * <p>
     * Check the argument parsing against a command line containing:
     * <ul>
     * <li>the option to specify a configuration with an unexisting url,</li>
     * <li>no help flag,</li>
     * <li>no version flag,</li>
     * <li>error flag enabled,</li>
     * <li>no extra parameters,</li>
     * <li>with the stop command.</li>
     * </ul>
     * </p>
     * <p>
     * Expected results:
     * <ul>
     * <li>an error occurs about the missing URL.</li>
     * </ul>
     * </p>
     */
    @Test
    public final void testRun_Stop_Error_00() {

        final PrintStream standardConsoleOutput = System.out;
        final PrintStream standardConsoleError = System.err;

        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));
            final ByteArrayOutputStream outBAIS = new ByteArrayOutputStream();
            System.setOut(new PrintStream(outBAIS));

            System.setProperty(PetalsServerFactory.PROPERTY_NAME, PetalsServerUTest.class.getName());

            final String fileName = "unexisting-server.properties";
            PetalsLauncher.run(new String[] { "-" + PetalsLauncher.URL_SHORT_OPTION,
                    "file:///" + fileName, "-" + PetalsLauncher.ERROR_SHORT_OPTION,
                    PetalsLauncher.COMMAND_STOP });

            final String error = errBAIS.toString();
            final String output = outBAIS.toString();
            assertFalse("No error message print", error.isEmpty());
            assertTrue("It's not the expected error message.", error.contains(fileName));
            assertTrue("Stack trace is not present in error message",
                    error.contains(PetalsLauncher.class.getName()));
            assertTrue("Stack trace is not present in error message", error.contains("Caused by"));
            assertFalse("Usage header is present", output.contains(PetalsLauncher.NAME));
            assertFalse("Usage footer is present", output.contains(PetalsLauncher.USAGE_FOOTER));
        } finally {
            System.setOut(standardConsoleOutput);
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsServerFactory.PROPERTY_NAME);
        }
    }

    /**
     * <p>
     * Check the argument parsing against a command line containing:
     * <ul>
     * <li>the option to specify a configuration with a valid url,</li>
     * <li>no help flag,</li>
     * <li>no version flag,</li>
     * <li>error flag enabled,</li>
     * <li>no extra parameters,</li>
     * <li>with the stop command.</li>
     * </ul>
     * </p>
     * <p>
     * Expected results:
     * <ul>
     * <li>an error occurs about the missing URL.</li>
     * </ul>
     * </p>
     */
    @Test
    public final void testRun_Stop_00() throws IOException {

        final PrintStream standardConsoleOutput = System.out;
        final PrintStream standardConsoleError = System.err;

        try {
            final ByteArrayOutputStream errBAIS = new ByteArrayOutputStream();
            System.setErr(new PrintStream(errBAIS));
            final ByteArrayOutputStream outBAIS = new ByteArrayOutputStream();
            System.setOut(new PrintStream(outBAIS));

            System.setProperty(PetalsServerFactory.PROPERTY_NAME, PetalsServerUTest.class.getName());

            PetalsLauncher.run(new String[] { "-" + PetalsLauncher.URL_SHORT_OPTION,
                    getDefaultConfiguration().toString(), "-" + PetalsLauncher.ERROR_SHORT_OPTION,
                    PetalsLauncher.COMMAND_STOP });

            final String error = errBAIS.toString();
            final String output = outBAIS.toString();
            assertTrue("Error message print", error.isEmpty());
            assertFalse("Usage header is present", output.contains(PetalsLauncher.NAME));
            assertFalse("Usage footer is present", output.contains(PetalsLauncher.USAGE_FOOTER));
        } finally {
            System.setOut(standardConsoleOutput);
            System.setErr(standardConsoleError);
            System.clearProperty(PetalsServerFactory.PROPERTY_NAME);
        }
    }

    private static URL getDefaultConfiguration() {
        final URL defaultServerProperties = Thread.currentThread().getContextClassLoader()
                .getResource("default.server.properties");
        assertNotNull("Default configuration not found !!", defaultServerProperties);
        return defaultServerProperties;
    }

}
