/*
 * Copyright 2009 OW2 Chameleon
 * Licensed 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 org.ow2.chameleon.core;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

import junit.framework.TestCase;

/**
 * Test chameleon starting from the command line.
 * @author <a href="mailto:chameleon-dev@ow2.org">Chameleon Project Team</a>
 */
public class AdminSocketTest extends TestCase {

    /**
     * Maximum number of connection.
     */
    public static final int MAX_TRIES = 5;

    /**
     * Waiting time between two connections.
     */
    public static final int SLEEP_TIME = 1000;

    /**
     * Deletes the load folder if exists.
     * @see junit.framework.TestCase#tearDown()
     */
    public void tearDown() {
        File load = new File("load");
        if (load.exists()) {
            load.delete();
        }
    }


    /**
     * Tests to stop a chameleon from the default port.
     * @throws Exception something bad happened.
     */
    public void testAdminSocketOnDefaultPort() throws Exception {
        String[] args = new String[] {"--runtime=" + Constants.BOTH,
                "--core=" + Constants.FULL_CORE,
                "--app=" + Constants.ANOTHER_BOTH};
        Main.main(args);

        Socket client = null;
        int count = 0;
        while (client == null  && count < MAX_TRIES) {
            try {
                client = new Socket(InetAddress.getLocalHost(),
                        Main.DEFAULT_ADMIN_PORT);
            } catch (Exception e) {
                Thread.sleep(SLEEP_TIME);
                count++;
            }
        }

        assertNotNull("Cannot connect to the socket", client);

        PrintWriter out =
            new PrintWriter(
                    new OutputStreamWriter(client.getOutputStream()), true);
        InputStream input = client.getInputStream();
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(input));
        out.println("STOP");
        out.flush();
        String read = reader.readLine();
        assertEquals("OK", read);
        client.close();

    }

    /**
     * Tests to stop a chameleon from a customized port.
     * @throws Exception something bad happened.
     */
    public void testOnCustomPort() throws Exception {
        System.setProperty("chameleon.admin.port", "60901");
        String[] args = new String[] {"--runtime=" + Constants.BOTH,
                "--core=" + Constants.FULL_CORE,
                "--app=" + Constants.ANOTHER_BOTH};
        Main.main(args);

        Socket client = null;
        int count = 0;
        while (client == null  && count < MAX_TRIES) {
            try {
                client = new Socket(InetAddress.getLocalHost(),
                        Integer.parseInt("60901"));
            } catch (Exception e) {
                Thread.sleep(SLEEP_TIME);
                count++;
            }
        }

        assertNotNull("Cannot connect to the socket", client);

        PrintWriter out =
            new PrintWriter(
                    new OutputStreamWriter(client.getOutputStream()), true);
        InputStream input = client.getInputStream();
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(input));
        out.println("STOP");
        out.flush();
        String read = reader.readLine();
        assertEquals("OK", read);
        client.close();

        System.setProperty("chameleon.admin.port", "60900");
    }

    /**
     * Tests to stop a chameleon from a customized port.
     * The port is given in the command line.
     * @throws Exception something bad happened.
     */
    public void testOnCustomPortCL() throws Exception {
        String[] args = new String[] {"--runtime=" + Constants.BOTH,
                "--core=" + Constants.FULL_CORE,
                "--app=" + Constants.ANOTHER_BOTH,
                "--chameleon.admin.port=60902"};
        Main.main(args);

        Socket client = null;
        int count = 0;
        while (client == null  && count < MAX_TRIES) {
            try {
                client = new Socket(InetAddress.getLocalHost(),
                        Integer.parseInt("60902"));
            } catch (Exception e) {
                Thread.sleep(SLEEP_TIME);
                count++;
            }
        }

        assertNotNull("Cannot connect to the socket", client);

        PrintWriter out =
            new PrintWriter(
                    new OutputStreamWriter(client.getOutputStream()), true);
        InputStream input = client.getInputStream();
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(input));
        out.println("STOP");
        out.flush();
        String read = reader.readLine();
        assertEquals("OK", read);
        client.close();

    }

    /**
     * Tests to stop a chameleon from a customized port
     * with the --stop argument.
     * The port is given in the command line.
     * @throws Exception something bad happened.
     */
    public void testStopArgument() throws Exception {
        String[] args = new String[] {"--runtime=" + Constants.BOTH,
                "--core=" + Constants.FULL_CORE,
                "--app=" + Constants.ANOTHER_BOTH,
                "--chameleon.admin.port=60904"};
        Main.main(args);


        Socket client = null;
        int count = 0;
        while (client == null  && count < MAX_TRIES) {
            try {
                client = new Socket(InetAddress.getLocalHost(),
                        Integer.parseInt("60904"));
            } catch (Exception e) {
                Thread.sleep(SLEEP_TIME);
                count++;
            }
        }

        assertNotNull("Cannot connect to the socket", client);
        PrintWriter out =
            new PrintWriter(
                    new OutputStreamWriter(client.getOutputStream()), true);
        InputStream input = client.getInputStream();
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(input));
        out.println("THIS IS NOT A COMMAND");
        out.flush();
        String read = reader.readLine();
        assertEquals("KO : Unknown command", read);
        client.close();

        String[] args2 = new String[] {"--stop",
            "--chameleon.admin.port=60904"};
        Main.main(args2);

    }

    /**
     * Tests to stop a chameleon from the bad port.
     * @throws Exception something bad happened.
     */
    public void testBadPort() throws Exception {
        // No chameleon started

        try {
            new Socket(InetAddress.getLocalHost(),
                        Integer.parseInt("60999"));
            fail("Bound to a wrong port");
        } catch (Exception e) {
            // OK
        }
    }

    /**
     * Tests to send an bad command.
     * @throws Exception something bad happened.
     */
    public void testWrongCommand() throws Exception {
        String[] args = new String[] {"--runtime=" + Constants.BOTH,
                "--core=" + Constants.FULL_CORE,
                "--app=" + Constants.ANOTHER_BOTH};
        Main.main(args);

        Socket client = null;
        int count = 0;
        while (client == null  && count < MAX_TRIES) {
            try {
                client = new Socket(InetAddress.getLocalHost(),
                        Main.DEFAULT_ADMIN_PORT);
            } catch (Exception e) {
                Thread.sleep(SLEEP_TIME);
                count++;
            }
        }

        assertNotNull("Cannot connect to the socket", client);

        PrintWriter out =
            new PrintWriter(
                    new OutputStreamWriter(client.getOutputStream()), true);
        InputStream input = client.getInputStream();
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(input));
        out.println("THIS IS NOT A COMMAND");
        out.flush();
        String read = reader.readLine();
        assertEquals("KO : Unknown command", read);
        client.close();

        client =
            new Socket(InetAddress.getLocalHost(), Main.DEFAULT_ADMIN_PORT);

        out =
            new PrintWriter(
                    new OutputStreamWriter(client.getOutputStream()), true);
        input = client.getInputStream();
        reader =
            new BufferedReader(new InputStreamReader(input));
        out.println("STOP");
        out.flush();
        read = reader.readLine();
        client.close();
    }

}
