/* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.discovery.zen; import org.elasticsearch.Version; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.discovery.zen.ElectMasterService.MasterCandidate; import org.elasticsearch.test.ESTestCase; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; public class ElectMasterServiceTests extends ESTestCase { ElectMasterService electMasterService() { return new ElectMasterService(Settings.EMPTY); } List<DiscoveryNode> generateRandomNodes() { int count = scaledRandomIntBetween(1, 100); ArrayList<DiscoveryNode> nodes = new ArrayList<>(count); for (int i = 0; i < count; i++) { Set<DiscoveryNode.Role> roles = new HashSet<>(); if (randomBoolean()) { roles.add(DiscoveryNode.Role.MASTER); } DiscoveryNode node = new DiscoveryNode("n_" + i, "n_" + i, buildNewFakeTransportAddress(), Collections.emptyMap(), roles, Version.CURRENT); nodes.add(node); } Collections.shuffle(nodes, random()); return nodes; } List<MasterCandidate> generateRandomCandidates() { int count = scaledRandomIntBetween(1, 100); ArrayList<MasterCandidate> candidates = new ArrayList<>(count); for (int i = 0; i < count; i++) { Set<DiscoveryNode.Role> roles = new HashSet<>(); roles.add(DiscoveryNode.Role.MASTER); DiscoveryNode node = new DiscoveryNode("n_" + i, "n_" + i, buildNewFakeTransportAddress(), Collections.emptyMap(), roles, Version.CURRENT); candidates.add( new MasterCandidate(node, randomBoolean() ? MasterCandidate.UNRECOVERED_CLUSTER_VERSION : randomNonNegativeLong())); } Collections.shuffle(candidates, random()); return candidates; } public void testSortByMasterLikelihood() { List<DiscoveryNode> nodes = generateRandomNodes(); List<DiscoveryNode> sortedNodes = ElectMasterService.sortByMasterLikelihood(nodes); assertEquals(nodes.size(), sortedNodes.size()); DiscoveryNode prevNode = sortedNodes.get(0); for (int i = 1; i < sortedNodes.size(); i++) { DiscoveryNode node = sortedNodes.get(i); if (!prevNode.isMasterNode()) { assertFalse(node.isMasterNode()); } else if (node.isMasterNode()) { assertTrue(prevNode.getId().compareTo(node.getId()) < 0); } prevNode = node; } } public void testTieBreakActiveMasters() { List<DiscoveryNode> nodes = generateRandomCandidates().stream().map(MasterCandidate::getNode).collect(Collectors.toList()); DiscoveryNode bestMaster = electMasterService().tieBreakActiveMasters(nodes); for (DiscoveryNode node: nodes) { if (node.equals(bestMaster) == false) { assertTrue(bestMaster.getId().compareTo(node.getId()) < 0); } } } public void testHasEnoughNodes() { List<DiscoveryNode> nodes = rarely() ? Collections.emptyList() : generateRandomNodes(); ElectMasterService service = electMasterService(); int masterNodes = (int) nodes.stream().filter(DiscoveryNode::isMasterNode).count(); service.minimumMasterNodes(randomIntBetween(-1, masterNodes)); assertThat(service.hasEnoughMasterNodes(nodes), equalTo(masterNodes > 0)); service.minimumMasterNodes(masterNodes + 1 + randomIntBetween(0, nodes.size())); assertFalse(service.hasEnoughMasterNodes(nodes)); } public void testHasEnoughCandidates() { List<MasterCandidate> candidates = rarely() ? Collections.emptyList() : generateRandomCandidates(); ElectMasterService service = electMasterService(); service.minimumMasterNodes(randomIntBetween(-1, candidates.size())); assertThat(service.hasEnoughCandidates(candidates), equalTo(candidates.size() > 0)); service.minimumMasterNodes(candidates.size() + 1 + randomIntBetween(0, candidates.size())); assertFalse(service.hasEnoughCandidates(candidates)); } public void testElectMaster() { List<MasterCandidate> candidates = generateRandomCandidates(); ElectMasterService service = electMasterService(); int minMasterNodes = randomIntBetween(0, candidates.size()); service.minimumMasterNodes(minMasterNodes); MasterCandidate master = service.electMaster(candidates); assertNotNull(master); for (MasterCandidate candidate : candidates) { if (candidate.getNode().equals(master.getNode())) { // nothing much to test here } else if (candidate.getClusterStateVersion() == master.getClusterStateVersion()) { assertThat("candidate " + candidate + " has a lower or equal id than master " + master, candidate.getNode().getId(), greaterThan(master.getNode().getId())); } else { assertThat("candidate " + master + " has a higher cluster state version than candidate " + candidate, master.getClusterStateVersion(), greaterThan(candidate.getClusterStateVersion())); } } } public void testCountMasterNodes() { List<DiscoveryNode> nodes = generateRandomNodes(); ElectMasterService service = electMasterService(); int masterNodes = 0; for (DiscoveryNode node : nodes) { if (node.isMasterNode()) { masterNodes++; } } assertEquals(masterNodes, service.countMasterNodes(nodes)); } }