001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tctest.management;
006:
007: import com.tc.logging.TCLogger;
008: import com.tc.logging.TCLogging;
009: import com.tc.management.JMXConnectorProxy;
010: import com.tc.management.TerracottaManagement;
011: import com.tc.management.beans.sessions.SessionMonitorMBean;
012: import com.tc.test.server.appserver.deployment.AbstractDeploymentTest;
013: import com.tc.test.server.appserver.deployment.Deployment;
014: import com.tc.test.server.appserver.deployment.DeploymentBuilder;
015: import com.tc.test.server.appserver.deployment.ServerTestSetup;
016: import com.tc.test.server.appserver.deployment.WebApplicationServer;
017: import com.tc.test.server.appserver.load.Node;
018: import com.tc.test.server.util.TcConfigBuilder;
019: import com.tctest.webapp.servlets.CounterServlet;
020:
021: import java.net.URL;
022: import java.util.Iterator;
023: import java.util.Set;
024:
025: import javax.management.MBeanServerConnection;
026: import javax.management.ObjectName;
027: import javax.management.remote.JMXConnector;
028:
029: import junit.framework.Test;
030:
031: public final class RequestCountTest extends AbstractDeploymentTest {
032: private static final TCLogger logger = TCLogging
033: .getTestingLogger(RequestCountTest.class);
034:
035: private static final int SESSIONS_PER_NODE = 10;
036: private static final long TEST_DURATION = 30 * 1000;
037: private static final String CLIENT_NAME_PREFIX = "client-";
038:
039: private static final String CONTEXT = "RequestCountTest";
040: private static final String SERVLET = "RequestCountingServlet";
041:
042: private Deployment deployment;
043: private TcConfigBuilder configBuilder;
044:
045: public static Test suite() {
046: return new ServerTestSetup(RequestCountTest.class);
047: }
048:
049: public void setUp() throws Exception {
050: super .setUp();
051: if (deployment == null) {
052: deployment = makeDeployment();
053: configBuilder = new TcConfigBuilder();
054: configBuilder.addWebApplication(CONTEXT);
055: }
056: }
057:
058: public void testRequestCount() throws Throwable {
059: assertTimeDirection();
060: runNodes(2);
061: }
062:
063: private Deployment makeDeployment() throws Exception {
064: DeploymentBuilder builder = makeDeploymentBuilder(CONTEXT
065: + ".war");
066: builder.addServlet(SERVLET, "/" + SERVLET + "/*",
067: CounterServlet.class, null, false);
068: return builder.makeDeployment();
069: }
070:
071: private int createAndStartServer(String extraJvmArg)
072: throws Exception {
073: WebApplicationServer server = makeWebApplicationServer(configBuilder);
074: server.addWarDeployment(deployment, CONTEXT);
075: server.getServerParameters().appendJvmArgs(extraJvmArg);
076: server.start();
077: return server.getPort();
078: }
079:
080: private URL createUrl(int port, String params) throws Exception {
081: URL url = new URL("http://localhost:" + port + "/" + CONTEXT
082: + "/" + SERVLET
083: + (params.length() > 0 ? "?" + params : ""));
084: return url;
085: }
086:
087: private void runNodes(int nodeCount) throws Throwable {
088: Thread[] nodeRunners = new Thread[nodeCount];
089: NodeWithJMX[] nodes = new NodeWithJMX[nodeCount];
090: int[] ports = new int[nodeCount];
091:
092: for (int i = 0; i < nodeCount; i++) {
093: ports[i] = createAndStartServer("-Dtc.node-name="
094: + CLIENT_NAME_PREFIX + i);
095: }
096:
097: final JMXConnector jmxConnector = getJMXConnector();
098: final MBeanServerConnection mbs = jmxConnector
099: .getMBeanServerConnection();
100: final long beanCutoffTime = System.currentTimeMillis()
101: + (60 * 1000);
102: Set beanSet = null;
103: for (beanSet = TerracottaManagement
104: .getAllSessionMonitorMBeans(mbs); beanSet.size() != nodeCount; beanSet = TerracottaManagement
105: .getAllSessionMonitorMBeans(mbs)) {
106: if (!beanSet.isEmpty()) {
107: logger.info("Found some session beans but not all:");
108: for (final Iterator pos = beanSet.iterator(); pos
109: .hasNext();) {
110: logger.info("Session bean["
111: + ((ObjectName) pos.next())
112: .getCanonicalName() + "]");
113: }
114: } else {
115: logger.info("No session beans found, expecting "
116: + nodeCount + " of them");
117: }
118: if (System.currentTimeMillis() > beanCutoffTime) {
119: final String errMsg = "Unable to find DSO client MBeans within 60 seconds of starting the node";
120: logger.error(errMsg);
121: fail(errMsg);
122: } else {
123: logger.info("Unable to find DSO client MBeans after "
124: + (beanCutoffTime - System.currentTimeMillis())
125: + "ms, sleeping for 3 seconds");
126: try {
127: Thread.sleep(3000);
128: } catch (InterruptedException ie) {
129: // ignore
130: }
131: }
132: }
133: logger.info("We have all of our DSO client Mbeans after "
134: + (beanCutoffTime - System.currentTimeMillis()) + ":");
135: for (final Iterator pos = beanSet.iterator(); pos.hasNext();) {
136: logger.info("Session bean["
137: + ((ObjectName) pos.next()).getCanonicalName()
138: + "]");
139: }
140: final SessionMonitorMBean[] mbeans = new SessionMonitorMBean[nodeCount];
141: for (int i = 0; i < nodeCount; i++) {
142: SessionMonitorMBean clientMBean = TerracottaManagement
143: .getClientSessionMonitorMBean(mbs, beanSet,
144: CLIENT_NAME_PREFIX + i);
145: if (clientMBean == null) {
146: final String errMsg = "We thought we had all of our DSO client MBeans, turns out we don't have one for client["
147: + CLIENT_NAME_PREFIX + i + "]";
148: logger.error(errMsg);
149: fail(errMsg);
150: }
151: mbeans[i] = clientMBean;
152: }
153:
154: for (int i = 0; i < nodeCount; i++) {
155: URL mutateUrl = createUrl(ports[i], "");
156: URL validateUrl = createUrl(ports[(i + 1) % nodeCount],
157: "read=true");
158: nodes[i] = new NodeWithJMX(mutateUrl, validateUrl,
159: SESSIONS_PER_NODE, TEST_DURATION);
160: nodeRunners[i] = new Thread(nodes[i],
161: "Runner for server at port " + ports[i]);
162: }
163:
164: for (int i = 0; i < nodeCount; i++) {
165: nodeRunners[i].start();
166: }
167:
168: for (int i = 0; i < nodeCount; i++) {
169: nodeRunners[i].join();
170: }
171:
172: for (int i = 0; i < nodeCount; i++) {
173: nodes[i].checkError();
174: }
175:
176: for (int i = 0; i < nodeCount; i++) {
177: nodes[i].validateMBean(mbeans[i]);
178: }
179:
180: jmxConnector.close();
181: }
182:
183: private JMXConnector getJMXConnector() {
184: int jmxPort = getServerManager().getServerTcConfig()
185: .getJmxPort();
186: return new JMXConnectorProxy("localhost", jmxPort);
187: }
188:
189: private static class NodeWithJMX extends Node {
190:
191: public NodeWithJMX(URL mutateUrl, URL validateUrl,
192: int numSessions, long duration) {
193: super (mutateUrl, validateUrl, numSessions, duration);
194: }
195:
196: public void validateMBean(
197: SessionMonitorMBean sessionMonitorMBean) {
198: int totalRequests = 0;
199: for (int i = 0; i < numRequests.length; i++) {
200: totalRequests += numRequests[i];
201: }
202:
203: assertEquals(totalRequests, sessionMonitorMBean
204: .getRequestCount());
205:
206: assertEquals(1, validateUrls.length);
207: final URL validateUrl = validateUrls[0];
208:
209: System.err.println("validated value of " + totalRequests
210: + " for client " + validateUrl);
211: }
212: }
213: }
|