/* * Copyright (c) 2010 Ecole des Mines de Nantes. * * This file is part of Entropy. * * Entropy is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Entropy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Entropy. If not, see <http://www.gnu.org/licenses/>. */ package entropy.plan.choco; import java.util.ArrayList; import java.util.List; import org.testng.Assert; import org.testng.annotations.Test; import choco.kernel.common.logging.ChocoLogging; import entropy.PropertiesHelper; import entropy.TestHelper; import entropy.configuration.Configuration; import entropy.configuration.DefaultManagedElementSet; import entropy.configuration.ManagedElementSet; import entropy.configuration.Node; import entropy.configuration.SimpleConfiguration; import entropy.configuration.SimpleManagedElementSet; import entropy.configuration.SimpleNode; import entropy.configuration.SimpleVirtualMachine; import entropy.configuration.VirtualMachine; import entropy.plan.CustomizablePlannerModule; import entropy.plan.MultipleResultingStateException; import entropy.plan.NoAvailableTransitionException; import entropy.plan.NonViableSourceConfigurationException; import entropy.plan.PlanException; import entropy.plan.SolutionStatistics; import entropy.plan.SolvingStatistics; import entropy.plan.TimedReconfigurationPlan; import entropy.plan.UnknownResultingStateException; import entropy.plan.action.Action; import entropy.plan.action.Migration; import entropy.plan.action.Shutdown; import entropy.plan.durationEvaluator.MockDurationEvaluator; import entropy.vjob.BasicVJob; import entropy.vjob.ExplodedSet; import entropy.vjob.LazySpread; import entropy.vjob.VJob; import entropy.vjob.builder.ConstraintsCatalogBuilderFromProperties; import entropy.vjob.builder.MockVirtualMachineBuilder; import entropy.vjob.builder.VJobBuilder; import entropy.vjob.builder.VJobElementBuilder; /** * Unit tests for CustomizablePlannerModule. * * @author Fabien Hermenier */ @Test(groups = {"unit", "RP-core"}) public class TestChocoCustomRP { private static final String RESOURCES_DIR = "src/test/resources/entropy/plan/choco/TestChocoCustomizablePlannerModule."; private ChocoCustomRP makeModule() { return new ChocoCustomRP(new MockDurationEvaluator(5, 1, 1, 7, 14, 7, 2, 4)); } @Test(expectedExceptions = {PlanException.class}) public void testWithoutConstraintsAndSolution() throws PlanException { ChocoCustomRP planner = makeModule(); planner.setTimeLimit(10); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "noSolution.txt"); List<VJob> vjobs = new ArrayList<VJob>(); VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(src.getRunnings())); new MockVirtualMachineBuilder(); vjobs.add(v); try { planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); } catch (MultipleResultingStateException e) { Assert.fail(e.getMessage(), e); } catch (NoAvailableTransitionException e) { Assert.fail(e.getMessage(), e); } catch (NonViableSourceConfigurationException e) { Assert.fail(e.getMessage(), e); } catch (UnknownResultingStateException e) { Assert.fail(e.getMessage()); } } public void testWithoutVJobs() { CustomizablePlannerModule planner = makeModule(); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "empty.txt"); List<VJob> vjobs = new ArrayList<VJob>(); new MockVirtualMachineBuilder(); try { TimedReconfigurationPlan plan = planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); Assert.assertEquals(plan.size(), 0); } catch (Exception e) { Assert.fail(e.getMessage(), e); } } public void testViableWithoutConstraints() { //BasicConfigurator.configure(); CustomizablePlannerModule planner = makeModule(); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "simple.txt"); List<VJob> vjobs = new ArrayList<VJob>(); VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(src.getRunnings())); new MockVirtualMachineBuilder(); vjobs.add(v); try { TimedReconfigurationPlan plan = planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); //System.out.println(plan); Assert.assertEquals(plan.size(), 0); } catch (Exception e) { Assert.fail(e.getMessage(), e); } } public void testWithSequences() { //ChocoLogging.setVerbosity(Verbosity.SEARCH); ChocoCustomRP planner = makeModule(); planner.setRepairMode(false); //required to have a solution Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "sequencing_src.txt"); Configuration dst = TestHelper.readConfiguration(RESOURCES_DIR + "sequencing_dst.txt"); List<VJob> vjobs = new ArrayList<VJob>(); VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(src.getRunnings())); new MockVirtualMachineBuilder(); vjobs.add(v); try { TimedReconfigurationPlan plan = planner.compute(src, dst.getRunnings(), dst.getWaitings(), dst.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), dst.getOnlines(), dst.getOfflines(), vjobs); Assert.assertEquals(plan.size(), 5); Shutdown s = null; Migration m1 = null, m2 = null, m3 = null, m4 = null; for (Action a : plan.getActions()) { if (a instanceof Shutdown) { s = (Shutdown) a; } else if (a instanceof Migration) { Migration m = (Migration) a; if (m.getVirtualMachine().getName().equals("VM1")) m1 = m; else if (m.getVirtualMachine().getName().equals("VM2")) m2 = m; else if (m.getVirtualMachine().getName().equals("VM3")) m3 = m; else if (m.getVirtualMachine().getName().equals("VM4")) m4 = m; } } Assert.assertTrue(s.getStartMoment() >= m1.getFinishMoment()); Assert.assertTrue(s.getStartMoment() >= m2.getFinishMoment()); Assert.assertTrue(m1.getStartMoment() >= m3.getFinishMoment()); Assert.assertTrue(m2.getStartMoment() >= m4.getFinishMoment()); } catch (Exception e) { Assert.fail(e.getMessage(), e); } } public void testNonViableWithoutConstraints() { //ChocoLogging.setVerbosity(Verbosity.SEARCH); CustomizablePlannerModule planner = makeModule(); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "nonViable.txt"); //System.err.println(src.getCurrentlyOverloadedNodes()); List<VJob> vjobs = new ArrayList<VJob>(); VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(src.getRunnings())); new MockVirtualMachineBuilder(); vjobs.add(v); try { TimedReconfigurationPlan plan = planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); System.out.println(plan); Assert.assertEquals(plan.getDuration(), 5); } catch (Exception e) { Assert.fail(e.getMessage(), e); } } /** * Test solving with basic constraints. */ public void testWithSatisfiableConstraints() { CustomizablePlannerModule planner = makeModule(); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "nonViable.txt"); List<VJob> vjobs = new ArrayList<VJob>(); VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(src.getRunnings())); try { v.addConstraint(new LazySpread(new ExplodedSet<VirtualMachine>(v.getVirtualMachines()))); } catch (Exception e) { Assert.fail(e.getMessage(), e); } new MockVirtualMachineBuilder(); vjobs.add(v); try { TimedReconfigurationPlan plan = planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); System.err.println(plan); Assert.assertEquals(plan.size(), 3); } catch (Exception e) { Assert.fail(e.getMessage(), e); } } public void testWithBootAndShutdownActions() { //ChocoLogging.setVerbosity(Verbosity.SEARCH); ChocoCustomRP planner = makeModule(); //Check solving statistics Assert.assertTrue(planner.getSolvingStatistics() == SolvingStatistics.getStatisticsForNotSolvingProcess()); Assert.assertEquals(planner.getSolutionsStatistics().size(), 0); planner.setRepairMode(false); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "nonViable.txt"); src.addOffline(src.getOnlines().get("N9")); List<VJob> vjobs = new ArrayList<VJob>(); ManagedElementSet<Node> offs = new DefaultManagedElementSet<Node>(); ManagedElementSet<Node> ons = new DefaultManagedElementSet<Node>(); ons.addAll(src.getOnlines()); ons.remove(src.getOnlines().get("N3")); offs.add(src.getOnlines().get("N3")); ons.add(src.getAllNodes().get("N9")); VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(src.getRunnings())); vjobs.add(v); try { TimedReconfigurationPlan plan = planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), ons, offs, vjobs); System.err.println(plan); Assert.assertEquals(plan.getActions().size(), 6); } catch (Exception e) { Assert.fail(e.getMessage(), e); } SolvingStatistics st = planner.getSolvingStatistics(); List<SolutionStatistics> sols = planner.getSolutionsStatistics(); //Every solutions, asc sorted wrt. solving duration Assert.assertTrue(sols.size() > 1); for (int i = 1; i < sols.size(); i++) { SolutionStatistics s2 = sols.get(i); SolutionStatistics s1 = sols.get(i - 1); Assert.assertTrue(s2.getNbBacktracks() >= s1.getNbBacktracks() && s2.getNbNodes() >= s1.getNbNodes() && s2.getTimeCount() >= s1.getTimeCount() && s1.getObjective() > s2.getObjective()); } //Solvin statistics at least equals to the last solution SolutionStatistics s = sols.get(sols.size() - 1); st = planner.getSolvingStatistics(); Assert.assertTrue(st.getNbBacktracks() >= s.getNbBacktracks() && st.getNbNodes() >= s.getNbNodes() && st.getTimeCount() >= s.getTimeCount()); } /** * Solve a plan with some slice with no requirements. */ public void testWithNoRequirements() { CustomizablePlannerModule planner = makeModule(); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "noRequirements.txt"); List<VJob> vjobs = new ArrayList<VJob>(); VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(src.getRunnings())); new MockVirtualMachineBuilder(); vjobs.add(v); try { TimedReconfigurationPlan plan = planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); Assert.assertEquals(plan.size(), 0); } catch (Exception e) { Assert.fail(e.getMessage(), e); } } public void testCosts() { //ChocoLogging.setVerbosity(Verbosity.SEARCH); CustomizablePlannerModule planner = makeModule(); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "testCost.txt"); List<VJob> vjobs = new ArrayList<VJob>(); VJob v = new BasicVJob("v1"); v.addVirtualMachines(new ExplodedSet<VirtualMachine>(src.getRunnings())); new MockVirtualMachineBuilder(); vjobs.add(v); try { TimedReconfigurationPlan plan = planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new SimpleManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); System.out.println(plan); Assert.assertEquals(plan.size(), 1); Assert.assertEquals(plan.getDuration(), 5); } catch (Exception e) { Assert.fail(e.getMessage(), e); } } /*public void dummy() { ChocoCustomRP planner = makeModule(); Configuration src = TestHelper.readConfiguration(RESOURCES_DIR + "multipleOneOf_cfg.txt"); try { MockVirtualMachineBuilder builder = new MockVirtualMachineBuilder(); VJobBuilder b = new VJobBuilder(new VJobElementBuilder(builder), new ConstraintsCatalogBuilderFromProperties(new PropertiesHelper("src/main/config/entropy.properties")).build()); b.getElementBuilder().useConfiguration(src); VJob v = b.build("m", new File(RESOURCES_DIR + "multipleOneOf.txt")); List<VJob> vjobs = new ArrayList<VJob>(); vjobs.add(v); TimedReconfigurationPlan plan = planner.compute(src, src.getRunnings(), src.getWaitings(), src.getSleepings(), new DefaultManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); System.out.println(plan); } catch (Exception e) { Assert.fail(e.getMessage(), e); } finally { ChocoLogging.flushLogs(); } } */ public void testMigrateThenRun() { //ChocoLogging.setVerbosity(Verbosity.SILENT); Node n1 = new SimpleNode("N1", 5, 5, 5); Node n2 = new SimpleNode("N2", 4, 4, 4); Node n3 = new SimpleNode("N3", 4, 4, 4); VirtualMachine vm1 = new SimpleVirtualMachine("VM1", 2, 2, 2); VirtualMachine vm2 = new SimpleVirtualMachine("VM2", 2, 5, 5); Configuration src = new SimpleConfiguration(); src.addOnline(n1); src.addOnline(n2); src.addOnline(n3); src.setRunOn(vm1, n1); src.addWaiting(vm2); ChocoCustomRP planner = makeModule(); try { MockVirtualMachineBuilder builder = new MockVirtualMachineBuilder(); VJobBuilder b = new VJobBuilder(new VJobElementBuilder(builder), new ConstraintsCatalogBuilderFromProperties(new PropertiesHelper("src/main/config/entropy.properties")).build()); b.getElementBuilder().useConfiguration(src); VJob v = new BasicVJob("V1"); List<VJob> vjobs = new ArrayList<VJob>(); vjobs.add(v); planner.setRepairMode(false); TimedReconfigurationPlan plan = planner.compute(src, src.getAllVirtualMachines(), new SimpleManagedElementSet<VirtualMachine>(), new SimpleManagedElementSet<VirtualMachine>(), new SimpleManagedElementSet<VirtualMachine>(), src.getOnlines(), src.getOfflines(), vjobs); System.out.println(plan); } catch (Exception e) { Assert.fail(e.getMessage(), e); } finally { ChocoLogging.flushLogs(); } } }