| /* |
| * Copyright 2008 Google Inc. |
| * |
| * 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 com.google.gwt.junit.remote; |
| |
| import junit.framework.TestCase; |
| |
| import java.io.File; |
| import java.net.MalformedURLException; |
| import java.rmi.Naming; |
| import java.rmi.NotBoundException; |
| import java.rmi.RemoteException; |
| import java.rmi.registry.LocateRegistry; |
| import java.rmi.registry.Registry; |
| import java.util.Properties; |
| |
| /** |
| * Exercise the BrowserManagerServer with the serialized option turned on and |
| * off. |
| */ |
| public class BrowserManagerServerTest extends TestCase { |
| /** |
| * Seconds for simulated browser to hang. |
| */ |
| static final int TIMEOUT_MS = 2000; |
| /** |
| * Time to wait between keepAlive calls to all browsers. |
| */ |
| static final int PING_INTERVAL_MS = 100; |
| static final boolean LOG = false; |
| |
| private static final String REGISTRATION_KEY = "sleep-" + (TIMEOUT_MS / 1000) |
| + "-seconds"; |
| private static Registry rmiRegistry = null; |
| |
| private int portArg = Registry.REGISTRY_PORT; |
| private BrowserManagerServer server = null; |
| |
| /** |
| * Run a test with the 'serialized' flag on. |
| */ |
| public void testSerializedServer() throws Exception { |
| BrowserManager browserManager = startBrowserManagerServer(true); |
| |
| // Launch some browsers all at once. |
| final int NUM_BROWSERS = 4; |
| int tokens[] = new int[NUM_BROWSERS]; |
| |
| for (int i = 0; i < NUM_BROWSERS; i++) { |
| tokens[i] = launchBrowser(browserManager, i); |
| } |
| |
| // Give them a chance to startup. |
| Thread.sleep(TIMEOUT_MS / 4); |
| |
| int numQueued = server.numQueued(); |
| int numRunning = server.numRunning(); |
| assertEquals("Did not find the number of expected browsers queued up", |
| NUM_BROWSERS - 1, numQueued); |
| assertEquals("Expected only one running at a time for serialized.", 1, |
| numRunning); |
| |
| outer : for (int runningBrowser = 0; runningBrowser < NUM_BROWSERS; ++runningBrowser) { |
| // The current browser should be dead within twice the expected timeout. |
| long shouldBeDeadBy = System.currentTimeMillis() + (TIMEOUT_MS * 2); |
| while (System.currentTimeMillis() < shouldBeDeadBy) { |
| assertTrue(server.numRunning() <= 1); |
| |
| // Ping every alive browser. |
| for (int i = runningBrowser; i < NUM_BROWSERS; ++i) { |
| // Keep the browser alive with a margin of safety until the next ping. |
| try { |
| browserManager.keepAlive(tokens[runningBrowser], TIMEOUT_MS); |
| } catch (IllegalStateException ise) { |
| // Expected. |
| assertEquals("The wrong browser is dead", runningBrowser, i); |
| if (LOG) { |
| System.out.println("Browser token: " + tokens[i] |
| + " exited sucessfully"); |
| } |
| // Ensure it's legal to kill the dead browser. |
| browserManager.killBrowser(tokens[i]); |
| // Continue with the next active browser. |
| continue outer; |
| } |
| } |
| Thread.sleep(PING_INTERVAL_MS); |
| } |
| // Error case |
| fail("Browser " + runningBrowser + " failed to exit in a timely manner"); |
| } |
| } |
| |
| /** |
| * Run a test with the 'serialized' flag on. |
| */ |
| public void testUnserializedServer() throws Exception { |
| BrowserManager browserManager = startBrowserManagerServer(false); |
| |
| // Launch some browsers all at once. |
| final int NUM_BROWSERS = 6; |
| int tokens[] = new int[NUM_BROWSERS]; |
| |
| for (int i = 0; i < NUM_BROWSERS; i++) { |
| tokens[i] = launchBrowser(browserManager, i); |
| } |
| |
| // Give them a chance to startup. |
| Thread.sleep(TIMEOUT_MS / 4); |
| |
| int numQueued = server.numQueued(); |
| int numRunning = server.numRunning(); |
| assertEquals("No queuing should occur", 0, numQueued); |
| assertEquals("All browers should be running", NUM_BROWSERS, numRunning); |
| |
| // The current browser should be dead within twice the expected timeout. |
| long shouldBeDeadBy = System.currentTimeMillis() + (TIMEOUT_MS * 2); |
| int liveBrowsers = NUM_BROWSERS; |
| while (System.currentTimeMillis() < shouldBeDeadBy) { |
| // Ping every alive browser. |
| for (int i = 0; i < NUM_BROWSERS; ++i) { |
| if (tokens[i] == 0) { |
| // This one's already dead. |
| continue; |
| } |
| // Keep the browser alive with a margin of safety until the next ping. |
| try { |
| browserManager.keepAlive(tokens[i], TIMEOUT_MS); |
| } catch (IllegalStateException ise) { |
| // Expected. |
| if (LOG) { |
| System.out.println("Browser token: " + tokens[i] |
| + " exited sucessfully"); |
| } |
| // Ensure it's legal to kill the dead browser. |
| browserManager.killBrowser(tokens[i]); |
| |
| tokens[i] = 0; |
| --liveBrowsers; |
| |
| if (liveBrowsers == 0) { |
| // All done; |
| return; |
| } |
| } |
| } |
| Thread.sleep(PING_INTERVAL_MS); |
| } |
| // Error case |
| fail(liveBrowsers + " browsers failed to exit in a timely manner"); |
| } |
| |
| /** |
| * Start up the RMI registry and create a shell script that just sleeps for |
| * 'timeout' seconds. |
| */ |
| @Override |
| protected void setUp() throws Exception { |
| if (rmiRegistry == null) { |
| rmiRegistry = LocateRegistry.createRegistry(portArg); |
| } |
| } |
| |
| /** |
| * Clean up temporary files. |
| */ |
| @Override |
| protected void tearDown() throws Exception { |
| // De-register the server. |
| if (rmiRegistry != null) { |
| rmiRegistry.unbind(REGISTRATION_KEY); |
| } |
| } |
| |
| /** |
| * Start a browser task on the server. |
| * |
| * @param browserManager handle to the browser manager instance |
| * @param token browser ident number |
| */ |
| private int launchBrowser(BrowserManager browserManager, int token) |
| throws RemoteException { |
| return browserManager.launchNewBrowser("# client" + token, TIMEOUT_MS); |
| } |
| |
| /** |
| * Starts up an instance of BrowserManagerServer. |
| * |
| * @param isSerialized true to enable the serialized mode (run one browser |
| * instance at a time, queue any others.) |
| * @return the newly created instance of BrowserManagerServer on success |
| */ |
| private BrowserManager startBrowserManagerServer(boolean isSerialized) |
| throws RemoteException, MalformedURLException, NotBoundException { |
| // Construct a launch command for relaunching the JVM out of process, |
| // running DummyProcess. |
| StringBuilder sb = new StringBuilder(); |
| Properties properties = System.getProperties(); |
| sb.append(properties.getProperty("java.home")); |
| sb.append(File.separatorChar); |
| sb.append("bin"); |
| sb.append(File.separatorChar); |
| sb.append("java"); |
| sb.append('\n'); |
| |
| sb.append("-classpath"); |
| sb.append('\n'); |
| |
| sb.append(properties.getProperty("java.class.path")); |
| sb.append('\n'); |
| |
| sb.append(DummyProcess.class.getName()); |
| |
| server = new BrowserManagerServer(sb.toString(), isSerialized); |
| rmiRegistry.rebind(REGISTRATION_KEY, server); |
| |
| // Server started. Now, create a client and send some commands to it |
| String url = "rmi://localhost/" + REGISTRATION_KEY; |
| BrowserManager browserManager = (BrowserManager) Naming.lookup(url); |
| return browserManager; |
| } |
| } |