/* * Copyright © 2014 Cask Data, Inc. * * 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 co.cask.cdap.common.zookeeper.coordination; import com.google.common.base.Predicate; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import org.junit.Assert; import org.junit.Test; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * Tests for different {@link AssignmentStrategy}. */ public class AssignmentStrategyTest { @Test public void testBalance() { // Create a 2x2 requirement (2 partition, 2 replicas each). ResourceRequirement requirement = ResourceRequirement.builder("resource") .addPartitions("p", 2, 2) .build(); ResourceAssigner<String> assigner = DefaultResourceAssigner.create(HashMultimap.<String, PartitionReplica>create()); AssignmentStrategy strategy = new BalancedAssignmentStrategy(); Set<String> handlers = ImmutableSet.of("h1"); strategy.assign(requirement, handlers, assigner); Multimap<String, PartitionReplica> assignments = assigner.get(); // All resources should be assigned to the only handler. Assert.assertEquals(4, assignments.get("h1").size()); // Now, reassign to more than 4 handlers, it should be assigned to four handlers evenly with "h1" should be one // of them. handlers = ImmutableSet.of("h1", "h2", "h3", "h4", "h5"); strategy.assign(requirement, handlers, assigner); Map<String, Collection<PartitionReplica>> result = Maps.filterValues( assigner.get().asMap(), new Predicate<Collection<PartitionReplica>>() { @Override public boolean apply(Collection<PartitionReplica> input) { return input.size() == 1; } }); Assert.assertEquals(4, result.size()); Assert.assertTrue(result.containsKey("h1")); Set<PartitionReplica> handlerOneAssignment = ImmutableSet.copyOf(result.get("h1")); // Now modify the requirement to have 10x2 requirement = ResourceRequirement.builder("resource") .addPartitions("p", 10, 2) .build(); strategy.assign(requirement, handlers, assigner); // Each handler should received 4 partition replica. for (Map.Entry<String, Collection<PartitionReplica>> entry : assigner.get().asMap().entrySet()) { Assert.assertEquals(4, entry.getValue().size()); } // Make sure the same partition replica get assigned to multiple handler Assert.assertEquals(20, ImmutableSet.copyOf(assigner.get().values()).size()); // Make sure whatever was assigned to "h1" stays in "h1". Assert.assertTrue(Sets.difference(handlerOneAssignment, ImmutableSet.copyOf(assigner.get().get("h1"))).isEmpty()); // Now reduce the requirement to 7x2 requirement = ResourceRequirement.builder("resource") .addPartitions("p", 6, 2) .build(); // Create a new assigner with invalid partitions removed. Multimap<String, PartitionReplica> oldAssignments = assigner.get(); assignments = HashMultimap.create(oldAssignments); Iterator<Map.Entry<String, PartitionReplica>> iterator = assignments.entries().iterator(); while (iterator.hasNext()) { Map.Entry<String, PartitionReplica> entry = iterator.next(); if (Integer.parseInt(entry.getValue().getName().substring(1)) >= 6) { iterator.remove(); } } handlers = ImmutableSet.of("h1", "h2", "h3", "h4", "h5", "h6", "h7"); assigner = DefaultResourceAssigner.create(assignments); strategy.assign(requirement, handlers, assigner); for (Map.Entry<String, Collection<PartitionReplica>> entry : assigner.get().asMap().entrySet()) { // Check if all the partitions that was assigned to a handler stay there. Collection<PartitionReplica> oldAssignment = oldAssignments.get(entry.getKey()); if (!oldAssignment.isEmpty()) { Assert.assertTrue(Sets.difference(ImmutableSet.copyOf(entry.getValue()), ImmutableSet.copyOf(oldAssignment)).isEmpty()); } } } }