diff options
Diffstat (limited to 'clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/EventDiffCalculatorTest.java')
-rw-r--r-- | clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/EventDiffCalculatorTest.java | 151 |
1 files changed, 121 insertions, 30 deletions
diff --git a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/EventDiffCalculatorTest.java b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/EventDiffCalculatorTest.java index a09be817e1c..743fddcf48b 100644 --- a/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/EventDiffCalculatorTest.java +++ b/clustercontroller-core/src/test/java/com/yahoo/vespa/clustercontroller/core/EventDiffCalculatorTest.java @@ -2,6 +2,8 @@ package com.yahoo.vespa.clustercontroller.core; import static com.yahoo.vespa.clustercontroller.core.matchers.EventForNode.eventForNode; +import static com.yahoo.vespa.clustercontroller.core.matchers.NodeEventForBucketSpace.nodeEventForBucketSpace; +import static com.yahoo.vespa.clustercontroller.core.matchers.NodeEventForBucketSpace.nodeEventForBaseline; import static com.yahoo.vespa.clustercontroller.core.matchers.NodeEventWithDescription.nodeEventWithDescription; import static com.yahoo.vespa.clustercontroller.core.matchers.ClusterEventWithDescription.clusterEventWithDescription; import static com.yahoo.vespa.clustercontroller.core.matchers.EventTypeIs.eventTypeIs; @@ -14,31 +16,21 @@ import static org.hamcrest.CoreMatchers.hasItem; import static com.yahoo.vespa.clustercontroller.core.ClusterFixture.storageNode; import static com.yahoo.vespa.clustercontroller.core.ClusterFixture.distributorNode; -import com.yahoo.vdslib.state.ClusterState; -import com.yahoo.vdslib.state.Node; import org.junit.Test; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; +import java.util.stream.Collectors; public class EventDiffCalculatorTest { - private static Map<Node, NodeStateReason> emptyNodeStateReasons() { - return Collections.emptyMap(); - } - private static class EventFixture { final ClusterFixture clusterFixture; - // TODO could reasonably put shared state into a common class to avoid dupes for both before/after - Optional<ClusterStateReason> clusterReasonBefore = Optional.empty(); - Optional<ClusterStateReason> clusterReasonAfter = Optional.empty(); - ClusterState clusterStateBefore = ClusterState.emptyState(); - ClusterState clusterStateAfter = ClusterState.emptyState(); - final Map<Node, NodeStateReason> nodeReasonsBefore = new HashMap<>(); - final Map<Node, NodeStateReason> nodeReasonsAfter = new HashMap<>(); + AnnotatedClusterState.Builder baselineBefore = new AnnotatedClusterState.Builder(); + AnnotatedClusterState.Builder baselineAfter = new AnnotatedClusterState.Builder(); + Map<String, AnnotatedClusterState.Builder> derivedBefore = new HashMap<>(); + Map<String, AnnotatedClusterState.Builder> derivedAfter = new HashMap<>(); long currentTimeMs = 0; EventFixture(int nodeCount) { @@ -46,48 +38,67 @@ public class EventDiffCalculatorTest { } EventFixture clusterStateBefore(String stateStr) { - clusterStateBefore = ClusterState.stateFromString(stateStr); + baselineBefore.clusterState(stateStr); return this; } EventFixture clusterStateAfter(String stateStr) { - clusterStateAfter = ClusterState.stateFromString(stateStr); + baselineAfter.clusterState(stateStr); return this; } - EventFixture storageNodeReasonBefore(int index, NodeStateReason reason) { - nodeReasonsBefore.put(storageNode(index), reason); + EventFixture storageNodeReasonBefore(int nodeIndex, NodeStateReason reason) { + baselineBefore.storageNodeReason(nodeIndex, reason); return this; } - EventFixture storageNodeReasonAfter(int index, NodeStateReason reason) { - nodeReasonsAfter.put(storageNode(index), reason); + EventFixture storageNodeReasonAfter(int nodeIndex, NodeStateReason reason) { + baselineAfter.storageNodeReason(nodeIndex, reason); return this; } EventFixture clusterReasonBefore(ClusterStateReason reason) { - this.clusterReasonBefore = Optional.of(reason); + baselineBefore.clusterReason(reason); return this; } EventFixture clusterReasonAfter(ClusterStateReason reason) { - this.clusterReasonAfter = Optional.of(reason); + baselineAfter.clusterReason(reason); return this; } EventFixture currentTimeMs(long timeMs) { this.currentTimeMs = timeMs; return this; } + EventFixture derivedClusterStateBefore(String bucketSpace, String stateStr) { + getBuilder(derivedBefore, bucketSpace).clusterState(stateStr); + return this; + } + EventFixture derivedClusterStateAfter(String bucketSpace, String stateStr) { + getBuilder(derivedAfter, bucketSpace).clusterState(stateStr); + return this; + } + EventFixture derivedStorageNodeReasonBefore(String bucketSpace, int nodeIndex, NodeStateReason reason) { + getBuilder(derivedBefore, bucketSpace).storageNodeReason(nodeIndex, reason); + return this; + } + EventFixture derivedStorageNodeReasonAfter(String bucketSpace, int nodeIndex, NodeStateReason reason) { + getBuilder(derivedAfter, bucketSpace).storageNodeReason(nodeIndex, reason); + return this; + } + private static AnnotatedClusterState.Builder getBuilder(Map<String, AnnotatedClusterState.Builder> derivedStates, String bucketSpace) { + return derivedStates.computeIfAbsent(bucketSpace, key -> new AnnotatedClusterState.Builder()); + } List<Event> computeEventDiff() { - final AnnotatedClusterState stateBefore = new AnnotatedClusterState( - clusterStateBefore, clusterReasonBefore, nodeReasonsBefore); - final AnnotatedClusterState stateAfter = new AnnotatedClusterState( - clusterStateAfter, clusterReasonAfter, nodeReasonsAfter); - return EventDiffCalculator.computeEventDiff( EventDiffCalculator.params() .cluster(clusterFixture.cluster()) - .fromState(stateBefore) - .toState(stateAfter) + .fromState(ClusterStateBundle.of(baselineBefore.build(), toDerivedStates(derivedBefore))) + .toState(ClusterStateBundle.of(baselineAfter.build(), toDerivedStates(derivedAfter))) .currentTimeMs(currentTimeMs)); } + private static Map<String, AnnotatedClusterState> toDerivedStates(Map<String, AnnotatedClusterState.Builder> derivedBuilders) { + return derivedBuilders.entrySet().stream() + .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue().build())); + } + static EventFixture createForNodes(int nodeCount) { return new EventFixture(nodeCount); } @@ -316,4 +327,84 @@ public class EventDiffCalculatorTest { clusterEventWithDescription("Too low ratio of available distributor nodes. Setting cluster state down"))); } + @Test + public void may_have_merges_pending_up_edge_event_emitted_if_derived_bucket_space_state_differs_from_baseline() { + EventFixture f = EventFixture.createForNodes(3) + .clusterStateBefore("distributor:3 storage:3") + .derivedClusterStateBefore("default", "distributor:3 storage:3") + .clusterStateAfter("distributor:3 storage:3") + .derivedClusterStateAfter("default", "distributor:3 storage:3 .1.s:m") + .derivedStorageNodeReasonAfter("default", 1, NodeStateReason.MAY_HAVE_MERGES_PENDING); + + List<Event> events = f.computeEventDiff(); + assertThat(events.size(), equalTo(2)); + assertThat(events, hasItem(allOf( + eventForNode(storageNode(1)), + nodeEventForBucketSpace("default"), + nodeEventWithDescription("Altered node state in cluster state from 'U' to 'M'")))); + assertThat(events, hasItem(allOf( + eventForNode(storageNode(1)), + nodeEventForBucketSpace("default"), + nodeEventWithDescription("Node may have merges pending")))); + } + + @Test + public void may_have_merges_pending_down_edge_event_emitted_if_derived_bucket_space_state_differs_from_baseline() { + EventFixture f = EventFixture.createForNodes(3) + .clusterStateBefore("distributor:3 storage:3") + .derivedClusterStateBefore("default", "distributor:3 storage:3 .1.s:m") + .derivedStorageNodeReasonBefore("default", 1, NodeStateReason.MAY_HAVE_MERGES_PENDING) + .clusterStateAfter("distributor:3 storage:3") + .derivedClusterStateAfter("default", "distributor:3 storage:3"); + + List<Event> events = f.computeEventDiff(); + assertThat(events.size(), equalTo(2)); + assertThat(events, hasItem(allOf( + eventForNode(storageNode(1)), + nodeEventForBucketSpace("default"), + nodeEventWithDescription("Altered node state in cluster state from 'M' to 'U'")))); + assertThat(events, hasItem(allOf( + eventForNode(storageNode(1)), + nodeEventForBucketSpace("default"), + nodeEventWithDescription("Node no longer have merges pending")))); + } + + @Test + public void both_baseline_and_derived_bucket_space_state_events_are_emitted() { + EventFixture f = EventFixture.createForNodes(3) + .clusterStateBefore("distributor:3 storage:3") + .derivedClusterStateBefore("default", "distributor:3 storage:3") + .clusterStateAfter("distributor:3 storage:3 .0.s:m") + .derivedClusterStateAfter("default", "distributor:3 storage:3 .1.s:m"); + + List<Event> events = f.computeEventDiff(); + assertThat(events.size(), equalTo(2)); + assertThat(events, hasItem(allOf( + eventForNode(storageNode(0)), + nodeEventForBaseline(), + nodeEventWithDescription("Altered node state in cluster state from 'U' to 'M'")))); + assertThat(events, hasItem(allOf( + eventForNode(storageNode(1)), + nodeEventForBucketSpace("default"), + nodeEventWithDescription("Altered node state in cluster state from 'U' to 'M'")))); + } + + @Test + public void derived_bucket_space_state_events_are_not_emitted_if_similar_to_baseline() { + EventFixture f = EventFixture.createForNodes(3) + .clusterStateBefore("distributor:3 storage:3") + .derivedClusterStateBefore("default", "distributor:3 storage:3") + .derivedClusterStateBefore("global", "distributor:3 storage:3") + .clusterStateAfter("distributor:3 storage:3 .0.s:m") + .derivedClusterStateAfter("default", "distributor:3 storage:3 .0.s:m") + .derivedClusterStateAfter("global", "distributor:3 storage:3 .0.s:m"); + + List<Event> events = f.computeEventDiff(); + assertThat(events.size(), equalTo(1)); + assertThat(events, hasItem(allOf( + eventForNode(storageNode(0)), + nodeEventForBaseline(), + nodeEventWithDescription("Altered node state in cluster state from 'U' to 'M'")))); + } + } |