From 10df538c1cc33cd80ae58914ad72a135b42b62ba Mon Sep 17 00:00:00 2001 From: Richard Achmatowicz Date: Thu, 5 Sep 2024 16:39:06 -0400 Subject: [PATCH] Add explanatory javadoc to all of the testcases for this project. --- .../org/jboss/ejb/_private/NetworkUtil.java | 3 + ...BasedEJBClientContextSelectorTestCase.java | 18 ++- ...DiscoveryEJBClientInterceptorTestCase.java | 17 ++- .../ejb/client/EJBRootContextTestCase.java | 29 ++++ .../ejb/client/ProxyEqualityTestCase.java | 12 ++ ...LegacyPropertiesConfigurationTestCase.java | 22 +++ .../remoting/MethodInvocationRequest.java | 2 + .../ProxySerializationTestCase.java | 17 ++- .../jboss/ejb/client/test/ClassCallback.java | 3 + .../test/ClusterNodeSelectorTestCase.java | 50 ++++--- .../ClusteredInvocationFailOverTestCase.java | 42 +++++- .../test/ClusteredInvocationTestCase.java | 15 +- ...DefaultConfigurationDiscoveryTestCase.java | 3 +- .../test/DeploymentNodeSelectorTestCase.java | 132 ++++++++++-------- .../test/InterruptRunningCallTestCase.java | 33 ++++- .../test/JBossEJBPropertiesTestCase.java | 41 +----- .../ejb/client/test/LearningTestCase.java | 65 ++++++++- .../ejb/client/test/ManualTestRunner.java | 35 ++++- .../NetworkBlackHoleInvocationTestCase.java | 3 +- .../test/RemoteDiscoveryTimeoutTestCase.java | 24 +++- .../client/test/SimpleInvocationTestCase.java | 7 +- .../ejb/client/test/TransactionTestCase.java | 130 ++++++++++++++--- .../test/UnmarshallingFilterTestCase.java | 22 ++- .../client/test/WildflyClientXMLTestCase.java | 24 +++- .../byteman/BytemanTransactionTestCase.java | 41 +++++- .../byteman/MixedModeServiceURLTestCase.java | 7 +- .../test/byteman/MixedModeTestHelper.java | 7 + .../byteman/OOMEInInvocationTestCase.java | 55 ++++---- .../test/byteman/TimeoutRetryTestCase.java | 29 ++-- .../client/test/common/TypeReporterBean.java | 3 + .../protocol/remote/NetworkUtilTestCase.java | 8 ++ .../clustered-jboss-ejb-client.properties | 4 +- .../test/byteman/TimeoutRetryTestCase.btm | 2 +- 33 files changed, 667 insertions(+), 238 deletions(-) diff --git a/src/main/java/org/jboss/ejb/_private/NetworkUtil.java b/src/main/java/org/jboss/ejb/_private/NetworkUtil.java index 43d84c2f1..11967422c 100644 --- a/src/main/java/org/jboss/ejb/_private/NetworkUtil.java +++ b/src/main/java/org/jboss/ejb/_private/NetworkUtil.java @@ -23,6 +23,9 @@ import java.net.InetAddress; /** + * Tests for the network utility class, used to determine if an internet address belongs to a particular network, where + * the network is defined by a network address and netmask. + * * @author Jaikiran Pai */ public class NetworkUtil { diff --git a/src/test/java/org/jboss/ejb/client/ConfigurationBasedEJBClientContextSelectorTestCase.java b/src/test/java/org/jboss/ejb/client/ConfigurationBasedEJBClientContextSelectorTestCase.java index 218931758..6f5d9809b 100644 --- a/src/test/java/org/jboss/ejb/client/ConfigurationBasedEJBClientContextSelectorTestCase.java +++ b/src/test/java/org/jboss/ejb/client/ConfigurationBasedEJBClientContextSelectorTestCase.java @@ -26,7 +26,8 @@ import org.junit.Test; /** - * Tests some basic features of ConfigurationBasedEJBClientContextSelector + * Tests some basic features of ConfigurationBasedEJBClientContextSelector, responsible for initialization of + * the contextual for EJBClientContext. * * @author Joerg Baesner */ @@ -36,8 +37,8 @@ public class ConfigurationBasedEJBClientContextSelectorTestCase { private static final String CONFIGURATION_FILE = "wildfly-client.xml"; /** - * Do any general setup here - * + * Configure the wildfly-client.xml file to be used in initialize the EJBClientConext. + * * @throws Exception */ @BeforeClass @@ -50,6 +51,9 @@ public static void beforeClass() throws Exception { ClassCallback.beforeClassCallback(); } + /** + * A test which validates that the EJBCLientContext has been initialized with the configured DeploymentNodeSelector. + */ @Test public void testDeploymentNodeSelector() { EJBClientContext clientContext = EJBClientContext.getCurrent(); @@ -60,6 +64,9 @@ public void testDeploymentNodeSelector() { Assert.assertEquals("Wrong value,", DummyNodeSelector.DEPLOYMENT_NODE_IDENTIFIER, dns.selectNode(null, null, null, null)); } + /** + * A test which validates that the EJBCLientContext has been initialized with the configured ClusterNodeSelector. + */ @Test public void testClusterNodeSelector() { EJBClientContext clientContext = EJBClientContext.getCurrent(); @@ -70,6 +77,10 @@ public void testClusterNodeSelector() { Assert.assertEquals("Wrong value,", DummyNodeSelector.CLUSTER_NODE_IDENTIFIER, cns.selectNode(null, null, null)); } + /** + * A test which validates that the EJBCLientContext has been initialized with the configured value for + * the max-allowed-connected-nodes property. + */ @Test public void testMaximumAllowedClusterNodes() { EJBClientContext clientContext = EJBClientContext.getCurrent(); @@ -77,5 +88,4 @@ public void testMaximumAllowedClusterNodes() { Assert.assertEquals("Wrong value,", 15, nodes); } - } diff --git a/src/test/java/org/jboss/ejb/client/DiscoveryEJBClientInterceptorTestCase.java b/src/test/java/org/jboss/ejb/client/DiscoveryEJBClientInterceptorTestCase.java index 0ada08338..6ea1c167d 100644 --- a/src/test/java/org/jboss/ejb/client/DiscoveryEJBClientInterceptorTestCase.java +++ b/src/test/java/org/jboss/ejb/client/DiscoveryEJBClientInterceptorTestCase.java @@ -24,12 +24,22 @@ import org.junit.Test; /** - * Tests on DiscoveryEJBClientInterceptor + * Tests for the DiscoveryEJBClientInterceptor * * @author Lin Gao */ public class DiscoveryEJBClientInterceptorTestCase { + /** + * A test for the "blocklist" feature of the DiscoveryEJBClientInterceptor which allows invocation targets + * to be added to a blocklist. Presence of a URL on the blocklist eans that they should currently be excluded + * from discovery request results. The blocklist has an associated timeout; blocklisted entries are cleared + * once their time in the blocklist has passed the timeout to avoid being blocklisted forever. + * + * THis test validates the addition of a URL to the blicklist, as well as its expiration from the blocklist. + * + * @throws Exception + */ @Test public void testBlocklist() throws Exception { long timeout = 1000L; @@ -44,9 +54,8 @@ public void requestRetry() { Assert.assertTrue(DiscoveryEJBClientInterceptor.isBlocklisted(context, destination)); Assert.assertEquals(1, DiscoveryEJBClientInterceptor.getBlocklist().size()); - // If sleeping for just the timeout duration, the lifespan of - // the blocklist may equal to, but not greater than, the configured - // timeout, and so will not be removed yet. So sleep a bit longer. + // If sleeping for just the timeout duration, the lifespan of the blocklist may equal to, but not greater than, + // the configured timeout, and so will not be removed yet. So sleep a bit longer. Thread.sleep(timeout * 2); Assert.assertFalse(DiscoveryEJBClientInterceptor.isBlocklisted(context, destination)); Assert.assertEquals(0, DiscoveryEJBClientInterceptor.getBlocklist().size()); diff --git a/src/test/java/org/jboss/ejb/client/EJBRootContextTestCase.java b/src/test/java/org/jboss/ejb/client/EJBRootContextTestCase.java index 92b12c96b..7eea13002 100644 --- a/src/test/java/org/jboss/ejb/client/EJBRootContextTestCase.java +++ b/src/test/java/org/jboss/ejb/client/EJBRootContextTestCase.java @@ -9,10 +9,22 @@ import javax.naming.InvalidNameException; import javax.naming.NamingException; +/** + * A set of tests which validate that invocation.timeout values set in the properties map of a JNDI context + * get propagated to the proxies created from that JNDI context. + * + * @author unknown + */ public class EJBRootContextTestCase { private static final String LOOKUP_NAME = "appName/moduleName/distinctName!org.jboss.ejb.client.test.common.Echo"; + /** + * Test which validates that an integer-valued invocation.timeout property set in the properties map for + * a JNDI context gets passed through to a proxy created from that JNDI context. + * + * @throws NamingException + */ @Test public void testInvocationTimeoutEnvPropertyInteger() throws NamingException { FastHashtable env = new FastHashtable<>(); @@ -23,6 +35,12 @@ public void testInvocationTimeoutEnvPropertyInteger() throws NamingException { Assert.assertEquals(100, EJBInvocationHandler.forProxy(proxy).getInvocationTimeout()); } + /** + * Test which validates that a string-valued invocation.timeout property set in the properties map for + * a JNDI context gets passed through to a proxy created from that JNDI context. + * + * @throws NamingException + */ @Test public void testInvocationTimeoutEnvPropertyString() throws NamingException { FastHashtable env = new FastHashtable<>(); @@ -33,6 +51,12 @@ public void testInvocationTimeoutEnvPropertyString() throws NamingException { Assert.assertEquals(100, EJBInvocationHandler.forProxy(proxy).getInvocationTimeout()); } + /** + * Test which validates that a long-valued invocation.timeout property set in the properties map for + * a JNDI context gets passed through to a proxy created from that JNDI context. + * + * @throws NamingException + */ @Test public void testInvocationTimeoutEnvPropertyLong() throws NamingException { FastHashtable env = new FastHashtable<>(); @@ -43,6 +67,11 @@ public void testInvocationTimeoutEnvPropertyLong() throws NamingException { Assert.assertEquals(100, EJBInvocationHandler.forProxy(proxy).getInvocationTimeout()); } + /** + * Test which validates that the default invocation.timeout property for a JNDI context is -1. + * + * @throws NamingException + */ @Test public void testInvocationTimeoutEnvPropertyEmpty() throws NamingException { FastHashtable env = new FastHashtable<>(); diff --git a/src/test/java/org/jboss/ejb/client/ProxyEqualityTestCase.java b/src/test/java/org/jboss/ejb/client/ProxyEqualityTestCase.java index 1d863d3e8..c083ad639 100644 --- a/src/test/java/org/jboss/ejb/client/ProxyEqualityTestCase.java +++ b/src/test/java/org/jboss/ejb/client/ProxyEqualityTestCase.java @@ -24,12 +24,20 @@ import org.junit.Test; /** + * Tests which validate the test for proxy equality works for proxies created by the EJB Client API. + * + * Proxy equality is based on module name, use of an EJBINvocationHandler and viewType. + * * @author Stuart Douglas */ public class ProxyEqualityTestCase { + /** + * A test for proxy equality, inequality and use of the correct invocation handler. + */ @Test public void testClientProxyEquality() { + // create a proxy with appName = a, moduleName = m, beanName = b and distinctName = d final StatelessEJBLocator locatorA = new StatelessEJBLocator(SimpleInterface.class, "a", "m", "b", "d"); SimpleInterface proxyA = EJBClient.createProxy(locatorA); @@ -39,11 +47,15 @@ public void testClientProxyEquality() { final StatelessEJBLocator locatorC = new StatelessEJBLocator(SimpleInterface.class, "a", "m", "b", "other"); SimpleInterface proxyC = EJBClient.createProxy(locatorC); + // validate proxy equality Assert.assertTrue(proxyA.equals(proxyB)); Assert.assertEquals(proxyA.hashCode(), proxyB.hashCode()); + + // valite proxy inequality Assert.assertFalse(proxyA.equals(proxyC)); Assert.assertTrue(proxyA.hashCode() != proxyC.hashCode()); + // validate the proxy was created from EJB Client API Assert.assertTrue(EJBClient.isEJBProxy(proxyA)); Assert.assertTrue(EJBClient.isEJBProxy(proxyB)); Assert.assertTrue(EJBClient.isEJBProxy(proxyC)); diff --git a/src/test/java/org/jboss/ejb/client/legacy/LegacyPropertiesConfigurationTestCase.java b/src/test/java/org/jboss/ejb/client/legacy/LegacyPropertiesConfigurationTestCase.java index 4d948c6d1..234f609ab 100644 --- a/src/test/java/org/jboss/ejb/client/legacy/LegacyPropertiesConfigurationTestCase.java +++ b/src/test/java/org/jboss/ejb/client/legacy/LegacyPropertiesConfigurationTestCase.java @@ -6,11 +6,27 @@ import java.io.IOException; +/** + * Tests to verify that configuration of the EJBClientContext by a legacy jboss-ejb-client.properties file works + * as expected. The jboss-ejb-client.properties file allows configuring invocation-related properties for the + * EJBClientContext at three different levels: + * - invocations targetting singleton nodes + * - invocations targetting clusters + * - invocations targetting specific nodes in clusters + * + * @author Thomas Hofman + */ public class LegacyPropertiesConfigurationTestCase { private static final String PROPERTIES_FILE_MAX_NODES_SET = "maximum-connected-nodes-jboss-ejb-client.properties"; private static final String PROPERTIES_FILE_MAX_NODES_NOT_SET = "clustered-jboss-ejb-client.properties"; + /** + * Tests that values configured for the cluster property "max-allowed-connected-nodes" are passed through + * to the resulting EJBClientContext. + * + * @throws IOException + */ @Test public void testMaximumConnectedNodesSet() throws IOException { JBossEJBProperties ejbProperties = JBossEJBProperties.fromClassPath(JBossEJBProperties.class.getClassLoader(), PROPERTIES_FILE_MAX_NODES_SET); @@ -21,6 +37,12 @@ public void testMaximumConnectedNodesSet() throws IOException { Assert.assertEquals(42, context.getMaximumConnectedClusterNodes()); } + /** + * Tests that default values configured for the cluster property "max-allowed-connected-nodes" are passed through + * to the resulting EJBClientContext when the property is not set. + * + * @throws IOException + */ @Test public void testMaximumConnectedNodesNotSet() throws IOException { JBossEJBProperties ejbProperties = JBossEJBProperties.fromClassPath(JBossEJBProperties.class.getClassLoader(), PROPERTIES_FILE_MAX_NODES_NOT_SET); diff --git a/src/test/java/org/jboss/ejb/client/remoting/MethodInvocationRequest.java b/src/test/java/org/jboss/ejb/client/remoting/MethodInvocationRequest.java index 12523fa77..468fe2c28 100644 --- a/src/test/java/org/jboss/ejb/client/remoting/MethodInvocationRequest.java +++ b/src/test/java/org/jboss/ejb/client/remoting/MethodInvocationRequest.java @@ -20,6 +20,8 @@ import java.util.Map; /** + * Test framework class representing a method invocation and its associated data. + * * @author Carlo de Wolf */ public class MethodInvocationRequest { diff --git a/src/test/java/org/jboss/ejb/client/serialization/ProxySerializationTestCase.java b/src/test/java/org/jboss/ejb/client/serialization/ProxySerializationTestCase.java index f130bc554..40d9f7fae 100644 --- a/src/test/java/org/jboss/ejb/client/serialization/ProxySerializationTestCase.java +++ b/src/test/java/org/jboss/ejb/client/serialization/ProxySerializationTestCase.java @@ -34,16 +34,27 @@ import org.junit.Test; /** - * Tests that an Enterprise Bean proxy can be serialized + * Tests that validate that an Enterprise Bean proxy can be serialized using JBoss Marshalling. * * @author Stuart Douglas */ public class ProxySerializationTestCase { + /** + * Tests that marshalling/unmarshalling an EJB proxy to and from a byte stream does not affect + * the validity of the proxy. + * + * @throws IOException + * @throws ClassNotFoundException + */ @Test public void testProxySerialization() throws IOException, ClassNotFoundException { + + // create a sample EJB client proxy final StatelessEJBLocator locator = new StatelessEJBLocator(SimpleInterface.class, "a", "m", "b", "d"); final Object proxy = EJBClient.createProxy(locator); + + // configure a JBoss Marshalling marshaller and marshall the proxy into a byte array, "bytes" final MarshallingConfiguration marshallingConfiguration = new MarshallingConfiguration(); marshallingConfiguration.setVersion(2); org.jboss.marshalling.MarshallerFactory factory = new RiverMarshallerFactory(); @@ -52,10 +63,14 @@ public void testProxySerialization() throws IOException, ClassNotFoundException marshaller.start(new OutputStreamByteOutput(bytes)); marshaller.writeObject(proxy); marshaller.finish(); + + // configure a JBoss Marshalling unmarshaller and unmarshal the byte array, "bytes", into an Object Unmarshaller unmarshaller = factory.createUnmarshaller(marshallingConfiguration); ByteArrayInputStream in = new ByteArrayInputStream(bytes.toByteArray()); unmarshaller.start(new InputStreamByteInput(in)); Object deserialized = unmarshaller.readObject(); + + // check for equality of the original proxy and the marshalled/unmarshalled proxy Assert.assertEquals(proxy, deserialized); } diff --git a/src/test/java/org/jboss/ejb/client/test/ClassCallback.java b/src/test/java/org/jboss/ejb/client/test/ClassCallback.java index d31b5e6a4..744707fda 100644 --- a/src/test/java/org/jboss/ejb/client/test/ClassCallback.java +++ b/src/test/java/org/jboss/ejb/client/test/ClassCallback.java @@ -1,5 +1,8 @@ package org.jboss.ejb.client.test; +/** + * A helper class to allow calling an arbitrary Runnable + */ public class ClassCallback { private static volatile Runnable beforeClassCallback; diff --git a/src/test/java/org/jboss/ejb/client/test/ClusterNodeSelectorTestCase.java b/src/test/java/org/jboss/ejb/client/test/ClusterNodeSelectorTestCase.java index 5cf0dffe6..b071ba93f 100644 --- a/src/test/java/org/jboss/ejb/client/test/ClusterNodeSelectorTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/ClusterNodeSelectorTestCase.java @@ -45,7 +45,8 @@ import org.junit.Test; /** - * Tests usage of ClusterNodeSelector + * Tests use of the ClusterNodeSelector to control the choice of target node for an invocation, when all invocations + * have a strong affinity to a cluster. * * @author Jason T. Greene * @author Richard Achmatowicz @@ -55,6 +56,9 @@ public class ClusterNodeSelectorTestCase extends AbstractEJBClientTestCase { private static final Logger logger = Logger.getLogger(ClusterNodeSelectorTestCase.class); private static final String PROPERTIES_FILE = "cluster-node-selector-jboss-ejb-client.properties"; + /* + * A cluster node selector which returns the pick node (if set) or the first connected node otherwise. + */ public static class TestSelector implements ClusterNodeSelector { private static volatile String PICK_NODE = null; @@ -67,9 +71,9 @@ public String selectNode(String clusterName, String[] connectedNodes, String[] t } } - /** - * Do any general setup here + * Configure the EJBClientContext to be aware of servers localhost:6999 and localhost:7099 as a cluster "ejb", + * as well as which ClusterNodeSelector to use. * @throws Exception */ @BeforeClass @@ -83,7 +87,7 @@ public static void beforeClass() throws Exception { } /** - * Do any test specific setup here + * Before each test, start the two servers as a cluster and deploy deploy stateless and stateful applicatuons on each. */ @Before public void beforeTest() throws Exception { @@ -103,6 +107,10 @@ public void beforeTest() throws Exception { defineCluster(1, CLUSTER); } + /** + * A convenince test to ensure that the EJBClientContext is setup correctly for this test. + * It expects two servers in a cluster called "ejb". + */ @Test public void testConfiguredConnections() { EJBClientContext context = EJBClientContext.getCurrent(); @@ -114,13 +122,19 @@ public void testConfiguredConnections() { } Collection clusters = context.getInitialConfiguredClusters(); + //Assert.assertEquals("Number of configured clusters is incorrect", 1, clusters.size()); for (EJBClientCluster cluster: clusters) { - logger.info("found cluster: name = " + cluster.getName()); + String name = cluster.getName(); + logger.info("found cluster: name = " + name); + //Assert.assertEquals("Cluster name should be ejb", "ejb", name); } } /** - * Test a basic invocation on clustered SLSB + * Test the operation of the ClusterNodeSelector with a SLSB deployment. + * + * This test uses the pick node to select the target node for the invocation and verifies that the invocation + * arrived at the correct node. */ @Test public void testClusteredSLSBInvocation() { @@ -136,11 +150,13 @@ public void testClusteredSLSBInvocation() { logger.info("Invoking on proxy..."); + // use the cluster node selector to always use node1 as the target node for the invocation TestSelector.PICK_NODE = NODE1_NAME; for (int i = 0; i < 10; i++) { Assert.assertEquals(NODE1_NAME, proxy.echo("someMsg").getNode()); } + // use the cluster node selector to always use node2 as the target node for the invocation TestSelector.PICK_NODE = NODE2_NAME; for (int i = 0; i < 10; i++) { Assert.assertEquals(NODE2_NAME, proxy.echo("someMsg").getNode()); @@ -148,18 +164,24 @@ public void testClusteredSLSBInvocation() { } /** - * Test a basic invocation on clustered SFSB + * Test the operation of the ClusterNodeSelector with a SLSB deployment. + * + * Creating a SFSB proxy for a clustered deployment has the side-effect of setting the weak affinity to the node + * the session was created on. So in the absence of failures, all invocations using that proxy should be directed + * to that node. This test validates that the ClusterNodeSelector can be used to control the target for + * session creation. */ @Test public void testClusteredSFSBInvocation() throws Exception { logger.info("Testing invocation on SFSB proxy with ClusterAffinity"); TestSelector.PICK_NODE = NODE2_NAME; - // create a proxy for invocation + // create a proxy for invocation and, using the ClusterNodeSelector, force session creation onto node2 final StatelessEJBLocator statelessEJBLocator = new StatelessEJBLocator(Echo.class, APP_NAME, MODULE_NAME, StatefulEchoBean.class.getSimpleName(), DISTINCT_NAME); StatefulEJBLocator statefulEJBLocator = null; statefulEJBLocator = EJBClient.createSession(statelessEJBLocator.withNewAffinity(new ClusterAffinity("ejb"))); + // verify that all invocations are sticky to node2 Echo proxy = EJBClient.createProxy(statefulEJBLocator); Assert.assertNotNull("Received a null proxy", proxy); for (int i = 0; i < 10; i++) { @@ -167,16 +189,18 @@ public void testClusteredSFSBInvocation() throws Exception { } TestSelector.PICK_NODE = NODE1_NAME; + // create a new proxy for invocation and using the ClusterNodeSelector, force session creation onto node1 statefulEJBLocator = EJBClient.createSession(statelessEJBLocator.withNewAffinity(new ClusterAffinity("ejb"))); proxy = EJBClient.createProxy(statefulEJBLocator); + // verify that all invocations are now sticky to node2 for (int i = 0; i < 10; i++) { Assert.assertEquals(NODE1_NAME, proxy.echo("someMsg").getNode()); } } /** - * Do any test-specific tear down here. + * After each test, undeploy the applications and stop the servers in the cluster. */ @After public void afterTest() { @@ -192,12 +216,4 @@ public void afterTest() { stopServer(0); stopServer(1); } - - /** - * Do any general tear down here. - */ - @AfterClass - public static void afterClass() { - } - } diff --git a/src/test/java/org/jboss/ejb/client/test/ClusteredInvocationFailOverTestCase.java b/src/test/java/org/jboss/ejb/client/test/ClusteredInvocationFailOverTestCase.java index dc415c2a5..de0d79725 100644 --- a/src/test/java/org/jboss/ejb/client/test/ClusteredInvocationFailOverTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/ClusteredInvocationFailOverTestCase.java @@ -58,6 +58,8 @@ * - topology update arrives which excludes A from available nodes * * @author Richard Achmatowicz + * + * @todo add test case for SFSB case */ public class ClusteredInvocationFailOverTestCase extends AbstractEJBClientTestCase { @@ -78,7 +80,9 @@ public class ClusteredInvocationFailOverTestCase extends AbstractEJBClientTestCa Map oneNodeUp = new HashMap(); /** - * Do any general setup here + * Initialize the EJBClientContext with configured connections to localhost:6999 and localhost:7099, and + * make available a thread pool for asynchronous task execution. + * * @throws Exception */ @BeforeClass @@ -91,7 +95,8 @@ public static void beforeClass() throws Exception { } /** - * Do any test specific setup here + * Before each test, start the servers, make them form a cluster called "ejb" and deploy the beans onto each + * node in the cluster. */ @Before public void beforeTest() throws Exception { @@ -107,7 +112,21 @@ public void beforeTest() throws Exception { /** - * Test a basic invocation on clustered SLSB + * Test invocations on a clustered SLSB + * + * The test is structured as follows: + * - a Callable is set up to act as client, making invocations and keeping statistics on the invocation contexts + * through use of the maps twoNodesUp and oneNodeUp to record invocations when one or two cluster nodes are + * available + * - the test case body then simulates the shutdown and subsquent startup of a server in the cluster + * - start with two nodesin the cluster active and sleep for 500ms to allow invoations to happen + * - shutdown node1 and sleep for 500 ms to allow invocations to happen + * - start node1 and then sleep for 500 ms to allow invocations to happen + * - stop the client Callable + * + * The expectation for the test validation: + * - there shoul be no failed invocations as one node is available at all times + * - the invocation targets should be split between node1 and node2 */ @Test public void testClusteredSLSBInvocation() throws Exception { @@ -186,7 +205,7 @@ public void testClusteredSLSBInvocation() throws Exception { // invoke Thread.sleep(500); - // start a server and update the topologuy of the new node and the remaining node + // start a server and update the topology of the new node and the remaining node logger.info("Starting server: " + serverNames[0]); startServer(0); deployStateless(0); @@ -198,18 +217,27 @@ public void testClusteredSLSBInvocation() throws Exception { Thread.sleep(500); runInvocations = false; + + // check that each Callable completed successfully for(Future i : retList) { - i.get(); + // i.get(); + Assert.assertEquals("ok", i.get()); } // check results + // two nodes map should have positive ccounts for node1 and node2 System.out.println("map twoNodesUp = " + twoNodesUp.toString()); - System.out.println("map oneNodeUp = " + oneNodeUp.toString()); + Assert.assertTrue(twoNodesUp.get("node1") != null && twoNodesUp.get("node1").get() > 0); + Assert.assertTrue(twoNodesUp.get("node2") != null && twoNodesUp.get("node2").get() > 0); + // one node map should have positive ccounts for node2 but not for node1 + System.out.println("map oneNodeUp = " + oneNodeUp.toString()); + Assert.assertTrue(oneNodeUp.get("node1") == null); + Assert.assertTrue(oneNodeUp.get("node2") != null && oneNodeUp.get("node2").get() > 0); } /** - * Do any test-specific tear down here. + * After each test, undeploy the applications, tear down the cluser and stop the servers. */ @After public void afterTest() throws Exception { diff --git a/src/test/java/org/jboss/ejb/client/test/ClusteredInvocationTestCase.java b/src/test/java/org/jboss/ejb/client/test/ClusteredInvocationTestCase.java index fee3db7a4..b68985e76 100644 --- a/src/test/java/org/jboss/ejb/client/test/ClusteredInvocationTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/ClusteredInvocationTestCase.java @@ -64,7 +64,9 @@ public class ClusteredInvocationTestCase extends AbstractEJBClientTestCase{ private static final String PROPERTIES_FILE = "clustered-jboss-ejb-client.properties"; /** - * Do any general setup here + * Initialize the EJBClientContext with configured connections to localhost:6999, localhost:7099 and + * localhost:7199 and a cluster called ejb + * * @throws Exception */ @BeforeClass @@ -78,7 +80,7 @@ public static void beforeClass() throws Exception { } /** - * Do any test specific setup here + * Before each test, start the servers, form the cluster and deploy the applications */ @Before public void beforeTest() throws Exception { @@ -431,7 +433,7 @@ public void testClusteredSLSBInvocationWithFailedNode() { } /** - * Do any test-specific tear down here. + * After each test, undeploy the applications and stop the servers. */ @After public void afterTest() { @@ -447,11 +449,4 @@ public void afterTest() { stopServer(i); } } - - /** - * Do any general tear down here. - */ - @AfterClass - public static void afterClass() { - } } diff --git a/src/test/java/org/jboss/ejb/client/test/DefaultConfigurationDiscoveryTestCase.java b/src/test/java/org/jboss/ejb/client/test/DefaultConfigurationDiscoveryTestCase.java index 111d8386e..50ed3340d 100644 --- a/src/test/java/org/jboss/ejb/client/test/DefaultConfigurationDiscoveryTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/DefaultConfigurationDiscoveryTestCase.java @@ -107,8 +107,7 @@ private void testDiscoveryTimeout(final Affinity affinity) throws Exception { } /** - * Creates the proxy to invoke the target ejb, and verifies that the - * invocation returns promptly (less than the maximum time). + * Creates the proxy to invoke the target ejb, and verifies that the invocation returns promptly (less than the maximum time). * @param locator ejb locator for creating proxy */ private static void verifyClient(EJBLocator locator) { diff --git a/src/test/java/org/jboss/ejb/client/test/DeploymentNodeSelectorTestCase.java b/src/test/java/org/jboss/ejb/client/test/DeploymentNodeSelectorTestCase.java index 2ab4c9cb9..627437f08 100644 --- a/src/test/java/org/jboss/ejb/client/test/DeploymentNodeSelectorTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/DeploymentNodeSelectorTestCase.java @@ -39,7 +39,8 @@ import org.wildfly.transaction.client.ContextTransactionSynchronizationRegistry; /** - * Tests DeploymentNodeSelector + * Tests the use of DeploymentNodeSelector to control the choice of target node for an invocation, when + * the target deployment is available on multiple nodes. * * @author Jason T. Greene * @author Richard Achmatowicz @@ -50,7 +51,9 @@ public class DeploymentNodeSelectorTestCase extends AbstractEJBClientTestCase { private static ContextTransactionSynchronizationRegistry txSyncRegistry; /** - * Do any general setup here + * Configure the EJBClientContext to be aware of servers localhost:6999 and localhost:7099 as well as + * which DeploymentNodeSelector to use. + * * @throws Exception */ @BeforeClass @@ -66,19 +69,23 @@ public static void beforeClass() throws Exception { } /** - * Do any test specific setup here + * Before each test, start the two servers at localhost:6999 and localhost:7099 and deploy deploy stateless + * and stateful applicatuons on each. */ @Before public void beforeTest() throws Exception { for (int i = 0; i < 2; i++) { // start a server - startServer(i, 6999 + (i*100), true); + startServer(i, 6999 + (i * 100), true); deployStateful(i); deployStateless(i); } } + /* + * A deployment node selector which returns the pick node (if set) or the first connected node otherwise. + */ public static class TestSelector implements DeploymentNodeSelector { private static volatile String PICK_NODE = null; @@ -91,54 +98,71 @@ public String selectNode(String[] eligibleNodes, String appName, String moduleNa } } + /** + * Test the operation of the DeploymentNodeSelector with a SLSB deployment. + * + * This test uses the pick node to select the target node for the invocation and verifies that the invocation + * arrived at the correct node. + * + * In this case, as the SLSB is deployed on both nodes, and not stateful, we can use a different pick node + * with the same proxy instance, and invocations will be correctly directed. + */ + @Test + public void testSLSBInvocation() { + // create a proxy for invocation + final StatelessEJBLocator statelessEJBLocator = new StatelessEJBLocator(Echo.class, APP_NAME, MODULE_NAME, StatelessEchoBean.class.getSimpleName(), DISTINCT_NAME); + final Echo proxy = EJBClient.createProxy(statelessEJBLocator); + + Assert.assertNotNull("Received a null proxy", proxy); + logger.info("Created proxy for Echo: " + proxy.toString()); + + logger.info("Invoking on proxy..."); + + TestSelector.PICK_NODE = SERVER1_NAME; + for (int i = 0; i < 10; i++) { + Assert.assertEquals(SERVER1_NAME, proxy.echo("someMsg").getNode()); + } + + TestSelector.PICK_NODE = SERVER2_NAME; + for (int i = 0; i < 10; i++) { + Assert.assertEquals(SERVER2_NAME, proxy.echo("someMsg").getNode()); + } + } + + /** + * Test the operation of the DeploymentNodeSelector with a SFSB deployment. + * + * This test uses the pick node to select the target node for the invocation and verifies that the invocation + * arrived at the correct node. + * + * In this case, as the SFSB is deployed on both nodes and stateful, each proxy will have affinity to the node + * where its session was created, and cannot be redirected to another node without invocation failure (no more + * destiations available). + */ @Test - public void testSLSBInvocation() { - // create a proxy for invocation - final StatelessEJBLocator statelessEJBLocator = new StatelessEJBLocator(Echo.class, APP_NAME, MODULE_NAME, StatelessEchoBean.class.getSimpleName(), DISTINCT_NAME); - final Echo proxy = EJBClient.createProxy(statelessEJBLocator); - - Assert.assertNotNull("Received a null proxy", proxy); - logger.info("Created proxy for Echo: " + proxy.toString()); - - logger.info("Invoking on proxy..."); - - TestSelector.PICK_NODE = SERVER1_NAME; - for (int i = 0; i < 10; i++) { - Assert.assertEquals(SERVER1_NAME, proxy.echo("someMsg").getNode()); - } - - TestSelector.PICK_NODE = SERVER2_NAME; - for (int i = 0; i < 10; i++) { - Assert.assertEquals(SERVER2_NAME, proxy.echo("someMsg").getNode()); - } - } - - /** - * Test a basic invocation on clustered SFSB - */ - @Test - public void testSFSBInvocation() throws Exception { - TestSelector.PICK_NODE = SERVER2_NAME; - // create a proxy for invocation - final StatelessEJBLocator statelessEJBLocator = new StatelessEJBLocator(Echo.class, APP_NAME, MODULE_NAME, StatefulEchoBean.class.getSimpleName(), DISTINCT_NAME); - StatefulEJBLocator statefulEJBLocator = null; - statefulEJBLocator = EJBClient.createSession(statelessEJBLocator); - - Echo proxy = EJBClient.createProxy(statefulEJBLocator); - Assert.assertNotNull("Received a null proxy", proxy); - for (int i = 0; i < 10; i++) { - Assert.assertEquals(SERVER2_NAME, proxy.echo("someMsg").getNode()); - } - - TestSelector.PICK_NODE = SERVER1_NAME; - statefulEJBLocator = EJBClient.createSession(statelessEJBLocator); - proxy = EJBClient.createProxy(statefulEJBLocator); - for (int i = 0; i < 10; i++) { - Assert.assertEquals(SERVER1_NAME, proxy.echo("someMsg").getNode()); - } - } + public void testSFSBInvocation() throws Exception { + TestSelector.PICK_NODE = SERVER2_NAME; + // create a proxy for invocation + final StatelessEJBLocator statelessEJBLocator = new StatelessEJBLocator(Echo.class, APP_NAME, MODULE_NAME, StatefulEchoBean.class.getSimpleName(), DISTINCT_NAME); + StatefulEJBLocator statefulEJBLocator = null; + statefulEJBLocator = EJBClient.createSession(statelessEJBLocator); + + Echo proxy = EJBClient.createProxy(statefulEJBLocator); + Assert.assertNotNull("Received a null proxy", proxy); + for (int i = 0; i < 10; i++) { + Assert.assertEquals(SERVER2_NAME, proxy.echo("someMsg").getNode()); + } + + TestSelector.PICK_NODE = SERVER1_NAME; + statefulEJBLocator = EJBClient.createSession(statelessEJBLocator); + proxy = EJBClient.createProxy(statefulEJBLocator); + for (int i = 0; i < 10; i++) { + Assert.assertEquals(SERVER1_NAME, proxy.echo("someMsg").getNode()); + } + } + /** - * Do any test-specific tear down here. + * After each test, undeploy the applications and stop the servers. */ @After public void afterTest() { @@ -150,12 +174,4 @@ public void afterTest() { stopServer(i); } } - - /** - * Do any general tear down here. - */ - @AfterClass - public static void afterClass() { - } - } diff --git a/src/test/java/org/jboss/ejb/client/test/InterruptRunningCallTestCase.java b/src/test/java/org/jboss/ejb/client/test/InterruptRunningCallTestCase.java index b1fe5678c..adbf9e902 100644 --- a/src/test/java/org/jboss/ejb/client/test/InterruptRunningCallTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/InterruptRunningCallTestCase.java @@ -23,7 +23,14 @@ import org.wildfly.naming.client.WildFlyRootContext; import org.wildfly.naming.client.util.FastHashtable; - +/** + * Test case to valiate that if long running tasks are interrupted, they clean up the MessageOutputStream + * (represented by OutboundMessage.accept()) upon cancellation. + * + * @todo this test case needs more explanation as to what is being tested and why (see EJBCLIENT-396) + * + * @author unknown + */ public class InterruptRunningCallTestCase extends AbstractEJBClientTestCase { private static final Logger logger = Logger.getLogger(InterruptRunningCallTestCase.class); @@ -54,6 +61,10 @@ public void testInterruptingLongRunningRequests() throws Exception ExecutorService executorService = Executors.newFixedThreadPool(1); Future future = null; + // perform a lopp of ten iterations where the loop: + // - cancels any currently pending task, represented by a Future, even if it is still running + // - execute a callable, using a latch for synchonozation, and block for 5 seconds to give the task time to complete + // - sleep before repeating the loop for (int i = 0; i < 10; i++) { if (future != null) { @@ -67,13 +78,22 @@ public void testInterruptingLongRunningRequests() throws Exception Thread.sleep(10); } + // get the result produced by the last iteration future.get(); + // verify that no threads are waiting on OutboundMessage.accept() Map stackTraces = Thread.getAllStackTraces(); long stackedThreads = countThreadsStackedInOutboundMessageAccept(stackTraces); Assert.assertEquals("Threads are stacked in OutboundMessage$1.accept", 0, stackedThreads); } + /** + * Method which takes as input a map of threads to arrays of stack traces, and returs the count of threads + * which are blocked in OutboundMessage.accept + * + * @param stackTraces the map of threads to arrays of stack traces + * @return + */ private long countThreadsStackedInOutboundMessageAccept(Map stackTraces) { return stackTraces.entrySet().stream() .filter(e -> e.getKey().getName().startsWith("Remoting \"test-server\" task-")) @@ -83,6 +103,17 @@ private long countThreadsStackedInOutboundMessageAccept(Map echoCallable(WildFlyRootContext context, CountDownLatch latch) { return () -> { Echo echo = (Echo) lookupBean(context); diff --git a/src/test/java/org/jboss/ejb/client/test/JBossEJBPropertiesTestCase.java b/src/test/java/org/jboss/ejb/client/test/JBossEJBPropertiesTestCase.java index 9900de7d7..011d41e28 100644 --- a/src/test/java/org/jboss/ejb/client/test/JBossEJBPropertiesTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/JBossEJBPropertiesTestCase.java @@ -38,7 +38,8 @@ import java.util.Map; /** - * Tests basic function of JBossEJBProperties class. + * Tests basic function of JBossEJBProperties class, whch involves reading a jboss-ejb-client.properties file + * on the classpath and populating the fields of the JBossEJBClientProperties instance. * * Reads in a legacy configuration file with all possible options specified. * Some variation in how passwords are supplied. @@ -51,23 +52,11 @@ public class JBossEJBPropertiesTestCase { private static final String PROPERTIES_FILE = "complete-jboss-ejb-client.properties"; /** - * Do any general setup here - * @throws Exception - */ - @BeforeClass - public static void beforeClass() throws Exception { - } - - /** - * Do any test specific setup here - */ - @Before - public void beforeTest() throws Exception { - - } - - /** - * Test some basic stuff. + * Test which validates the translation from jboss-ejb-client.properties file to the JBossEJBProperties + * instance created from that file. The test covers all properties that may be defined, including: + * - defined connections and their options + * - defined clusters and their options + * - defined nodes within clusters and their options */ @Test public void testLegacyProperties() throws Exception { @@ -76,7 +65,6 @@ public void testLegacyProperties() throws Exception { testLegacyPropertiesFunctionality(ejbProperties); } - private void testLegacyPropertiesFunctionality(JBossEJBProperties properties) { logger.info("Testing JBossEJBProperties functionality"); @@ -232,21 +220,6 @@ private void checkAuthConfiguration(String componentName, AuthenticationConfigur Assert.assertEquals("Bad " + componentName + " realm value", realm, authConfig.getMechanismRealm()); } - - /** - * Do any test-specific tear down here. - */ - @After - public void afterTest() { - } - - /** - * Do any general tear down here. - */ - @AfterClass - public static void afterClass() { - } - public static void main(String[] args) throws Exception { JBossEJBPropertiesTestCase props = new JBossEJBPropertiesTestCase(); props.testLegacyProperties(); diff --git a/src/test/java/org/jboss/ejb/client/test/LearningTestCase.java b/src/test/java/org/jboss/ejb/client/test/LearningTestCase.java index d864cde66..fe134d890 100644 --- a/src/test/java/org/jboss/ejb/client/test/LearningTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/LearningTestCase.java @@ -41,13 +41,16 @@ /** - * Tests support for a feature where proxies constructed from the same JNDI initial context share default values for strong affinity. + * Tests support for a feature where proxies constructed from the same JNDI initial context share iniial values for strong affinity. * * @author Jason T. Greene */ public class LearningTestCase extends AbstractEJBClientTestCase { private static final Logger logger = Logger.getLogger(LearningTestCase.class); + /* + * Before each test, start a singleton server and deploy two stateful applications. + */ @Before public void beforeTest() throws Exception { // start a server @@ -58,6 +61,9 @@ public void beforeTest() throws Exception { deployCustomBean(0, APP_NAME, MODULE_NAME, DISTINCT_NAME, FooBean.class.getSimpleName(), new FooBean()); } + /* + * After each test, undeploy the stateful applications and shutdown the server. + */ @After public void afterTest() { undeployStateful(0); @@ -65,19 +71,46 @@ public void afterTest() { stopServer(0); } + /** + * A helper method for strong affinity validation of created proxies, which does the following: + * + * - create a JNDI context using the properties specified for initializing the context + * - using the JNDI context, create a first proxy and validate its expected strong affinity; because the bean + * is stateful, this will result in an interaction with the server which will update the weak affinity + * - set the strong affinity of the first proxy to cluster affinity and make an invocation + * - using the JNDI context, create a second proxy and validate its expected strong affinity + * + * @param props the properties used to initialize the JNDI conext + * @param match1 the expected strong affinty value of the first proxy created from the JNDI context + * @param match2 the expected strong affinity of the second proxy created from the JNDI context + * @throws NamingException + */ private void verifyAffinity(FastHashtable props, Affinity match1, Affinity match2) throws NamingException { + // initialize the JNDI context WildFlyRootContext context = new WildFlyRootContext(props); + // create a stateful proxy using JNDI lookup, which results in an interaction with the server, possibly updating the weak affinity Object echo = context.lookup("ejb:" + APP_NAME + "/" + MODULE_NAME + "/" + StatefulEchoBean.class.getSimpleName() + "!" + Echo.class.getName() + "?stateful"); Assert.assertEquals(match1, EJBClient.getStrongAffinity(echo)); + // reset the strong affinity of the proxy and make an invocation EJBClient.setStrongAffinity(echo, new ClusterAffinity("test")); ((Echo)echo).echo("test"); + // create a second stateful proxy using JNDI lookup, which results in an interaction with the server, possibly updating the weak affinity Object foo = context.lookup("ejb:" + APP_NAME + "/" + MODULE_NAME + "/" + FooBean.class.getSimpleName() + "!" + Foo.class.getName() + "?stateful"); Assert.assertEquals(match2, EJBClient.getStrongAffinity(foo)); } + /** + * A helper method for strong affinity validation of created proxies, which uses an existing JNDI context for + * proxy creation. + * + * @param context the JNDI context used to create the proxies + * @param match1 the expected strong affinty value of the first proxy created from the JNDI context + * @param match2 the expected strong affinity of the second proxy created from the JNDI context + * @throws NamingException + */ private void verifyAffinity(WildFlyRootContext context, Affinity match1, Affinity match2) throws NamingException { Object echo = context.lookup("ejb:" + APP_NAME + "/" + MODULE_NAME + "/" + StatefulEchoBean.class.getSimpleName() + "!" + Echo.class.getName() + "?stateful"); Assert.assertEquals(match1, EJBClient.getStrongAffinity(echo)); @@ -89,7 +122,14 @@ private void verifyAffinity(WildFlyRootContext context, Affinity match1, Affinit Assert.assertEquals(match2, EJBClient.getStrongAffinity(foo)); } - + /** + * Verify, using a shared JNDI context, that the created proxies have the following strong affinity values: + * - the first proxy has an initial strong affinity of type URIAffinity, based on its JNDI context PROVIDER_URL + * - the second proxy has an initial strong affinity of type ClusterAffinity, "learned" from the shared + * JNDI context and the activity of the first proxy + * + * @throws Exception + */ @Test public void testLearning() throws Exception { FastHashtable props = new FastHashtable<>(); @@ -100,6 +140,15 @@ public void testLearning() throws Exception { verifyAffinity(props, serverURIAffinity, new ClusterAffinity("test")); } + /** + * Verify, using a shared JNDI context with learning disabled, that the created proxies have the following + * strong affinity values: + * - the first proxy has an initial strong affinity of type URIAffinity, based on its JNDI context PROVIDER_URL + * - the second proxy has an initial strong affinity of type URIAffinity, based on its JNDI context PROVIDER_URL + * as learning has been disabled + * + * @throws Exception + */ @Test public void testDisabledLearning() throws Exception { FastHashtable props = new FastHashtable<>(); @@ -111,6 +160,14 @@ public void testDisabledLearning() throws Exception { verifyAffinity(props, serverURIAffinity, new URIAffinity(new URI("remote://localhost:6999"))); } + /** + * Verify, using a shared JNDI context, that the created proxies have the following strong affinity values: + * - the first proxy has an initial strong affinity of type ClusterAffinity, based on the use of the property + * jboss.cluster-affinity to set the default value of strong affinity for the JNDI context + * - the second proxy has an initial strong affinity of type ClusterAffinity, based on learning + * + * @throws Exception + */ @Test public void testExplicitlyDefined() throws Exception { FastHashtable props = new FastHashtable<>(); @@ -122,6 +179,10 @@ public void testExplicitlyDefined() throws Exception { verifyAffinity(props, bob, bob); } + /** + * THis test does not seem correct! + * @throws Exception + */ @Test public void testNoInterference() throws Exception { FastHashtable props = new FastHashtable<>(); diff --git a/src/test/java/org/jboss/ejb/client/test/ManualTestRunner.java b/src/test/java/org/jboss/ejb/client/test/ManualTestRunner.java index f9e94f840..15da6f8f4 100644 --- a/src/test/java/org/jboss/ejb/client/test/ManualTestRunner.java +++ b/src/test/java/org/jboss/ejb/client/test/ManualTestRunner.java @@ -27,8 +27,21 @@ import org.junit.runner.Result; import org.junit.runner.notification.Failure; -// Manually launches Enterprise Bean tests (e.g. for Xbootclasspath testing) +/** + * A test class for manually running a subset of Enterprise Bean tests (e.g. for Xbootclasspath testing) + * + * @author Jason T. Greene + */ + public class ManualTestRunner { + + /** + * Run a subset of tests, making use of ClassCallback to reload the EJBClientContext if the test calls + * ClassCallback.beforeClassCallback() in is test setup. + * + * @param args the name to use for identifying the testsuite run + * @throws Exception + */ public static void main(String[] args) throws Exception { String summary = args.length > 0 ? args[0] : null; if (summary == null || summary.length() == 0) { @@ -38,13 +51,17 @@ public static void main(String[] args) throws Exception { System.out.printf(" %s \n", summary); System.out.println("==========================="); + // reload the configuration of the EJBClientContext ClassCallback.setBeforeClassCallback(ManualTestRunner::reloadConfiguration); + // Run a subset of the test classes in the testsuite Result result = JUnitCore.runClasses(JBossEJBPropertiesTestCase.class, ClusteredInvocationTestCase.class, SimpleInvocationTestCase.class, ProxySerializationTestCase.class, WildflyClientXMLTestCase.class); - System.out.println("Failed: " + result.getFailureCount() + " Ignored: " + result.getIgnoreCount() + - " Succeeded: " + (result.getRunCount() - result.getFailureCount() - result.getIgnoreCount())); - for (Failure failure: result.getFailures()) { + // report the results of the test run + System.out.println("Failed: " + result.getFailureCount() + + " Ignored: " + result.getIgnoreCount() + + " Succeeded: " + (result.getRunCount() - result.getFailureCount() - result.getIgnoreCount())); + for (Failure failure : result.getFailures()) { System.out.println(failure.getDescription()); System.out.println(failure.getTrace()); } @@ -52,7 +69,10 @@ public static void main(String[] args) throws Exception { System.exit(result.wasSuccessful() ? 0 : 1); } - private static void reloadConfiguration() { + /** + * Call the method ConfigurationBasedEJBClientContextSelector.loadConfiguration() to reload the properties + */ + private static void reloadConfiguration() { try { // Force reconfiguration so that one test class doesn't pollute the other // (since we are running them all in one JVM) @@ -60,6 +80,9 @@ private static void reloadConfiguration() { Method init = clazz.getDeclaredMethod("loadConfiguration"); init.setAccessible(true); Object o = init.invoke(null); + + System.out.println("Executing class callback!"); + Field field = clazz.getDeclaredField("configuredContext"); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); @@ -70,6 +93,6 @@ private static void reloadConfiguration() { } catch (Exception e) { throw new RuntimeException(e); } - } + } } diff --git a/src/test/java/org/jboss/ejb/client/test/NetworkBlackHoleInvocationTestCase.java b/src/test/java/org/jboss/ejb/client/test/NetworkBlackHoleInvocationTestCase.java index fa5908a7d..93adedc58 100644 --- a/src/test/java/org/jboss/ejb/client/test/NetworkBlackHoleInvocationTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/NetworkBlackHoleInvocationTestCase.java @@ -134,8 +134,7 @@ private void testDiscoveryTimeout(final Affinity affinity) throws Exception { } /** - * Creates the proxy to invoke the target ejb, and verifies that the - * invocation returns promptly (less than the maximum time). + * Creates the proxy to invoke the target ejb, and verifies that the invocation returns promptly (less than the maximum time). * @param locator ejb locator for creating proxy */ private static void verifyClient(EJBLocator locator) { diff --git a/src/test/java/org/jboss/ejb/client/test/RemoteDiscoveryTimeoutTestCase.java b/src/test/java/org/jboss/ejb/client/test/RemoteDiscoveryTimeoutTestCase.java index 745420fe2..b24e3caf8 100644 --- a/src/test/java/org/jboss/ejb/client/test/RemoteDiscoveryTimeoutTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/RemoteDiscoveryTimeoutTestCase.java @@ -34,6 +34,17 @@ import org.junit.Test; /** + * Tests which validate the timeout mechanism(s) used in discovery. + * + * A call to discovery is made up of two independent activities: an activity which generates discovery results, + * amd an activity which consumes discovery results. Under normal circumstances, discovery result generation + * terminates, but this is not always the case. + * + * The system property org.jboss.ejb.client.discovery.timeout is a property which can set a timeout value for + * discovery result consumption: if we have not consumed all results before the expiration of the timeout, + * discovery result consumption is terminated, and returns the (possibly incomplete) set of already consumed + * results. + * * @author Ingo Weiss */ public class RemoteDiscoveryTimeoutTestCase extends AbstractEJBClientTestCase { @@ -41,7 +52,10 @@ public class RemoteDiscoveryTimeoutTestCase extends AbstractEJBClientTestCase { private static final String PROPERTIES_FILE = "no-protocol-jboss-ejb-client.properties"; /** - * Do any general setup here + * Initialize the legacy JBossEJBProperties contextual with a jboss-ejb-client.properties file which has one + * remote destination with a missing protocol; this will result in the client not being able to connect to + * the server during discovery. + * * @throws Exception */ @BeforeClass @@ -52,7 +66,7 @@ public static void beforeClass() throws Exception { } /** - * Do any test specific setup here + * Before each test, start a server at localhost:6999 and deploy a stateless bean. */ @Before public void beforeTest() throws Exception { @@ -63,7 +77,7 @@ public void beforeTest() throws Exception { } /** - * Do any test-specific tear down here. + * After each test, undeploy the staless bean and stop the server. */ @After public void afterTest() { @@ -74,7 +88,9 @@ public void afterTest() { } /** - * Test a failed client discovery + * Test a failed client discovery attempt, using the discovery timeout to avoid the test hanging. + * + * @todo need to consider exceptions and connect timeouts and avoid sitiations where processes can hang */ @Test public void testClientDiscoveryTimeout() throws InterruptedException { diff --git a/src/test/java/org/jboss/ejb/client/test/SimpleInvocationTestCase.java b/src/test/java/org/jboss/ejb/client/test/SimpleInvocationTestCase.java index 3378b69a9..ff8a32717 100644 --- a/src/test/java/org/jboss/ejb/client/test/SimpleInvocationTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/SimpleInvocationTestCase.java @@ -54,7 +54,8 @@ public class SimpleInvocationTestCase extends AbstractEJBClientTestCase { private static final String PROPERTIES_FILE = "jboss-ejb-client.properties"; /** - * Do any general setup here + * Configure the EJBClientContext with two servers localhost:6999, localhost:7099 + * * @throws Exception on errors */ @BeforeClass @@ -71,7 +72,7 @@ public static void beforeClass() throws Exception { } /** - * Do any test specific setup here + * Before each test, starts the servers and deploy the beans */ @Before public void beforeTest() throws Exception { @@ -454,7 +455,7 @@ public void testSLSBInvocationWithFailedNode() { } /** - * Do any test-specific tear down here. + * After each test, undeploy the beans and stop the servers */ @After public void afterTest() { diff --git a/src/test/java/org/jboss/ejb/client/test/TransactionTestCase.java b/src/test/java/org/jboss/ejb/client/test/TransactionTestCase.java index 035bc8f8f..e333ba78e 100644 --- a/src/test/java/org/jboss/ejb/client/test/TransactionTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/TransactionTestCase.java @@ -55,7 +55,13 @@ import org.wildfly.transaction.client.provider.jboss.JBossLocalTransactionProvider; /** - * Tests transaction stickiness + * Tests transaction stickiness for transaction-scoped invocations. + *

+ * NOTE: Transaction stickiness requirements vary based on three factors: + * - whether the bean being invoked upon is stateless or stateful + * - whether the client making the invocation is local (using a LocalTransaction) or remote (using a RemoteTransaction) + * - any ClientTransaction annotation describing the client-side transaction policy on the client-side interface + * (the default policy is ClientSideTransactionPolicy.SUPPORTS which supports transaction context propagation) * * @author Jason T. Greene * @author Richard Achmatowicz @@ -66,7 +72,13 @@ public class TransactionTestCase extends AbstractEJBClientTestCase { private static ContextTransactionSynchronizationRegistry txSyncRegistry; /** - * Do any general setup here + * Setup a local JTA transaction environment for use with any tests in this class. + * The key elements of a local transaction context for the EJB client are: + * - JBossLocalTransactionProvider, which represents an underlying Narayana TransactionManager instance and + * XATerminator instance + * - LocalTransactionContext contextual, which makes the LocalTransactionProvider available to the EJB client + * application itself + * * @throws Exception */ @BeforeClass @@ -78,7 +90,6 @@ public static void beforeClass() throws Exception { BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "stateStore") .setObjectStoreDir("target/tx-object-store"); - final JTAEnvironmentBean jtaEnvironmentBean = jtaPropertyManager.getJTAEnvironmentBean(); jtaEnvironmentBean.setTransactionManagerClassName(TransactionManagerImple.class.getName()); jtaEnvironmentBean.setTransactionSynchronizationRegistryClassName(TransactionSynchronizationRegistryImple.class.getName()); @@ -104,7 +115,15 @@ public void removeXAResourceRecovery(XAResourceRecovery xaResourceRecovery) { } /** - * Do any test specific setup here + * Before each test, start four mock server instances and deploy specific combinations of stateful and stateless + * beans used in the tests. The final arrangement of nodes and beans is as follows: + * + * node1: SFSB, SLSB + * node2: OSFSB, OSLSB + * node3: SFSB, SLSB, OSFSB, OSLSB + * node4: SFSB, SLSB, OSFSB, OSLSB + * + * where OSFSL/OSLSB refers to the OtherStateful and OtherStateless beans. */ @Before public void beforeTest() throws Exception { @@ -130,47 +149,108 @@ public void beforeTest() throws Exception { deployOtherStateless(3); } + /** + * Validates transaction stickiness in the case of invocations on stateless beans by a local client (i.e. a client + * application deployed on a server). + * + * @throws Exception + */ @Test public void testTransactionStickiness() throws Exception { verifyStickiness(false, false); } + /** + * Validates transaction stickiness in the case of invocations on stateless beans by a remote client (i.e. a client + * application not deployed on a server). + * + * @throws Exception + */ @Test public void testRemoteTransactionStickiness() throws Exception { verifyStickiness(false, true); } + /** + * Validates transaction stickiness in the case of invocations on stateful beans by a remote client (i.e. a client + * application not deployed on a server). + * + * @throws Exception + */ @Test public void testRemoteStatefulTransactionStickiness() throws Exception { verifyStickiness(true, true); } + /** + * Validates transaction stickiness in the case of invocations on stateful beans by a local client (i.e. a client + * application deployed on a server). + * + * @throws Exception + */ @Test public void testStatefulTransactionStickiness() throws Exception { verifyStickiness(true, false); } + /** + * Validates transaction stickiness in the case of invocations on stateless beans by a local client (i.e. a client + * application deployed on a server) where transaction contexts are not propagated. + *

+ * i.e. the method echoNonTx is annotated with @ClientTransaction(ClientTransactionPolicy.NOT_SUPPORTED) to + * supress transaction context propagation + *

+ * Expected behavior is that such stateless invocations are not sticky to a particular node. + * + * @throws Exception + */ @Test public void testNonPropagatingInvocation() throws Exception { verifyNonTxBehavior(false, false); } - @Test + /** + * Validates transaction stickiness in the case of invocations on stateful beans by a local client (i.e. a client + * application deployed on a server) where transaction contexts are not propagated. + *

+ * i.e. the method echoNonTx is annotated with @ClientTransaction(ClientTransactionPolicy.NOT_SUPPORTED) to + * supress transaction context propagation + *

+ * Expected behavior is that such stateful invocations are sticky to a particular node due to the session + * stickiness of the SFSB. + * + * @throws Exception + */ + @Test public void testStatefulNonPropagatingInvocation() throws Exception { - // Session open is sticky, resulting in a weak affinity and therefore - // stickiness even with non-propagating method calls. + // Session open is sticky, resulting in a weak affinity and therefore stickiness even with + // non-propagating method calls. verifyNonTxBehavior(true, true); } + /** + * A method which returns a UserTransaction, configuted for use with a remote application client or + * from a deployment on a server. + * + * @param remote if true, returns a RemoteUserTransaction; otherwise, returns a LocalUserTransaction + * @return the UserTransaction instance + */ private UserTransaction getTransaction(boolean remote) { if (remote) { return RemoteTransactionContext.getInstance().getUserTransaction(); } else { return LocalUserTransaction.getInstance(); } - } + /** + * Verifies the stickiness properties of invocations scoped by transactions, which constrain which nodes + * may be targetted by such invocations. + * + * @param stateful if true, assumes beans under test are stateful; assumes stateless otherwise + * @param remote if true, assumes client application is remote; assumes application is local otherwise + * @throws Exception + */ private void verifyStickiness(boolean stateful, boolean remote) throws Exception { UserTransaction transaction = getTransaction(remote); FastHashtable props = new FastHashtable<>(); @@ -220,6 +300,17 @@ private void verifyStickiness(boolean stateful, boolean remote) throws Exception Assert.assertEquals(Stream.of("node1", "node3", "node4").collect(Collectors.toSet()), ids); } + /** + * Verifies the stickiness properties of invocations scoped by transactions, which constrain which nodes + * may be targetted by such invocations. + * + * i.e. the method echoNonTx is annotated with @ClientTransaction(ClientTransactionPolicy.NOT_SUPPORTED) to + * supress transaction context propagation + * + * @param stateful if true, assumes beans under test are stateful; assumes stateless otherwise + * @param sticky if true, indicates that session stickiness will be present for invocations + * @throws Exception + */ private void verifyNonTxBehavior(boolean stateful, boolean sticky) throws Exception { FastHashtable props = new FastHashtable<>(); @@ -270,9 +361,15 @@ private void verifyNonTxBehavior(boolean stateful, boolean sticky) throws Except } + /** + * + * @throws Exception + */ @Test public void testTransactionPreference() throws Exception { FastHashtable props = new FastHashtable<>(); + + // this context is not used .. props.put("java.naming.provider.url", "remote://localhost:7199"); props.put("java.naming.factory.initial", WildFlyInitialContextFactory.class.getName()); WildFlyRootContext context2 = new WildFlyRootContext(props); @@ -284,8 +381,11 @@ public void testTransactionPreference() throws Exception { HashSet id1s = new HashSet<>(); HashSet id2s = new HashSet<>(); + for (int attempts = 0; attempts < 80; attempts++) { txManager.begin(); + + // invoke on APP_NAME deployments on node1, node3 and node4 HashMap replies = new HashMap<>(); String id1 = null; for (int i = 0; i < 20; i++) { @@ -301,6 +401,7 @@ public void testTransactionPreference() throws Exception { Assert.assertEquals(20, replies.values().iterator().next().intValue()); id1s.add(id1); + // invoke on OTHER_APP deployments on node2, node3 and node4 replies.clear(); String id2 = null; for (int i = 0; i < 20; i++) { @@ -315,6 +416,9 @@ public void testTransactionPreference() throws Exception { Assert.assertEquals(1, replies.size()); Assert.assertEquals(20, replies.values().iterator().next().intValue()); + // 1. if invocations on APP_NAME land on node1, invocations on OTHER_APP must land on another node + // due to the way the deployments are distributed on servers + // 2. otherwise, invocations on both apps should land on the same nodes, due to ...??? System.out.println(id1 + ":" + id2); if (id1.equals("node1")) { Assert.assertTrue(Stream.of("node2", "node3", "node4").collect(Collectors.toSet()).contains(id2)); @@ -332,7 +436,7 @@ public void testTransactionPreference() throws Exception { } /** - * Do any test-specific tear down here. + * After each test, undeploy the beans and stop the mock servers. */ @After public void afterTest() { @@ -355,12 +459,4 @@ public void afterTest() { stopServer(i); } } - - /** - * Do any general tear down here. - */ - @AfterClass - public static void afterClass() { - } - } diff --git a/src/test/java/org/jboss/ejb/client/test/UnmarshallingFilterTestCase.java b/src/test/java/org/jboss/ejb/client/test/UnmarshallingFilterTestCase.java index d3077fe02..ff22123b5 100644 --- a/src/test/java/org/jboss/ejb/client/test/UnmarshallingFilterTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/UnmarshallingFilterTestCase.java @@ -38,12 +38,22 @@ import org.junit.Test; /** - * Tests server-sdie filtering of classes before unmarshalling. + * Tests server-side filtering of classes before unmarshalling. + * + * A class resolver filter is a Function which allows defining a mapping of class names to the + * boolean values true or false and is used to control which invocation paramaters may be unmarshalled by the server. + * + * The class resolver filter is a parameter to the RemoteEJBService, used to initialize the server-side handing + * of incoming EJB client requests. If the class resolver filter is null, no filtering is performed. Otherwise, + * filtering is performed based on parameter class names and the boolean value returned by the class resolver filter. + * + * The DummyServer used in these test cases has a class resolver filter which rejects unmarshalling of the + * IllegalArgumentException class only. * * @author Brian Stansberry */ public class UnmarshallingFilterTestCase extends AbstractEJBClientTestCase { - private static final Logger logger = Logger.getLogger(LearningTestCase.class); + private static final Logger logger = Logger.getLogger(UnmarshallingFilterTestCase.class); @Before public void beforeTest() throws Exception { @@ -59,7 +69,8 @@ public void afterTest() { } /** - * Test a basic invocation + * Test the operation of the class resolver filter with an invocation whose paraeter type should be filtered, + * as well as with an invocation whose parameter type shpuld not be filtered. */ @Test public void testUnmarshallingFiltering() { @@ -68,6 +79,8 @@ public void testUnmarshallingFiltering() { // create a proxy for invocation final StatelessEJBLocator statelessEJBLocator = new StatelessEJBLocator(TypeReporter.class, APP_NAME, MODULE_NAME, TypeReporter.class.getSimpleName(), DISTINCT_NAME); final TypeReporter proxy = EJBClient.createProxy(statelessEJBLocator); + + // set the target for the invocation URI uri = null; try { uri = new URI("remote", null,"localhost", 6999, null, null,null); @@ -78,11 +91,12 @@ public void testUnmarshallingFiltering() { Assert.assertNotNull("Received a null proxy", proxy); logger.info("Created proxy for Echo: " + proxy.toString()); + // perform an invocation with parameter type String, which we expect not to be filtered logger.info("Invoking on proxy..."); - // invoke on the proxy (use a URIAffinity for now) final String type = proxy.getObjectType("hello"); Assert.assertEquals("Got an unexpected type", String.class.getName(), type); + // perform an invocation with parameter type IllegalArgumentException, which we expect to be filtered try { final String bad = proxy.getObjectType(new IllegalArgumentException("bad")); Assert.fail("IllegalArgumentException was not rejected; got " + bad); diff --git a/src/test/java/org/jboss/ejb/client/test/WildflyClientXMLTestCase.java b/src/test/java/org/jboss/ejb/client/test/WildflyClientXMLTestCase.java index 95af51ffe..a9e8c8972 100644 --- a/src/test/java/org/jboss/ejb/client/test/WildflyClientXMLTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/WildflyClientXMLTestCase.java @@ -27,9 +27,23 @@ import java.net.URL; /** - * Tests some basic features of wildfly-client.xml processing + * Tests some basic features of using a wildfly-config.xml file to configure the various contextuals which + * the EJB client library depends on for configuration of key cross cutting concerns. + * + * This processing reads a wildfly-config.xml file from the classpath (or one referenced by the system property + * wildfly.config.url) and uses the configuration in that file to configure the following contextuals: + * - Endpoint + * - XNIOWorker + * - EJBClientContext + * - AuthenticationConfiguration + * - Discovery + * - WildflyHttpContext + * * * @author Richard Achmatowicz + * + * @todo this test should include complete coverage of all available settings realting to the EJBClientContext + * at a minimum. */ public class WildflyClientXMLTestCase { @@ -39,12 +53,12 @@ public class WildflyClientXMLTestCase { private static final long INVOCATION_TIMEOUT = 10*1000; /** - * Do any general setup here + * Initialize the contextuals by setting the wildfly.config.url system property * @throws Exception */ @BeforeClass public static void beforeClass() throws Exception { - // make sure the desired configuration file is picked up + // make sure the desired configuration file is picked up for processing ClassLoader cl = WildflyClientXMLTestCase.class.getClassLoader(); URL resource = cl != null ? cl.getResource(CONFIGURATION_FILE) : ClassLoader.getSystemResource(CONFIGURATION_FILE); File file = new File(resource.getFile()); @@ -52,6 +66,10 @@ public static void beforeClass() throws Exception { ClassCallback.beforeClassCallback(); } + /* + * Tests that the invocation timeout value set in wildfly-config.xml is used to populate the invocation timeout + * value in the EJBClientContext. + */ @Test public void testInvocationTimeout() { EJBClientContext clientContext = EJBClientContext.getCurrent(); diff --git a/src/test/java/org/jboss/ejb/client/test/byteman/BytemanTransactionTestCase.java b/src/test/java/org/jboss/ejb/client/test/byteman/BytemanTransactionTestCase.java index 4cae14fc1..5c09161bf 100644 --- a/src/test/java/org/jboss/ejb/client/test/byteman/BytemanTransactionTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/byteman/BytemanTransactionTestCase.java @@ -47,6 +47,16 @@ import java.util.HashMap; import java.util.HashSet; +/** + * A test which validates that when performing a series of EJB client invocations, each in transaction scope, + * the PeerTransactionMap of the EJBClientChannel does not contain any leftover connection references used + * in transaction processing. + * + * This test uses the Byteman rule defined in BytemanTransactionTestCase.btm to maintain the PeerTransactionMap + * size. After all remote transactions have committed, the PeerTransactionMap should be empty. + * + * @author unknown + */ @RunWith(BMUnitRunner.class) @BMScript(dir="target/test-classes") public class BytemanTransactionTestCase extends AbstractEJBClientTestCase { @@ -55,11 +65,19 @@ public class BytemanTransactionTestCase extends AbstractEJBClientTestCase { private static ContextTransactionSynchronizationRegistry txSyncRegistry; /** - * Do any general setup here + * Setup a local JTA transaction environment for use with any tests in this class. + * The key elements of a local transaction context for the EJB client are: + * - JBossLocalTransactionProvider, which represents an underlying Narayana TransactionManager instance and + * XATerminator instance + * - LocalTransactionContext contextual, which makes the LocalTransactionProvider available to the EJB client + * application itself + * * @throws Exception */ @BeforeClass public static void beforeClass() throws Exception { + + // some Narayana-specific setup required for a JTA transaction environment BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, null) .setObjectStoreDir("target/tx-object-store"); BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "communicationStore") @@ -67,12 +85,13 @@ public static void beforeClass() throws Exception { BeanPopulator.getNamedInstance(ObjectStoreEnvironmentBean.class, "stateStore") .setObjectStoreDir("target/tx-object-store"); - final JTAEnvironmentBean jtaEnvironmentBean = jtaPropertyManager.getJTAEnvironmentBean(); jtaEnvironmentBean.setTransactionManagerClassName(TransactionManagerImple.class.getName()); jtaEnvironmentBean.setTransactionSynchronizationRegistryClassName(TransactionSynchronizationRegistryImple.class.getName()); final TransactionManager narayanaTm = jtaEnvironmentBean.getTransactionManager(); final XATerminator xat = new XATerminator(); + + // create the JBossLocalTransactionProvider instance final JBossLocalTransactionProvider.Builder builder = JBossLocalTransactionProvider.builder(); builder.setExtendedJBossXATerminator(xat); builder.setTransactionManager(narayanaTm); @@ -87,13 +106,16 @@ public void removeXAResourceRecovery(XAResourceRecovery xaResourceRecovery) { }); builder.setXARecoveryLogDirRelativeToPath(new File("target/tx-object-store").toPath()); builder.build(); + + // createthe LocalTransactionContext for the EJB client applicatiopn LocalTransactionContext.getContextManager().setGlobalDefault(new LocalTransactionContext(builder.build())); + txManager = ContextTransactionManager.getInstance(); txSyncRegistry = ContextTransactionSynchronizationRegistry.getInstance(); } /** - * Do any test specific setup here + * Before each test, start a single mock server instance and deploy a stateless application */ @Before public void beforeTest() throws Exception { @@ -107,6 +129,11 @@ public void testCacheCleaning() throws Exception { verifyCacheCleaning(); } + /** + * Tests that the PeerTransactionMap of the EJBClientChannel is cleaned up correctly after transaction commit. + * + * @throws Exception + */ private void verifyCacheCleaning() throws Exception { UserTransaction transaction = RemoteTransactionContext.getInstance().getUserTransaction(); FastHashtable props = new FastHashtable<>(); @@ -129,15 +156,15 @@ private void verifyCacheCleaning() throws Exception { echo.echo("someMsg"); transaction.commit(); } - - - + // after all transactions have completed, verify that the peerMap maintained by Byteman is zero Assert.assertEquals(0, Integer.parseInt(System.getProperty("peerMapSize"))); } + /** + * After each test, undeploy the stateless application and stop the mock server + */ @After public void afterTest() { - undeployStateless(0); stopServer(0); } diff --git a/src/test/java/org/jboss/ejb/client/test/byteman/MixedModeServiceURLTestCase.java b/src/test/java/org/jboss/ejb/client/test/byteman/MixedModeServiceURLTestCase.java index 86afae0cf..e3b76b1bf 100644 --- a/src/test/java/org/jboss/ejb/client/test/byteman/MixedModeServiceURLTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/byteman/MixedModeServiceURLTestCase.java @@ -38,12 +38,7 @@ import org.jboss.ejb.client.test.common.Echo; import org.jboss.ejb.server.ClusterTopologyListener; import org.jboss.logging.Logger; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; import org.junit.runner.RunWith; import org.wildfly.discovery.ServiceURL; diff --git a/src/test/java/org/jboss/ejb/client/test/byteman/MixedModeTestHelper.java b/src/test/java/org/jboss/ejb/client/test/byteman/MixedModeTestHelper.java index 09084a39c..d5490276c 100644 --- a/src/test/java/org/jboss/ejb/client/test/byteman/MixedModeTestHelper.java +++ b/src/test/java/org/jboss/ejb/client/test/byteman/MixedModeTestHelper.java @@ -10,6 +10,13 @@ import org.wildfly.discovery.FilterSpec; import org.wildfly.discovery.ServiceURL; +/** + * Helper class for the MixedModeServiceURLTestCase. + * + * Maintains a map of nodes to ServiceURLs used for test validation. + * + * @author rachmato@redhat.com + */ public class MixedModeTestHelper extends Helper { private static final String NODE_LIST_MAP_NAME = "nodeListMap"; diff --git a/src/test/java/org/jboss/ejb/client/test/byteman/OOMEInInvocationTestCase.java b/src/test/java/org/jboss/ejb/client/test/byteman/OOMEInInvocationTestCase.java index aa0bc1765..d76afe2ae 100644 --- a/src/test/java/org/jboss/ejb/client/test/byteman/OOMEInInvocationTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/byteman/OOMEInInvocationTestCase.java @@ -27,29 +27,28 @@ import org.jboss.ejb.client.test.ClassCallback; import org.jboss.ejb.client.test.common.Echo; import org.jboss.logging.Logger; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; import org.junit.runner.RunWith; /** * This test throws OutOfMemoryException on receiver through byteman, we check the log returned by XNIO contains - * all the information - * @author tmiyar + * all the information. + * + * This test depends on the BytemaN rules in OOMEInvocationTestCase.btm which do the following: + * - throw an out of memory error when we try to marshal an object * + * @author tmiyar */ @RunWith(BMUnitRunner.class) -@BMScript(dir="target/test-classes") +@BMScript(dir = "target/test-classes") public class OOMEInInvocationTestCase extends AbstractEJBClientTestCase { private static final Logger logger = Logger.getLogger(OOMEInInvocationTestCase.class); private static final String PROPERTIES_FILE = "jboss-ejb-client.properties"; /** - * Do any general setup here + * Configure the EJBClientContext to be aware of servers localhost:6999 and localhost:7099 + * * @throws Exception */ @BeforeClass @@ -63,33 +62,30 @@ public static void beforeClass() throws Exception { } /** - * Do any test specific setup here + * Before each test, start server localhost:6999 and deploy a stateless application */ @Before public void beforeTest() throws Exception { - // start server - startServer(0, 6999); - // deploy a stateful bean - deployStateless(0); - System.clearProperty("echo"); - } + startServer(0, 6999); + deployStateless(0); + System.clearProperty("echo"); + } /** * Test SLSB invocation - * + *

* scenario: - * invoked bean available on node1 - * strong affinity is set to Affinity.NONE + * invoked bean available on node1, strong affinity is set to Affinity.NONE * expected result: * invocation will fail and a message containing the invoked method will be displayed */ @Test public void testSLSBInvocation() { - + Assert.assertEquals("echo system property exists", null, System.getProperty("echo")); - + Affinity expectedStrongAffinity = Affinity.NONE; - + // create a proxy for SLSB final StatelessEJBLocator statelessEJBLocator = StatelessEJBLocator.create(Echo.class, STATELESS_IDENTIFIER, expectedStrongAffinity); Echo proxy = EJBClient.createProxy(statelessEJBLocator); @@ -103,19 +99,20 @@ public void testSLSBInvocation() { } catch (RuntimeException e) { //don't do anything, it is expected } + // check the property contents Assert.assertEquals("method echo not in error message", "true", System.getProperty("echo")); } /** - * Do any test-specific tear down here. + * After each test, undeploy the stateless application and stop the server */ @After public void afterTest() { // undeploy server - undeployStateless(0); - stopServer(0); - System.clearProperty("echo"); + undeployStateless(0); + stopServer(0); + System.clearProperty("echo"); } /** @@ -124,5 +121,5 @@ public void afterTest() { @AfterClass public static void afterClass() { } - - } + +} diff --git a/src/test/java/org/jboss/ejb/client/test/byteman/TimeoutRetryTestCase.java b/src/test/java/org/jboss/ejb/client/test/byteman/TimeoutRetryTestCase.java index cbe2afba3..d03f7c4df 100644 --- a/src/test/java/org/jboss/ejb/client/test/byteman/TimeoutRetryTestCase.java +++ b/src/test/java/org/jboss/ejb/client/test/byteman/TimeoutRetryTestCase.java @@ -36,16 +36,14 @@ import org.jboss.ejb.client.test.common.Echo; import org.jboss.ejb.client.test.common.EchoBean; import org.jboss.logging.Logger; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; import org.junit.runner.RunWith; /** - * Tests that a hang does not happen if timeout happens concurrently with retry + * Tests that validate that invocation timeouts and the invocation retry mechanism work together as expected. + * + * This test depends on the Byteman rule TimeoutRetryTestCase.btm which introduces a 3000 ms delay whenever + * the retry of an invocation is attempted. */ @RunWith(BMUnitRunner.class) @BMScript(dir = "target/test-classes") @@ -64,7 +62,7 @@ public class TimeoutRetryTestCase { private static final String SERVER_NAME = "test-server"; /** - * Do any general setup here + * Configure the EJBClientContext to be aware of servers localhost:6999 and localhost:7099 * * @throws Exception */ @@ -79,7 +77,7 @@ public static void beforeClass() throws Exception { } /** - * Do any test specific setup here + * Before each test, start server localhost:6999 and deploy a stateless application */ @Before public void beforeTest() throws Exception { @@ -94,7 +92,12 @@ public void beforeTest() throws Exception { } /** - * Test a basic invocation + * Test which verifies that if an invocation timeout and an invocation retry occur at the same time, + * the invocation does not hang and returns an exception of the correct type. + * + * This test makes an invocation on a non-existent bean, which will trigger the retry mechanism, and has an + * invocation timeout of 1000 ms. A Byteman rule is used to delay the retry by 3000 ms, which is shorter than + * the invocation timeout. We expect to see the invocation return with a TimeoutException. */ @Test public void testInvocationWithURIAffinity() { @@ -129,9 +132,7 @@ public void testInvocationWithURIAffinity() { expectedException = expected; } - //we have a 3s sleep in the retry code - //and a 1s timeout - //so we verify it was less than 1s + // we have a 3s sleep in the retry code and a 1s timeout so we verify it was less than 1s final long invocationDuration = System.currentTimeMillis() - start; Assert.assertTrue("Invocation should have timed out after 1000 ms, but actual duration is " + invocationDuration, invocationDuration < 2000); logger.infof("Invocation correctly timed out in %s ms", invocationDuration); @@ -155,7 +156,7 @@ public void testInvocationWithURIAffinity() { } /** - * Do any test-specific tear down here. + * After each test, undeploy the stateless application and stop the server */ @After public void afterTest() { diff --git a/src/test/java/org/jboss/ejb/client/test/common/TypeReporterBean.java b/src/test/java/org/jboss/ejb/client/test/common/TypeReporterBean.java index 29ba32fa5..0047d7998 100644 --- a/src/test/java/org/jboss/ejb/client/test/common/TypeReporterBean.java +++ b/src/test/java/org/jboss/ejb/client/test/common/TypeReporterBean.java @@ -17,6 +17,9 @@ */ package org.jboss.ejb.client.test.common; +/** + * A bean which can be used to report the type of the Object parameter passed to its only method. + */ public class TypeReporterBean implements TypeReporter { @Override diff --git a/src/test/java/org/jboss/ejb/protocol/remote/NetworkUtilTestCase.java b/src/test/java/org/jboss/ejb/protocol/remote/NetworkUtilTestCase.java index 454868d20..dd641c797 100644 --- a/src/test/java/org/jboss/ejb/protocol/remote/NetworkUtilTestCase.java +++ b/src/test/java/org/jboss/ejb/protocol/remote/NetworkUtilTestCase.java @@ -26,10 +26,18 @@ import org.junit.Test; /** + * Tests for the NetworkUtil network utility class. + * * @author David M. Lloyd */ public final class NetworkUtilTestCase { + /** + * Validation of the method NetworkUtil.belongsToNetwork(...) used to determine if a given host InetAddress belongs + * to a network specified by a network InetAddress value and a network mask. + * + * @throws UnknownHostException + */ @Test public void testNetmask1() throws UnknownHostException { assertTrue(NetworkUtil.belongsToNetwork(InetAddress.getByAddress("", new byte[] { 10, 0, 0, 1 }), InetAddress.getByAddress("", new byte[] { 10, 64, 33, 17 }), 8)); diff --git a/src/test/resources/clustered-jboss-ejb-client.properties b/src/test/resources/clustered-jboss-ejb-client.properties index 66ea5265c..568e1a9f6 100644 --- a/src/test/resources/clustered-jboss-ejb-client.properties +++ b/src/test/resources/clustered-jboss-ejb-client.properties @@ -51,5 +51,5 @@ remote.connection.three.realm=default remote.clusters=ejb remote.cluster.ejb.node.node1.username=test remote.cluster.ejb.node.node1.password=test -#remote.cluster.ejb.node.node2.username=test -#remote.cluster.ejb.node.node2.password=test \ No newline at end of file +remote.cluster.ejb.node.node2.username=test +remote.cluster.ejb.node.node2.password=test \ No newline at end of file diff --git a/src/test/resources/org/jboss/ejb/client/test/byteman/TimeoutRetryTestCase.btm b/src/test/resources/org/jboss/ejb/client/test/byteman/TimeoutRetryTestCase.btm index 4d851f41d..82598953d 100644 --- a/src/test/resources/org/jboss/ejb/client/test/byteman/TimeoutRetryTestCase.btm +++ b/src/test/resources/org/jboss/ejb/client/test/byteman/TimeoutRetryTestCase.btm @@ -15,7 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -RULE @1 delay innvocation +RULE @1 delay invocation CLASS org.jboss.ejb.client.EJBClientInvocationContext AT ENTRY METHOD retryOperation