001: package net.sourceforge.cruisecontrol.builders;
002:
003: import junit.framework.TestCase;
004: import junit.framework.Test;
005: import junit.framework.TestSuite;
006: import junit.extensions.TestSetup;
007:
008: import java.util.Properties;
009: import java.util.Arrays;
010: import java.util.Map;
011: import java.util.HashMap;
012: import java.io.File;
013: import java.io.IOException;
014: import java.io.EOFException;
015: import java.net.URL;
016: import java.net.InetAddress;
017: import java.net.ConnectException;
018: import java.net.SocketException;
019: import java.net.MalformedURLException;
020:
021: import org.apache.log4j.Logger;
022: import org.apache.log4j.Level;
023: import net.sourceforge.cruisecontrol.util.Commandline;
024: import net.sourceforge.cruisecontrol.util.Util;
025: import net.sourceforge.cruisecontrol.util.StreamPumper;
026: import net.sourceforge.cruisecontrol.util.OSEnvironment;
027: import net.sourceforge.cruisecontrol.util.StreamConsumer;
028: import net.sourceforge.cruisecontrol.distributed.BuildAgent;
029: import net.sourceforge.cruisecontrol.distributed.BuildAgentService;
030: import net.sourceforge.cruisecontrol.distributed.BuildAgentServiceImplTest;
031: import net.sourceforge.cruisecontrol.distributed.BuildAgentTest;
032: import net.sourceforge.cruisecontrol.distributed.core.ReggieUtil;
033: import net.sourceforge.cruisecontrol.distributed.core.MulticastDiscovery;
034: import net.sourceforge.cruisecontrol.distributed.core.MulticastDiscoveryTest;
035: import net.sourceforge.cruisecontrol.distributed.core.PropertiesHelper;
036: import net.sourceforge.cruisecontrol.distributed.core.RemoteResultTest;
037: import net.sourceforge.cruisecontrol.MockProject;
038: import net.sourceforge.cruisecontrol.Progress;
039: import net.sourceforge.cruisecontrol.ProjectConfig;
040: import net.sourceforge.cruisecontrol.labelincrementers.DefaultLabelIncrementer;
041: import net.jini.core.lookup.ServiceRegistrar;
042: import net.jini.core.lookup.ServiceID;
043: import net.jini.core.discovery.LookupLocator;
044: import net.jini.config.ConfigurationProvider;
045: import net.jini.config.Configuration;
046: import net.jini.config.ConfigurationException;
047: import net.jini.discovery.DiscoveryListener;
048: import net.jini.discovery.DiscoveryEvent;
049: import net.jini.lookup.ServiceIDListener;
050:
051: /**
052: * @author Dan Rollo
053: * Date: May 6, 2005
054: * Time: 2:34:24 PM
055: */
056: public class DistributedMasterBuilderTest extends TestCase {
057:
058: private static final Logger LOG = Logger
059: .getLogger(DistributedMasterBuilderTest.class);
060:
061: /** NOTE: Assumes we are executing with current dir cc/contrig/distributed/target */
062: // @todo Change if we move CCDist into main
063: public static final String MAIN_CCDIST_DIR = "../";
064: static {
065: final File mainCCDistDir;
066: try {
067: mainCCDistDir = new File(MAIN_CCDIST_DIR)
068: .getCanonicalFile();
069: } catch (IOException e) {
070: throw new RuntimeException(e);
071: }
072: final String msg = "Executing unit tests in unexpected directory: "
073: + mainCCDistDir.getAbsolutePath() + ";";
074: assertEquals(msg, "distributed", mainCCDistDir.getName());
075:
076: final File ccDistTargetDir;
077: try {
078: ccDistTargetDir = new File(".").getCanonicalFile();
079: } catch (IOException e) {
080: throw new RuntimeException(e);
081: }
082: assertEquals(msg, "target", ccDistTargetDir.getName());
083: }
084:
085: private static final String INSECURE_POLICY_FILENAME = "insecure.policy";
086: private static Properties origSysProps;
087:
088: private static final String CONFIG_START_JINI = "conf/start-jini.config";
089: public static final String JINI_URL_LOCALHOST;
090: static {
091: final Configuration config;
092: String hostname;
093: try {
094: config = ConfigurationProvider
095: .getInstance(new String[] { MAIN_CCDIST_DIR
096: + CONFIG_START_JINI });
097: hostname = (String) config.getEntry("com.sun.jini.start",
098: "hostname", String.class);
099: } catch (ConfigurationException e) {
100: throw new RuntimeException("Error loading jini config: "
101: + CONFIG_START_JINI, e);
102: }
103: if (hostname != null) {
104: JINI_URL_LOCALHOST = "jini://" + hostname;
105: } else {
106: JINI_URL_LOCALHOST = "jini://localhost";
107: }
108: LOG.info("Using local Jini URL: " + JINI_URL_LOCALHOST);
109: }
110:
111: private static final OSEnvironment OS_ENV = new OSEnvironment();
112:
113: private static ProcessInfoPump jiniProcessPump;
114:
115: /** Common error message if multicast is being blocked. */
116: private static final String MSG_DISOCVERY_CHECK_FIREWALL = "1. Make sure MULTICAST is enabled on your network devices (ifconfig -a).\n"
117: + "2. No Firewall is blocking multicasts.\n"
118: + "3. Using an IDE? See @todo in setUp/tearDown (LUS normally started by LUSTestSetup decorator).\n";
119:
120: public static final String MSG_PREFIX_STATS = "STATS: ";
121:
122: private static String getTestDMBEntries() {
123: final Map userProps = PropertiesHelper
124: .loadRequiredProperties(BuildAgentServiceImplTest.TEST_USER_DEFINED_PROPERTIES_FILE);
125:
126: final Object retval = userProps
127: .get(BuildAgentServiceImplTest.ENTRY_NAME_BUILD_TYPE);
128: assertNotNull("Missing required entry for DMB unit test: "
129: + BuildAgentServiceImplTest.ENTRY_NAME_BUILD_TYPE,
130: retval);
131: assertTrue(retval instanceof String);
132:
133: return BuildAgentServiceImplTest.ENTRY_NAME_BUILD_TYPE + "="
134: + retval;
135: }
136:
137: /**
138: * Show what's happening with the Jini Process.
139: */
140: private static final class PrefixedStreamConsumer implements
141: StreamConsumer {
142: private final String prefix;
143: private final Logger logger;
144: private final Level level;
145:
146: PrefixedStreamConsumer(final String prefix,
147: final Logger logger, final Level level) {
148: this .prefix = prefix;
149: this .logger = logger;
150: this .level = level;
151: }
152:
153: /** {@inheritDoc} */
154: public void consumeLine(String line) {
155: logger.log(level, prefix + line);
156: }
157: }
158:
159: /**
160: * @return the Process in which Jini Lookup _service is running, for use in killing it.
161: * @throws Exception if we can't start jini lookup service
162: */
163: public static ProcessInfoPump startJini() throws Exception {
164: final long begin = System.currentTimeMillis();
165:
166: final Logger logger = LOG;
167: final Level level = Level.INFO;
168:
169: // make sure local lookup service is not already running
170: verifyNoLocalLookupService();
171:
172: origSysProps = System.getProperties();
173:
174: // Build Lookup Service command line just like the one in lookup-build.xml
175:
176: // <java jar="jini-lib/start.jar" fork="true" >
177: // <jvmarg value="-Djava.security.policy=conf/${jini.policy.file}" />
178: // <jvmarg value="-Djini.lib=jini-lib" />
179: // <jvmarg value="-Djini.lib.dl=jini-lib-dl" />
180: // <jvmarg value="-Djini.httpPort=${jini.port}" />
181: // <arg value="conf/${jini.config}"/>
182:
183: final String jiniLibDir = "jini-lib";
184:
185: final String[] args = new String[] {
186: "-Djava.security.policy=conf/insecure.policy", //${jini.policy.file}
187: "-Djini.lib=" + jiniLibDir,
188: "-Djini.lib.dl=jini-lib-dl", //Downloadable Jini jars
189: "-Djini.httpPort=8050", //${jini.port}"
190: };
191:
192: final Commandline cmdLine = new Commandline();
193: cmdLine.addArguments(args);
194: Commandline.Argument argClasspath = cmdLine.createArgument();
195: argClasspath.setLine("-classpath " + "conf");
196:
197: Commandline.Argument argStart = cmdLine.createArgument();
198: argStart.setLine("-jar " + jiniLibDir + "/start.jar");
199:
200: Commandline.Argument argProg = cmdLine.createArgument();
201: argProg.setValue(CONFIG_START_JINI); // ${jini.config}
202:
203: cmdLine.setExecutable(getJavaExec());
204:
205: LOG.debug("jini startup command: "
206: + Arrays.asList(cmdLine.getCommandline()));
207: final Process newJiniProcess = Runtime.getRuntime().exec(
208: cmdLine.getCommandline(), null,
209: new File(MAIN_CCDIST_DIR));
210:
211: newJiniProcess.getOutputStream().close();
212:
213: final ProcessInfoPump jiniProcessInfoPump = new ProcessInfoPump(
214: newJiniProcess,
215: // show what's happening with the jiniProcessPump
216: new StreamPumper(newJiniProcess.getErrorStream(),
217: new PrefixedStreamConsumer("[JiniErr] ",
218: logger, level)), new StreamPumper(
219: newJiniProcess.getInputStream(),
220: new PrefixedStreamConsumer("[JiniOut] ",
221: logger, level)), logger, level);
222:
223: Thread.sleep(2000); // allow LUS some spin up time, first time is longest (~3.5 secs)
224:
225: // Verify the Lookup Service started
226:
227: // setup security policy
228: setupInsecurePolicy();
229:
230: // The startup time for the first LUS appears to be much longer than subsequent startups...
231: ServiceRegistrar serviceRegistrar = findTestLookupService(50 * 1000);
232: try {
233: assertNotNull("Failed to start local lookup _service.",
234: serviceRegistrar);
235: } finally {
236: if (serviceRegistrar == null) {
237: // kill service in case it is just really slow to start, to help avoid orphaned LUS processes
238: killJini(jiniProcessInfoPump);
239: }
240: }
241: assertEquals("Unexpected local lookup _service host",
242: InetAddress.getLocalHost().getCanonicalHostName(),
243: serviceRegistrar.getLocator().getHost());
244:
245: LOG
246: .info(MSG_PREFIX_STATS + "Jini Startup took: "
247: + (System.currentTimeMillis() - begin) / 1000f
248: + " sec");
249:
250: return jiniProcessInfoPump;
251: }
252:
253: /**
254: * Setup an insecure policy file for use during unit tests that require Jini.
255: */
256: public static void setupInsecurePolicy() {
257: URL policyFile = ClassLoader.getSystemClassLoader()
258: .getResource(INSECURE_POLICY_FILENAME);
259: assertNotNull(
260: "Can't load policy file resource: "
261: + INSECURE_POLICY_FILENAME
262: + ". Make sure this file is in the classes (bin) directory.",
263: policyFile);
264: System.setProperty(BuildAgent.JAVA_SECURITY_POLICY, policyFile
265: .toExternalForm());
266: ReggieUtil.setupRMISecurityManager();
267: }
268:
269: private static String javaExecutable;
270:
271: private static String getJavaExec() {
272: if (javaExecutable == null) {
273: final String javaExecFilename;
274: if (Util.isWindows()) {
275: javaExecFilename = "java.exe";
276: } else {
277: javaExecFilename = "java";
278: }
279: // use javaHome env var to find java
280: if (getJavaHome() != null) {
281: File checkExists = new File(getJavaHome()
282: + File.separator + "bin" + File.separator
283: + javaExecFilename);
284: if (checkExists.exists()) {
285: javaExecutable = checkExists.getAbsolutePath();
286: } else {
287: // maybe JAVA_HOME env var is bad, try sys prop of current vm
288: LOG
289: .warn("Is JAVA_HOME valid? Unit Test couldn't find: "
290: + checkExists.getAbsolutePath());
291: checkExists = new File(System
292: .getProperty("java.home")
293: + File.separator
294: + "bin"
295: + File.separator
296: + javaExecFilename);
297: if (checkExists.exists()) {
298: javaExecutable = checkExists.getAbsolutePath();
299: } else {
300: LOG
301: .warn("Unit Test couldn't find java. Might work if java is on the path? Here goes...");
302: javaExecutable = javaExecFilename;
303: }
304: }
305: } else {
306: final String msg = "Unit Test couldn't find JAVA_HOME env var. Maybe java/bin is in the path? Here goes...";
307: System.out.println(msg);
308: LOG.warn(msg);
309: javaExecutable = javaExecFilename;
310: }
311: }
312: return javaExecutable;
313: }
314:
315: private static String javaHome;
316:
317: private static String getJavaHome() {
318: if (javaHome == null) {
319: String envJavaHome = OS_ENV.getVariable("JAVA_HOME");
320: if (envJavaHome != null) {
321: javaHome = envJavaHome;
322: } else {
323: // try system prop for java.home
324: javaHome = System.getProperty("java.home");
325: }
326: }
327: return javaHome;
328: }
329:
330: public static ServiceRegistrar findTestLookupService(
331: int retryTimeoutMillis) throws IOException,
332: ClassNotFoundException, InterruptedException {
333:
334: // find/wait for lookup _service
335: final long startTime = System.currentTimeMillis();
336:
337: ServiceRegistrar serviceRegistrar = null;
338: final LookupLocator lookup = new LookupLocator(
339: JINI_URL_LOCALHOST);
340:
341: // making this polling loop pause too short actually slows the unit tests down
342: final int sleepMillisAfterException = 250;
343:
344: while (serviceRegistrar == null
345: && (System.currentTimeMillis() - startTime < retryTimeoutMillis)) {
346:
347: try {
348: serviceRegistrar = lookup.getRegistrar();
349: } catch (ConnectException e) {
350: Thread.sleep(sleepMillisAfterException);
351: } catch (SocketException e) {
352: Thread.sleep(sleepMillisAfterException);
353: } catch (EOFException e) {
354: Thread.sleep(sleepMillisAfterException);
355: }
356: // more exceptions will likely need to added here as the Jini libraries are updated.
357: // could catch a generic super class, but I kinda like to know what's being thrown.
358: }
359:
360: LOG.info(MSG_PREFIX_STATS + "Find Test LUS took: "
361: + (System.currentTimeMillis() - startTime) / 1000f
362: + " sec; Timeout: " + retryTimeoutMillis + "; Found: "
363: + (serviceRegistrar != null));
364:
365: return serviceRegistrar;
366: }
367:
368: public static void killJini(final ProcessInfoPump jiniProcessPump)
369: throws Exception {
370: if (jiniProcessPump != null) {
371:
372: final long begin = System.currentTimeMillis();
373:
374: jiniProcessPump.kill();
375: LOG.debug("Jini process killed.");
376:
377: verifyNoLocalLookupService();
378:
379: LOG.info(MSG_PREFIX_STATS + "Jini Shutdown took: "
380: + (System.currentTimeMillis() - begin) / 1000f
381: + " sec");
382: }
383:
384: // restore original system properties
385: System.setProperties(origSysProps);
386: }
387:
388: private static void verifyNoLocalLookupService()
389: throws IOException, ClassNotFoundException,
390: InterruptedException {
391:
392: final String msgLUSFoundCheckForOrphanedProc = "Found local lookup service, but it should be dead. Is an orphaned java process still running?";
393:
394: final ServiceRegistrar serviceRegistrar;
395: try {
396: serviceRegistrar = findTestLookupService(1000);
397: } catch (ClassNotFoundException e) {
398: assertFalse(msgLUSFoundCheckForOrphanedProc,
399: "com.sun.jini.reggie.ConstrainableRegistrarProxy"
400: .equals(e.getMessage()));
401: throw e;
402: }
403: assertNull(msgLUSFoundCheckForOrphanedProc, serviceRegistrar);
404: }
405:
406: /**
407: * Holds a executing process and it's associated stream pump threads.
408: */
409: public static final class ProcessInfoPump {
410: private final Process process;
411: private final Thread inputPumpThread;
412: private final Thread errorPumpThread;
413:
414: private final Logger logger;
415: private final Level level;
416:
417: public ProcessInfoPump(final Process process,
418: final StreamPumper inputPump,
419: final StreamPumper errorPump, final Logger logger,
420: final Level level) {
421:
422: this .process = process;
423:
424: this .logger = logger;
425: this .level = level;
426:
427: errorPumpThread = new Thread(errorPump);
428: inputPumpThread = new Thread(inputPump);
429:
430: errorPumpThread.start();
431: inputPumpThread.start();
432: }
433:
434: public void kill() throws IOException, InterruptedException {
435: process.destroy();
436:
437: logger.log(level, "Process destroyed.");
438:
439: // wait for stream pumps to end
440: if (errorPumpThread != null) {
441: errorPumpThread.join();
442: }
443: if (inputPumpThread != null) {
444: inputPumpThread.join();
445: }
446:
447: process.getInputStream().close();
448: process.getErrorStream().close();
449: process.getOutputStream().close();
450:
451: logger.log(level, "Process pumps finished.");
452: }
453: }
454:
455: /**
456: * Test Decorator to launch Jini LUS once for this class.
457: */
458: public static final class LUSTestSetup extends TestSetup {
459:
460: public LUSTestSetup(Test test) {
461: super (test);
462: }
463:
464: protected void setUp() throws Exception {
465: jiniProcessPump = DistributedMasterBuilderTest.startJini();
466: }
467:
468: protected void tearDown() throws Exception {
469: DistributedMasterBuilderTest.killJini(jiniProcessPump);
470: }
471: }
472:
473: /**
474: * Use LUSTestSetup decorator to run Jini LUS once for this test class.
475: * @return a TestSuite wrapper by the LUSTestSetup decorator
476: */
477: public static Test suite() {
478: final TestSuite ts = new TestSuite();
479: ts.addTestSuite(DistributedMasterBuilderTest.class);
480: return new LUSTestSetup(ts);
481: }
482:
483: // @todo Add one slash in front of "/*" below to run individual tests in an IDE
484: /*
485: protected void setUp() throws Exception {
486: jiniProcessPump = DistributedMasterBuilderTest.startJini();
487: }
488: protected void tearDown() throws Exception {
489: DistributedMasterBuilderTest.killJini(jiniProcessPump);
490: }
491: //*/
492:
493: public void testRemoteProgress() throws Exception {
494: // register agent
495: final BuildAgent agentAvailable = createBuildAgent();
496: try {
497: final DistributedMasterBuilder masterBuilder = getMasterBuilder_LocalhostONLY();
498:
499: final MockBuilder mockBuilder = new MockBuilder();
500: masterBuilder.add(mockBuilder);
501: masterBuilder.validate();
502:
503: final Map projectProperties = new HashMap();
504: projectProperties.put(PropertiesHelper.PROJECT_NAME,
505: "testProjectName");
506:
507: final MockProject mockProject = new MockProject();
508: final Progress progress = mockProject.getProgress();
509:
510: final ProjectConfig projectConfig = new ProjectConfig();
511: projectConfig.add(new DefaultLabelIncrementer());
512: mockProject.setProjectConfig(projectConfig);
513:
514: masterBuilder.build(projectProperties, progress);
515:
516: final BuildAgentService agentService = masterBuilder
517: .pickAgent(null, null);
518: assertNotNull("Couldn't find released agent.\n"
519: + MSG_DISOCVERY_CHECK_FIREWALL, agentService);
520: assertTrue(
521: "Claimed agent should show as busy. (Did we find a better way?)",
522: agentService.isBusy());
523:
524: assertTrue("Wrong progress value: " + progress.getValue(),
525: progress.getValue().indexOf(
526: " retrieving results from ") == 8);
527: } finally {
528: // terminate JoinManager in BuildAgent
529: BuildAgentTest.terminateTestAgent(agentAvailable);
530: }
531: }
532:
533: public void testPickAgent2Agents() throws Exception {
534: // register agent
535: final BuildAgent agentAvailable = createBuildAgent();
536: final BuildAgent agentAvailable2 = createBuildAgent();
537: try {
538: assertFalse(agentAvailable.getService().isBusy());
539: assertFalse(agentAvailable2.getService().isBusy());
540:
541: final DistributedMasterBuilder masterBuilder = getMasterBuilder_LocalhostONLY();
542:
543: // try to find agents
544: final BuildAgentService agentFoundFirst = masterBuilder
545: .pickAgent(null, null);
546: assertNotNull("Couldn't find first agent.\n"
547: + MSG_DISOCVERY_CHECK_FIREWALL, agentFoundFirst);
548: assertTrue(agentFoundFirst.isBusy());
549:
550: final BuildAgentService agentFoundSecond = masterBuilder
551: .pickAgent(null, null);
552: assertNotNull("Couldn't find second agent",
553: agentFoundSecond);
554: assertTrue(agentFoundFirst.isBusy());
555: assertTrue(agentFoundSecond.isBusy());
556:
557: assertNull("Shouldn't find third agent", masterBuilder
558: .pickAgent(null, null));
559:
560: // set Agent to Not busy, then make sure it can be found again.
561: // callTestDoBuildSuccess() only needed to clearOuputFiles() will succeed
562: assertNotNull(BuildAgentServiceImplTest
563: .callTestDoBuildSuccess(agentAvailable.getService()));
564: agentAvailable.getService().clearOutputFiles();
565: RemoteResultTest
566: .resetTempZippedFile(BuildAgentServiceImplTest.REMOTE_RESULTS_ONE[0]);
567:
568: final BuildAgentService agentRefound = masterBuilder
569: .pickAgent(null, null);
570: assertNotNull("Couldn't find released agent", agentRefound);
571: assertTrue(
572: "Claimed agent should show as busy. (Did we find a better way?)",
573: agentRefound.isBusy());
574:
575: } finally {
576: // terminate JoinManager in BuildAgent
577: BuildAgentTest.terminateTestAgent(agentAvailable);
578: BuildAgentTest.terminateTestAgent(agentAvailable2);
579: }
580: }
581:
582: public void testPickAgentAfterReleased() throws Exception {
583: // register agent
584: final BuildAgent agentAvailable = createBuildAgent();
585: try {
586: assertFalse(agentAvailable.getService().isBusy());
587: agentAvailable.getService().claim(); // mark as busy
588:
589: final DistributedMasterBuilder masterBuilder = getMasterBuilder_LocalhostONLY();
590:
591: // try to find agent, shouldn't find any available
592: assertNull("Shouldn't find any available agents",
593: masterBuilder.pickAgent(null, null));
594:
595: // set Agent to Not busy, then make sure it can be found again.
596: // callTestDoBuildSuccess() only needed to clearOuputFiles() will succeed
597: assertNotNull(BuildAgentServiceImplTest
598: .callTestDoBuildSuccess(agentAvailable.getService()));
599: agentAvailable.getService().clearOutputFiles();
600: RemoteResultTest
601: .resetTempZippedFile(BuildAgentServiceImplTest.REMOTE_RESULTS_ONE[0]);
602:
603: final BuildAgentService agentRefound = masterBuilder
604: .pickAgent(null, null);
605: assertNotNull("Couldn't find released agent.\n"
606: + MSG_DISOCVERY_CHECK_FIREWALL, agentRefound);
607: assertTrue(
608: "Claimed agent should show as busy. (Did we find a better way?)",
609: agentRefound.isBusy());
610:
611: } finally {
612: // terminate JoinManager in BuildAgent
613: BuildAgentTest.terminateTestAgent(agentAvailable);
614: }
615: }
616:
617: public void testPickAgentAgentNotBusy() throws Exception {
618: // register agent
619: final BuildAgent agentAvailable = createBuildAgent();
620: try {
621: assertFalse(agentAvailable.getService().isBusy());
622:
623: final DistributedMasterBuilder masterBuilder = getMasterBuilder_LocalhostONLY();
624:
625: final BuildAgentService agent = masterBuilder.pickAgent(
626: null, null);
627: assertNotNull("Couldn't find agent.\n"
628: + MSG_DISOCVERY_CHECK_FIREWALL, agent);
629: assertTrue(
630: "Claimed agent should show as busy. (Did we find a better way?)",
631: agent.isBusy());
632:
633: // try to find agent, shouldn't find any available
634: assertNull("Shouldn't find any available agents",
635: masterBuilder.pickAgent(null, null));
636:
637: // set Agent to Not busy, then make sure it can be found again.
638:
639: // only needed so clearOuputFiles() will succeed
640: assertNotNull(BuildAgentServiceImplTest
641: .callTestDoBuildSuccess(agent));
642: agent.clearOutputFiles();
643: RemoteResultTest
644: .resetTempZippedFile(BuildAgentServiceImplTest.REMOTE_RESULTS_ONE[0]);
645:
646: final BuildAgentService agentRefound = masterBuilder
647: .pickAgent(null, null);
648: assertNotNull("Couldn't find released agent", agentRefound);
649: assertTrue(
650: "Claimed agent should show as busy. (Did we find a better way?)",
651: agentRefound.isBusy());
652: } finally {
653: // terminate JoinManager in BuildAgent
654: BuildAgentTest.terminateTestAgent(agentAvailable);
655: }
656: }
657:
658: public void testPickAgentNoAgents() throws Exception {
659:
660: DistributedMasterBuilder masterBuilder = getMasterBuilder_LocalhostONLY();
661:
662: assertNull("Shouldn't find any available agents", masterBuilder
663: .pickAgent(null, null));
664: }
665:
666: private static int testAgentID = 0;
667:
668: private static BuildAgent createBuildAgent()
669: throws InterruptedException {
670: return createBuildAgent(true);
671: }
672:
673: public static BuildAgent createBuildAgent(
674: final boolean isDiscoveryRequired)
675: throws InterruptedException {
676:
677: final int this AgentID = ++testAgentID;
678:
679: final long begin = System.currentTimeMillis();
680:
681: BuildAgentTest.setSkipMainSystemExit();
682: BuildAgentTest.setTerminateFast();
683:
684: // listen for agent to discover LUS
685: final String lock = "agentDiscLock" + this AgentID;
686: final class MyServiceIDListener implements ServiceIDListener {
687:
688: private volatile ServiceID myServiceID;
689:
690: /**
691: * Called when the JoinManager gets a valid ServiceID from a lookup
692: * service.
693: *
694: * @param serviceID the service ID assigned by the lookup service.
695: */
696: public void serviceIDNotify(ServiceID serviceID) {
697: myServiceID = serviceID;
698: LOG.info("Agent assigned serviceID: " + serviceID
699: + ". (agentID: " + this AgentID + ")");
700: synchronized (lock) {
701: lock.notifyAll();
702: }
703: }
704: }
705: final MyServiceIDListener utestListener = new MyServiceIDListener();
706:
707: LOG.info("Creating test Agent (agentID: " + this AgentID + ")");
708:
709: final BuildAgent agent = BuildAgentTest
710: .createTestBuildAgent(
711: BuildAgentServiceImplTest.TEST_AGENT_PROPERTIES_FILE,
712: BuildAgentServiceImplTest.TEST_USER_DEFINED_PROPERTIES_FILE,
713: true, utestListener, this AgentID);
714:
715: if (isDiscoveryRequired) {
716: synchronized (lock) {
717: int count = 0;
718: while (utestListener.myServiceID == null && count < 6) {
719: lock.wait(10 * 1000);
720: count++;
721: }
722: }
723:
724: final float elapsedSecs = (System.currentTimeMillis() - begin) / 1000f;
725:
726: assertNotNull(
727: "Unit test Agent was not discovered before timeout. elapsed: "
728: + elapsedSecs + " sec \n"
729: + MSG_DISOCVERY_CHECK_FIREWALL,
730: utestListener.myServiceID);
731:
732: LOG.info(MSG_PREFIX_STATS + "Unit test Agent (agentID: "
733: + this AgentID + ") discovery took: " + elapsedSecs
734: + " sec");
735: }
736:
737: return agent;
738: }
739:
740: static DistributedMasterBuilder getMasterBuilder_LocalhostONLY()
741: throws MalformedURLException, InterruptedException {
742:
743: if (!MulticastDiscoveryTest.isDiscoverySet()) {
744: final long begin = System.currentTimeMillis();
745:
746: final MulticastDiscovery discovery = MulticastDiscoveryTest
747: .getLocalDiscovery();
748: MulticastDiscoveryTest.setDiscovery(discovery);
749: // wait to discover lookupservice
750: final DiscoveryListener discoveryListener = new DiscoveryListener() {
751:
752: public void discovered(DiscoveryEvent e) {
753: synchronized (discovery) {
754: discovery.notifyAll();
755: }
756: }
757:
758: public void discarded(DiscoveryEvent e) {
759: synchronized (discovery) {
760: discovery.notifyAll();
761: }
762: }
763: };
764: MulticastDiscoveryTest
765: .addDiscoveryListener(discoveryListener);
766: try {
767: synchronized (discovery) {
768: int count = 0;
769: while (!MulticastDiscoveryTest.isDiscovered()
770: && count < 6) {
771: discovery.wait(10 * 1000);
772: count++;
773: }
774: }
775: } finally {
776: MulticastDiscoveryTest
777: .removeDiscoveryListener(discoveryListener);
778: }
779:
780: final float elapsedSecs = (System.currentTimeMillis() - begin) / 1000f;
781:
782: assertTrue(
783: "MulticastDiscovery was not discovered before timeout. elapsed: \n"
784: + elapsedSecs + " sec\n"
785: + MSG_DISOCVERY_CHECK_FIREWALL,
786: MulticastDiscoveryTest.isDiscovered());
787:
788: LOG.info(MSG_PREFIX_STATS
789: + "Unit test MulticastDiscovery took: "
790: + elapsedSecs + " sec");
791: }
792:
793: final DistributedMasterBuilder masterBuilder = new DistributedMasterBuilder();
794: // need to set Entries to prevent finding non-local LUS and/or non-local Build Agents
795: masterBuilder.setEntries(getTestDMBEntries());
796: masterBuilder.setFailFast(); // don't block until an available agent is found
797:
798: return masterBuilder;
799: }
800:
801: }
|