/* * Copyright to the original author or authors. * * 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 org.rioproject.test.monitor; import net.jini.lookup.ServiceDiscoveryManager; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.rioproject.cybernode.Cybernode; import org.rioproject.monitor.ProvisionMonitor; import org.rioproject.test.RioTestRunner; import org.rioproject.test.ServiceMonitor; import org.rioproject.test.SetTestManager; import org.rioproject.test.TestManager; import org.rioproject.test.simple.Simple; import org.rioproject.test.utils.CybernodeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.List; /** * The class tests backup behavior of Provision Monitors. * <p> * The class tests backup behavior of Provision Monitors which is * specified in <em>Rio Specification Bits. Provision Monitors. Backup * Behavior</em>. The test basically tests the following specification * statement: * <p> * If an opstring is deployed to one or more Provision Monitors of * a federation, then the federation keeps enforcing the opstring * as long as there is at least one Provision Monitor remaining * in the federation. * <p> * Since federation is a dynamic set of Provision Monitors and there * is an infinite number of scenarios of how a federation can change * over time, it is impossible to test all of the scenarios. That is * why for this test we pick two scenarios - scenario A and scenario * B - which we believe are representative enough. * * <h1>Scenario A</h1> * In this scenario the test starts <code>N</code> (some number of) * Provision Monitors at once, deploys the opstring to the first * Provision Monitor, and then stops the Provision Monitors one by one, * starting from the first one, and verifying that the opstring remains * enforced until there are no running Provision Monitors. * * <h1>Scenario B</h1> * In this scenario the federation of Provision Monitors changes more * dramatically. The test starts one Provision Monitor, deploys the * opstring to it, then starts another Provision Monitor, stops * the first one, starts another one, stops the previous one, and * so on <code>N</code> times, having no more than two and no less * than one Provision Monitor at any moment of time, and verifying * on each step that the opstring is still enforced. */ @RunWith (RioTestRunner.class) //@IfPropertySet(name = "org.rioproject.test", value = "backup") public class BackupTest { private static Logger logger = LoggerFactory.getLogger(BackupTest.class.getPackage().getName()); @SetTestManager TestManager testManager; @Test public void runScenarios() throws Exception { scenarioA(); scenarioB(); } /** * Runs scenario A. * * @throws Exception if the test fails */ public void scenarioA() throws Exception { logger.info("\n*******************\nRunning scenario A ...\n*******************"); Assert.assertNotNull(testManager); testManager.startReggie(); // 0. N=max{4,number of test hosts} // If there are more than 4 hosts participating in the test, we // want to have one Cybernode and one Provision Monitor running // on each host. Otherwise we want to have 4 Cybernodes and 4 // Provision Monitors (started in a round-robin fashion) in order // to have meaningful test. final int N = Math.max(4, testManager.getHostList().size()); // 1. START N CYBERNODES AND N PROVISION MONITORS IN A ROUND-ROBIN // FASHION logger.info("Starting [" + N + "] Cybernodes and " + "[" + N + "] Provision Monitors " + "in a round-robin fashion ..."); for (int i = 0; i < N; i++) { testManager.startProvisionMonitor(i); testManager.startCybernode(i); } logger.info("[" + N + "] Cybernodes and " + "[" + N + "] Provision Monitors have been started"); ServiceDiscoveryManager sdm = testManager.getServiceDiscoveryManager(); ServiceMonitor<Cybernode> cyMon = new ServiceMonitor<Cybernode>(sdm, Cybernode.class); ServiceMonitor<ProvisionMonitor> pmMon = new ServiceMonitor<ProvisionMonitor>(sdm, ProvisionMonitor.class); cyMon.waitFor(N); pmMon.waitFor(N); List<Cybernode> cybernodes = cyMon.getServices(); List<ProvisionMonitor> pms = pmMon.getServices(); Assert.assertEquals("Provision Monitor collection should have 4 entries", 4, pms.size()); Assert.assertEquals("Cybernode collection should have 4 entries", 4, cybernodes.size()); for(ProvisionMonitor pm : pms) Assert.assertNotNull("Provision Monitor proxy should not be null", pm); for(Cybernode cybernode : cybernodes) Assert.assertNotNull("Cybernode proxy should not be null", cybernode); // 2. DEPLOY OPSTRING testManager.deploy(new File("src/test/resources/opstring/simple_opstring.groovy"), pms.get(0)); // 3. ASSERTION: ONE SERVICE INSTANCE SHOULD APPEAR ServiceMonitor<Simple> simpleMon = new ServiceMonitor<Simple>(sdm, Simple.class); simpleMon.waitFor(1); // 4. DO THE MAIN CYCLE for (int i = 0; i < N - 1; i++) { try { // 5. STOP PROVISION MONTIOR logger.info("---> Stopping Provision Monitor [" + i + "] ..."); ProvisionMonitor pm = pms.get(i); testManager.stopProvisionMonitor(pm); //pms.remove(pm); logger.info("Provision Monitor [" + i + "] has been stopped"); // 6. STOP CYBERNODE RUNNING THE SERVICE logger.info("---> Stopping the busy Cybernode ..."); Cybernode cybernode = CybernodeUtils.findBusy(cybernodes); testManager.stopCybernode(cybernode); cybernodes.remove(cybernode); logger.info("---> The busy Cybernode has been stopped"); pmMon.waitFor(N - 1 - i); cyMon.waitFor(N - 1 - i); // 7. ASSERTION: THE SERVICE SHOULD BE PROVISIONED ONTO ANOTHER // CYBERNODE simpleMon.waitFor(1); } catch (Throwable t) { t.printStackTrace(); } } // 8. START ADDITIONAL CYBERNODE logger.info("Starting additional Cybernode ..."); cybernodes.add(testManager.startCybernode(0)); logger.info("Additional Cybernode has been started"); // 9. STOP THE LAST PROVISION MONITOR logger.info("Stopping the last Provision Monitor ..."); testManager.stopService(pms.get(N-1), "Monitor"); logger.info("The last Provision Monitor has been stopped"); cyMon.waitFor(2); pmMon.waitFor(0); // 10. STOP THE CYBERNODE RUNNING THE SERVICE logger.info("Stopping the busy Cybernode ..."); testManager.stopCybernode(cybernodes.get(0)); logger.info("The busy Cybernode has been stopped"); cyMon.waitFor(1); // 11. ASSERTION: THE SERVICE SHOULD NOT APPEAR // (BECAUSE THERE ARE NO MORE PROVISION MONITORS) simpleMon.waitFor(0); // Cleanup testManager.stopCybernode(cybernodes.get(1)); testManager.shutdown(); logger.info("\n*******************\nScenario A completed\n*******************"); } /** * Runs scenario B. * * @throws Exception if the test fails */ public void scenarioB() throws Exception { logger.info("\n*******************\nRunning scenario B\n*******************"); Assert.assertNotNull(testManager); testManager.startReggie(); // 0. N=max{4,number of test hosts} // If there are more than 4 hosts participating in the test, we // want to have as many iterations as hosts. Otherwise we want // to have 4 iterations in order to have meaningful test. final int N = Math.max(4, testManager.getHostList().size()); ServiceDiscoveryManager sdm = testManager.getServiceDiscoveryManager(); // 1. START PROVISION MONITOR logger.info("Starting Provision Monitor ..."); //ProvisionMonitor pm = testManager.startProvisionMonitor(-1); testManager.startProvisionMonitor(-1); logger.info("Provision Monitor has been started"); ServiceMonitor<ProvisionMonitor> pmMon = new ServiceMonitor<ProvisionMonitor>(sdm, ProvisionMonitor.class); // 2. START CYBERNODE logger.info("Starting Cybernode ..."); //Cybernode cybernode = testManager.startCybernode(-1); testManager.startCybernode(-1); logger.info("Cybernode has been started"); ServiceMonitor<Cybernode> cyMon = new ServiceMonitor<Cybernode>(sdm, Cybernode.class); pmMon.waitFor(1); cyMon.waitFor(1); List<Cybernode> cybernodes = cyMon.getServices(); List<ProvisionMonitor> pms = pmMon.getServices(); Cybernode cybernode = cybernodes.get(0); ProvisionMonitor pm = pms.get(0); // 3. DEPLOY OPSTRING testManager.deploy(new File("src/test/resources/opstring/simple_opstring.groovy")); // 4. ASSERTION: ONE SERVICE INSTANCE SHOULD APPEAR //TODO : port Dummy.class ServiceMonitor<Simple> simpleMon = new ServiceMonitor<Simple>(sdm, Simple.class); simpleMon.waitFor(1); // 5. DO THE MAIN CYCLE for (int i = 0; i < N; i++) { // 6. START THE NEXT PROVISION MONITOR logger.info("---> Starting the next Provision Monitor ..."); //ProvisionMonitor nextPM = testManager.startProvisionMonitor(-1); testManager.startProvisionMonitor(-1); logger.info("The next Provision Monitor has been started"); // 7. START THE NEXT CYBERNODE logger.info("---> Starting the next Cybernode ..."); //Cybernode nextCybernode = testManager.startCybernode(-1); testManager.startCybernode(-1); logger.info("---> The next Cybernode has been started"); cyMon.waitFor(2); pmMon.waitFor(2); // 8. GIVE PROVISION MONITORS SOME TIME TO DISCOVER EACH OTHER Thread.sleep(2000); // 9. STOP THE PREVIOUS PROVISION MONTIOR logger.info("Stopping the previous Provision Monitor ..."); testManager.stopProvisionMonitor(pm); logger.info("The previous Provision Monitor has been stopped"); // 10. STOP THE PREVIOUS CYBERNODE logger.info("Stopping the previous Cybernode ..."); testManager.stopCybernode(cybernode); logger.info("The previous Cybernode has been stopped"); pmMon.waitFor(1); cyMon.waitFor(1); // 11. ASSERTION: THE SERVICE SHOULD BE PROVISIONED ONTO ANOTHER // CYBERNODE simpleMon.waitFor(1); //cybernode = nextCybernode; //pm = nextPM; cybernodes = cyMon.getServices(); pms = pmMon.getServices(); cybernode = cybernodes.get(0); pm = pms.get(0); } // 12. START ADDITIONAL CYBERNODE logger.info("Starting additional Cybernode ..."); testManager.startCybernode(-1); logger.info("Additional Cybernode has been started"); // 13. STOP THE LAST PROVISION MONITOR logger.info("Stopping the last Provision Monitor ..."); testManager.stopProvisionMonitor(pm); logger.info("The last Provision Monitor has been stopped"); cyMon.waitFor(2); pmMon.waitFor(0); // 14. STOP THE CYBERNODE RUNNING THE SERVICE logger.info("Stopping the busy Cybernode ..."); testManager.stopCybernode(cybernode); logger.info("The busy Cybernode has been stopped"); // 15. ASSERTION: THE SERVICE SHOULD NOT APPEAR // (BECAUSE THERE ARE NO MORE PROVISION MONITORS) simpleMon.waitFor(0); for(Cybernode c : cyMon.getServices()) { testManager.stopCybernode(c); } cyMon.waitFor(0); logger.info("\n*******************\nScenario B completed\n*******************"); } }