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.tc.test.server.appserver.load;
006:
007: import EDU.oswego.cs.dl.util.concurrent.SynchronizedRef;
008:
009: import com.meterware.httpunit.WebConversation;
010: import com.meterware.httpunit.WebResponse;
011: import com.tc.logging.TCLogger;
012: import com.tc.logging.TCLogging;
013: import com.tc.util.concurrent.ThreadUtil;
014:
015: import java.net.URL;
016: import java.util.Random;
017:
018: import junit.framework.Assert;
019:
020: public class Node implements Runnable {
021: protected static final TCLogger logger = TCLogging
022: .getLogger(Node.class);
023: protected final long duration;
024: protected final int numRequests[];
025: protected final SynchronizedRef error = new SynchronizedRef(null);
026: protected final URL[] mutateUrls;
027: protected final URL[] validateUrls;
028: protected final Random random = new Random();
029: protected final WebConversation[] conversations;
030:
031: public Node(URL mutateUrl, URL validateUrl, int numSessions,
032: long duration) {
033: this (new URL[] { mutateUrl }, new URL[] { validateUrl },
034: numSessions, duration);
035: }
036:
037: public Node(URL[] mutateUrls, URL[] validateUrls, int numSessions,
038: long duration) {
039: this .mutateUrls = mutateUrls;
040: this .validateUrls = validateUrls;
041: conversations = createConversations(numSessions);
042: this .duration = duration;
043: this .numRequests = new int[numSessions];
044: }
045:
046: private WebConversation[] createConversations(int count) {
047: WebConversation[] wc = new WebConversation[count];
048: for (int i = 0; i < count; i++) {
049: wc[i] = new WebConversation();
050: }
051: return wc;
052: }
053:
054: public void checkError() throws Throwable {
055: Throwable t = (Throwable) error.get();
056: if (t != null) {
057: throw t;
058: }
059: }
060:
061: public void run() {
062: try {
063: makeRequests();
064: validate();
065: } catch (Throwable t) {
066: logger.error(t);
067: error.set(t);
068: }
069: }
070:
071: private void validate() throws Exception {
072: for (int i = 0; i < conversations.length; i++) {
073: int expect = numRequests[i];
074: if (expect == 0) {
075: throw new AssertionError(
076: "No requests were ever made for client " + i);
077: }
078:
079: WebConversation wc = conversations[i];
080:
081: for (int u = 0; u < validateUrls.length; u++) {
082: int actual = getResponseAsInt(wc, validateUrls[u]);
083: Assert.assertEquals(getSessionID(wc), expect, actual);
084: logger
085: .info("validated value of " + expect
086: + " for client " + i + " on "
087: + validateUrls[u]);
088: // Recording the request that was just made. This is needed for RequestCountTest.
089: numRequests[i]++;
090: }
091: }
092: }
093:
094: private int getResponseAsInt(WebConversation wc, URL url)
095: throws Exception {
096: WebResponse response = wc.getResponse(url.toString());
097: return Integer.parseInt(response.getText().trim());
098: }
099:
100: private void makeRequests() throws Exception {
101: final int numURLS = mutateUrls.length;
102:
103: int session = 0;
104: final long end = System.currentTimeMillis() + duration;
105: while (System.currentTimeMillis() <= end) {
106: WebConversation wc = conversations[session];
107: URL mutateUrl = numURLS == 1 ? mutateUrls[0]
108: : mutateUrls[random.nextInt(mutateUrls.length)];
109:
110: final long start = System.currentTimeMillis();
111: try {
112: int newVal = getResponseAsInt(wc, mutateUrl);
113: numRequests[session]++;
114: Assert.assertEquals(getSessionID(wc),
115: numRequests[session], newVal);
116: session = (session + 1) % conversations.length;
117: ThreadUtil.reallySleep(random.nextInt(5) + 1);
118: } catch (Exception e) {
119: logger.error("Elapsed time for failed request was "
120: + (System.currentTimeMillis() - start)
121: + " millis, url = " + mutateUrl);
122: throw e;
123: }
124: }
125: }
126:
127: private String getSessionID(WebConversation wc) {
128: return wc.getCookieValue("JSESSIONID");
129: }
130:
131: }
|