/**
 * Copyright (c) 2002-2014 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.neo4j.server.enterprise;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Properties;

import org.junit.After;
import org.junit.Test;

import org.neo4j.cluster.ClusterSettings;
import org.neo4j.kernel.impl.util.StringLogger;
import org.neo4j.server.ServerStartupException;
import org.neo4j.server.configuration.Configurator;
import org.neo4j.server.configuration.PropertyFileConfigurator;
import org.neo4j.server.modules.ServerModule;
import org.neo4j.test.TargetDirectory;

import static org.neo4j.test.TargetDirectory.forTest;

public class StartupTimeoutFunctionalTest
{
    public EnterpriseNeoServer server;

    @After
    public void stopServer()
    {
        if ( server != null )
        {
            server.stop();
            server = null;
        }
    }

    @Test
    public void shouldTimeoutIfStartupTakesLongerThanTimeout() throws IOException
    {
        Configurator configurator = buildProperties();
        configurator.configuration().setProperty( Configurator.STARTUP_TIMEOUT, 1 );
        server = createSlowServer( configurator );

        try
        {
            server.start();
            fail( "Should have been interrupted." );
        }
        catch ( ServerStartupException e )
        {
            // ok!
        }

    }

    @Test
    public void shouldNotFailIfStartupTakesLessTimeThanTimeout() throws IOException
    {
        Configurator configurator = buildProperties();
        configurator.configuration().setProperty( Configurator.STARTUP_TIMEOUT, 20 );
        server = new EnterpriseNeoServer( configurator )
        {
            @Override
            protected Iterable<ServerModule> createServerModules()
            {
                return Arrays.asList();
            }
        };

        try
        {
            server.start();
        }
        catch ( ServerStartupException e )
        {
            fail( "Should not have been interrupted.", e );
        }
    }

    @Test
    public void shouldNotTimeOutIfTimeoutDisabled() throws IOException
    {
        Configurator configurator = buildProperties();
        configurator.configuration().setProperty( Configurator.STARTUP_TIMEOUT, 0 );
        server = createSlowServer( configurator );

        try
        {
            server.start();
        }
        catch ( ServerStartupException e )
        {
            fail( "Should not have been interrupted.", e );
        }
    }

    private EnterpriseNeoServer createSlowServer( Configurator configurator )
    {
        EnterpriseNeoServer server = new EnterpriseNeoServer( configurator )
        {
            @Override
            protected Iterable<ServerModule> createServerModules()
            {
                ServerModule slowModule = new ServerModule()
                {
                    @Override
                    public void start( StringLogger logger )
                    {
                        try
                        {
                            Thread.sleep( 1000 * 5 );
                        }
                        catch ( InterruptedException e )
                        {
                            throw new RuntimeException( e );
                        }
                    }

                    @Override
                    public void stop()
                    {
                    }
                };
                return Arrays.asList( slowModule );
            }
        };
        return server;
    }

    private Configurator buildProperties() throws IOException
    {
        TargetDirectory target = forTest( StartupTimeoutFunctionalTest.class );
        target.cleanup();

        target.directory( "conf" );

        Properties databaseProperties = new Properties();
        String databasePropertiesFileName = target.file( "conf/neo4j.properties" ).getAbsolutePath();
        databaseProperties.setProperty( ClusterSettings.server_id.name(), "1" );
        databaseProperties.setProperty( ClusterSettings.initial_hosts.name(), ":5001,:5002,:5003" );
        databaseProperties.store( new FileWriter( databasePropertiesFileName ), null );

        Properties serverProperties = new Properties();
        String serverPropertiesFilename = target.file( "conf/neo4j-server.properties" ).getAbsolutePath();
        serverProperties.setProperty( Configurator.DATABASE_LOCATION_PROPERTY_KEY,
                target.directory( "data/graph.db", true ).getAbsolutePath() );
        serverProperties.setProperty( Configurator.DB_TUNING_PROPERTY_FILE_KEY, databasePropertiesFileName );
        serverProperties.setProperty( Configurator.NEO_SERVER_CONFIG_FILE_KEY, serverPropertiesFilename );
        serverProperties.store( new FileWriter( serverPropertiesFilename ), null );

        return new PropertyFileConfigurator( new File( serverPropertiesFilename ) );
    }

    private void fail( String message )
    {
        throw new AssertionError( message );
    }

    private void fail( String message, Throwable cause )
    {
        throw new AssertionError( message, cause );
    }
}

@@ -1367,16 +1367,54 @@
 ctory;%0A%0A
+import static org.junit.Assert.fail;%0A%0A
 import s
@@ -1459,16 +1459,16 @@
 orTest;%0A
-
 %0Apublic 
@@ -2182,25 +2182,24 @@
 !%0A        %7D%0A
-%0A
     %7D%0A%0A    @
@@ -2682,182 +2682,23 @@
     
-try%0A        %7B%0A            server.start();%0A        %7D%0A        catch ( ServerStartupException e )%0A        %7B%0A            fail( %22Should not have been interrupted.%22, e );%0A        %7D
+server.start();
 %0A   
@@ -2992,182 +2992,23 @@
     
-try%0A        %7B%0A            server.start();%0A        %7D%0A        catch ( ServerStartupException e )%0A        %7B%0A            fail( %22Should not have been interrupted.%22, e );%0A        %7D
+server.start();
 %0A   
@@ -3107,36 +3107,14 @@
     
-EnterpriseNeoServer server =
+return
  new
@@ -3995,31 +3995,8 @@
  %7D;%0A
-        return server;%0A
     
@@ -5260,32 +5260,32 @@
 ame ), null );%0A%0A
+
         return n
@@ -5362,227 +5362,7 @@
    %7D
-%0A%0A    private void fail( String message )%0A    %7B%0A        throw new AssertionError( message );%0A    %7D%0A%0A    private void fail( String message, Throwable cause )%0A    %7B%0A        throw new AssertionError( message, cause );%0A    %7D
 %0A%7D%0A

Simplify failure handling in StartupTimeoutFunctionalTest.