blob: 130656dc28ae2ac73d887be8244fa116761427ab [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF 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.apache.geode.cache.wan;
import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runners.Parameterized;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.distributed.ConfigurationPersistenceService;
import org.apache.geode.distributed.internal.InternalConfigurationPersistenceService;
import org.apache.geode.distributed.internal.InternalLocator;
import org.apache.geode.internal.AvailablePort;
import org.apache.geode.internal.cache.xmlcache.CacheCreation;
import org.apache.geode.internal.cache.xmlcache.CacheXmlGenerator;
import org.apache.geode.management.internal.configuration.domain.Configuration;
import org.apache.geode.management.internal.configuration.utils.XmlUtils;
import org.apache.geode.test.dunit.DistributedTestUtils;
import org.apache.geode.test.dunit.Host;
import org.apache.geode.test.dunit.NetworkUtils;
import org.apache.geode.test.dunit.VM;
import org.apache.geode.test.version.TestVersion;
import org.apache.geode.test.version.VersionManager;
public class WANRollingUpgradeMultipleReceiversDefinedInClusterConfiguration
extends WANRollingUpgradeDUnitTest {
@Parameterized.Parameter(1)
public List<Attribute> attributes;
@Parameterized.Parameter(2)
public int expectedReceiverElements;
@Parameterized.Parameter(3)
public int expectedReceivers;
@Parameterized.Parameters(name = "from_v{0}; attributes={1}; expectedReceiverCount={2}")
public static Collection data() {
// Get initial versions to test against
List<String> versions = getVersionsToTest();
// Build up a list of version->attributes->expectedReceivers
List<Object[]> result = new ArrayList<>();
versions.forEach(version -> {
// Add a case for hostname-for-senders
addReceiversWithHostNameForSenders(result, version);
// Add a case for bind-address
addReceiversWithBindAddresses(result, version);
// Add a case for multiple receivers with default attributes
addMultipleReceiversWithDefaultAttributes(result, version);
// Add a case for single receiver with default bind-address
addSingleReceiverWithDefaultBindAddress(result, version);
// Add a case for single receiver with default attributes
addSingleReceiverWithDefaultAttributes(result, version);
});
System.out.println("running against these versions and attributes: "
+ result.stream().map(Arrays::toString).collect(Collectors.joining(", ")));
return result;
}
private static List<String> getVersionsToTest() {
// There is no need to test old versions beyond 130. Individual member configuration is not
// saved in cluster configuration and multiple receivers are not supported starting in 140.
// Note: This comparison works because '130' < '140'.
List<String> result = VersionManager.getInstance().getVersionsWithoutCurrent();
result.removeIf(version -> (TestVersion.compare(version, "1.4.0") >= 0));
if (result.size() < 1) {
throw new RuntimeException("No older versions of Geode were found to test against");
}
return result;
}
private static void addReceiversWithHostNameForSenders(List<Object[]> result, String version) {
List<Attribute> attributes = new ArrayList<>();
attributes.add(new Attribute("hostname-for-senders", "121.21.21.21"));
attributes.add(new Attribute("hostname-for-senders", "121.21.21.22"));
result.add(new Object[] {version, attributes, 2, 0});
}
private static void addReceiversWithBindAddresses(List<Object[]> result, String version) {
List<Attribute> attributes = new ArrayList<>();
attributes.add(new Attribute("bind-address", "121.21.21.21"));
attributes.add(new Attribute("bind-address", "121.21.21.22"));
result.add(new Object[] {version, attributes, 2, 0});
}
private static void addMultipleReceiversWithDefaultAttributes(List<Object[]> result,
String version) {
List<Attribute> attributes = new ArrayList<>();
attributes.add(Attribute.DEFAULT);
attributes.add(Attribute.DEFAULT);
result.add(new Object[] {version, attributes, 2, 1});
}
private static void addSingleReceiverWithDefaultAttributes(List<Object[]> result,
String version) {
List<Attribute> attributes = new ArrayList<>();
attributes.add(Attribute.DEFAULT);
result.add(new Object[] {version, attributes, 1, 1});
}
private static void addSingleReceiverWithDefaultBindAddress(List<Object[]> result,
String version) {
List<Attribute> attributes = new ArrayList<>();
attributes.add(new Attribute("bind-address", "0.0.0.0"));
result.add(new Object[] {version, attributes, 1, 1});
}
@Test
public void testMultipleReceiversRemovedDuringRoll() {
// Get old locator properties
VM locator = Host.getHost(0).getVM(oldVersion, 0);
String hostName = NetworkUtils.getServerHostName();
final int locatorPort = AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET);
final String locators = hostName + "[" + locatorPort + "]";
// Start old locator
locator.invoke(() -> {
DistributedTestUtils.deleteLocatorStateFile(locatorPort);
startLocator(locatorPort, 0,
locators, null, true);
});
// Wait for configuration configuration to be ready.
locator.invoke(
() -> await()
.untilAsserted(() -> assertThat(
InternalLocator.getLocator().isSharedConfigurationRunning()).isTrue()));
// Add cluster configuration elements containing multiple receivers
locator.invoke(this::addMultipleGatewayReceiverElementsToClusterConfiguration);
// Roll old locator to current
rollLocatorToCurrent(locator, locatorPort, 0, locators,
null, true);
// Verify cluster configuration contains expected number of receivers
locator.invoke(this::verifyGatewayReceiverClusterConfigurationElements);
// Start member in current version with cluster configuration enabled
VM server = Host.getHost(0).getVM(VersionManager.CURRENT_VERSION, 1);
server.invoke(() -> createCache(locators, true, true));
// Verify member has expected number of receivers
server.invoke(this::verifyGatewayReceivers);
}
private void addMultipleGatewayReceiverElementsToClusterConfiguration()
throws Exception {
// Create empty xml document
CacheCreation creation = new CacheCreation();
final StringWriter stringWriter = new StringWriter();
final PrintWriter printWriter = new PrintWriter(stringWriter);
CacheXmlGenerator.generate(creation, printWriter, true, false, false);
printWriter.close();
String baseXml = stringWriter.toString();
Document document = XmlUtils.createDocumentFromXml(baseXml);
// Add gateway-receiver for each attribute
for (Attribute attribute : attributes) {
Node rootNode = document.getDocumentElement();
Element receiverElement = document.createElement("gateway-receiver");
if (!attribute.name.equals("default")) {
receiverElement.setAttribute(attribute.name, attribute.value);
}
rootNode.appendChild(receiverElement);
}
assertThat(document.getElementsByTagName("gateway-receiver").getLength())
.isEqualTo(expectedReceiverElements);
// Get configuration region
Region<String, Configuration> configurationRegion = CacheFactory.getAnyInstance().getRegion(
InternalConfigurationPersistenceService.CONFIG_REGION_NAME);
// Create a configuration and put into the configuration region
Configuration configuration = new Configuration(ConfigurationPersistenceService.CLUSTER_CONFIG);
configuration.setCacheXmlContent(XmlUtils.prettyXml(document));
configurationRegion.put(ConfigurationPersistenceService.CLUSTER_CONFIG, configuration);
}
private void verifyGatewayReceiverClusterConfigurationElements() throws Exception {
// Get configuration region
Region<String, Configuration> configurationRegion = CacheFactory.getAnyInstance().getRegion(
InternalConfigurationPersistenceService.CONFIG_REGION_NAME);
// Get the configuration from the region
Configuration configuration =
configurationRegion.get(ConfigurationPersistenceService.CLUSTER_CONFIG);
// Verify the configuration contains no gateway-receiver elements
Document document = XmlUtils.createDocumentFromXml(configuration.getCacheXmlContent());
assertThat(document.getElementsByTagName("gateway-receiver").getLength())
.isEqualTo(expectedReceivers);
}
private void verifyGatewayReceivers() {
assertThat(CacheFactory.getAnyInstance().getGatewayReceivers().size())
.isEqualTo(expectedReceivers);
}
private static class Attribute implements Serializable {
private String name;
private String value;
private static final Attribute DEFAULT = new Attribute("default", "");
Attribute(String name, String value) {
this.name = name;
this.value = value;
}
public String toString() {
return name + "=" + value;
}
}
}