This is an automated email from the ASF dual-hosted git repository.
eshu11 pushed a commit to branch feature/GEODE-7109
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/feature/GEODE-7109 by this
push:
new 04bc76c GEODE-7109: add test case that multiple sessions can be
maintained.
04bc76c is described below
commit 04bc76cb152aa80f5e06cc820dec9285b1559a29
Author: Eric Shu <[email protected]>
AuthorDate: Fri Feb 14 12:39:18 2020 -0800
GEODE-7109: add test case that multiple sessions can be maintained.
* work around an known issue by verifying after HARegionQueue is drained.
---
.../apache/geode/modules/session/QueryCommand.java | 3 +-
extensions/session-testing-war/build.gradle | 5 +
.../geode/modules/session/CommandServlet.java | 54 +++++
.../geode/modules/session/GetQueueSize.java} | 43 ++--
.../apache/geode/modules/session/QueryCommand.java | 4 +-
.../org/apache/geode/session/tests/Client.java | 12 +
.../apache/geode/session/tests/CargoTestBase.java | 58 +++--
.../apache/geode/session/tests/Tomcat6Test.java | 2 +-
.../apache/geode/session/tests/Tomcat7Test.java | 2 +-
.../apache/geode/session/tests/Tomcat8Test.java | 2 +-
.../apache/geode/session/tests/Tomcat9Test.java | 2 +-
.../session/tests/TomcatClientServerTest.java | 52 +++-
.../org/apache/geode/session/tests/TomcatTest.java | 267 +++++++++++++++++++++
13 files changed, 456 insertions(+), 50 deletions(-)
diff --git
a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/QueryCommand.java
b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/QueryCommand.java
index 62d5ee9..a6d9594 100644
---
a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/QueryCommand.java
+++
b/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/QueryCommand.java
@@ -33,6 +33,7 @@ public enum QueryCommand {
UNKNOWN,
- FUNCTION;
+ FUNCTION,
+ WAIT_UNTIL_QUEUE_DRAINED;
}
diff --git a/extensions/session-testing-war/build.gradle
b/extensions/session-testing-war/build.gradle
index 1e3e366..05f8a9a 100644
--- a/extensions/session-testing-war/build.gradle
+++ b/extensions/session-testing-war/build.gradle
@@ -24,6 +24,11 @@ apply plugin: 'war'
dependencies {
compile(platform(project(':boms:geode-all-bom')))
compile('javax.servlet:javax.servlet-api')
+ compileOnly(project(':extensions:geode-modules'))
+ compileOnly(project(':geode-assembly:geode-assembly-test'))
+ compile(project(':geode-junit')) {
+ exclude module: 'geode-core'
+ }
}
war {
diff --git
a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java
b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java
index 5a42a1d..58e8e55 100644
---
a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java
+++
b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/CommandServlet.java
@@ -15,8 +15,13 @@
package org.apache.geode.modules.session;
+import static org.assertj.core.api.Assertions.assertThat;
+
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Map;
import java.util.function.Function;
import javax.servlet.ServletConfig;
@@ -26,6 +31,18 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import org.apache.catalina.Manager;
+import org.apache.catalina.session.StandardSession;
+import org.apache.catalina.session.StandardSessionFacade;
+import org.awaitility.Duration;
+
+import org.apache.geode.cache.GemFireCache;
+import org.apache.geode.cache.execute.Execution;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.modules.session.catalina.DeltaSessionManager;
+import org.apache.geode.test.awaitility.GeodeAwaitility;
+
public class CommandServlet extends HttpServlet {
@SuppressWarnings("unused")
private ServletContext context;
@@ -92,10 +109,47 @@ public class CommandServlet extends HttpServlet {
out.write(result);
}
break;
+ case WAIT_UNTIL_QUEUE_DRAINED:
+ session = request.getSession();
+ DeltaSessionManager manager = (DeltaSessionManager)
getSessionManager(session);
+
GeodeAwaitility.await().pollInterval(Duration.TWO_HUNDRED_MILLISECONDS)
+ .untilAsserted(() ->
assertThat(checkQueueDrained(manager)).isTrue());
+ break;
}
} catch (Exception e) {
out.write("Error in servlet: " + e.toString());
e.printStackTrace(out);
}
}
+
+ private boolean checkQueueDrained(DeltaSessionManager manager) {
+ GemFireCache cache = manager.getSessionCache().getCache();
+ Execution execution = FunctionService.onServers(cache);
+
+ ResultCollector collector = execution.execute(GetQueueSize.ID);
+ List list = (List) collector.getResult();
+ for (Object object : list) {
+ for (Object queue : ((Map) object).keySet()) {
+ manager.getLogger().info("client cache has queue: " + queue);
+ }
+ }
+ for (Object object : list) {
+ for (Object size : ((Map) object).values()) {
+ if ((Integer) size != 0) {
+ manager.getLogger().info("checkQueueDrained not drained with size "
+ size);
+ return false;
+ }
+ }
+ }
+ manager.getLogger().info("checkQueueDrained drained");
+ return true;
+ }
+
+ private Manager getSessionManager(HttpSession session) throws Exception {
+ Field facadeSessionField =
StandardSessionFacade.class.getDeclaredField("session");
+ facadeSessionField.setAccessible(true);
+ StandardSession stdSession = (StandardSession)
facadeSessionField.get(session);
+
+ return stdSession.getManager();
+ }
}
diff --git
a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/QueryCommand.java
b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/GetQueueSize.java
similarity index 53%
copy from
extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/QueryCommand.java
copy to
extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/GetQueueSize.java
index 62d5ee9..15fd8f5 100644
---
a/extensions/geode-modules-test/src/main/java/org/apache/geode/modules/session/QueryCommand.java
+++
b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/GetQueueSize.java
@@ -14,25 +14,26 @@
*/
package org.apache.geode.modules.session;
-/**
- * Basic commands to pass to our test servlet
- */
-public enum QueryCommand {
-
- SET,
-
- SET_MAX_INACTIVE,
-
- GET,
-
- REMOVE,
-
- INVALIDATE,
-
- CALLBACK,
-
- UNKNOWN,
-
- FUNCTION;
-
+import java.util.Map;
+
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.internal.cache.tier.InternalClientMembership;
+
+public class GetQueueSize implements Function {
+ public static final String ID = "get-queue-size";
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void execute(FunctionContext context) {
+ InternalCache cache = (InternalCache) context.getCache();
+ Map clientProxyMembershipIDMap =
InternalClientMembership.getClientQueueSizes(cache);
+ context.getResultSender().lastResult(clientProxyMembershipIDMap);
+ }
+
+ @Override
+ public String getId() {
+ return ID;
+ }
}
diff --git
a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java
b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java
index b22787c..c1a729b 100644
---
a/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java
+++
b/extensions/session-testing-war/src/main/java/org/apache/geode/modules/session/QueryCommand.java
@@ -31,6 +31,8 @@ public enum QueryCommand {
UNKNOWN,
- FUNCTION;
+ FUNCTION,
+
+ WAIT_UNTIL_QUEUE_DRAINED;
}
diff --git
a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/session/tests/Client.java
b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/session/tests/Client.java
index d9257e8..c992482 100644
---
a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/session/tests/Client.java
+++
b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/session/tests/Client.java
@@ -248,6 +248,10 @@ public class Client {
}
}
+ public String getCookie() {
+ return cookie;
+ }
+
private String getCookieHeader(CloseableHttpResponse resp) {
Header lastHeader = resp.getLastHeader("Set-Cookie");
@@ -302,4 +306,12 @@ public class Client {
+ '\'' + '}';
}
}
+
+ public Response waitForQueueToDrain() throws IOException, URISyntaxException
{
+ resetURI();
+ reqURIBuild.setParameter("cmd",
QueryCommand.WAIT_UNTIL_QUEUE_DRAINED.name());
+ reqURIBuild.setParameter("param", null);
+
+ return doRequest(new HttpGet(reqURIBuild.build()), true);
+ }
}
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/CargoTestBase.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/CargoTestBase.java
index 6299a8f..3607260 100644
---
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/CargoTestBase.java
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/CargoTestBase.java
@@ -14,6 +14,7 @@
*/
package org.apache.geode.session.tests;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
@@ -58,6 +59,8 @@ public abstract class CargoTestBase {
protected ContainerManager manager;
protected ContainerInstall install;
protected MemberVM locatorVM;
+ protected boolean dumpLogs = true;
+ protected int numberOfContainers = 2;
/**
* Should only be called once per test.
@@ -88,7 +91,7 @@ public abstract class CargoTestBase {
install = getInstall(portSupplier::getAvailablePort);
install.setDefaultLocatorPort(locatorVM.getPort());
- manager.addContainers(2, install);
+ manager.addContainers(numberOfContainers, install);
customizeContainers();
}
@@ -104,7 +107,9 @@ public abstract class CargoTestBase {
manager.stopAllActiveContainers();
} finally {
try {
- manager.dumpLogs();
+ if (dumpLogs) {
+ manager.dumpLogs();
+ }
} finally {
try {
manager.cleanUp();
@@ -121,6 +126,12 @@ public abstract class CargoTestBase {
*/
public void getKeyValueDataOnAllClients(String key, String expectedValue,
String expectedCookie)
throws IOException, URISyntaxException {
+ getKeyValueDataOnAllClients(client, key, expectedValue, expectedCookie);
+ }
+
+ public void getKeyValueDataOnAllClients(Client client, String key, String
expectedValue,
+ String expectedCookie)
+ throws IOException, URISyntaxException {
for (int i = 0; i < manager.numContainers(); i++) {
// Set the port for this server
client.setPort(Integer.parseInt(manager.getContainerPort(i)));
@@ -139,22 +150,38 @@ public abstract class CargoTestBase {
String value = resp.getResponse();
if (!expectedValue.equals(value)) {
LogService.getLogger().info("verifying container {} for expected
value of {}"
- + " for key {}, but gets response value of {}. Waiting for
update from server.", i,
- expectedValue, key, value);
+ + " for key {}, but gets response value of {} from client {}.
Waiting for update from server.",
+ i, expectedValue, key, value, client);
}
- GeodeAwaitility.await().until(() ->
expectedValue.equals(getResponseValue(client, key)));
+ GeodeAwaitility.await().pollInSameThread().untilAsserted(
+ () -> assertThat(getResponseValue(client,
key)).isEqualTo(expectedValue));
} else {
// either p2p cache or client cache which has proxy/empty region -
retrieving session from
// servers
- assertEquals("Session data is not replicating properly",
expectedValue, resp.getResponse());
+ assertEquals("Session data is not replicating properly for key " +
key, expectedValue,
+ resp.getResponse());
}
}
}
+ protected void getKeyValueDataOnOperatingClient(Client client, String key,
String expectedValue,
+ String expectedCookie, int operatingContainer)
+ throws IOException, URISyntaxException {
+
client.setPort(Integer.parseInt(manager.getContainerPort(operatingContainer)));
+ Client.Response resp = client.get(key);
+ if (expectedCookie != null)
+ assertEquals("Sessions are not replicating properly", expectedCookie,
+ resp.getSessionCookie());
+
+ assertEquals("Session data is not replicating properly for key " + key,
expectedValue,
+ resp.getResponse());
+
+ }
+
private String getResponseValue(Client client, String key)
throws IOException, URISyntaxException {
- String value = client.get(key).getResponse();
- LogService.getLogger().info("client gets response value of {}", value);
+ Client.Response response = client.get(key);
+ String value = response.getResponse();
return value;
}
@@ -190,8 +217,8 @@ public abstract class CargoTestBase {
}
/**
- * Test that when a container fails, session attributes that were previously
set in that container
- * are still available in other containers
+ * Test that when a container fails, session attributes that were previously
set in that
+ * container are still available in other containers
*/
@Test
public void failureShouldStillAllowOtherContainersDataAccess()
@@ -293,8 +320,8 @@ public abstract class CargoTestBase {
/**
- * Test that if one container is accessing a session, that will prevent the
session from expiring
- * in all containers.
+ * Test that if one container is accessing a session, that will prevent the
session from
+ * expiring in all containers.
*/
@Test
public void containersShouldShareSessionExpirationReset()
@@ -329,7 +356,8 @@ public abstract class CargoTestBase {
}
/**
- * Test that if a session attribute is removed in one container, it is
removed from all containers
+ * Test that if a session attribute is removed in one container, it is
removed from all
+ * containers
*/
@Test
public void containersShouldShareDataRemovals() throws IOException,
URISyntaxException {
@@ -350,8 +378,8 @@ public abstract class CargoTestBase {
}
/**
- * Test that a container added to the system after puts still can access the
correct sessions and
- * data.
+ * Test that a container added to the system after puts still can access the
correct sessions
+ * and data.
*/
@Test
public void newContainersShouldShareDataAccess() throws Exception {
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat6Test.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat6Test.java
index 60dface..42511c8 100644
---
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat6Test.java
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat6Test.java
@@ -19,7 +19,7 @@ import static
org.apache.geode.session.tests.TomcatInstall.TomcatVersion.TOMCAT6
import java.util.function.IntSupplier;
-public class Tomcat6Test extends CargoTestBase {
+public class Tomcat6Test extends TomcatTest {
@Override
public ContainerInstall getInstall(IntSupplier portSupplier) throws
Exception {
return new TomcatInstall(getClass().getSimpleName(), TOMCAT6,
PEER_TO_PEER, portSupplier);
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat7Test.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat7Test.java
index 1922fdb..4b6836d 100644
---
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat7Test.java
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat7Test.java
@@ -19,7 +19,7 @@ import static
org.apache.geode.session.tests.TomcatInstall.TomcatVersion.TOMCAT7
import java.util.function.IntSupplier;
-public class Tomcat7Test extends CargoTestBase {
+public class Tomcat7Test extends TomcatTest {
@Override
public ContainerInstall getInstall(IntSupplier portSupplier) throws
Exception {
return new TomcatInstall(getClass().getSimpleName(), TOMCAT7,
PEER_TO_PEER, portSupplier);
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat8Test.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat8Test.java
index 93a7441..97b73d9 100644
---
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat8Test.java
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat8Test.java
@@ -19,7 +19,7 @@ import static
org.apache.geode.session.tests.TomcatInstall.TomcatVersion.TOMCAT8
import java.util.function.IntSupplier;
-public class Tomcat8Test extends CargoTestBase {
+public class Tomcat8Test extends TomcatTest {
@Override
public ContainerInstall getInstall(IntSupplier portSupplier) throws
Exception {
return new TomcatInstall(getClass().getSimpleName(), TOMCAT8,
PEER_TO_PEER, portSupplier);
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat9Test.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat9Test.java
index b7777d1..90f5392 100644
---
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat9Test.java
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/Tomcat9Test.java
@@ -19,7 +19,7 @@ import static
org.apache.geode.session.tests.TomcatInstall.TomcatVersion.TOMCAT9
import java.util.function.IntSupplier;
-public class Tomcat9Test extends CargoTestBase {
+public class Tomcat9Test extends TomcatTest {
@Override
public ContainerInstall getInstall(IntSupplier portSupplier) throws
Exception {
return new TomcatInstall(getClass().getSimpleName(), TOMCAT9,
PEER_TO_PEER, portSupplier);
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/TomcatClientServerTest.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/TomcatClientServerTest.java
index 75af639..e86ee0d 100644
---
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/TomcatClientServerTest.java
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/TomcatClientServerTest.java
@@ -14,26 +14,30 @@
*/
package org.apache.geode.session.tests;
+
import java.io.File;
+import java.util.ArrayList;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
+import org.apache.geode.internal.serialization.Version;
import org.apache.geode.management.internal.cli.util.CommandStringBuilder;
import org.apache.geode.management.internal.i18n.CliStrings;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.junit.rules.GfshCommandRule;
+import org.apache.geode.test.junit.rules.RequiresGeodeHome;
/**
* Setup class for Tomcat Client Server tests
*
* Sets up the server needed for the client container to connect to
*/
-public abstract class TomcatClientServerTest extends CargoTestBase {
- private String serverName1;
- private String serverName2;
+public abstract class TomcatClientServerTest extends TomcatTest {
+ private final ArrayList<String> serverList = new ArrayList<>();
+ private final int numberOfServers = 2;
@Rule
public transient TemporaryFolder temporaryFolder = new TemporaryFolder();
@@ -41,16 +45,38 @@ public abstract class TomcatClientServerTest extends
CargoTestBase {
@Rule
public transient GfshCommandRule gfsh = new GfshCommandRule();
+ @Rule
+ public RequiresGeodeHome requiresGeodeHome = new RequiresGeodeHome();
+
/**
* Starts a server for the client Tomcat container to connect to using the
GFSH command line
* before each test
*/
@Before
public void startServer() throws Exception {
- serverName1 = startAServer(1);
- serverName2 = startAServer(2);
+ for (int i = 0; i < numberOfServers; i++) {
+ serverList.add(startAServer(i));
+ }
afterStartServers();
+
+ if (isCachingClient()) {
+ deployJars();
+ }
+ }
+
+ private void deployJars() throws Exception {
+ String currentVersion = Version.CURRENT.getName();
+
+ String geodeHome = requiresGeodeHome.getGeodeHome().getAbsolutePath();
+ int index = geodeHome.indexOf("geode-assembly");
+ geodeHome = geodeHome.substring(0, index);
+ String fileName = geodeHome +
"extensions/session-testing-war/build/libs/session-testing-war-"
+ + currentVersion + "-SNAPSHOT.jar";
+ CommandStringBuilder command = new CommandStringBuilder(CliStrings.DEPLOY);
+ command.addOption(CliStrings.JAR, fileName);
+ gfsh.connectAndVerify(locatorVM.getPort(),
GfshCommandRule.PortType.locator);
+ gfsh.executeAndAssertThat(command.toString()).statusIsSuccess();
}
public void afterStartServers() throws Exception {}
@@ -73,7 +99,13 @@ public abstract class TomcatClientServerTest extends
CargoTestBase {
binDirJars + File.pathSeparator + libDirJars);
command.addOption(CliStrings.START_SERVER__LOCATORS,
locatorVM.invoke(() -> ClusterStartupRule.getLocator().asString()));
+ // statistic file
+ command.addOption(CliStrings.START_SERVER__STATISTIC_ARCHIVE_FILE,
"statArchive.gfs");
+
command.addOption(CliStrings.START_SERVER__J,
"-Dgemfire.member-timeout=60000");
+ command.addOption(CliStrings.START_SERVER__J,
"-Dgemfire.statistic-sampling-enabled=true");
+ command.addOption(CliStrings.START_SERVER__J,
"-XX:+HeapDumpOnOutOfMemoryError");
+ command.addOption(CliStrings.START_SERVER__J,
"-XX:+JavaMonitorsInStackTrace");
// Start server
gfsh.executeAndAssertThat(command.toString()).statusIsSuccess();
@@ -85,9 +117,13 @@ public abstract class TomcatClientServerTest extends
CargoTestBase {
* Stops the server for the client Tomcat container is has been connecting to
*/
@After
- public void stopServer() throws Exception {
- stopAServer(serverName1);
- stopAServer(serverName2);
+ public void stopServer() {
+ for (int i = 0; i < numberOfServers; i++) {
+ try {
+ stopAServer(serverList.get(i));
+ } catch (Exception ignore) {
+ }
+ }
}
private void stopAServer(String serverName) {
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/TomcatTest.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/TomcatTest.java
new file mode 100644
index 0000000..01bf0ef
--- /dev/null
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/session/tests/TomcatTest.java
@@ -0,0 +1,267 @@
+/*
+ * 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.session.tests;
+
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ErrorCollector;
+
+import org.apache.geode.logging.internal.log4j.api.LogService;
+import org.apache.geode.test.junit.rules.ExecutorServiceRule;
+
+public abstract class TomcatTest extends CargoTestBase {
+ @Rule
+ public ExecutorServiceRule executorServiceRule = new ExecutorServiceRule();
+
+ @Rule
+ public ErrorCollector errorCollector = new ErrorCollector();
+
+ protected int numberOfConcurrentClients;
+ protected CountDownLatch latch;
+ protected CountDownLatch finishLatch;
+ protected CountDownLatch checkQueueLatch;
+ private final Random random = new Random();
+ private final Map<Client, HashMap<String, String>> clientAttributesMap =
+ new ConcurrentHashMap<>();
+ private int counter = 0;
+
+ @Test
+ public void multipleClientsCanMaintainOwnSessions() throws Throwable {
+ dumpLogs = false;
+ numberOfConcurrentClients = 20;
+ latch = new CountDownLatch(numberOfConcurrentClients);
+ finishLatch = new CountDownLatch(numberOfConcurrentClients);
+ checkQueueLatch = new CountDownLatch(1);
+ manager.startAllInactiveContainers();
+ for (int i = 0; i < numberOfConcurrentClients; i++) {
+ executorServiceRule.submit(() -> doSessionOps(20));
+ }
+ if (isCachingClient()) {
+ waitUntilHARegionQueueAreDrainedOnAllServers();
+ }
+ finishLatch.await();
+ }
+
+ protected void doSessionOps(int maxNumOfOperations) throws Exception {
+ String key = "key";
+ String value = "Foo55";
+ String key1 = "key1";
+ String value1 = "Bar1226";
+
+ Client client = new Client();
+ int operatingContainer = random.nextInt(numberOfContainers);
+ try {
+
client.setPort(Integer.parseInt(manager.getContainerPort(operatingContainer)));
+ LogService.getLogger().info(
+ "doing work for client " + client + " on Container
operatingContainer "
+ + operatingContainer);
+ LogService.getLogger().info("putting key " + key + " value " + value);
+ Client.Response resp = client.set(key, value);
+ // To reproduce GEODE-7780 uncomment out the following code
+ // if (operatingContainer == 0) {
+ // getKeyValueDataOnOperatingClient(client, key, value,
resp.getSessionCookie(), 1);
+ // } else {
+ // getKeyValueDataOnOperatingClient(client, key, value,
resp.getSessionCookie(), 0);
+ // }
+ if (isCachingClient()) {
+ // assume sticky session for client with caching proxy
+ getKeyValueDataOnOperatingClient(client, key, value,
resp.getSessionCookie(),
+ operatingContainer);
+ } else {
+ getKeyValueDataOnAllClients(client, key, value,
resp.getSessionCookie());
+ }
+ resp = client.set(key1, value1);
+ if (isCachingClient()) {
+ getKeyValueDataOnOperatingClient(client, key1, value1,
resp.getSessionCookie(),
+ operatingContainer);
+ } else {
+ getKeyValueDataOnAllClients(client, key1, value1,
resp.getSessionCookie());
+ }
+ resp = client.set(key, null);
+ if (isCachingClient()) {
+ getKeyValueDataOnOperatingClient(client, key, "",
resp.getSessionCookie(),
+ operatingContainer);
+ } else {
+ getKeyValueDataOnAllClients(client, key, "", resp.getSessionCookie());
+ }
+ doSetsAndVerifyGets(client, maxNumOfOperations, operatingContainer);
+ } catch (Throwable e) {
+ errorCollector.addError(e);
+ } finally {
+ latch.countDown();
+ }
+
+ if (isCachingClient()) {
+ checkQueueLatch.await();
+ }
+
+ try {
+ verifySessionAllAttributes(client, clientAttributesMap.get(client),
client.get(key, true));
+ } catch (Throwable e) {
+ errorCollector.addError(e);
+ } finally {
+ finishLatch.countDown();
+ }
+ }
+
+ private void waitUntilHARegionQueueAreDrainedOnAllServers() throws Exception
{
+ latch.await();
+ for (int i = 0; i < manager.numContainers(); i++) {
+ client.setPort(Integer.parseInt(manager.getContainerPort(i)));
+ LogService.getLogger().info("waitForQueueToDrain on container " + i);
+ client.waitForQueueToDrain();
+ LogService.getLogger().info("done waitForQueueToDrain on container " +
i);
+ }
+ checkQueueLatch.countDown();
+ }
+
+ private synchronized void updateDoneCounter() {
+ ++counter;
+ LogService.getLogger().info("finished {} of sessions", counter);
+ }
+
+ private void doSetsAndVerifyGets(Client client, int maxNumberOfOperations,
int operatingContainer)
+ throws Exception {
+ HashMap<String, String> attributes = new HashMap();
+ clientAttributesMap.put(client, attributes);
+
+ int numberOfOperations = random.nextInt(maxNumberOfOperations) + 1;
+ LogService.getLogger().info("performing {} of operations",
numberOfOperations);
+ for (int i = 0; i < numberOfOperations; i++) {
+ if (i % 2 == 0) {
+ doGetsAndSets(client, attributes, operatingContainer);
+ } else {
+ doSetsAndGetWithUpdate(client, attributes, operatingContainer);
+ }
+ }
+ LogService.getLogger().info("finished doSetsAndVerifyGets ops for {}
times",
+ numberOfOperations);
+ updateDoneCounter();
+ }
+
+ private void doGetsAndSets(Client client, HashMap<String, String> attributes,
+ int operatingContainer)
+ throws IOException, URISyntaxException {
+ String key = getKey(client, attributes);
+ int maxLength = 100;
+ String value = getRandomVarChar(client, attributes, maxLength);
+ attributes.put(key, value);
+ verifySets(client, attributes, operatingContainer, key, value);
+ }
+
+ private void verifySets(Client client, HashMap<String, String> attributes,
int operatingContainer,
+ String key, String value) throws IOException, URISyntaxException {
+ int whichContainer =
+ isCachingClient() ? operatingContainer :
random.nextInt(numberOfContainers);
+ client.setPort(Integer.parseInt(manager.getContainerPort(whichContainer)));
+ Client.Response resp = client.set(key, value);
+ if (isCachingClient()) {
+ getKeyValueDataOnOperatingClient(client, key, value,
resp.getSessionCookie(),
+ operatingContainer);
+ verifySessionGets(client, attributes, resp, operatingContainer);
+ } else {
+ getKeyValueDataOnAllClients(client, key, value, resp.getSessionCookie());
+ verifySessionGets(client, attributes, resp);
+ }
+ }
+
+ private void doSetsAndGetWithUpdate(Client client, HashMap<String, String>
attributes,
+ int operatingContainer)
+ throws IOException, URISyntaxException {
+ String key = getKey(client, attributes);
+ if (random.nextInt(10) == 1) {
+ // do update on an existing attribute
+ key = "key";
+ }
+ int maxLength = 100;
+ String value = getRandomVarChar(client, attributes, maxLength);
+ attributes.put(key, value);
+ verifySets(client, attributes, operatingContainer, key, value);
+ }
+
+ protected String getKey(Client client, Map attributes) {
+ return "key" + (attributes.size() + 1) + "_" + client.getCookie();
+ }
+
+ protected String getRandomVarChar(Client client, Map attributes, int length)
{
+ if (length == 0) {
+ return "";
+ }
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("value" + (attributes.size() + 1) + "_" +
client.getCookie());
+ int randomLength = random.nextInt(length) + 1;
+
+ int sp = ' ';
+ int tilde = '~';
+ for (int j = 0; j < randomLength; j++) {
+ buffer.append((char) (random.nextInt(tilde - sp) + sp));
+ }
+ return buffer.toString();
+ }
+
+ private void verifySessionGets(Client client, HashMap<String, String>
attributes,
+ Client.Response resp) throws IOException, URISyntaxException {
+ verifySessionGets(client, attributes, resp, -1);
+ }
+
+ private void verifySessionGets(Client client, HashMap<String, String>
attributes,
+ Client.Response resp, int operatingContainer) throws IOException,
URISyntaxException {
+ int count = 0;
+ int whichOne = random.nextInt(attributes.size());
+ Iterator iterator = attributes.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ if (count == whichOne) {
+ String key = (String) entry.getKey();
+ String expectedValue = (String) entry.getValue();
+ if (isCachingClient()) {
+ getKeyValueDataOnOperatingClient(client, key, expectedValue,
+ resp.getSessionCookie(), operatingContainer);
+ } else {
+ getKeyValueDataOnAllClients(client, key, expectedValue,
+ resp.getSessionCookie());
+ }
+ break;
+ }
+ count++;
+ }
+ }
+
+ private void verifySessionAllAttributes(Client client, HashMap<String,
String> attributes,
+ Client.Response resp) throws IOException, URISyntaxException {
+ Iterator iterator = attributes.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) iterator.next();
+ String key = (String) entry.getKey();
+ String expectedValue = (String) entry.getValue();
+ getKeyValueDataOnAllClients(client, key, expectedValue,
+ resp.getSessionCookie());
+ }
+ }
+
+ protected boolean isCachingClient() {
+ return install.getConnectionType() ==
ContainerInstall.ConnectionType.CACHING_CLIENT_SERVER;
+ }
+}