GroupByContainerCount implements BalancingTaskNameGrouper { @Override public Set<ContainerModel> group(Set<TaskModel> tasks) { validateTasks(tasks); List<TaskModel> sortedTasks = new ArrayList<>(tasks); Collections.sort(sortedTasks); Map<TaskName, TaskModel>[] taskGroups = new Map[containerCount]; for (int i = 0; i < containerCount; i++) { taskGroups[i] = new HashMap<>(); } for (int i = 0; i < sortedTasks.size(); i++) { TaskModel tm = sortedTasks.get(i); taskGroups[i % containerCount].put(tm.getTaskName(), tm); } Set<ContainerModel> containerModels = new HashSet<>(); for (int i = 0; i < containerCount; i++) { containerModels.add(new ContainerModel(String.valueOf(i), taskGroups[i])); } return Collections.unmodifiableSet(containerModels); } GroupByContainerCount(int containerCount); @Override Set<ContainerModel> group(Set<TaskModel> tasks); @Override Set<ContainerModel> group(Set<TaskModel> tasks, GrouperMetadata grouperMetadata);  }
@Test(expected = IllegalArgumentException.class) public void testGroupEmptyTasks() { new GroupByContainerCount(1).group(new HashSet<>()); }
@Test(expected = IllegalArgumentException.class) public void testGroupFewerTasksThanContainers() { Set<TaskModel> taskModels = new HashSet<>(); taskModels.add(getTaskModel(1)); new GroupByContainerCount(2).group(taskModels); }
@Test(expected = UnsupportedOperationException.class) public void testGrouperResultImmutable() { Set<TaskModel> taskModels = generateTaskModels(3); Set<ContainerModel> containers = new GroupByContainerCount(3).group(taskModels); containers.remove(containers.iterator().next()); }
@Test public void testGroupHappyPath() { Set<TaskModel> taskModels = generateTaskModels(5); Set<ContainerModel> containers = new GroupByContainerCount(2).group(taskModels); Map<String, ContainerModel> containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(2, containers.size()); ContainerModel container0 = containersMap.get("0"); ContainerModel container1 = containersMap.get("1"); assertNotNull(container0); assertNotNull(container1); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals(3, container0.getTasks().size()); assertEquals(2, container1.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(2))); assertTrue(container0.getTasks().containsKey(getTaskName(4))); assertTrue(container1.getTasks().containsKey(getTaskName(1))); assertTrue(container1.getTasks().containsKey(getTaskName(3))); }
@Test public void testGroupManyTasks() { Set<TaskModel> taskModels = generateTaskModels(21); Set<ContainerModel> containers = new GroupByContainerCount(2).group(taskModels); Map<String, ContainerModel> containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(2, containers.size()); ContainerModel container0 = containersMap.get("0"); ContainerModel container1 = containersMap.get("1"); assertNotNull(container0); assertNotNull(container1); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals(11, container0.getTasks().size()); assertEquals(10, container1.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(10))); assertTrue(container0.getTasks().containsKey(getTaskName(12))); assertTrue(container0.getTasks().containsKey(getTaskName(14))); assertTrue(container0.getTasks().containsKey(getTaskName(16))); assertTrue(container0.getTasks().containsKey(getTaskName(18))); assertTrue(container0.getTasks().containsKey(getTaskName(2))); assertTrue(container0.getTasks().containsKey(getTaskName(3))); assertTrue(container0.getTasks().containsKey(getTaskName(5))); assertTrue(container0.getTasks().containsKey(getTaskName(7))); assertTrue(container0.getTasks().containsKey(getTaskName(9))); assertTrue(container1.getTasks().containsKey(getTaskName(1))); assertTrue(container1.getTasks().containsKey(getTaskName(11))); assertTrue(container1.getTasks().containsKey(getTaskName(13))); assertTrue(container1.getTasks().containsKey(getTaskName(15))); assertTrue(container1.getTasks().containsKey(getTaskName(17))); assertTrue(container1.getTasks().containsKey(getTaskName(19))); assertTrue(container1.getTasks().containsKey(getTaskName(20))); assertTrue(container1.getTasks().containsKey(getTaskName(4))); assertTrue(container1.getTasks().containsKey(getTaskName(6))); assertTrue(container1.getTasks().containsKey(getTaskName(8))); }
@Test public void testBalancerAfterContainerIncrease() { Set<TaskModel> taskModels = generateTaskModels(9); Set<ContainerModel> prevContainers = new GroupByContainerCount(2).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> containers = new GroupByContainerCount(4).group(taskModels, grouperMetadata); Map<String, ContainerModel> containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(4, containers.size()); ContainerModel container0 = containersMap.get("0"); ContainerModel container1 = containersMap.get("1"); ContainerModel container2 = containersMap.get("2"); ContainerModel container3 = containersMap.get("3"); assertNotNull(container0); assertNotNull(container1); assertNotNull(container2); assertNotNull(container3); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals(3, container0.getTasks().size()); assertEquals(2, container1.getTasks().size()); assertEquals(2, container2.getTasks().size()); assertEquals(2, container3.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(2))); assertTrue(container0.getTasks().containsKey(getTaskName(4))); assertTrue(container1.getTasks().containsKey(getTaskName(1))); assertTrue(container1.getTasks().containsKey(getTaskName(3))); assertTrue(container2.getTasks().containsKey(getTaskName(8))); assertTrue(container2.getTasks().containsKey(getTaskName(6))); assertTrue(container3.getTasks().containsKey(getTaskName(5))); assertTrue(container3.getTasks().containsKey(getTaskName(7))); }
@Test public void testBalancerAfterContainerDecrease() { Set<TaskModel> taskModels = generateTaskModels(9); Set<ContainerModel> prevContainers = new GroupByContainerCount(4).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> containers = new GroupByContainerCount(2).group(taskModels, grouperMetadata); Map<String, ContainerModel> containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(2, containers.size()); ContainerModel container0 = containersMap.get("0"); ContainerModel container1 = containersMap.get("1"); assertNotNull(container0); assertNotNull(container1); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals(5, container0.getTasks().size()); assertEquals(4, container1.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(4))); assertTrue(container0.getTasks().containsKey(getTaskName(8))); assertTrue(container1.getTasks().containsKey(getTaskName(1))); assertTrue(container1.getTasks().containsKey(getTaskName(5))); assertTrue(container0.getTasks().containsKey(getTaskName(6))); assertTrue(container0.getTasks().containsKey(getTaskName(2))); assertTrue(container1.getTasks().containsKey(getTaskName(7))); assertTrue(container1.getTasks().containsKey(getTaskName(3))); }
@Test public void testBalancerMultipleReblances() { Set<TaskModel> taskModels = generateTaskModels(9); Set<ContainerModel> prevContainers = new GroupByContainerCount(4).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> containers = new GroupByContainerCount(2).group(taskModels, grouperMetadata); Map<String, ContainerModel> containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(2, containers.size()); ContainerModel container0 = containersMap.get("0"); ContainerModel container1 = containersMap.get("1"); assertNotNull(container0); assertNotNull(container1); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals(5, container0.getTasks().size()); assertEquals(4, container1.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(4))); assertTrue(container0.getTasks().containsKey(getTaskName(8))); assertTrue(container1.getTasks().containsKey(getTaskName(1))); assertTrue(container1.getTasks().containsKey(getTaskName(5))); assertTrue(container0.getTasks().containsKey(getTaskName(6))); assertTrue(container0.getTasks().containsKey(getTaskName(2))); assertTrue(container1.getTasks().containsKey(getTaskName(7))); assertTrue(container1.getTasks().containsKey(getTaskName(3))); prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata1 = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); containers = new GroupByContainerCount(3).group(taskModels, grouperMetadata1); containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(3, containers.size()); container0 = containersMap.get("0"); container1 = containersMap.get("1"); ContainerModel container2 = containersMap.get("2"); assertNotNull(container0); assertNotNull(container1); assertNotNull(container2); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals("2", container2.getId()); assertEquals(3, container0.getTasks().size()); assertEquals(3, container1.getTasks().size()); assertEquals(3, container2.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(4))); assertTrue(container0.getTasks().containsKey(getTaskName(8))); assertTrue(container1.getTasks().containsKey(getTaskName(1))); assertTrue(container1.getTasks().containsKey(getTaskName(5))); assertTrue(container1.getTasks().containsKey(getTaskName(7))); assertTrue(container2.getTasks().containsKey(getTaskName(6))); assertTrue(container2.getTasks().containsKey(getTaskName(2))); assertTrue(container2.getTasks().containsKey(getTaskName(3))); }
@Test public void testBalancerAfterContainerSame() { Set<TaskModel> taskModels = generateTaskModels(9); Set<ContainerModel> prevContainers = new GroupByContainerCount(2).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> containers = new GroupByContainerCount(2).group(taskModels, grouperMetadata); Map<String, ContainerModel> containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(2, containers.size()); ContainerModel container0 = containersMap.get("0"); ContainerModel container1 = containersMap.get("1"); assertNotNull(container0); assertNotNull(container1); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals(5, container0.getTasks().size()); assertEquals(4, container1.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(2))); assertTrue(container0.getTasks().containsKey(getTaskName(4))); assertTrue(container0.getTasks().containsKey(getTaskName(6))); assertTrue(container0.getTasks().containsKey(getTaskName(8))); assertTrue(container1.getTasks().containsKey(getTaskName(1))); assertTrue(container1.getTasks().containsKey(getTaskName(3))); assertTrue(container1.getTasks().containsKey(getTaskName(5))); assertTrue(container1.getTasks().containsKey(getTaskName(7))); }
@Test public void testBalancerAfterContainerSameCustomAssignment() { Set<TaskModel> taskModels = generateTaskModels(9); Map<TaskName, String> prevTaskToContainerMapping = new HashMap<>(); prevTaskToContainerMapping.put(getTaskName(0), "0"); prevTaskToContainerMapping.put(getTaskName(1), "0"); prevTaskToContainerMapping.put(getTaskName(2), "0"); prevTaskToContainerMapping.put(getTaskName(3), "0"); prevTaskToContainerMapping.put(getTaskName(4), "0"); prevTaskToContainerMapping.put(getTaskName(5), "0"); prevTaskToContainerMapping.put(getTaskName(6), "1"); prevTaskToContainerMapping.put(getTaskName(7), "1"); prevTaskToContainerMapping.put(getTaskName(8), "1"); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> containers = new GroupByContainerCount(2).group(taskModels, grouperMetadata); Map<String, ContainerModel> containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(2, containers.size()); ContainerModel container0 = containersMap.get("0"); ContainerModel container1 = containersMap.get("1"); assertNotNull(container0); assertNotNull(container1); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals(6, container0.getTasks().size()); assertEquals(3, container1.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(1))); assertTrue(container0.getTasks().containsKey(getTaskName(2))); assertTrue(container0.getTasks().containsKey(getTaskName(3))); assertTrue(container0.getTasks().containsKey(getTaskName(4))); assertTrue(container0.getTasks().containsKey(getTaskName(5))); assertTrue(container1.getTasks().containsKey(getTaskName(6))); assertTrue(container1.getTasks().containsKey(getTaskName(7))); assertTrue(container1.getTasks().containsKey(getTaskName(8))); }
@Test public void testBalancerAfterContainerSameCustomAssignmentAndContainerIncrease() { Set<TaskModel> taskModels = generateTaskModels(6); Map<TaskName, String> prevTaskToContainerMapping = new HashMap<>(); prevTaskToContainerMapping.put(getTaskName(0), "0"); prevTaskToContainerMapping.put(getTaskName(1), "1"); prevTaskToContainerMapping.put(getTaskName(2), "1"); prevTaskToContainerMapping.put(getTaskName(3), "1"); prevTaskToContainerMapping.put(getTaskName(4), "1"); prevTaskToContainerMapping.put(getTaskName(5), "1"); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> containers = new GroupByContainerCount(3).group(taskModels, grouperMetadata); Map<String, ContainerModel> containersMap = new HashMap<>(); for (ContainerModel container : containers) { containersMap.put(container.getId(), container); } assertEquals(3, containers.size()); ContainerModel container0 = containersMap.get("0"); ContainerModel container1 = containersMap.get("1"); ContainerModel container2 = containersMap.get("2"); assertNotNull(container0); assertNotNull(container1); assertNotNull(container2); assertEquals("0", container0.getId()); assertEquals("1", container1.getId()); assertEquals("2", container2.getId()); assertEquals(2, container0.getTasks().size()); assertEquals(2, container1.getTasks().size()); assertEquals(2, container1.getTasks().size()); assertTrue(container0.getTasks().containsKey(getTaskName(0))); assertTrue(container0.getTasks().containsKey(getTaskName(5))); assertTrue(container1.getTasks().containsKey(getTaskName(1))); assertTrue(container1.getTasks().containsKey(getTaskName(2))); assertTrue(container2.getTasks().containsKey(getTaskName(4))); assertTrue(container2.getTasks().containsKey(getTaskName(3))); }
@Test public void testBalancerOldContainerCountOne() { Set<TaskModel> taskModels = generateTaskModels(3); Set<ContainerModel> prevContainers = new GroupByContainerCount(1).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> groupContainers = new GroupByContainerCount(3).group(taskModels); Set<ContainerModel> balanceContainers = new GroupByContainerCount(3).group(taskModels, grouperMetadata); assertEquals(groupContainers, balanceContainers); }
@Test public void testBalancerNewContainerCountOne() { Set<TaskModel> taskModels = generateTaskModels(3); Set<ContainerModel> prevContainers = new GroupByContainerCount(3).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> groupContainers = new GroupByContainerCount(1).group(taskModels); Set<ContainerModel> balanceContainers = new GroupByContainerCount(1).group(taskModels, grouperMetadata); assertEquals(groupContainers, balanceContainers); }
@Test public void testBalancerEmptyTaskMapping() { Set<TaskModel> taskModels = generateTaskModels(3); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), new HashMap<>()); Set<ContainerModel> groupContainers = new GroupByContainerCount(1).group(taskModels); Set<ContainerModel> balanceContainers = new GroupByContainerCount(1).group(taskModels, grouperMetadata); assertEquals(groupContainers, balanceContainers); }
@Test public void testGroupTaskCountIncrease() { int taskCount = 3; Set<TaskModel> taskModels = generateTaskModels(taskCount); Set<ContainerModel> prevContainers = new GroupByContainerCount(2).group(generateTaskModels(taskCount - 1)); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> groupContainers = new GroupByContainerCount(1).group(taskModels); Set<ContainerModel> balanceContainers = new GroupByContainerCount(1).group(taskModels, grouperMetadata); assertEquals(groupContainers, balanceContainers); }
@Test public void testGroupTaskCountDecrease() { int taskCount = 3; Set<TaskModel> taskModels = generateTaskModels(taskCount); Set<ContainerModel> prevContainers = new GroupByContainerCount(3).group(generateTaskModels(taskCount + 1)); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> groupContainers = new GroupByContainerCount(1).group(taskModels); Set<ContainerModel> balanceContainers = new GroupByContainerCount(1).group(taskModels, grouperMetadata); assertEquals(groupContainers, balanceContainers); }
@Test(expected = IllegalArgumentException.class) public void testBalancerNewContainerCountGreaterThanTasks() { Set<TaskModel> taskModels = generateTaskModels(3); Set<ContainerModel> prevContainers = new GroupByContainerCount(3).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); new GroupByContainerCount(5).group(taskModels, grouperMetadata); }
@Test(expected = IllegalArgumentException.class) public void testBalancerEmptyTasks() { Set<TaskModel> taskModels = generateTaskModels(3); Set<ContainerModel> prevContainers = new GroupByContainerCount(3).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); new GroupByContainerCount(5).group(new HashSet<>(), grouperMetadata); }
@Test(expected = UnsupportedOperationException.class) public void testBalancerResultImmutable() { Set<TaskModel> taskModels = generateTaskModels(3); Set<ContainerModel> prevContainers = new GroupByContainerCount(3).group(taskModels); Map<TaskName, String> prevTaskToContainerMapping = generateTaskContainerMapping(prevContainers); GrouperMetadataImpl grouperMetadata = new GrouperMetadataImpl(new HashMap<>(), new HashMap<>(), new HashMap<>(), prevTaskToContainerMapping); Set<ContainerModel> containers = new GroupByContainerCount(2).group(taskModels, grouperMetadata); containers.remove(containers.iterator().next()); }
@Test public void testBalancerWithNullLocalityManager() { Set<TaskModel> taskModels = generateTaskModels(3); Set<ContainerModel> groupContainers = new GroupByContainerCount(3).group(taskModels); Set<ContainerModel> balanceContainers = new GroupByContainerCount(3).balance(taskModels, null); assertEquals(groupContainers, balanceContainers); }