/* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* http://www.sun.com/cddl/cddl.html or
* install_dir/legal/LICENSE
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at install_dir/legal/LICENSE.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id$
*
* Copyright 2005-2009 Sun Microsystems Inc. All Rights Reserved
*/
package com.sun.faban.loadtest;
import com.sun.faban.driver.*;
import com.sun.faban.driver.util.Random;
import javax.xml.xpath.XPathExpressionException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Logger;
/** The driver to drive load against the Faban harness. */
@BenchmarkDefinition (
name = "Faban Harness Workload",
version = "0.1"
)
@BenchmarkDriver (
name = "UIDriver",
threadPerScale = 1
)
@MatrixMix (
operations = {"Home Page", "List Results", "View Result",
"Submit Run", "Pending Runs"},
mix = { @Row({ 0, 80, 0, 5, 15 }),
@Row({ 5, 10, 70, 5, 10 }),
@Row({ 5, 80, 0, 5, 10 }),
@Row({ 0, 80, 0, 0, 20 }),
@Row({ 20, 60, 0, 20, 0 }) },
deviation = 2
)
@NegativeExponential (
cycleType = CycleType.CYCLETIME,
cycleMean = 5000,
cycleDeviation = 2
)
public class UIDriver {
/** The driver context for this instance. */
private DriverContext ctx;
private HttpTransport http;
boolean realSubmit;
Logger logger;
Random random;
String baseURL;
String[] homePageGets;
String resultList;
String[] submitRuns;
String pendingList;
String deleteRuns;
String[] runIds;
String runId;
/**
* Constructs a UIDriver instance.
* @throws XPathExpressionException Invalid XPath
*/
public UIDriver() throws XPathExpressionException {
ctx = DriverContext.getContext();
http = HttpTransport.newInstance();
logger = ctx.getLogger();
random = ctx.getRandom();
String host = ctx.getXPathValue("/fabanLoad/serverConfig/fa:hostConfig/fa:host");
String port = ctx.getXPathValue("/fabanLoad/serverConfig/port");
realSubmit = Boolean.parseBoolean(ctx.getProperty("realSubmit"));
baseURL = "http://" + host + ':' + port + '/';
homePageGets = new String[4];
homePageGets[0] = baseURL;
homePageGets[1] = baseURL + "banner.jsp";
homePageGets[2] = baseURL + "welcome.jsp";
homePageGets[3] = baseURL + "menu.jsp";
resultList = baseURL + "resultlist.jsp";
submitRuns = new String[3];
submitRuns[0] = baseURL + "selectprofile.jsp";
submitRuns[1] = baseURL + "new-run.jsp";
submitRuns[2] = baseURL + "benchmarks/fabanload/config.xhtml";
pendingList = baseURL + "pending-runs.jsp";
deleteRuns = baseURL + "delete-runs.jsp";
}
/**
* Clears the pending runs.
* @throws IOException Error clearing the pending runs.
*/
@OnceAfter public void cleanPendingRuns() throws IOException {
pendingRuns();
}
/**
* Access the home page.
* @throws IOException Error accessing the home page.
*/
@BenchmarkOperation (
name = "Home Page",
max90th = 2,
timing = Timing.AUTO
)
public void homePage() throws IOException {
for (String get : homePageGets) {
logger.finest("Accessing " + get);
http.readURL(get);
}
}
/**
* Tests listing the results.
* @throws IOException Error obtaining the result list.
*/
@BenchmarkOperation (
name = "List Results",
max90th = 2,
timing = Timing.AUTO
)
public void listResults() throws IOException {
logger.finest("Accessing " + resultList);
if (runIds == null) { // Just parse the runIds once
http.fetchURL(resultList);
StringBuilder response = http.getResponseBuffer();
int tableIdx = response.indexOf("<table");
if (tableIdx != -1)
runIds = parseResultTable(response, tableIdx);
} else { // RunIds won't change much over the run.
http.readURL(resultList);
}
if (runIds != null) {
int idx = random.random(0, runIds.length - 1);
runId = runIds[idx];
}
}
/**
* Test viewing a result.
* @throws IOException Error viewing the result
*/
@BenchmarkOperation (
name = "View Result",
max90th = 2,
timing = Timing.AUTO
)
public void viewResult() throws IOException {
if (runId == null) {
logger.warning("No results just yet. Try again next run.");
return;
}
http.readURL(baseURL + "resultframe.jsp?runId=" + runId +
"&result=summary.xml&show=logs");
http.readURL(baseURL + "LogReader?runId=" + runId);
http.fetchURL(baseURL + "resultnavigator.jsp?runId=" + runId);
StringBuilder b = http.getResponseBuffer();
// Search for summary file
final String href = "href=\"";
String summaryPath = null;
String detailPath = null;
int endIdx = b.indexOf("\" target=\"display\">Summary Result</a>");
if (endIdx != -1) {
int begIdx = b.lastIndexOf(href, endIdx) + href.length();
summaryPath = b.substring(begIdx, endIdx);
}
// Search for detail file
endIdx = b.indexOf("\" target=\"display\">Detailed Results</a>");
if (endIdx != -1) {
int begIdx = b.lastIndexOf(href, endIdx) + href.length();
detailPath = b.substring(begIdx, endIdx);
}
if (summaryPath != null)
http.readURL(baseURL + summaryPath);
if (detailPath != null)
http.readURL(baseURL + detailPath);
http.readURL(baseURL + "output/" + runId + "/run.xml");
http.readURL(baseURL + "statsnavigator.jsp?runId=" + runId);
}
/**
* Test submitting a run.
* @throws IOException Error submitting run
*/
@BenchmarkOperation (
name = "Submit Run",
max90th = 2,
timing = Timing.AUTO
)
public void submitRun() throws IOException {
http.fetchURL(submitRuns[0]);
StringBuilder b = http.getResponseBuffer();
if (-1 == b.indexOf( // Selection required
"<meta HTTP-EQUIV=REFRESH CONTENT=\"0;URL=new-run.jsp\">"))
http.readURL(submitRuns[1], "profile=test&profilelist=test&" +
"benchmark=Faban+Harness+Workload");
else
http.readURL(submitRuns[1]);
http.readURL(submitRuns[2]);
http.readURL(submitRuns[2], "t_trigger-runConfig=Driver&" +
"d_input-javaHome=%2Fopt%2Fjdk1.6.0&d_input-jvmOptions=" +
"-Xmx256m+-Xms64m+-XX%3A%2BDisableExplicitGC");
http.readURL(submitRuns[2], "t_trigger-uiDriver=" +
"Harness%C2%A0UI%C2%A0Driver&d_input-description=" +
"Sample+benchmark+run&d_input-agent-host=sucharitakul&" +
"d_input-scale=100&d_input-agent-tools=vmstat+10&" +
"d_input-rampUp=60&d_input-steadyState=300&" +
"d_input-rampDown=30");
if (realSubmit)
http.readURL(submitRuns[2], "d_input-driver-agents=1&" +
"d_input-driver-statsInterval=30&" +
"d_select1-driver-realSubmit=false&" +
"d_select1-driver-realSubmit=&" +
"d_input-server-host=sucharitakul&" +
"d_input-server-port=9980&t_trigger-ok=Ok");
}
/**
* Tests viewing pending runs.
* @throws IOException Error viewing pending runs
*/
@BenchmarkOperation (
name = "Pending Runs",
max90th = 2,
timing = Timing.AUTO
)
public void pendingRuns() throws IOException {
if (realSubmit) {
http.fetchURL(pendingList);
StringBuilder response = http.getResponseBuffer();
String postList = parsePendingTable(response);
if (postList != null)
http.readURL(deleteRuns, postList);
} else {
http.readURL(pendingList);
}
}
private String[] parseResultTable(StringBuilder content, int start) {
ArrayList<String> runIdList = new ArrayList<String>();
int tableEnd = content.indexOf("</table>", start);
rowLoop:
for (;;) {
int rowIdx = content.indexOf("<tr>", start);
if (rowIdx > tableEnd || rowIdx == -1)
break;
rowIdx += 4;
int rowEnd = content.indexOf("</tr>", rowIdx);
start = rowEnd + 5;
for (int col = 0;;col++) {
rowIdx = content.indexOf("<td>", rowIdx);
if (rowIdx > rowEnd)
continue rowLoop;
rowIdx += 4;
int fieldEnd = content.indexOf("</td>", rowIdx);
if (col == 1) {
String runId = content.substring(rowIdx, fieldEnd);
logger.finest("Found runId: " + runId);
runIdList.add(runId);
continue rowLoop;
}
}
}
String[] runIds = new String[runIdList.size()];
return runIdList.toArray(runIds);
}
private String parsePendingTable(StringBuilder response) {
final String search = "<input type=\"checkbox\" " +
"name=\"selected-runs\" value=\"";
final String searchEnd = "\">";
StringBuilder post = new StringBuilder();
int idx = 0;
for (;;) {
int runIdStart = response.indexOf(search, idx);
if (runIdStart == -1)
break;
else
runIdStart += search.length();
int runIdEnd = response.indexOf(searchEnd, runIdStart);
if (post.length() > 0)
post.append('&');
post.append("selected-runs=");
post.append(response.substring(runIdStart, runIdEnd));
idx = runIdEnd + searchEnd.length();
}
String postString = null;
if (post.length() > 0)
postString = post.toString();
return postString;
}
}