public void testSerializationFailureDuringDiffPublishing() throws Exception { MockNode nodeA = createMockNode( "nodeA", Settings.EMPTY, new ClusterStateListener() { @Override public void clusterChanged(ClusterChangedEvent event) { fail("Shouldn't send cluster state to myself"); } }) .setAsMaster(); MockNode nodeB = createMockNode("nodeB"); // Initial cluster state with both states - the second node still shouldn't get // diff even though it's present in the previous cluster state DiscoveryNodes discoveryNodes = DiscoveryNodes.builder(nodeA.nodes()).add(nodeB.discoveryNode).build(); ClusterState previousClusterState = ClusterState.builder(CLUSTER_NAME).nodes(discoveryNodes).build(); ClusterState clusterState = ClusterState.builder(previousClusterState).incrementVersion().build(); publishStateAndWait(nodeA.action, clusterState, previousClusterState); assertSameStateFromFull(nodeB.clusterState, clusterState); // cluster state update - add block previousClusterState = clusterState; clusterState = ClusterState.builder(clusterState) .blocks(ClusterBlocks.builder().addGlobalBlock(MetaData.CLUSTER_READ_ONLY_BLOCK)) .incrementVersion() .build(); ClusterState unserializableClusterState = new ClusterState(clusterState.version(), clusterState.stateUUID(), clusterState) { @Override public Diff<ClusterState> diff(ClusterState previousState) { return new Diff<ClusterState>() { @Override public ClusterState apply(ClusterState part) { fail("this diff shouldn't be applied"); return part; } @Override public void writeTo(StreamOutput out) throws IOException { throw new IOException("Simulated failure of diff serialization"); } }; } }; try { publishStateAndWait(nodeA.action, unserializableClusterState, previousClusterState); fail("cluster state published despite of diff errors"); } catch (Discovery.FailedToCommitClusterStateException e) { assertThat(e.getCause(), notNullValue()); assertThat(e.getCause().getMessage(), containsString("failed to serialize")); } }
public void testPublishingWithSendingErrors() throws Exception { int goodNodes = randomIntBetween(2, 5); int errorNodes = randomIntBetween(1, 5); int timeOutNodes = randomBoolean() ? 0 : randomIntBetween(1, 5); // adding timeout nodes will force timeout errors final int numberOfMasterNodes = goodNodes + errorNodes + timeOutNodes + 1; // master final boolean expectingToCommit = randomBoolean(); Settings.Builder settings = Settings.builder(); // make sure we have a reasonable timeout if we expect to timeout, o.w. one that will make the // test "hang" settings .put( DiscoverySettings.COMMIT_TIMEOUT_SETTING.getKey(), expectingToCommit == false && timeOutNodes > 0 ? "100ms" : "1h") .put(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), "5ms"); // test is about committing MockNode master = createMockNode("master", settings.build(), null); // randomize things a bit int[] nodeTypes = new int[goodNodes + errorNodes + timeOutNodes]; for (int i = 0; i < goodNodes; i++) { nodeTypes[i] = 0; } for (int i = goodNodes; i < goodNodes + errorNodes; i++) { nodeTypes[i] = 1; } for (int i = goodNodes + errorNodes; i < nodeTypes.length; i++) { nodeTypes[i] = 2; } Collections.shuffle(Arrays.asList(nodeTypes), random()); DiscoveryNodes.Builder discoveryNodesBuilder = DiscoveryNodes.builder().add(master.discoveryNode); for (int i = 0; i < nodeTypes.length; i++) { final MockNode mockNode = createMockNode("node" + i); discoveryNodesBuilder.add(mockNode.discoveryNode); switch (nodeTypes[i]) { case 1: mockNode.action.errorOnSend.set(true); break; case 2: mockNode.action.timeoutOnSend.set(true); break; } } final int dataNodes = randomIntBetween(0, 3); // data nodes don't matter for (int i = 0; i < dataNodes; i++) { final MockNode mockNode = createMockNode( "data_" + i, Settings.builder().put(Node.NODE_MASTER_SETTING.getKey(), false).build(), null); discoveryNodesBuilder.add(mockNode.discoveryNode); if (randomBoolean()) { // we really don't care - just chaos monkey mockNode.action.errorOnCommit.set(randomBoolean()); mockNode.action.errorOnSend.set(randomBoolean()); mockNode.action.timeoutOnCommit.set(randomBoolean()); mockNode.action.timeoutOnSend.set(randomBoolean()); } } final int minMasterNodes; final String expectedBehavior; if (expectingToCommit) { minMasterNodes = randomIntBetween(0, goodNodes + 1); // count master expectedBehavior = "succeed"; } else { minMasterNodes = randomIntBetween(goodNodes + 2, numberOfMasterNodes); // +2 because of master expectedBehavior = timeOutNodes > 0 ? "timeout" : "fail"; } logger.info( "--> expecting commit to {}. good nodes [{}], errors [{}], timeouts [{}]. min_master_nodes [{}]", expectedBehavior, goodNodes + 1, errorNodes, timeOutNodes, minMasterNodes); discoveryNodesBuilder .localNodeId(master.discoveryNode.getId()) .masterNodeId(master.discoveryNode.getId()); DiscoveryNodes discoveryNodes = discoveryNodesBuilder.build(); MetaData metaData = MetaData.EMPTY_META_DATA; ClusterState clusterState = ClusterState.builder(CLUSTER_NAME).metaData(metaData).nodes(discoveryNodes).build(); ClusterState previousState = master.clusterState; try { publishState(master.action, clusterState, previousState, minMasterNodes); if (expectingToCommit == false) { fail("cluster state publishing didn't fail despite of not have enough nodes"); } } catch (Discovery.FailedToCommitClusterStateException exception) { logger.debug("failed to publish as expected", exception); if (expectingToCommit) { throw exception; } assertThat(exception.getMessage(), containsString(timeOutNodes > 0 ? "timed out" : "failed")); } }