public void testDeleteIsAppliedFirst() {
    DiscoverySettings discoverySettings = getDiscoverySettings();

    assertEquals(
        discoverySettings.getPublishTimeout(),
        DiscoverySettings.PUBLISH_TIMEOUT_SETTING.get(Settings.EMPTY));
    assertTrue(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY));

    ClusterUpdateSettingsResponse response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setTransientSettings(
                Settings.builder()
                    .put(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey(), false)
                    .put(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), "1s")
                    .build())
            .get();

    assertAcked(response);
    assertEquals(
        response
            .getTransientSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()),
        "1s");
    assertTrue(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY));
    assertFalse(
        response
            .getTransientSettings()
            .getAsBoolean(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey(), null));

    response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setTransientSettings(
                Settings.builder()
                    .putNull((randomBoolean() ? "discovery.zen.*" : "*"))
                    .put(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), "2s"))
            .get();
    assertEquals(
        response
            .getTransientSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()),
        "2s");
    assertNull(
        response
            .getTransientSettings()
            .getAsBoolean(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey(), null));
  }
  public void testDisablingDiffPublishing() throws Exception {
    Settings noDiffPublishingSettings =
        Settings.builder()
            .put(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey(), false)
            .build();

    MockNode nodeA =
        createMockNode(
            "nodeA",
            noDiffPublishingSettings,
            new ClusterStateListener() {
              @Override
              public void clusterChanged(ClusterChangedEvent event) {
                fail("Shouldn't send cluster state to myself");
              }
            });

    MockNode nodeB =
        createMockNode(
            "nodeB",
            noDiffPublishingSettings,
            new ClusterStateListener() {
              @Override
              public void clusterChanged(ClusterChangedEvent event) {
                assertFalse(event.state().wasReadFromDiff());
              }
            });

    // Initial cluster state
    DiscoveryNodes discoveryNodes =
        DiscoveryNodes.builder()
            .add(nodeA.discoveryNode)
            .localNodeId(nodeA.discoveryNode.getId())
            .masterNodeId(nodeA.discoveryNode.getId())
            .build();
    ClusterState clusterState = ClusterState.builder(CLUSTER_NAME).nodes(discoveryNodes).build();

    // cluster state update - add nodeB
    discoveryNodes = DiscoveryNodes.builder(discoveryNodes).add(nodeB.discoveryNode).build();
    ClusterState previousClusterState = clusterState;
    clusterState =
        ClusterState.builder(clusterState).nodes(discoveryNodes).incrementVersion().build();
    publishStateAndWait(nodeA.action, clusterState, previousClusterState);

    // cluster state update - add block
    previousClusterState = clusterState;
    clusterState =
        ClusterState.builder(clusterState)
            .blocks(ClusterBlocks.builder().addGlobalBlock(MetaData.CLUSTER_READ_ONLY_BLOCK))
            .incrementVersion()
            .build();
    publishStateAndWait(nodeA.action, clusterState, previousClusterState);
  }
  /** Test not waiting on publishing works correctly (i.e., publishing times out) */
  public void testSimultaneousClusterStatePublishing() throws Exception {
    int numberOfNodes = randomIntBetween(2, 10);
    int numberOfIterations = scaledRandomIntBetween(5, 50);
    Settings settings =
        Settings.builder()
            .put(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey(), randomBoolean())
            .build();
    MockNode master =
        createMockNode(
                "node0",
                settings,
                new ClusterStateListener() {
                  @Override
                  public void clusterChanged(ClusterChangedEvent event) {
                    assertProperMetaDataForVersion(
                        event.state().metaData(), event.state().version());
                  }
                })
            .setAsMaster();
    DiscoveryNodes.Builder discoveryNodesBuilder = DiscoveryNodes.builder(master.nodes());
    for (int i = 1; i < numberOfNodes; i++) {
      final String name = "node" + i;
      final MockNode node =
          createMockNode(
              name,
              settings,
              new ClusterStateListener() {
                @Override
                public void clusterChanged(ClusterChangedEvent event) {
                  assertProperMetaDataForVersion(event.state().metaData(), event.state().version());
                }
              });
      discoveryNodesBuilder.add(node.discoveryNode);
    }

    AssertingAckListener[] listeners = new AssertingAckListener[numberOfIterations];
    DiscoveryNodes discoveryNodes = discoveryNodesBuilder.build();
    MetaData metaData = MetaData.EMPTY_META_DATA;
    ClusterState clusterState = ClusterState.builder(CLUSTER_NAME).metaData(metaData).build();
    ClusterState previousState;
    for (int i = 0; i < numberOfIterations; i++) {
      previousState = clusterState;
      metaData = buildMetaDataForVersion(metaData, i + 1);
      clusterState =
          ClusterState.builder(clusterState)
              .incrementVersion()
              .metaData(metaData)
              .nodes(discoveryNodes)
              .build();
      listeners[i] = publishState(master.action, clusterState, previousState);
    }

    for (int i = 0; i < numberOfIterations; i++) {
      listeners[i].await(1, TimeUnit.SECONDS);
    }

    // set the master cs
    master.clusterState = clusterState;

    for (MockNode node : nodes.values()) {
      assertSameState(node.clusterState, clusterState);
      assertThat(node.clusterState.nodes().getLocalNode(), equalTo(node.discoveryNode));
    }
  }
  public void testResetClusterSetting() {
    DiscoverySettings discoverySettings = getDiscoverySettings();

    assertThat(
        discoverySettings.getPublishTimeout(),
        equalTo(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.get(Settings.EMPTY)));
    assertThat(
        discoverySettings.getPublishDiff(),
        equalTo(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY)));

    ClusterUpdateSettingsResponse response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setTransientSettings(
                Settings.builder()
                    .put(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), "1s")
                    .build())
            .get();

    assertAcked(response);
    assertThat(
        response
            .getTransientSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()),
        equalTo("1s"));
    assertThat(discoverySettings.getPublishTimeout().seconds(), equalTo(1L));
    assertThat(
        discoverySettings.getPublishDiff(),
        equalTo(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY)));

    response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setTransientSettings(
                Settings.builder().putNull(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()))
            .get();

    assertAcked(response);
    assertNull(
        response
            .getTransientSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()));
    assertThat(
        discoverySettings.getPublishTimeout(),
        equalTo(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.get(Settings.EMPTY)));
    assertThat(
        discoverySettings.getPublishDiff(),
        equalTo(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY)));

    response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setTransientSettings(
                Settings.builder()
                    .put(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), "1s")
                    .put(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey(), false)
                    .build())
            .get();

    assertAcked(response);
    assertThat(
        response
            .getTransientSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()),
        equalTo("1s"));
    assertThat(discoverySettings.getPublishTimeout().seconds(), equalTo(1L));
    assertFalse(discoverySettings.getPublishDiff());
    response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setTransientSettings(
                Settings.builder().putNull((randomBoolean() ? "discovery.zen.*" : "*")))
            .get();

    assertNull(
        response
            .getTransientSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()));
    assertNull(
        response
            .getTransientSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey()));
    assertThat(
        discoverySettings.getPublishTimeout(),
        equalTo(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.get(Settings.EMPTY)));
    assertThat(
        discoverySettings.getPublishDiff(),
        equalTo(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY)));

    // now persistent
    response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setPersistentSettings(
                Settings.builder()
                    .put(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), "1s")
                    .build())
            .get();

    assertAcked(response);
    assertThat(
        response
            .getPersistentSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()),
        equalTo("1s"));
    assertThat(discoverySettings.getPublishTimeout().seconds(), equalTo(1L));
    assertThat(
        discoverySettings.getPublishDiff(),
        equalTo(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY)));

    response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setPersistentSettings(
                Settings.builder().putNull((DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey())))
            .get();

    assertAcked(response);
    assertNull(
        response
            .getPersistentSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()));
    assertThat(
        discoverySettings.getPublishTimeout(),
        equalTo(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.get(Settings.EMPTY)));
    assertThat(
        discoverySettings.getPublishDiff(),
        equalTo(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY)));

    response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setPersistentSettings(
                Settings.builder()
                    .put(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), "1s")
                    .put(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey(), false)
                    .build())
            .get();

    assertAcked(response);
    assertThat(
        response
            .getPersistentSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()),
        equalTo("1s"));
    assertThat(discoverySettings.getPublishTimeout().seconds(), equalTo(1L));
    assertFalse(discoverySettings.getPublishDiff());
    response =
        client()
            .admin()
            .cluster()
            .prepareUpdateSettings()
            .setPersistentSettings(
                Settings.builder().putNull((randomBoolean() ? "discovery.zen.*" : "*")))
            .get();

    assertNull(
        response
            .getPersistentSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey()));
    assertNull(
        response
            .getPersistentSettings()
            .getAsMap()
            .get(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.getKey()));
    assertThat(
        discoverySettings.getPublishTimeout(),
        equalTo(DiscoverySettings.PUBLISH_TIMEOUT_SETTING.get(Settings.EMPTY)));
    assertThat(
        discoverySettings.getPublishDiff(),
        equalTo(DiscoverySettings.PUBLISH_DIFF_ENABLE_SETTING.get(Settings.EMPTY)));
  }