| | |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014-2015 ForgeRock AS. |
| | | * Portions Copyright 2026 3A Systems, LLC. |
| | | */ |
| | | package org.opends.server.replication.service; |
| | | |
| | | import java.net.InetAddress; |
| | | import java.net.UnknownHostException; |
| | | import java.util.*; |
| | | |
| | | import org.opends.server.DirectoryServerTestCase; |
| | | import org.opends.server.replication.common.DSInfo; |
| | | import org.opends.server.replication.common.RSInfo; |
| | | import org.opends.server.replication.common.ServerState; |
| | | import org.opends.server.replication.protocol.TopologyMsg; |
| | | import org.opends.server.replication.service.ReplicationBroker.RSEvaluations; |
| | | import org.opends.server.replication.service.ReplicationBroker.ReplicationServerInfo; |
| | | import org.opends.server.replication.service.ReplicationBroker.Topology; |
| | | import org.testng.Assert; |
| | | import org.testng.SkipException; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import static java.util.Collections.*; |
| | | |
| | | import static org.assertj.core.api.Assertions.*; |
| | | import static org.opends.server.replication.service.ReplicationBroker.computeBestReplicationServer; |
| | | import static org.opends.server.util.CollectionUtils.*; |
| | | import static org.testng.Assert.*; |
| | | |
| | |
| | | assertThat(currentRS.isLocallyConfigured()).isTrue(); |
| | | assertThat(anotherRS.isLocallyConfigured()).isFalse(); |
| | | } |
| | | |
| | | /** |
| | | * A topology names a replication server before the configuration of the domain lists it: the next |
| | | * topology, built once the configuration lists it, must stamp it as locally configured. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldStampRSAddedToTheConfigurationAfterThePreviousTopology(TopologyCtorToUse toUse) |
| | | { |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "127.0.0.1:1389", 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), newHashSet(CURRENT_RS.getServerURL()), EMPTY_MAP); |
| | | assertThat(find(before.rsInfos, announcedRS).isLocallyConfigured()).isFalse(); |
| | | |
| | | final RSInfo configuredRS = new RSInfo(ANOTHER_RS_ID, "localhost:1389", 0, (byte) 0, 0); |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), configuredRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), |
| | | newHashSet(CURRENT_RS.getServerURL(), "localhost:1389"), before.rsInfos); |
| | | assertInvariants(after); |
| | | final ReplicationServerInfo anotherRS = find(after.rsInfos, configuredRS); |
| | | assertThat(anotherRS.isLocallyConfigured()).isTrue(); |
| | | assertThat(anotherRS.getServerURL()).isEqualTo("localhost:1389"); |
| | | assertThat(find(after.rsInfos, CURRENT_RS.toRSInfo()).isLocallyConfigured()).isTrue(); |
| | | } |
| | | |
| | | /** |
| | | * A configured replication server announces in the topology messages a URL other than the |
| | | * configured one (a port mapped by NAT or by Docker), and the broker hears of it first that way. |
| | | * Once a phase-one handshake has reached it at the configured URL, it is locally configured, and |
| | | * stays so when the next topology message names it with the announced URL again. |
| | | */ |
| | | @Test |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldStampRSReachedAtAConfiguredURLItDoesNotAnnounce() |
| | | { |
| | | final Set<String> configured = newHashSet(CURRENT_RS.getServerURL(), "localhost:28989"); |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "localhost:8989", 0, (byte) 0, 0); |
| | | final Topology heard = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), configured, EMPTY_MAP); |
| | | assertThat(find(heard.rsInfos, announcedRS).isLocallyConfigured()).isFalse(); |
| | | |
| | | final RSInfo reachedRS = new RSInfo(ANOTHER_RS_ID, "localhost:28989", 0, (byte) 0, 0); |
| | | final Topology connected = newTopology(TopologyCtorToUse.BUILD_WITH_DS_RS_LISTS, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), reachedRS), |
| | | CURRENT_DS.getDsId(), ANOTHER_RS_ID, configured, heard.rsInfos); |
| | | ReplicationServerInfo anotherRS = find(connected.rsInfos, reachedRS); |
| | | assertThat(anotherRS.isLocallyConfigured()).isTrue(); |
| | | assertThat(anotherRS.getServerURL()).isEqualTo("localhost:28989"); |
| | | |
| | | final Topology next = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), ANOTHER_RS_ID, configured, connected.rsInfos); |
| | | anotherRS = find(next.rsInfos, announcedRS); |
| | | assertThat(anotherRS.isLocallyConfigured()).isTrue(); |
| | | assertThat(anotherRS.getServerURL()).isEqualTo("localhost:28989"); |
| | | } |
| | | |
| | | /** |
| | | * A replication server the previous topology stamped as locally configured stays so as long as the |
| | | * configuration lists the URL it is known with, even when the topology names it with another URL (a port |
| | | * mapped by NAT or by Docker) and its host name cannot be resolved at that moment: losing the flag |
| | | * would make the broker leave the server it is connected to. |
| | | * <p> |
| | | * The case shows that the host is not resolved only where resolving it fails: a resolver which |
| | | * answers for any name (the fake addresses of a proxy or VPN DNS) skips it. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldKeepStampedAConfiguredRSWithoutResolvingItsHost(TopologyCtorToUse toUse) |
| | | { |
| | | try |
| | | { |
| | | final InetAddress[] answer = InetAddress.getAllByName("rs.invalid"); |
| | | throw new SkipException("The resolver answers for rs.invalid with " + Arrays.toString(answer) |
| | | + ": this case could not tell a resolved host from one that is not"); |
| | | } |
| | | catch (UnknownHostException expected) |
| | | { |
| | | // The premise of this case: resolving the host fails |
| | | } |
| | | final String unresolvableURL = "rs.invalid:1389"; |
| | | final RSInfo connectedRS = new RSInfo(ANOTHER_RS_ID, unresolvableURL, 0, (byte) 0, 0); |
| | | final Map<Integer, ReplicationServerInfo> previousRSs = |
| | | newMap(new ReplicationServerInfo(connectedRS, newHashSet(CURRENT_DS.getDsId()))); |
| | | |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "rs.invalid:8989", 0, (byte) 0, 0); |
| | | final Topology topo = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(announcedRS), |
| | | CURRENT_DS.getDsId(), ANOTHER_RS_ID, newHashSet(unresolvableURL), previousRSs); |
| | | assertInvariants(topo); |
| | | final ReplicationServerInfo anotherRS = find(topo.rsInfos, announcedRS); |
| | | assertThat(anotherRS.isLocallyConfigured()).isTrue(); |
| | | assertThat(anotherRS.getServerURL()).isEqualTo(unresolvableURL); |
| | | } |
| | | |
| | | /** |
| | | * A replication server is removed from the configuration of the domain: the next topology must no |
| | | * longer stamp it as locally configured. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldNotStampRSRemovedFromTheConfigurationAfterThePreviousTopology(TopologyCtorToUse toUse) |
| | | { |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "localhost:1389", 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), |
| | | newHashSet(CURRENT_RS.getServerURL(), "localhost:1389"), EMPTY_MAP); |
| | | assertThat(find(before.rsInfos, announcedRS).isLocallyConfigured()).isTrue(); |
| | | |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), newHashSet(CURRENT_RS.getServerURL()), before.rsInfos); |
| | | assertInvariants(after); |
| | | assertThat(find(after.rsInfos, announcedRS).isLocallyConfigured()).isFalse(); |
| | | } |
| | | |
| | | /** |
| | | * A topology names a replication server before the configuration of the domain lists it, with the URL |
| | | * the configuration then lists it with: the next topology must stamp it as locally configured. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldStampRSAddedToTheConfigurationWithTheURLItAnnounces(TopologyCtorToUse toUse) |
| | | { |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "localhost:1389", 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), newHashSet(CURRENT_RS.getServerURL()), EMPTY_MAP); |
| | | assertThat(find(before.rsInfos, announcedRS).isLocallyConfigured()).isFalse(); |
| | | |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), |
| | | newHashSet(CURRENT_RS.getServerURL(), "localhost:1389"), before.rsInfos); |
| | | assertInvariants(after); |
| | | assertThat(find(after.rsInfos, announcedRS).isLocallyConfigured()).isTrue(); |
| | | } |
| | | |
| | | /** |
| | | * The broker has reconnected to a replication server a topology named before the configuration of |
| | | * the domain listed it, and the topology of the new session has the infos of the phase-one handshakes: |
| | | * the periodic check of the best replication server must not reject it as a server which is not |
| | | * locally configured. |
| | | * <p> |
| | | * The other server is not on this host, so the same-host filter keeps only this one, and the check |
| | | * returns it before it reads which server the broker is connected to: the case pins the filter of the |
| | | * locally configured servers only. |
| | | */ |
| | | @Test |
| | | @SuppressWarnings("unchecked") |
| | | public void bestServerCheckShouldNotRejectTheRSAddedToTheConfiguration() |
| | | { |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "localhost:1389", 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), newHashSet(CURRENT_RS.getServerURL()), EMPTY_MAP); |
| | | |
| | | final Topology reconnected = newTopology(TopologyCtorToUse.BUILD_WITH_DS_RS_LISTS, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), ANOTHER_RS_ID, |
| | | newHashSet(CURRENT_RS.getServerURL(), "localhost:1389"), before.rsInfos); |
| | | final RSEvaluations evals = computeBestReplicationServer(false, ANOTHER_RS_ID, new ServerState(), |
| | | reconnected.rsInfos, CURRENT_DS.getDsId(), (byte) 0, 0); |
| | | assertThat(evals.getBestRS()).isNotNull(); |
| | | assertThat(evals.getBestRS().getServerId()).as(evals.toString()).isEqualTo(ANOTHER_RS_ID); |
| | | } |
| | | |
| | | /** |
| | | * The entry of the configuration which lists a replication server stamped as locally configured is |
| | | * written another way, with an equivalent URL: the server must keep the flag, with the configured URL, |
| | | * even when the restart of the session this asks for is refused (while a total update runs). |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldKeepStampedRSWhoseConfiguredURLIsWrittenAnotherWay(TopologyCtorToUse toUse) |
| | | { |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "localhost:8989", 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), |
| | | newHashSet(CURRENT_RS.getServerURL(), "localhost:8989"), EMPTY_MAP); |
| | | assertThat(find(before.rsInfos, announcedRS).isLocallyConfigured()).isTrue(); |
| | | |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), |
| | | newHashSet(CURRENT_RS.getServerURL(), "127.0.0.1:8989"), before.rsInfos); |
| | | assertInvariants(after); |
| | | final ReplicationServerInfo anotherRS = find(after.rsInfos, announcedRS); |
| | | assertThat(anotherRS.isLocallyConfigured()).isTrue(); |
| | | assertThat(anotherRS.getServerURL()).isEqualTo("127.0.0.1:8989"); |
| | | } |
| | | |
| | | /** |
| | | * A known replication server which is not locally configured comes with a URL which is only an |
| | | * equivalent of a configured one: the topology message must not resolve it, so the server gets the flag |
| | | * at the next connection only. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldNotResolveTheURLAKnownRSComesWith(TopologyCtorToUse toUse) |
| | | { |
| | | final Set<String> configured = newHashSet(CURRENT_RS.getServerURL(), "localhost:28989"); |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "localhost:8989", 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), configured, EMPTY_MAP); |
| | | assertThat(find(before.rsInfos, announcedRS).isLocallyConfigured()).isFalse(); |
| | | |
| | | final RSInfo equivalentRS = new RSInfo(ANOTHER_RS_ID, "127.0.0.1:28989", 0, (byte) 0, 0); |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), equivalentRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), configured, before.rsInfos); |
| | | assertInvariants(after); |
| | | assertThat(find(after.rsInfos, equivalentRS).isLocallyConfigured()).isFalse(); |
| | | } |
| | | |
| | | /** |
| | | * A known replication server which is not locally configured gets an equivalent of its URL in the |
| | | * configuration of the domain, written another way: the next topology must not resolve it either, so |
| | | * the server gets the flag at the next connection only. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldNotResolveTheURLAKnownRSIsKnownWith(TopologyCtorToUse toUse) |
| | | { |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "127.0.0.1:28989", 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), newHashSet(CURRENT_RS.getServerURL()), EMPTY_MAP); |
| | | assertThat(find(before.rsInfos, announcedRS).isLocallyConfigured()).isFalse(); |
| | | |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), |
| | | newHashSet(CURRENT_RS.getServerURL(), "localhost:28989"), before.rsInfos); |
| | | assertInvariants(after); |
| | | assertThat(find(after.rsInfos, announcedRS).isLocallyConfigured()).isFalse(); |
| | | } |
| | | |
| | | /** |
| | | * A known replication server comes with another URL in the next topology (a mapped port) while the |
| | | * configuration of the domain now lists the URL it is known with: it is locally configured, without |
| | | * resolving any host name. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldStampRSAddedToTheConfigurationWithTheURLItIsKnownWith(TopologyCtorToUse toUse) |
| | | { |
| | | final RSInfo knownRS = new RSInfo(ANOTHER_RS_ID, "127.0.0.2:28989", 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), knownRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), newHashSet(CURRENT_RS.getServerURL()), EMPTY_MAP); |
| | | assertThat(find(before.rsInfos, knownRS).isLocallyConfigured()).isFalse(); |
| | | |
| | | final RSInfo mappedRS = new RSInfo(ANOTHER_RS_ID, "127.0.0.3:28989", 0, (byte) 0, 0); |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), mappedRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), |
| | | newHashSet(CURRENT_RS.getServerURL(), "127.0.0.2:28989"), before.rsInfos); |
| | | assertInvariants(after); |
| | | final ReplicationServerInfo rs = find(after.rsInfos, mappedRS); |
| | | assertThat(rs.isLocallyConfigured()).isTrue(); |
| | | assertThat(rs.getServerURL()).isEqualTo("127.0.0.2:28989"); |
| | | } |
| | | |
| | | /** |
| | | * A known replication server with no URL (protocol version below 4) is not locally configured, and the |
| | | * check must not ask the configured URLs for a null one: they are a sorted set, as in the configuration, |
| | | * whose contains(null) throws. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldNotStampKnownRSWithoutURL(TopologyCtorToUse toUse) |
| | | { |
| | | // sorted, as the configuration is: contains(null) throws |
| | | final Set<String> configured = new TreeSet<>(Arrays.asList(CURRENT_RS.getServerURL(), "localhost:8989")); |
| | | final RSInfo noUrlRS = new RSInfo(ANOTHER_RS_ID, null, 0, (byte) 0, 0); |
| | | final Topology before = newTopology(TopologyCtorToUse.BUILD_WITH_TOPOLOGY_MSG, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), noUrlRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), configured, EMPTY_MAP); |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), noUrlRS), |
| | | CURRENT_DS.getDsId(), CURRENT_RS.getServerId(), configured, before.rsInfos); |
| | | assertThat(find(after.rsInfos, noUrlRS).isLocallyConfigured()).isFalse(); |
| | | } |
| | | |
| | | /** |
| | | * A locally configured replication server, known with the configured URL a phase-one handshake reached |
| | | * it at, comes with another URL (a port mapped by NAT or by Docker), and the entry of the configuration |
| | | * is written another way, as an equivalent of the URL it comes with: the server must keep the flag, |
| | | * with the configured URL. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldKeepStampedRSWhoseConfiguredURLIsWrittenAsTheURLItComesWith(TopologyCtorToUse toUse) |
| | | { |
| | | final RSInfo reachedRS = new RSInfo(ANOTHER_RS_ID, "localhost:28989", 0, (byte) 0, 0); |
| | | final Topology connected = newTopology(TopologyCtorToUse.BUILD_WITH_DS_RS_LISTS, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), reachedRS), |
| | | CURRENT_DS.getDsId(), ANOTHER_RS_ID, newHashSet(CURRENT_RS.getServerURL(), "localhost:28989"), EMPTY_MAP); |
| | | assertThat(find(connected.rsInfos, reachedRS).isLocallyConfigured()).isTrue(); |
| | | |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "localhost:8989", 0, (byte) 0, 0); |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), ANOTHER_RS_ID, |
| | | newHashSet(CURRENT_RS.getServerURL(), "127.0.0.1:8989"), connected.rsInfos); |
| | | assertInvariants(after); |
| | | final ReplicationServerInfo rs = find(after.rsInfos, announcedRS); |
| | | assertThat(rs.isLocallyConfigured()).isTrue(); |
| | | assertThat(rs.getServerURL()).isEqualTo("127.0.0.1:8989"); |
| | | } |
| | | |
| | | /** |
| | | * A locally configured replication server, known with the configured URL a phase-one handshake reached |
| | | * it at, comes with another URL, and the entry of the configuration is replaced with a URL equivalent to |
| | | * neither: the server loses the flag, and keeps the URL it is known with. |
| | | */ |
| | | @Test(dataProvider = "topologyCtorProvider") |
| | | @SuppressWarnings("unchecked") |
| | | public void topologyShouldNotStampRSWhoseConfiguredURLNamesNeitherOfItsURLs(TopologyCtorToUse toUse) |
| | | { |
| | | final RSInfo reachedRS = new RSInfo(ANOTHER_RS_ID, "localhost:28989", 0, (byte) 0, 0); |
| | | final Topology connected = newTopology(TopologyCtorToUse.BUILD_WITH_DS_RS_LISTS, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), reachedRS), |
| | | CURRENT_DS.getDsId(), ANOTHER_RS_ID, newHashSet(CURRENT_RS.getServerURL(), "localhost:28989"), EMPTY_MAP); |
| | | assertThat(find(connected.rsInfos, reachedRS).isLocallyConfigured()).isTrue(); |
| | | |
| | | final RSInfo announcedRS = new RSInfo(ANOTHER_RS_ID, "localhost:8989", 0, (byte) 0, 0); |
| | | final Topology after = newTopology(toUse, |
| | | newMap(OTHER_DS), newArrayList(CURRENT_RS.toRSInfo(), announcedRS), |
| | | CURRENT_DS.getDsId(), ANOTHER_RS_ID, |
| | | newHashSet(CURRENT_RS.getServerURL(), "127.0.0.1:18989"), connected.rsInfos); |
| | | assertInvariants(after); |
| | | final ReplicationServerInfo rs = find(after.rsInfos, announcedRS); |
| | | assertThat(rs.isLocallyConfigured()).isFalse(); |
| | | assertThat(rs.getServerURL()).isEqualTo("localhost:28989"); |
| | | } |
| | | } |