001: package net.sourceforge.cruisecontrol.distributed;
002:
003: import junit.framework.TestCase;
004: import junit.framework.Test;
005: import junit.framework.TestSuite;
006: import org.apache.log4j.Logger;
007: import net.sourceforge.cruisecontrol.builders.DistributedMasterBuilderTest;
008: import net.sourceforge.cruisecontrol.distributed.core.MulticastDiscovery;
009: import net.jini.core.lookup.ServiceRegistrar;
010: import net.jini.core.lookup.ServiceTemplate;
011: import net.jini.core.entry.Entry;
012: import net.jini.lookup.ServiceIDListener;
013:
014: import java.rmi.RemoteException;
015:
016: import java.awt.GraphicsEnvironment;
017:
018: /**
019: * @author Dan Rollo
020: * Date: Jul 6, 2005
021: * Time: 4:12:20 PM
022: */
023: public class BuildAgentTest extends TestCase {
024:
025: private static final Logger LOG = Logger
026: .getLogger(BuildAgentTest.class);
027:
028: /**
029: * Use LUSTestSetup decorator to run Jini LUS once for this test class.
030: * @return a TestSuite wrapper by the LUSTestSetup decorator
031: */
032: public static Test suite() {
033: final TestSuite ts = new TestSuite();
034: ts.addTestSuite(BuildAgentTest.class);
035: return new DistributedMasterBuilderTest.LUSTestSetup(ts);
036: }
037:
038: // @todo Remove one slash in front of "/*" below to run individual tests in an IDE
039: //*
040: protected void setUp() throws Exception {
041: BuildAgentTest.setSkipMainSystemExit();
042: BuildAgentTest.setTerminateFast();
043: }
044:
045: protected void tearDown() throws Exception {
046: BuildAgent.kill();
047: }
048:
049: //*/
050:
051: // @todo Add one slash in front of "/*" below to run individual tests in an IDE
052: /*
053: private static DistributedMasterBuilderTest.ProcessInfoPump jiniProcessPump;
054: protected void setUp() throws Exception {
055: jiniProcessPump = DistributedMasterBuilderTest.startJini(LOG);
056: BuildAgent.setSkipMainSystemExit();
057: BuildAgentTest.setTerminateFast();
058: }
059: protected void tearDown() throws Exception {
060: DistributedMasterBuilderTest.killJini(jiniProcessPump);
061: BuildAgent.kill();
062: }
063: //*/
064:
065: private static void assertFindAgent(final ServiceRegistrar reg,
066: final int retries, final boolean expectedFoundResult)
067: throws RemoteException, InterruptedException {
068:
069: final Entry[] entries = SearchablePropertyEntries
070: .getPropertiesAsEntryArray(new SearchablePropertyEntries(
071: BuildAgentServiceImplTest.TEST_USER_DEFINED_PROPERTIES_FILE)
072: .getProperties());
073: findAgent(reg, retries, expectedFoundResult, entries);
074: }
075:
076: private static Object findAgent(final ServiceRegistrar reg,
077: final int retries, final boolean expectedFoundResult,
078: final Entry[] entries) throws RemoteException,
079: InterruptedException {
080:
081: int retryCount = 0;
082: Object result;
083: boolean isFound;
084: do {
085: if (retryCount > 0) {
086: LOG.info("\tFind agent unit test retry " + retryCount
087: + "...Entries: "
088: + MulticastDiscovery.toStringEntries(entries));
089: Thread.sleep(1000 + (250 * retryCount)); // wait a bit before retry, longer for subsequent retries
090: }
091:
092: result = reg.lookup(new ServiceTemplate(null,
093: new Class[] { BuildAgentService.class }, entries));
094:
095: isFound = (result != null);
096:
097: retryCount++;
098:
099: } while ((expectedFoundResult != isFound)
100: && (retryCount < retries));
101:
102: if (expectedFoundResult) {
103: assertNotNull("Should find agent", result);
104: } else {
105: assertNull("Should not find agent", result);
106: }
107:
108: return result;
109: }
110:
111: public static void setSkipMainSystemExit() {
112: BuildAgent.setSkipMainSystemExit();
113: }
114:
115: public static void setTerminateFast() {
116: BuildAgent.setTerminateFast();
117: }
118:
119: public static BuildAgent createTestBuildAgent(
120: final String propsFile,
121: final String userDefinedPropertiesFilename,
122: final boolean isSkipUI,
123: final ServiceIDListener testListener, final int testAgentID) {
124:
125: return new BuildAgent(propsFile, userDefinedPropertiesFilename,
126: isSkipUI, testListener, testAgentID);
127: }
128:
129: public static void terminateTestAgent(final BuildAgent agent) {
130: agent.terminateTestAgent(agent);
131: }
132:
133: /**
134: * This test requires a bunch of manual steps:
135: * 1. Build the cc-agent.war (created via: ant war-agent).
136: * 2. Deploy cc-agent.war to a web server.
137: * 3. Manually launch agent via webstat (http://localhost:8080/cc-agent/agent.jnlp).
138: * 4. Manually run this test.
139: * @throws Exception if anything unexpected goes wrong in the test
140: */
141: public void manual_testRestart() throws Exception {
142: final ServiceRegistrar reg = DistributedMasterBuilderTest
143: .findTestLookupService(20 * 1000);
144: assertNotNull("Couldn't find registrar.", reg);
145:
146: final Entry[] entries = SearchablePropertyEntries
147: .getPropertiesAsEntryArray(new SearchablePropertyEntries(
148: BuildAgentServiceImplTest.TEST_USER_DEFINED_PROPERTIES_FILE)
149: .getProperties());
150: // work around timestamp prefix in build.type entry
151: final int idxBuildTypeEntry = 3;
152: assertEquals(
153: "Wrong entry in position where we expected to find 'build.type'.",
154: BuildAgentServiceImplTest.ENTRY_NAME_BUILD_TYPE,
155: ((PropertyEntry) entries[idxBuildTypeEntry]).name);
156: entries[idxBuildTypeEntry] = new PropertyEntry(
157: ((PropertyEntry) entries[idxBuildTypeEntry]).name,
158: "test");
159:
160: final BuildAgentService agentService = (BuildAgentService) findAgent(
161: reg, 3, true, entries);
162: assertNotNull(agentService.getMachineName());
163: agentService.restart(false);
164: // allow time for the relaunched agent to spin up and register
165: Thread.sleep(20 * 1000);
166: // verify first agent is dead
167: try {
168: agentService.getMachineName();
169: fail("Agent should be dead");
170: } catch (Exception e) {
171: // good, this is what we want.
172: }
173: // find the newly relaunched agent
174: final BuildAgentService agentService2 = (BuildAgentService) findAgent(
175: reg, 3, true, entries);
176: assertNotNull(agentService2.getMachineName());
177: agentService2.kill(false);
178: }
179:
180: public void testKillNoUI() throws Exception {
181: ServiceRegistrar reg = DistributedMasterBuilderTest
182: .findTestLookupService(20 * 1000);
183: assertNotNull("Couldn't find registrar.", reg);
184: assertFindAgent(reg, 3, false);
185:
186: final Thread t = new Thread(
187: "BuildAgentTest testKillNoUI Thread") {
188: public void run() {
189: BuildAgent
190: .main(new String[] {
191: "-" + BuildAgent.MAIN_ARG_AGENT_PROPS,
192: BuildAgentServiceImplTest.TEST_AGENT_PROPERTIES_FILE,
193: "-" + BuildAgent.MAIN_ARG_USER_PROPS,
194: BuildAgentServiceImplTest.TEST_USER_DEFINED_PROPERTIES_FILE,
195: "-" + BuildAgent.MAIN_ARG_SKIP_UI });
196: }
197: };
198: t.start();
199: // allow BuildAgent main to load and register
200: final int maxWaitStartup = 30;
201: int count = 0;
202: while (count < maxWaitStartup && t.isAlive()
203: && BuildAgent.getMainThread() == null) {
204: Thread.sleep(500);
205: count++;
206: }
207: assertTrue("Agent start thread should be alive.", t.isAlive());
208: assertNotNull("Agent didn't start before timeout.", BuildAgent
209: .getMainThread());
210: assertTrue("Agent didn't init before timeout.", BuildAgent
211: .getMainThread().isAlive());
212: assertFindAgent(reg, 10, true);
213: final Thread mainThread = BuildAgent.getMainThread(); // hold onto main thread since kill nullifies it
214: assertNotNull("Main thread should not be null.", mainThread);
215:
216: BuildAgent.kill();
217: assertFalse("Agent start thread should be dead.", t.isAlive());
218: assertFalse("Agent didn't die before timeout.", mainThread
219: .isAlive()); // check held thread
220: assertFindAgent(reg, 10, false);
221: }
222:
223: public void testKill() throws Exception {
224: if (GraphicsEnvironment.isHeadless()) {
225: LOG
226: .warn("WARNING: DETECTED HEADLESS ENVIRONMENT. Skipping test: "
227: + getClass().getName() + ".testKill()");
228: return;
229: }
230:
231: ServiceRegistrar reg = DistributedMasterBuilderTest
232: .findTestLookupService(20 * 1000);
233: assertNotNull("Couldn't find registrar.", reg);
234: assertFindAgent(reg, 3, false);
235:
236: final Thread t = new Thread("BuildAgentTest testKill Thread") {
237: public void run() {
238: BuildAgent
239: .main(new String[] {
240: "-" + BuildAgent.MAIN_ARG_AGENT_PROPS,
241: BuildAgentServiceImplTest.TEST_AGENT_PROPERTIES_FILE,
242: "-" + BuildAgent.MAIN_ARG_USER_PROPS,
243: BuildAgentServiceImplTest.TEST_USER_DEFINED_PROPERTIES_FILE });
244: }
245: };
246: t.start();
247: // allow BuildAgent main to load and register
248: final int maxWaitStartup = 30;
249: int count = 0;
250: while (count < maxWaitStartup && t.isAlive()
251: && BuildAgent.getMainThread() == null) {
252: Thread.sleep(500);
253: count++;
254: }
255: assertTrue("Agent start thread should be alive.", t.isAlive());
256: assertNotNull("Agent didn't start before timeout.", BuildAgent
257: .getMainThread());
258: assertTrue("Agent didn't init before timeout.", BuildAgent
259: .getMainThread().isAlive());
260: assertFindAgent(reg, 10, true);
261: final Thread mainThread = BuildAgent.getMainThread(); // hold onto main thread since kill nullifies it
262: assertNotNull("Main thread should not be null.", mainThread);
263:
264: BuildAgent.kill();
265: assertFalse("Agent start thread should be dead.", t.isAlive());
266: assertFalse("Agent didn't die before timeout.", mainThread
267: .isAlive()); // check held thread
268: assertFindAgent(reg, 20, false);
269: }
270:
271: public void testSetEntryOverrides() throws Exception {
272: final BuildAgent buildAgent = DistributedMasterBuilderTest
273: .createBuildAgent(false);
274: try {
275: final int expectedOrigEntryCount = 5;
276: final PropertyEntry[] origEnties = buildAgent.getEntries();
277: assertEquals(
278: "Did the unit test props file change? : "
279: + BuildAgentServiceImplTest.TEST_USER_DEFINED_PROPERTIES_FILE,
280: expectedOrigEntryCount, origEnties.length);
281:
282: // add new prop entry
283: final PropertyEntry newPropEntry = new PropertyEntry(
284: "newEntryName", "newEntryValue");
285: buildAgent
286: .setEntryOverrides(new PropertyEntry[] { newPropEntry });
287: assertEquals(expectedOrigEntryCount + 1, buildAgent
288: .getEntries().length);
289:
290: // set to empty array
291: buildAgent.setEntryOverrides(new PropertyEntry[] {});
292: assertEquals(expectedOrigEntryCount, buildAgent
293: .getEntries().length);
294:
295: // test clear overrides
296: buildAgent
297: .setEntryOverrides(new PropertyEntry[] { newPropEntry });
298: assertEquals(expectedOrigEntryCount + 1, buildAgent
299: .getEntries().length);
300: buildAgent.clearEntryOverrides();
301: assertEquals(expectedOrigEntryCount, buildAgent
302: .getEntries().length);
303: // test multiple clear calls
304: buildAgent.clearEntryOverrides();
305: assertEquals(expectedOrigEntryCount, buildAgent
306: .getEntries().length);
307:
308: // test override user-defined entry and system entry
309: final PropertyEntry newOverrideUser = new PropertyEntry(
310: "build.type", "OverrideTest");
311: final PropertyEntry newOverrideSystem = new PropertyEntry(
312: SearchablePropertyEntries.SYSTEM_ENTRY_KEYS[0],
313: "OverrideSystemEntry");
314: buildAgent.setEntryOverrides(new PropertyEntry[] {
315: newPropEntry, newOverrideUser, newOverrideSystem });
316: assertEquals(expectedOrigEntryCount + 1, buildAgent
317: .getEntries().length);
318:
319: buildAgent.clearEntryOverrides();
320: assertEquals(expectedOrigEntryCount, buildAgent
321: .getEntries().length);
322: } finally {
323: // clear overrides
324: buildAgent.clearEntryOverrides();
325: // clear all agent prefs
326: buildAgent.getPrefsRoot().removeNode();
327: buildAgent.getPrefsRoot().flush();
328:
329: BuildAgent.kill();
330: }
331: }
332: }
|