package brooklyn.entity.webapp.tomcat;

import static brooklyn.test.TestUtils.isPortInUse;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.fail;

import java.net.ServerSocket;

import org.jclouds.util.Throwables2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import brooklyn.entity.basic.ApplicationBuilder;
import brooklyn.entity.basic.Entities;
import brooklyn.entity.proxying.EntitySpec;
import brooklyn.location.basic.LocalhostMachineProvisioningLocation;
import brooklyn.test.entity.TestApplication;

import com.google.common.collect.ImmutableList;

/**
 * This tests the operation of the {@link TomcatServer} entity.
 * 
 * FIXME this test is largely superseded by WebApp*IntegrationTest which tests inter alia Tomcat
 */
public class TomcatServerSimpleIntegrationTest {
    @SuppressWarnings("unused")
    private static final Logger LOG = LoggerFactory.getLogger(TomcatServerSimpleIntegrationTest.class);
    
    /** don't use 8080 since that is commonly used by testing software */
    static int DEFAULT_HTTP_PORT = 7880;

    static boolean httpPortLeftOpen = false;
    
    private TestApplication app;
    private TomcatServer tc;
    
    @BeforeMethod(alwaysRun=true)
    public void failIfHttpPortInUse() {
        if (isPortInUse(DEFAULT_HTTP_PORT, 5000L)) {
            httpPortLeftOpen = true;
            fail("someone is already listening on port "+DEFAULT_HTTP_PORT+"; tests assume that port "+DEFAULT_HTTP_PORT+" is free on localhost");
        }
    }
 
    @AfterMethod(alwaysRun=true)
    public void tearDown() throws Exception {
        if (app != null) Entities.destroy(app);
    }
    
    @Test(groups="Integration")
    public void detectFailureIfTomcatCantBindToPort() throws Exception {
        ServerSocket listener = new ServerSocket(DEFAULT_HTTP_PORT);
        try {
            app = ApplicationBuilder.newManagedApp(TestApplication.class);
            tc = app.createAndManageChild(EntitySpec.create(TomcatServer.class).configure("httpPort",DEFAULT_HTTP_PORT));
            
            try {
                tc.start(ImmutableList.of(app.getManagementContext().getLocationManager().manage(new LocalhostMachineProvisioningLocation())));
                fail("Should have thrown start-exception");
            } catch (Exception e) {
                // LocalhostMachineProvisioningLocation does NetworkUtils.isPortAvailable, so get -1
                IllegalArgumentException iae = Throwables2.getFirstThrowableOfType(e, IllegalArgumentException.class);
                if (iae == null || iae.getMessage() == null || !iae.getMessage().equals("port for httpPort is null")) throw e;
            } finally {
                tc.stop();
            }
            assertFalse(tc.getAttribute(TomcatServerImpl.SERVICE_UP));
        } finally {
            listener.close();
        }
    }
}

@@ -37,59 +37,8 @@
 t;%0A%0A
-import static brooklyn.test.TestUtils.isPortInUse;%0A
 impo
@@ -146,16 +146,43 @@
 rSocket;
+%0Aimport java.util.Iterator;
 %0A%0Aimport
@@ -525,16 +525,52 @@
 tySpec;%0A
+import brooklyn.location.PortRange;%0A
 import b
@@ -630,16 +630,59 @@
 cation;%0A
+import brooklyn.location.basic.PortRanges;%0A
 import b
@@ -717,16 +717,53 @@
 ication;
+%0Aimport brooklyn.util.net.Networking;
 %0A%0Aimport
@@ -1238,16 +1238,49 @@
 software
+; use different from other tests.
  */%0A    
@@ -1286,19 +1286,25 @@
  static 
-int
+PortRange
  DEFAULT
@@ -1317,61 +1317,51 @@
 PORT
- = 7880;%0A%0A    static boolean httpPortLeftOpen = false
+_RANGE = PortRanges.fromString(%227880-7980%22)
 ;%0A  
@@ -1425,16 +1425,42 @@
 ver tc;%0A
+    private int httpPort;%0A
     %0A   
@@ -1510,126 +1510,291 @@
 oid 
-failIfHttpPortInUse() %7B%0A        if (isPortInUse(DEFAULT_HTTP_PORT, 5000L)) %7B%0A            httpPortLeftOpen = true;%0A    
+pickFreePort() %7B%0A        for (Iterator%3CInteger%3E iter = DEFAULT_HTTP_PORT_RANGE.iterator(); iter.hasNext();) %7B%0A            Integer port = iter.next();%0A            if (Networking.isPortAvailable(port)) %7B%0A                httpPort = port;%0A                return;%0A            %7D%0A        %7D%0A
     
@@ -1835,24 +1835,25 @@
 ning on port
+s
  %22+DEFAULT_H
@@ -1860,16 +1860,22 @@
 TTP_PORT
+_RANGE
 +%22; test
@@ -1896,30 +1896,8 @@
 port
- %22+DEFAULT_HTTP_PORT+%22
  is 
@@ -1917,26 +1917,16 @@
 host%22);%0A
-        %7D%0A
     %7D%0A %0A
@@ -2217,33 +2217,24 @@
 rSocket(
-DEFAULT_HTTP_PORT
+httpPort
 );%0A     
@@ -2418,33 +2418,25 @@
 tpPort%22,
-DEFAULT_HTTP_PORT
+ httpPort
 ));%0A    

Make TomcatServerSimpleIntegrationTest more robust