/******************************************************************************* * Copyright 2013 Google Inc. All Rights Reserved. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * 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 com.google.gdt.eclipse.suite.launch; import com.google.gdt.eclipse.core.NetworkUtilities; import com.google.gdt.eclipse.core.launch.WebAppLaunchAttributes; import junit.framework.TestCase; import org.eclipse.core.runtime.CoreException; import org.eclipse.swtbot.swt.finder.SWTBot; import java.io.IOException; import java.net.ServerSocket; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * Test for WebAppLaunchDelegate * */ public class WebAppLaunchDelegateTest extends TestCase { private static SWTBot bot; /** * Set up the bot * */ @Override public void setUp() { bot = new SWTBot(); } /** * Test when auto port selection is on promptUserToContinueIfPortNotAvailable * return true (continue with launch, ignore port information) * * @throws CoreException */ public void testAutoPortSelection() throws CoreException { final MockLaunchConfiguration config = new MockLaunchConfiguration(); config.setAttribute(WebAppLaunchAttributes.AUTO_PORT_SELECTION, Boolean.TRUE); WebAppLaunchDelegate delegate = new WebAppLaunchDelegate(); assertTrue(delegate.promptUserToContinueIfPortNotAvailable(config)); } /** * Test when a port is in use and user explicitly continues * promptUserToContinueIfPortNotAvailable return true (continue with launch) * * @throws CoreException * @throws InterruptedException * @throws ExecutionException * @throws TimeoutException * @throws IOException */ public void testPortInUseAndContinue() throws CoreException, InterruptedException, ExecutionException, TimeoutException, IOException { assertTrue(checkPortConflictUI("Yes")); } /** * Test when a port is in use and user cancels * promptUserToContinueIfPortNotAvailable return false (abort launch) * * @throws CoreException * @throws InterruptedException * @throws ExecutionException * @throws TimeoutException * @throws IOException */ public void testPortInUseAndDontContinue() throws CoreException, InterruptedException, ExecutionException, TimeoutException, IOException { assertFalse(checkPortConflictUI("No")); } /** * Test when a port is not in use and promptUserToContinueIfPortNotAvailable * returns true (continue with launch) * * @throws CoreException */ public void testPortNotInUse() throws CoreException { final MockLaunchConfiguration config = new MockLaunchConfiguration(); for (int i = 3000; i < 3500; i++) { String port = Integer.toString(i); if (NetworkUtilities.isPortAvailable(port)) { config.setAttribute(WebAppLaunchAttributes.SERVER_PORT, port); config.setAttribute(WebAppLaunchAttributes.AUTO_PORT_SELECTION, Boolean.FALSE); WebAppLaunchDelegate delegate = new WebAppLaunchDelegate(); assertTrue(delegate.promptUserToContinueIfPortNotAvailable(config)); return; } } fail("Test failed because we couldn't find an open port to test with"); } /** * Internal function to check the result when a port is in use and a specific * action is taken on the UI * * @param buttonToClick the string representing the button to click (Yes, No) * @return the result from the UI element * @throws ExecutionException If the thread ends with an exception * @throws InterruptedException * @throws TimeoutException If getting the value back from UI Widget takes too * long * @throws IOException If an exception occurred with the socket (port not * available) */ private boolean checkPortConflictUI(String buttonToClick) throws InterruptedException, ExecutionException, TimeoutException, IOException { final MockLaunchConfiguration config = new MockLaunchConfiguration(); ServerSocket ss = null; try { ss = new ServerSocket(0); String port = (new Integer(ss.getLocalPort())).toString(); config.setAttribute(WebAppLaunchAttributes.SERVER_PORT, port); config.setAttribute(WebAppLaunchAttributes.AUTO_PORT_SELECTION, Boolean.FALSE); // this needs to run in separate thread because promptUser... is a // blocking call final Callable<Boolean> promptCallable = new Callable<Boolean>() { public Boolean call() throws CoreException { WebAppLaunchDelegate delegate = new WebAppLaunchDelegate(); return delegate.promptUserToContinueIfPortNotAvailable(config); } }; ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Boolean> result = executor.submit(promptCallable); // since the prompt is on another thread, allow it some time to come up // before trying to activate it bot.sleep(1000); bot.shell("Port in Use").activate(); bot.button(buttonToClick).click(); // get the result but timeout if something goes wrong after a second return result.get(1, TimeUnit.SECONDS).booleanValue(); } finally { if (ss != null) { try { ss.close(); } catch (IOException ioe) { // probably shouldn't be here } } } } }