Skip to content

Commit d1337a2

Browse files
authoredNov 30, 2017
Merge pull request wildfly#10673 from rhusar/WFLY-9449v2
WFLY-9449 SingletonPartitionTestCase can fail intermittently
2 parents 8ce600e + 5820a1e commit d1337a2

File tree

5 files changed

+53
-18
lines changed

5 files changed

+53
-18
lines changed
 

‎testsuite/integration/clustering/src/test/java/org/jboss/as/test/clustering/cluster/singleton/SingletonPartitionTestCase.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.jboss.as.test.clustering.cluster.singleton.service.NodeService;
5050
import org.jboss.as.test.clustering.cluster.singleton.service.NodeServiceServlet;
5151
import org.jboss.as.test.http.util.TestHttpClientUtils;
52+
import org.jboss.as.test.shared.TimeoutUtil;
5253
import org.jboss.msc.service.ServiceActivator;
5354
import org.jboss.shrinkwrap.api.Archive;
5455
import org.jboss.shrinkwrap.api.ShrinkWrap;
@@ -74,7 +75,8 @@
7475
@RunAsClient
7576
public class SingletonPartitionTestCase extends ClusterAbstractTestCase {
7677

77-
private static final long TOPOLOGY_CHANGE_TIMEOUT = 120000; // maximum time in ms to wait for cluster topology change
78+
private static final long TOPOLOGY_CHANGE_TIMEOUT = TimeoutUtil.adjust(120_000); // maximum time in ms to wait for cluster topology change
79+
private static final int SERVICE_TIMEOUT = TimeoutUtil.adjust(5_000); // it takes a little extra time after merge for the singleton service to migrate
7880
private static final String CONTAINER = "server";
7981

8082
@Deployment(name = DEPLOYMENT_1, managed = false, testable = false)
@@ -126,7 +128,7 @@ public void testSingletonService(
126128

127129
waitForView(baseURL1, NODE_1, NODE_2);
128130
waitForView(baseURL2, NODE_1, NODE_2);
129-
Thread.sleep(5000); // it takes a little extra time after merge for the singleton service to migrate
131+
Thread.sleep(SERVICE_TIMEOUT);
130132

131133

132134
// check service A
@@ -142,7 +144,7 @@ public void testSingletonService(
142144
partition(true, baseURL1, baseURL2);
143145
waitForView(baseURL1, NODE_1);
144146
waitForView(baseURL2, NODE_2);
145-
Thread.sleep(5000);
147+
Thread.sleep(SERVICE_TIMEOUT);
146148

147149
// check service A
148150
checkSingletonNode(serviceANode1Uri, NODE_1);
@@ -157,7 +159,7 @@ public void testSingletonService(
157159
partition(false, baseURL1, baseURL2);
158160
waitForView(baseURL1, NODE_1, NODE_2);
159161
waitForView(baseURL2, NODE_1, NODE_2);
160-
Thread.sleep(5000);
162+
Thread.sleep(SERVICE_TIMEOUT);
161163

162164
// check service A
163165
checkSingletonNode(serviceANode1Uri, SingletonServiceActivator.SERVICE_A_PREFERRED_NODE);
@@ -172,7 +174,7 @@ public void testSingletonService(
172174
partition(true, baseURL1, baseURL2);
173175
waitForView(baseURL1, NODE_1);
174176
waitForView(baseURL2, NODE_2);
175-
Thread.sleep(5000);
177+
Thread.sleep(SERVICE_TIMEOUT);
176178

177179
// check service A
178180
checkSingletonNode(serviceANode1Uri, NODE_1);
@@ -184,10 +186,10 @@ public void testSingletonService(
184186

185187
@Override
186188
public void afterTestMethod() {
187-
// Stop the container to ensure there aren't any remnants since the test operates on a live JGroups channel
188-
stop(CONTAINERS);
189-
190189
super.afterTestMethod();
190+
191+
// Stop the container to ensure there aren't any remnants since the test operates on a live JGroups channels
192+
stop(CONTAINERS);
191193
}
192194

193195
private static void checkSingletonNode(URI serviceUri, String expectedProviderNode) throws IOException {

‎testsuite/integration/clustering/src/test/java/org/jboss/as/test/clustering/cluster/singleton/partition/PartitionerServlet.java

+34-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.net.URI;
2727
import java.net.URISyntaxException;
2828
import java.net.URL;
29+
import java.util.HashMap;
30+
import java.util.Map;
2931

3032
import javax.servlet.ServletException;
3133
import javax.servlet.annotation.WebServlet;
@@ -36,25 +38,36 @@
3638
import org.jboss.as.server.CurrentServiceContainer;
3739
import org.jboss.msc.service.ServiceController;
3840
import org.jboss.msc.service.ServiceName;
41+
import org.jgroups.Address;
3942
import org.jgroups.Channel;
43+
import org.jgroups.Event;
4044
import org.jgroups.View;
4145
import org.jgroups.protocols.DISCARD;
4246
import org.jgroups.protocols.TP;
4347
import org.jgroups.protocols.pbcast.GMS;
4448
import org.jgroups.stack.ProtocolStack;
4549

4650
/**
47-
* Servlet used to simulate network partitions. Responds to {@code /partitioner?partition=true} by inserting DISCARD protocol to the
48-
* stack and {@code /partitioner?partition=false} by removing previously inserted DISCARD protocol.
51+
* Servlet used to simulate network partitions. Responds to {@code /partitioner?partition=true} by inserting DISCARD protocol to the stack
52+
* and installing new view directly on the {@link GMS} and responds to {@code /partitioner?partition=false} by removing previously inserted
53+
* {@link DISCARD} protocol and passing MERGE event up the stack.
54+
* <p>
55+
* Note that while it would be desirable for the tests to leave splitting and merging to the servers themselves, this is not practical in a
56+
* test suite. While FD/VERIFY_SUSPECT/GMS can be be configured to detect partitions quickly the MERGE3 handles merges within randomized
57+
* intervals and uses unreliable channel which can easily take several minutes for merge to actually happen. Also, speeds up the test
58+
* significantly.
4959
*
5060
* @author Radoslav Husar
5161
*/
5262
@WebServlet(urlPatterns = {PartitionerServlet.SERVLET_PATH})
5363
public class PartitionerServlet extends HttpServlet {
5464

65+
private static final long VIEWS_TIMEOUT = 3_000;
5566
public static final String SERVLET_PATH = "partitioner";
5667
private static final String PARTITION = "partition";
5768

69+
private static Map<Address, View> mergeViews;
70+
5871
public static URI createURI(URL baseURL, boolean partition) throws URISyntaxException {
5972
return baseURL.toURI().resolve(SERVLET_PATH + '?' + PARTITION + '=' + partition);
6073
}
@@ -71,17 +84,35 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
7184
Channel channel = service.awaitValue();
7285

7386
if (partition) {
87+
// Store views for future merge event
88+
GMS gms = (GMS) channel.getProtocolStack().findProtocol(GMS.class);
89+
mergeViews = new HashMap<>();
90+
channel.getView().getMembers().forEach(
91+
address -> mergeViews.put(address, View.create(address, gms.getViewId().getId() + 1, address))
92+
);
93+
// Wait a few seconds to ensure everyone stored a full view
94+
Thread.sleep(VIEWS_TIMEOUT);
95+
7496
// Simulate partitions by injecting DISCARD protocol
7597
DISCARD discard = new DISCARD();
7698
discard.setDiscardAll(true);
7799
channel.getProtocolStack().insertProtocol(discard, ProtocolStack.ABOVE, TP.class);
78100

79101
// Speed up partitioning
80-
GMS gms = (GMS) channel.getProtocolStack().findProtocol(GMS.class);
81102
View view = View.create(channel.getAddress(), gms.getViewId().getId() + 1, channel.getAddress());
82103
gms.installView(view);
83104
} else {
84105
channel.getProtocolStack().removeProtocol(DISCARD.class);
106+
// Wait a few seconds for the other node to remove DISCARD so it does not discard our MERGE request
107+
Thread.sleep(VIEWS_TIMEOUT);
108+
109+
// Since the coordinator is determined by ordering the address in org.jgroups.protocols.pbcast.Merger#determineMergeLeader
110+
// let just all nodes send the merge..
111+
this.log("Passing event up the stack: " + new Event(Event.MERGE, mergeViews));
112+
113+
GMS gms = (GMS) channel.getProtocolStack().findProtocol(GMS.class);
114+
gms.up(new Event(Event.MERGE, mergeViews));
115+
mergeViews = null;
85116
}
86117
} catch (Exception e) {
87118
throw new ServletException(e);

‎testsuite/integration/elytron/pom.xml

-7
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,11 @@
5555
<artifactId>jboss-logmanager</artifactId>
5656
<scope>test</scope>
5757
</dependency>
58-
5958
<dependency>
6059
<groupId>org.wildfly</groupId>
6160
<artifactId>wildfly-testsuite-shared</artifactId>
6261
<scope>test</scope>
6362
</dependency>
64-
65-
<dependency>
66-
<groupId>org.jboss.arquillian.junit</groupId>
67-
<artifactId>arquillian-junit-container</artifactId>
68-
<scope>test</scope>
69-
</dependency>
7063
<dependency>
7164
<groupId>org.wildfly.arquillian</groupId>
7265
<artifactId>wildfly-arquillian-container-managed</artifactId>

‎testsuite/integration/pom.xml

+7
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,13 @@
371371

372372
</configuration>
373373
</plugin>
374+
<plugin>
375+
<groupId>org.apache.maven.plugins</groupId>
376+
<artifactId>maven-antrun-plugin</artifactId>
377+
<configuration>
378+
<skip>${skip.antrun}</skip>
379+
</configuration>
380+
</plugin>
374381
</plugins>
375382
</build>
376383

‎testsuite/pom.xml

+2
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@
8080
<!-- This project's root dir. -->
8181
<jbossas.project.dir>${jbossas.ts.dir}/..</jbossas.project.dir>
8282

83+
<!-- Skips profile generation; to be used with running single test with -Dtest=... -->
84+
<skip.antrun>false</skip.antrun>
8385

8486
<!-- Used to provide an absolute location for the distribution under test. -->
8587
<!-- This value is overridden in modules with the correct relative pathname. -->

0 commit comments

Comments
 (0)
Please sign in to comment.