Skip to content

Commit

Permalink
Terracotta-OSS#191: Failover Galvan tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mathieucarbou committed Dec 17, 2016
1 parent 1726507 commit 9e9ac37
Show file tree
Hide file tree
Showing 7 changed files with 679 additions and 215 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestName;
import org.terracotta.testing.rules.BasicExternalCluster;

import java.io.File;
Expand All @@ -41,8 +42,12 @@ public abstract class AbstractHATest extends AbstractTest {
public org.terracotta.testing.rules.Cluster voltron =
new BasicExternalCluster(new File("target/galvan"), 2, emptyList(), "", resourceConfig, "");

@Rule
public TestName testName = new TestName();

@Before
public void setUp() throws Exception {
System.out.println(" => [" + testName.getMethodName() + "] " + getClass().getSimpleName() + ".setUp()");
voltron.getClusterControl().waitForActive();
voltron.getClusterControl().waitForRunningPassivesInStandby();
commonSetUp(voltron);
Expand All @@ -51,6 +56,7 @@ public void setUp() throws Exception {

@After
public void tearDown() throws Exception {
System.out.println(" => [" + testName.getMethodName() + "] " + getClass().getSimpleName() + ".tearDown()");
commonTearDown();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
/**
* @author Mathieu Carbou
*/
@Ignore // TODO activate
@Ignore("Impacted by https://github.com/Terracotta-OSS/terracotta-core/issues/405")
//TODO: VOLTRON ISSUE ? https://github.com/Terracotta-OSS/terracotta-core/issues/405
public class FailoverIT extends AbstractHATest {

@Test
Expand All @@ -47,16 +48,22 @@ public void failover_management() throws Exception {
tmsAgentService.readMessages();

// kill active - passive should take the active role
System.out.printf("==> terminateActive()");
voltron.getClusterControl().terminateActive();
System.out.printf("==> waitForActive()");
voltron.getClusterControl().waitForActive();

System.out.printf("==> readTopology()");
cluster = tmsAgentService.readTopology();
Server newActive = cluster.serverStream().filter(Server::isActive).findFirst().get();
assertThat(newActive.getState(), equalTo(Server.State.ACTIVE));
assertThat(newActive.getServerName(), equalTo(passive.getServerName()));

// read messages
List<Message> messages = tmsAgentService.readMessages();

messages.forEach(System.out::println);

assertThat(messages.size(), equalTo(3));

List<ContextualNotification> notifs = messages.stream()
Expand All @@ -79,4 +86,15 @@ public void failover_management() throws Exception {
//- check notification that might be there: CLIENT_RECONNECTED and SERVER_ENTITY_FAILOVER_COMPLETE
}

@Test
public void puts_can_be_seen_on_other_clients_after_failover() throws Exception {
put(0, "clients", "client1", "Mathieu");

// kill active - passive should take the active role
voltron.getClusterControl().terminateActive();
voltron.getClusterControl().waitForActive();

assertThat(get(1, "clients", "client1"), equalTo("Mathieu"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Terracotta, Inc.
*
* Licensed 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.terracotta.management.integration.tests;

import org.junit.Test;
import org.terracotta.management.model.cluster.Server;
import org.terracotta.management.model.message.Message;
import org.terracotta.management.model.notification.ContextualNotification;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

/**
* @author Mathieu Carbou
*/
public class PassiveLeaveIT extends AbstractHATest {

@Test
public void get_notifications_when_passive_leaves() throws Exception {
Server active = tmsAgentService.readTopology().serverStream().filter(Server::isActive).findFirst().get();
Server passive = tmsAgentService.readTopology().serverStream().filter(server -> !server.isActive()).findFirst().get();
assertThat(active.getState(), equalTo(Server.State.ACTIVE));
assertThat(passive.getState(), equalTo(Server.State.PASSIVE));

// clear notification buffer
tmsAgentService.readMessages();

// remove one passive
voltron.getClusterControl().terminateOnePassive();

// wait for SERVER_LEFT message
List<Message> messages;
do {
messages = tmsAgentService.readMessages();
}
while (messages.isEmpty() && !Thread.currentThread().isInterrupted());

assertThat(messages.stream()
.filter(message -> message.getType().equals("NOTIFICATION"))
.flatMap(message -> message.unwrap(ContextualNotification.class).stream())
.map(ContextualNotification::getType)
.collect(Collectors.toList()),
equalTo(Arrays.asList("SERVER_LEFT")));

assertThat(messages.stream()
.filter(message -> message.getType().equals("NOTIFICATION"))
.flatMap(message -> message.unwrap(ContextualNotification.class).stream())
.map(contextualNotification -> contextualNotification.getContext().get(Server.NAME_KEY))
.collect(Collectors.toList()),
equalTo(Arrays.asList(passive.getServerName())));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright Terracotta, Inc.
*
* Licensed 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.terracotta.management.integration.tests;

import org.junit.Before;
import org.junit.Test;
import org.terracotta.management.model.cluster.Server;
import org.terracotta.management.model.message.Message;
import org.terracotta.management.model.notification.ContextualNotification;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static org.junit.Assert.assertThat;

/**
* @author Mathieu Carbou
*/
public class PassiveStartupIT extends AbstractHATest {

@Before
@Override
public void setUp() throws Exception {
System.out.println(" => [" + testName.getMethodName() + "] " + getClass().getSimpleName() + ".setUp()");

// this sequence is so tha twe can have a stripe of 2 servers bu starting with only 1 active
// galvan does not have an easier way to do that
voltron.getClusterControl().waitForActive();
voltron.getClusterControl().waitForRunningPassivesInStandby();
voltron.getClusterControl().terminateOnePassive();

commonSetUp(voltron);
tmsAgentService.readMessages();
}

@Test
public void get_notifications_when_passive_joins() throws Exception {
put(0, "clients", "client1", "Mat");

// start a passive after management is connected to active
voltron.getClusterControl().startOneServer();
voltron.getClusterControl().waitForRunningPassivesInStandby();

assertThat(get(1, "clients", "client1"), equalTo("Mat"));

Server active = tmsAgentService.readTopology().serverStream().filter(Server::isActive).findFirst().get();
Server passive = tmsAgentService.readTopology().serverStream().filter(server -> !server.isActive()).findFirst().get();
assertThat(active.getState(), equalTo(Server.State.ACTIVE));
assertThat(passive.getState(), equalTo(Server.State.PASSIVE));

// read messages
List<Message> messages = tmsAgentService.readMessages();
assertThat(messages.size(), equalTo(13));
Map<String, List<Message>> map = messages.stream().collect(Collectors.groupingBy(Message::getType));
assertThat(map.size(), equalTo(2));
assertThat(map.keySet(), hasItem("TOPOLOGY"));
assertThat(map.keySet(), hasItem("NOTIFICATION"));
assertThat(map.get("NOTIFICATION").size(), equalTo(12));

List<ContextualNotification> notifs = map.get("NOTIFICATION").stream()
.flatMap(message -> message.unwrap(ContextualNotification.class).stream())
.collect(Collectors.toList());

// test notifications generated on active from passive "actions"
assertThat(
notifs.stream().map(ContextualNotification::getType).collect(Collectors.toList()),
equalTo(Arrays.asList(
"SERVER_JOINED",
"SERVER_STATE_CHANGED",
"SERVER_ENTITY_CREATED",
"SERVER_ENTITY_CREATED", "ENTITY_REGISTRY_AVAILABLE",
"SERVER_ENTITY_CREATED", "ENTITY_REGISTRY_AVAILABLE", "ENTITY_REGISTRY_UPDATED",
"SERVER_ENTITY_CREATED", "ENTITY_REGISTRY_AVAILABLE", "ENTITY_REGISTRY_UPDATED",
"SERVER_STATE_CHANGED")));

// only 1 server in source: passive server
assertThat(
notifs.stream().map(contextualNotification -> contextualNotification.getContext().get(Server.NAME_KEY)).collect(Collectors.toSet()),
equalTo(new HashSet<>(Arrays.asList(passive.getServerName()))));

// test state transition of passive
assertThat(
Stream.of(1, 11).map(idx -> notifs.get(idx).getAttributes().get("state")).collect(Collectors.toList()),
equalTo(Arrays.asList("SYNCHRONIZING", "PASSIVE")));

// wait for SYNC_END message to transit from passive to active
do {
messages = tmsAgentService.readMessages();
}
while (messages.isEmpty() && !Thread.currentThread().isInterrupted());

assertThat(messages.stream()
.filter(message -> message.getType().equals("NOTIFICATION"))
.flatMap(message -> message.unwrap(ContextualNotification.class).stream())
.map(ContextualNotification::getType)
.collect(Collectors.toList()),
equalTo(Arrays.asList("SYNC_END", "SYNC_END")));

assertThat(messages.stream()
.filter(message -> message.getType().equals("NOTIFICATION"))
.flatMap(message -> message.unwrap(ContextualNotification.class).stream())
.map(contextualNotification -> contextualNotification.getContext().get(Server.NAME_KEY))
.collect(Collectors.toList()),
equalTo(Arrays.asList(passive.getServerName(), passive.getServerName())));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,22 @@
*/
package org.terracotta.management.integration.tests;

import org.junit.Ignore;
import org.junit.Test;
import org.terracotta.management.model.capabilities.descriptors.Settings;
import org.terracotta.management.model.cluster.Cluster;
import org.terracotta.management.model.cluster.Server;
import org.terracotta.management.model.cluster.ServerEntity;
import org.terracotta.management.model.message.Message;
import org.terracotta.management.model.notification.ContextualNotification;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.io.File;
import java.io.FileWriter;
import java.util.stream.Stream;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.core.IsCollectionContaining.hasItem;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

/**
* @author Mathieu Carbou
*/
@Ignore // TODO activate
public class HAIT extends AbstractHATest {
public class PassiveTopologyIT extends AbstractHATest {

@Test
public void topology_includes_passives() throws Exception {
Expand All @@ -51,6 +42,9 @@ public void topology_includes_passives() throws Exception {
server.setActivateTime(0);
server.setStartTime(0);
server.setBuildId("Build ID");
server.setVersion("");
server.setGroupPort(0);
server.setBindPort(0);
});

cluster.serverEntityStream()
Expand All @@ -72,43 +66,13 @@ public void topology_includes_passives() throws Exception {
cluster.clientStream().forEach(client -> currentPassive[0] = currentPassive[0]
.replace(passive.getServerName(), "stripe-PASSIVE"));

// please leave this: easy to compare if something changes
/*FileWriter w = new FileWriter(new File("target/out.json"));
w.write(currentPassive[0]);
w.close();*/

// and compare
assertEquals(readJson("passive.json").toString(), currentPassive[0]);
}

@Test
public void get_notifications_when_passive_leaves() throws Exception {
Server active = tmsAgentService.readTopology().serverStream().filter(Server::isActive).findFirst().get();
Server passive = tmsAgentService.readTopology().serverStream().filter(server -> !server.isActive()).findFirst().get();
assertThat(active.getState(), equalTo(Server.State.ACTIVE));
assertThat(passive.getState(), equalTo(Server.State.PASSIVE));

// clear notification buffer
tmsAgentService.readMessages();

// remove one passive
voltron.getClusterControl().terminateOnePassive();

// read messages
List<Message> messages = tmsAgentService.readMessages();
assertThat(messages.size(), equalTo(2));
Map<String, List<Message>> map = messages.stream().collect(Collectors.groupingBy(Message::getType));
assertThat(map.size(), equalTo(2));
assertThat(map.keySet(), hasItem("TOPOLOGY"));
assertThat(map.keySet(), hasItem("NOTIFICATION"));
assertThat(map.get("NOTIFICATION").size(), equalTo(1));

List<ContextualNotification> notifs = map.get("NOTIFICATION").stream()
.flatMap(message -> message.unwrap(ContextualNotification.class).stream())
.collect(Collectors.toList());

assertThat(
notifs.stream().map(ContextualNotification::getType).collect(Collectors.toList()),
equalTo(Arrays.asList("SERVER_LEFT")));

assertThat(
notifs.get(0).getContext().get(Server.NAME_KEY),
equalTo(passive.getServerName()));
}

}
Loading

0 comments on commit 9e9ac37

Please sign in to comment.