incubator-olio-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sha...@apache.org
Subject svn commit: r815523 - /incubator/olio/workload/rails/trunk/src/org/apache/olio/workload/driver/UIDriver.java
Date Tue, 15 Sep 2009 22:14:37 GMT
Author: shanti
Date: Tue Sep 15 22:14:37 2009
New Revision: 815523

URL: http://svn.apache.org/viewvc?rev=815523&view=rev
Log:
Fix for OLIO-84. Also created prepareAddress() and prepareEvent() methods.

Modified:
    incubator/olio/workload/rails/trunk/src/org/apache/olio/workload/driver/UIDriver.java

Modified: incubator/olio/workload/rails/trunk/src/org/apache/olio/workload/driver/UIDriver.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/org/apache/olio/workload/driver/UIDriver.java?rev=815523&r1=815522&r2=815523&view=diff
==============================================================================
--- incubator/olio/workload/rails/trunk/src/org/apache/olio/workload/driver/UIDriver.java
(original)
+++ incubator/olio/workload/rails/trunk/src/org/apache/olio/workload/driver/UIDriver.java
Tue Sep 15 22:14:37 2009
@@ -14,8 +14,6 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- * 
- * $Id: UIDriver.java,v 1.26 2008/02/12 03:24:20 akara Exp $
  *
  */
 package org.apache.olio.workload.driver;
@@ -23,13 +21,13 @@
 import com.sun.faban.driver.*;
 import com.sun.faban.common.Utilities;
 import com.sun.faban.common.NameValuePair;
+import com.sun.faban.driver.transport.hc3.ApacheHC3Transport;
 import org.apache.olio.workload.util.RandomUtil;
 import org.apache.olio.workload.util.ScaleFactors;
 import org.apache.olio.workload.util.UserName;
 import org.apache.commons.httpclient.Header;
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.methods.MultipartPostMethod;
 
 import javax.xml.xpath.XPathExpressionException;
 import java.io.File;
@@ -41,44 +39,32 @@
 import org.apache.commons.httpclient.methods.GetMethod;
 import org.apache.commons.httpclient.methods.PostMethod;
 import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
 import org.apache.commons.httpclient.methods.multipart.Part;
 import org.apache.commons.httpclient.methods.multipart.StringPart;
 
-@BenchmarkDefinition (
-    name    = "Web20Bench",
-    version = "0.3",
-    scaleName = "Concurrent Users"
-
-)
-@BenchmarkDriver (
-    name           = "UIDriver",
-    threadPerScale    = 1
-)
-        // 90/10 Read/Write ratio
-       
-@MatrixMix (
-//    operations = {"HomePage", "Login", , "TagSearch", "EventDetail", "PersonDetail",
+@BenchmarkDefinition(
+	name = "OlioRails",
+	version = "0.2",
+    scaleName = "Concurrent Users")
+@BenchmarkDriver(name = "UIDriver",
+threadPerScale = 1)
+// 90/10 Read/Write ratio
+@MatrixMix( //    operations = {"HomePage", "Login", , "TagSearch", "EventDetail", "PersonDetail",
 //                  "Logout", "AddEvent",  "AddPerson"},
-    operations = { "HomePage", "Login", "TagSearch", "EventDetail", "PersonDetail", "AddPerson",
"AddEvent" },
-
-    mix = { @Row({  0, 11, 52, 36,  0, 1,  0 }), // Home Page
-            @Row({  0,  0, 60, 20,  0, 0, 20 }), // Login
-            @Row({ 21,  6, 41, 31,  0, 1,  0 }), // Tag Search
-            @Row({ 72, 21,  0,  0,  6, 1,  0 }), // Event Detail
-            @Row({ 52,  6,  0, 31, 11, 0,  0 }), // Person Detail
-            @Row({  0,  0,  0,  0,100, 0,  0 }), // Add Person
-            @Row({  0,  0,  0,100,  0, 0,  0 })  // Add Event
-          }
-)
-
-@NegativeExponential (
-    cycleType = CycleType.CYCLETIME,
-    cycleMean = 5000,
-    cycleDeviation = 2
-)
-
+operations = {"HomePage", "Login", "TagSearch", "EventDetail", "PersonDetail", "AddPerson",
"AddEvent"},
+mix = {@Row({0, 11, 52, 36, 0, 1, 0}), // Home Page
+    @Row({0, 0, 60, 20, 0, 0, 20}), // Login
+    @Row({21, 6, 41, 31, 0, 1, 0}), // Tag Search
+    @Row({72, 21, 0, 0, 6, 1, 0}), // Event Detail
+    @Row({52, 6, 0, 31, 11, 0, 0}), // Person Detail
+    @Row({0, 0, 0, 0, 100, 0, 0}), // Add Person
+    @Row({0, 0, 0, 100, 0, 0, 0}) // Add Event
+})
+@NegativeExponential(cycleType = CycleType.CYCLETIME,
+cycleMean = 5000,
+cycleDeviation = 2)
 public class UIDriver {
-
     public static final String[] HOME_STATICS = {
         "/javascripts/prototype.js",
         "/javascripts/effects.js",
@@ -102,8 +88,7 @@
         "/images/reflec_right.png",
         "/images/reflec_left.png",
         "/images/main_nav_hover_bg.gif"
-   };
-
+    };
     public static final String[] EVENTDETAIL_STATICS = {
         "/javascripts/prototype.js",
         "/javascripts/effects.js",
@@ -131,7 +116,6 @@
         "/images/reflec_right.png",
         "/images/reflec_left.png"
     };
-
     public static final String[] ADDPERSON_STATICS = {
         "/javascripts/prototype.js",
         "/javascripts/effects.js",
@@ -159,7 +143,6 @@
         "/images/reflec_right.png",
         "/images/reflec_left.png"
     };
-
     public static final String[] ADDEVENT_STATICS = {
         "/javascripts/prototype.js",
         "/javascripts/effects.js",
@@ -187,8 +170,6 @@
         "/images/reflec_right.png",
         "/images/reflec_left.png"
     };
-
-
     public static final String[] PERSON_STATICS = {
         "/javascripts/prototype.js",
         "/javascripts/effects.js",
@@ -213,7 +194,6 @@
         "/images/reflec_left.png",
         "/images/main_nav_hover_bg.gif"
     };
-
     public static final String[] PERSON_GETS = {
         "/javascripts/prototype.js",
         "/javascripts/effects.js",
@@ -238,7 +218,6 @@
         "/images/reflec_left.png",
         "/images/main_nav_hover_bg.gif"
     };
-
     public static final String[] TAGSEARCH_STATICS = {
         "/javascripts/prototype.js",
         "/javascripts/effects.js",
@@ -271,26 +250,22 @@
     public static final double AVG_IMAGE_BYTES_PER_HOMEPAGE_TARGET = 20000d;
     public static final double AVG_IMAGE_PER_TAG_SEARCH_TARGET = 10;
     public static final double AVG_IMGS_PER_EVENT_DETAIL_TARGET = 0d;
-
-
     // We just need today's date. java.sql.date does not have any time anyway.
     public static final java.sql.Date BASE_DATE =
-                                new java.sql.Date(System.currentTimeMillis());
-
+            new java.sql.Date(System.currentTimeMillis());
     private DriverContext ctx;
     private HttpTransport http;
     private String baseURL;
     private String personDetailURL;
     private String tagSearchURL;
-    private String homepageURL, loginURL, logoutURL;
-    private String addEventURL, addPersonURL, eventDetailURL;
-    private String addEventResultURL, addPersonResultURL;
+    private String homepageURL,  loginURL,  logoutURL;
+    private String addEventURL,  addPersonURL,  eventDetailURL;
+    private String addEventResultURL,  addPersonResultURL;
     private String addAttendeeURL; //GET update.php?id=$eventid
     private String checkNameURL;
     // private String updatePageURL; //POST gettextafterinsert.php list=attendees
     private String fileServiceURL;
-    private String[] homepageStatics, personStatics, personGets,
-    tagSearchStatics, eventDetailStatics, addPersonStatics, addEventStatics;
+    private String[] homepageStatics,  personStatics,  personGets,  tagSearchStatics,  eventDetailStatics,
 addPersonStatics,  addEventStatics;
     File eventImg, eventThumb, eventPdf, personImg, personThumb;
     private boolean isLoggedOn = false;
     private String username;
@@ -304,41 +279,55 @@
     private HashSet<String> cachedURLs = new HashSet<String>();
     private LinkedHashMap<String, String> loginHeaders =
             new LinkedHashMap<String, String>();
+    private LinkedHashMap<String, String> cachedHeaders;
     private UIDriverMetrics driverMetrics;
     private long imgBytes = 0;
     private int imagesLoaded = 0;
     private String tagCloudURL;
-
+    private StringBuilder tags = new StringBuilder();
+    private LinkedHashSet<Integer> tagSet = new LinkedHashSet<Integer>(7);
     private HttpClient httpClient;
 
     public UIDriver() throws XPathExpressionException {
         ctx = DriverContext.getContext();
         int scale = ctx.getScale();
         ScaleFactors.setActiveUsers(scale);
-        http = new HttpTransport();
+        HttpTransport.setProvider("com.sun.faban.driver.transport.hc3.ApacheHC3Transport");
+        http = HttpTransport.newInstance();
 
         logger = ctx.getLogger();
         random = ctx.getRandom();
         driverMetrics = new UIDriverMetrics();
         ctx.attachMetrics(driverMetrics);
+
+		// We use the proxy hostPort if it is set. 
+		// If not, then fall back to webserver.
         String hostPorts = ctx.getXPathValue(
-                                "/olio/webServer/fa:hostConfig/fa:hostPorts");
+                "/olio/proxyServer/fa:hostConfig/fa:hostPorts");
         List<NameValuePair<Integer>> hostPortList =
-                                            Utilities.parseHostPorts(hostPorts);
+                Utilities.parseHostPorts(hostPorts);
+        if (hostPortList.get(0).name == null) {
+            hostPorts = ctx.getXPathValue(
+                "/olio/webServer/fa:hostConfig/fa:hostPorts");
+            hostPortList = Utilities.parseHostPorts(hostPorts);
+        }
+
         int loadedScale = Integer.parseInt(
-                                    ctx.getXPathValue("/olio/dbServer/scale"));
+                ctx.getXPathValue("/olio/dbServer/scale"));
         loadedUsers = ScaleFactors.USERS_RATIO * loadedScale;
-        if (scale > loadedScale)
+        if (scale > loadedScale) {
             throw new FatalException("Data loaded only for " + loadedScale +
                     " concurrent users. Run is set for " + scale +
                     " concurrent users. Please load for enough concurrent " +
                     "users. Run terminating!");
+        }
 
         //String type = ctx.getProperty("serverType");
         String type = "html";
         String resourcePath = ctx.getResourceDir();
-        if (!resourcePath.endsWith(File.separator))
+        if (!resourcePath.endsWith(File.separator)) {
             resourcePath += File.separator;
+        }
         eventImg = new File(resourcePath + "event.jpg");
         // logger.info("eventImg: " + eventImg);
         eventThumb = new File(resourcePath + "event_thumb.jpg");
@@ -351,13 +340,14 @@
         // logger.info("personThumb: " + personThumb);
 
         int bucket = Utilities.selectBucket(ctx.getThreadId(),
-                            ctx.getClientsInDriver(), hostPortList.size());
+                ctx.getClientsInDriver(), hostPortList.size());
         NameValuePair<Integer> hostPort = hostPortList.get(bucket);
 
-        if (hostPort.value == null)
+        if (hostPort.value == null) {
             baseURL = "http://" + hostPort.name;
-        else
+        } else {
             baseURL = "http://" + hostPort.name + ':' + hostPort.value;
+        }
         personDetailURL = baseURL + "/users/";
         tagSearchURL = baseURL + "/events/tag_search/";
         tagCloudURL = baseURL + "/tagCloud." + type;
@@ -382,14 +372,19 @@
         addPersonStatics = populateList(ADDPERSON_STATICS);
         addEventStatics = populateList(ADDEVENT_STATICS);
 
-       if (hostPort.value == null)
+        if (hostPort.value == null) {
             loginHeaders.put("Host", hostPort.name);
-        else
+        } else {
             loginHeaders.put("Host", hostPort.name + ':' + hostPort.value);
+        }
         loginHeaders.put("User-Agent", "Mozilla/5.0");
         loginHeaders.put("Accept", "text/xml.application/xml,application/" +
                 "xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;" +
                 "q=0.5");
+
+		// We don't want the rest of the loginheaders in cachedHeaders
+		cachedHeaders = (LinkedHashMap)(loginHeaders.clone());
+
         loginHeaders.put("Accept-Language", "en-us,en;q=0.5");
         loginHeaders.put("Accept-Encoding", "gzip,deflate");
         loginHeaders.put("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
@@ -398,17 +393,22 @@
         loginHeaders.put("Referer", homepageURL);
 
         isLoggedOn = false;
+  
+		// Create headers for if-modified-since
+		String ifmod = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z").format(BASE_DATE);
+		cachedHeaders.put("If-Modified-Since", ifmod);
         isCached = cached();
-// Shanti: Why are we creating httpClient here ?
+        /**
         httpClient = new HttpClient();
         httpClient.setConnectionTimeout(5000);
+         */
+        httpClient = ((ApacheHC3Transport) http).getHttpClient();
+        httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
     }
 
-    @BenchmarkOperation (
-        name    = "HomePage",
-        max90th = 1,
-        timing  = Timing.AUTO
-    )
+    @BenchmarkOperation(name = "HomePage",
+    max90th = 1,
+    timing = Timing.AUTO)
     public void doHomePage() throws IOException {
         logger.finer("HomePage: Accessing " + homepageURL);
 
@@ -417,13 +417,12 @@
         imagesLoaded = 0;
 
         StringBuilder responseBuffer = http.getResponseBuffer();
-        if (responseBuffer.length() == 0)
+        if (responseBuffer.length() == 0) {
             throw new IOException("Received empty response");
+        }
 
+        loadStatics(homepageStatics);
         Set<String> images = parseImages(responseBuffer);
-        if (!isCached) {
-            loadStatics(homepageStatics);
-        }
         loadImages(images);
         selectedEvent = RandomUtil.randomEvent(random, responseBuffer);
         logger.finer("Images loaded: " + imagesLoaded);
@@ -435,11 +434,9 @@
         }
     }
 
-    @BenchmarkOperation (
-        name    = "Login",
-        max90th = 1,
-        timing  = Timing.MANUAL
-    )
+    @BenchmarkOperation(name = "Login",
+    max90th = 1,
+    timing = Timing.MANUAL)
     public void doLogin() throws IOException, Exception {
         httpClient = new HttpClient();
         logger.finer("In doLogin");
@@ -452,9 +449,9 @@
 
         randomId = selectUserID();
         username = UserName.getUserName(randomId);
-        logger.fine("Logging in as " + username + ", " + randomId);
+        logger.finer("Logging in as " + username + ", " + randomId);
         PostMethod loginPost = constructLoginPost(randomId);
-        loginPost.setFollowRedirects(true);
+		//loginPost.setFollowRedirects(true);
 
         ctx.recordTime();
 
@@ -463,195 +460,180 @@
         ctx.recordTime();
 
         int loginIdx = loginPost.getResponseBodyAsString().indexOf("Login:");
-        if (loginIdx != -1)
-            throw new Exception(" Found login prompt at index " + loginIdx); 
+        if (loginIdx != -1) {
+            throw new Exception(" Found login prompt at index " + loginIdx);
+        }
 
-        logger.fine("Login successful as " + username + ", " + randomId);
-        isLoggedOn=true;
+        logger.finer("Login successful as " + username + ", " + randomId);
+        isLoggedOn = true;
     }
 
-
-    @BenchmarkOperation (
-        name    = "Logout",
-        max90th = 1,
-        timing  = Timing.AUTO
-    )
+    @BenchmarkOperation(name = "Logout",
+    max90th = 1,
+    timing = Timing.AUTO)
     public void doLogout() throws IOException {
-        if (isLoggedOn){
+        if (isLoggedOn) {
             logger.finer("Logging off = " + isLoggedOn);
-	    GetMethod logout = new GetMethod(logoutURL);
+            GetMethod logout = new GetMethod(logoutURL);
             httpClient.executeMethod(logout);
             cachedURLs.clear();
             isCached = cached();
-            isLoggedOn=false;
+            isLoggedOn = false;
         }
     }
 
-
-    @BenchmarkOperation (
-        name    = "TagSearch",
-        max90th = 2,
-        timing  = Timing.AUTO
-    )
+    @BenchmarkOperation(name = "TagSearch",
+    max90th = 2,
+    timing = Timing.AUTO)
     public void doTagSearch() throws IOException {
         String tag = RandomUtil.randomTagName(random);
         String search = tagSearchURL + "?tag=" + tag + "&submit=Search+Tags";
         logger.finer("TagSearch: " + search);
         http.fetchURL(search);
         StringBuilder responseBuffer = http.getResponseBuffer();
-        if (responseBuffer.length() == 0)
+        if (responseBuffer.length() == 0) {
             throw new IOException("Received empty response");
+        }
         Set<String> images = parseImages(responseBuffer);
         loadStatics(tagSearchStatics);
         loadImages(images);
         String event = RandomUtil.randomEvent(random, responseBuffer);
-        if (event != null)
+        if (event != null) {
             selectedEvent = event;
-        if (ctx.isTxSteadyState())
+        }
+        if (ctx.isTxSteadyState()) {
             driverMetrics.tagSearchImages += images.size();
+        }
     }
 
-    @NegativeExponential (
-        cycleType = CycleType.CYCLETIME,
-        cycleMean = 5000,
-		cycleMin = 1000,
-        cycleDeviation = 2
-    )
-    @BenchmarkOperation (
-        name    = "AddEvent",
-        max90th = 4,
-        timing  = Timing.MANUAL
-    )
+    @BenchmarkOperation(name = "AddEvent",
+    max90th = 4,
+    timing = Timing.MANUAL)
     public void doAddEvent() throws Exception {
         logger.finer("entering doAddEvent()");
-        if(!isLoggedOn)
+        if (!isLoggedOn) {
             throw new IOException("User not logged when trying to add an event");
+        }
 
         ctx.recordTime();
         loadStatics(addEventStatics);
 
-        MultipartPostMethod post = new MultipartPostMethod(addEventResultURL);
         GetMethod eventForm = new GetMethod(addEventURL);
 
-        StringPart tmpPart = null;
-        // TODO: Implement prepareEvent() for Rails form data
-
-        String nvp[][] = {{"commit", "Create"},
-                          {"event[title]", RandomUtil.randomText(random, 15, 20)},
-                          {"event[summary]", RandomUtil.randomText(random, 50, 200)},
-                          {"event[description]", RandomUtil.randomText(random, 100, 495)},
-                          {"event[telephone]", RandomUtil.randomPhone(random, new StringBuilder(256))},
-                          {"event[event_timestamp(1i)]", "2008"},
-                          {"event[event_timestamp(2i)]", "10"},
-                          {"event[event_timestamp(3i)]", "20"},
-                          {"event[event_timestamp(4i)]", "20"},
-                          {"event[event_timestamp(5i)]", "10"}};
-
-        for (int i = 0; i < nvp.length; i++) {            
-            tmpPart = new StringPart(nvp[i][0], nvp[i][1]);
-            tmpPart.setContentType(null);
-            post.addPart(tmpPart);
-        }
-
-        Part imagePart = new FilePart("event_image", eventImg, "image/jpeg", null);
-        Part docPart = new FilePart("event_document", eventPdf, "application/pdf", null);
-
-        post.addPart(imagePart);
-        post.addPart(docPart);
-
-        tmpPart = new StringPart("tag_list", "tag1");
-        tmpPart.setContentType(null);
+        ArrayList<Part> params = new ArrayList();
+        String[] parameters = prepareEvent();
+        if (parameters[0] == null || parameters[0].length() == 0) {
+            logger.warning("Socialevent title is null!");
+        } else {
+            logger.finer("addEvent adding event title: " + parameters[0]);
+        }
 
-        post.addPart(tmpPart);
+        params.add(new NullContentTypePart("event[title]", parameters[0]));
+        params.add(new NullContentTypePart("event[summary]", parameters[1]));
+        params.add(new NullContentTypePart("event[description]", parameters[2]));
+        params.add(new NullContentTypePart("event[telephone]", parameters[3]));
+// What about timezone ?
+        params.add(new NullContentTypePart("event[event_timestamp(1i)]", parameters[5]));
+        params.add(new NullContentTypePart("event[event_timestamp(2i)]", parameters[6]));
+        params.add(new NullContentTypePart("event[event_timestamp(3i)]", parameters[7]));
+        params.add(new NullContentTypePart("event[event_timestamp(4i)]", parameters[8]));
+        params.add(new NullContentTypePart("event[event_timestamp(5i)]", parameters[9]));
 
-        addAddress(post);
+        params.add(new NullContentTypePart("tag_list", parameters[10]));
+// No submitter_user_name ?
+        //add the address
+        String[] addressArr = prepareAddress();
+        params.add(new NullContentTypePart("address[street1]", addressArr[0]));
+        params.add(new NullContentTypePart("address[street2]", addressArr[1]));
+        params.add(new NullContentTypePart("address[city]", addressArr[2]));
+        params.add(new NullContentTypePart("address[state]", addressArr[3]));
+        params.add(new NullContentTypePart("address[zip]", addressArr[4]));
+        params.add(new NullContentTypePart("address[country]", addressArr[5]));
+
+        params.add(new FilePart("event_image", eventImg, "image/jpeg", null));
+        params.add(new FilePart("event_document", eventPdf, "application/pdf", null));
+        params.add(new NullContentTypePart("commit", "Create"));
 
         // GET the new event form within a user session
         httpClient.executeMethod(eventForm);
         String responseBuffer = eventForm.getResponseBodyAsString();
-        if (responseBuffer.length() == 0)
+        if (responseBuffer.length() == 0) {
             throw new IOException("Received empty response");
+        }
 
         // Parse the authenticity_token from the response
         String token = parseAuthToken(responseBuffer);
         if (token != null) {
-            tmpPart = new StringPart("authenticity_token", token);
-            tmpPart.setContentType(null);
-            post.addPart(tmpPart);
+            params.add(new NullContentTypePart("authenticity_token", token));
         }
 
+        Part[] parts = new Part[params.size()];
+        parts = params.toArray(parts);
+        PostMethod post = new PostMethod(addEventResultURL);
+        post.setRequestEntity(
+                new MultipartRequestEntity(parts, post.getParams()));
+
         doMultiPartPost(post, "Event was successfully created.");
 
+
         ctx.recordTime();
         ++driverMetrics.addEventTotal;
     }
 
-    @NegativeExponential (
-        cycleType = CycleType.CYCLETIME,
-        cycleMean = 5000,
-		cycleMin = 1000,
-        cycleDeviation = 2
-    )
-    @BenchmarkOperation (
-        name    = "AddPerson",
-        max90th = 3,
-        timing  = Timing.MANUAL
-    )
+    @BenchmarkOperation(name = "AddPerson",
+    max90th = 3,
+    timing = Timing.MANUAL)
     public void doAddPerson() throws Exception {
         logger.finer("doAddPerson");
-        if (isLoggedOn)
+        if (isLoggedOn) {
             doLogout();
+        }
 
         ctx.recordTime(); // Start critical section
         http.readURL(addPersonURL);
-        MultipartPostMethod post = new MultipartPostMethod(addPersonResultURL);
-        
-        // TODO: Implement preparePerson() for Rails form data
-        // String fields[]  = new String[8];
-        StringBuilder b = new StringBuilder(256);
-        int id = loadedUsers + personsAdded++ * ScaleFactors.activeUsers +
-                                                        ctx.getThreadId() + 1;
-        String username = UserName.getUserName(id);
-        if (username == null || username.length() == 0)
-            logger.warning("Username is null!");
-
-        http.readURL(checkNameURL, "name=" + username);
-
-        StringPart tmpPart = null;
+        loadStatics(addPersonStatics);
 
-        String nvp[][] = {{"user[username]", username},
-                          {"user[password]", "" + id},
-                          {"user[password_confirmation]", "" + id},
-                          {"user[firstname]",  RandomUtil.randomName(random, new StringBuilder(256),
2, 12).toString()},
-                          {"user[lastname]",  RandomUtil.randomName(random, new StringBuilder(256),
5, 12).toString()},
-                          {"user[email]", username + "@" + random.makeCString(3, 10) + ".com"},
-                          {"user[telephone]", RandomUtil.randomPhone(random, new StringBuilder(256)).toString()},
-                          {"user[summary]", RandomUtil.randomText(random, 50, 200)},
-                          {"user[timezone]", RandomUtil.randomTimeZone(random)}};
-
-        for (int i = 0; i < nvp.length; i++) {
-            tmpPart = new StringPart(nvp[i][0], nvp[i][1]);
-            tmpPart.setContentType(null);
-            post.addPart(tmpPart);
-        }
-        
-        Part imagePart = new FilePart("user_image", personImg, "image/jpeg", null);
-        post.addPart(imagePart);
-        
-        addAddress(post);
+        String[] parameters = preparePerson();
+        ArrayList<Part> params = new ArrayList();
+        // Debug
+        if (parameters[0] == null || parameters[0].length() == 0) {
+            logger.warning("Username is null!");
+        } else {
+            logger.finer("addPerson adding user: " + parameters[0]);
+        }
+        params.add(new NullContentTypePart("user[username]", parameters[0]));
+        http.readURL(checkNameURL, "name=" + parameters[0]);
 
-        loadStatics(addPersonStatics);
+        params.add(new NullContentTypePart("user[password]", parameters[1]));
+        params.add(new NullContentTypePart("user[password_confirmation]", parameters[1]));
+        params.add(new NullContentTypePart("user[firstname]", parameters[2]));
+        params.add(new NullContentTypePart("user[lastname]", parameters[3]));
+        params.add(new NullContentTypePart("user[email]", parameters[4]));
+        String[] addressArr = prepareAddress();
+        params.add(new NullContentTypePart("address[street1]", addressArr[0]));
+        params.add(new NullContentTypePart("address[street2]", addressArr[1]));
+        params.add(new NullContentTypePart("address[city]", addressArr[2]));
+        params.add(new NullContentTypePart("address[state]", addressArr[3]));
+        params.add(new NullContentTypePart("address[zip]", addressArr[4]));
+        params.add(new NullContentTypePart("address[country]", addressArr[5]));
+        params.add(new NullContentTypePart("user[telephone]", parameters[5]));
+        params.add(new NullContentTypePart("user[timezone]", parameters[7]));
+        params.add(new NullContentTypePart("user[summary]", parameters[6]));
+        params.add(new FilePart("user_image", personImg, "image/jpeg", null));
+        Part[] parts = new Part[params.size()];
+        parts = params.toArray(parts);
+        PostMethod post = new PostMethod(addPersonResultURL);
+        post.setRequestEntity(
+                new MultipartRequestEntity(parts, post.getParams()));
         doMultiPartPost(post, "Succeeded in creating user.");
 
         ctx.recordTime();
         ++driverMetrics.addPersonTotal;
     }
 
-    @BenchmarkOperation (
-        name    = "EventDetail",
-        max90th = 2,
-        timing  = Timing.AUTO
-    )
+    @BenchmarkOperation(name = "EventDetail",
+    max90th = 2,
+    timing = Timing.AUTO)
     public void doEventDetail() throws Exception {
         //select random event
         logger.finer("doEventDetail");
@@ -662,69 +644,73 @@
             selectedEvent = RandomUtil.randomEvent(random, responseBuffer);
             if (selectedEvent == null) {
                 throw new IOException("In event detail and select event is null");
-            }    
+            }
         }
 
         http.fetchURL(eventDetailURL + selectedEvent);
         StringBuilder responseBuffer = http.getResponseBuffer();
-        if (responseBuffer.length() == 0)
+        if (responseBuffer.length() == 0) {
             throw new IOException("Received empty response");
+        }
         boolean canAddAttendee = isLoggedOn &&
-            responseBuffer.indexOf("Unattend") == -1;
+                responseBuffer.indexOf("Unattend") == -1;
 
         Set<String> images = parseImages(responseBuffer);
         loadStatics(eventDetailStatics);
         loadImages(images);
-        if (ctx.isTxSteadyState())
+        if (ctx.isTxSteadyState()) {
             driverMetrics.eventDetailImages += images.size();
+        }
         if (canAddAttendee) {
             // 10% of the time we can add ourselves, we will.
             int card = random.random(0, 9);
             if (card == 0) {
                 doAddAttendee();
-                if (ctx.isTxSteadyState())
+                if (ctx.isTxSteadyState()) {
                     ++driverMetrics.addAttendeeCount;
+                }
             }
-            if (ctx.isTxSteadyState())
+            if (ctx.isTxSteadyState()) {
                 ++driverMetrics.addAttendeeReadyCount;
+            }
         }
     }
 
-    @BenchmarkOperation (
-        name = "PersonDetail",
-        max90th = 2,
-        timing = Timing.MANUAL
-    )
+    @BenchmarkOperation(name = "PersonDetail",
+    max90th = 2,
+    timing = Timing.MANUAL)
     public void doPersonDetail() throws IOException {
         logger.finer("doPersonDetail");
         StringBuilder buffer = new StringBuilder(fileServiceURL.length() + 20);
         //buffer.append(fileServiceURL).append("file=p");
-        
+
         ctx.recordTime();
-		// Shanti: No need to be logged on to see user
-		/**
+        // Shanti: No need to be logged on to see user
+        /**
         if (isLoggedOn) {
-		**/
-            int id = random.random(1, ScaleFactors.users);
-            GetMethod personDetailGet = new GetMethod(personDetailURL + id);
-            httpClient.executeMethod(personDetailGet);
-            StringBuilder responseBuffer = new StringBuilder(personDetailGet.getResponseBodyAsString());
-            if (responseBuffer.length() == 0)
-                throw new IOException("Received empty response");
-            Set<String> images = parseImages(responseBuffer);
-			loadImages(images);
-            String event = RandomUtil.randomEvent(random, responseBuffer);
-            if (event != null)
-                selectedEvent = event;
-		/***
+         **/
+        int id = random.random(1, ScaleFactors.users);
+        GetMethod personDetailGet = new GetMethod(personDetailURL + id);
+        httpClient.executeMethod(personDetailGet);
+        StringBuilder responseBuffer = new StringBuilder(personDetailGet.getResponseBodyAsString());
+        if (responseBuffer.length() == 0) {
+            throw new IOException("Received empty response");
+        }
+        Set<String> images = parseImages(responseBuffer);
+        loadImages(images);
+        String event = RandomUtil.randomEvent(random, responseBuffer);
+        if (event != null) {
+            selectedEvent = event;
+        }
+        /***
         }
         else
         {
-            // Need to handle this better. User profile is only for logged in users.
-            logger.warning("Trying to view user, but not logged in");
-            http.fetchURL(homepageURL);
+        // Need to handle this better. User profile is only for logged in users.
+        logger.warning("Trying to view user, but not logged in");
+        http.fetchURL(homepageURL);
         }
-		***/
+         ***/
         ctx.recordTime();
     }
 
@@ -732,7 +718,8 @@
         //can only add yourself (one attendee) to party
         // Need to add header that will request js instead of
         // html. This will prevent the redirect.
-        PostMethod attendeePost = new PostMethod(addAttendeeURL + selectedEvent + "/attend");
+        PostMethod attendeePost = new PostMethod(addAttendeeURL +
+                selectedEvent + "/attend");
         Header header = new Header("Accept", "text/javascript");
         attendeePost.setRequestHeader(header);
         int status = httpClient.executeMethod(attendeePost);
@@ -742,7 +729,7 @@
         String buffer = attendeePost.getResponseBodyAsString();
         if (buffer.indexOf("You are attending") == -1) {
             logger.warning("Add attendee failed, possible race condition");
-            // throw new Exception("Add attendee failed, could not find: You are attending");
+        // throw new Exception("Add attendee failed, could not find: You are attending");
         }
     }
 
@@ -759,12 +746,14 @@
 
             // Find and copy out the element.
             idx = buffer.indexOf(elStart, idx);
-            if (idx == -1)
+            if (idx == -1) {
                 break;
+            }
             idx += elStartLen;
             int endIdx = buffer.indexOf(")", idx) + 1; // +1 to include the '('
-            if (endIdx == -1)
+            if (endIdx == -1) {
                 break;
+            }
             String elText = buffer.substring(idx, endIdx);
             logger.finest(elText);
             idx = endIdx + 1;
@@ -803,16 +792,18 @@
 
         int endIdx = responseBuffer.indexOf("\" />", idx);
 
-        if (endIdx == -1)
+        if (endIdx == -1) {
             throw new IOException("Invalid authenticity_token element. Buffer(100 chars)
= " +
                     responseBuffer.substring(idx, idx + 100));
+        }
 
         String tmpString = responseBuffer.substring(idx, endIdx);
         String[] splitStr = tmpString.split("value=\"");
 
-        if (splitStr.length < 2)
+        if (splitStr.length < 2) {
             throw new IOException("Invalid authenticity_token element. Buffer(100 chars)
= " +
                     responseBuffer.substring(idx, idx + 100));
+        }
 
         String token = splitStr[1];
 
@@ -854,30 +845,37 @@
     }
 
     private void loadStatics(String[] urls) throws IOException {
-        if (!isCached) {
+        // Comment out next line to test if-modified-since headers
+        // if (!isCached) {
             for (String url : urls) {
-                if (cachedURLs.add(url)) {
-                    logger.finer("Loading URL " + url);
-                    http.readURL(url);
-                } else {
-                    logger.finer("URL already cached: Not loading " + url);
+            // If we are simulating browser caching, send if-modified-since
+           // hdr. We won't check return code.
+                if (isCached)
+                    http.readURL(url, cachedHeaders);
+                else {
+                    if (cachedURLs.add(url)) {
+                        logger.finer("Loading URL " + url);
+                        http.readURL(url);
+                    } else {
+                        logger.finer("URL already cached: Not loading " + url);
+                    }
                 }
             }
-        }
+        // }
     }
 
     public DateFormat getDateFormat() {
-        if (df == null)
-            df = new SimpleDateFormat("yyyy-MM-dd");
+        if (df == null) {
+            df = new SimpleDateFormat("yyyy-MM-dd-hh-mm");
+        }
         return df;
     }
 
     public int selectUserID() {
         return random.random(0, ScaleFactors.USERS_RATIO - 1) *
-                     ScaleFactors.activeUsers + ctx.getThreadId() + 1;
+                ScaleFactors.activeUsers + ctx.getThreadId() + 1;
     }
 
-
     private String[] populateList(String[] arrList) {
 
         String[] returnList = new String[arrList.length];
@@ -889,7 +887,7 @@
 
                 }
             } catch (Exception e) {
-                System.out.println ("Exception - " + e);
+                System.out.println("Exception - " + e);
                 e.printStackTrace();
             }
         }
@@ -897,94 +895,147 @@
     }
 
     private PostMethod constructLoginPost(int randomId) {
+        /***
+        ArrayList<Part> loginparams = new ArrayList();
+        loginparams.add(new NullContentTypePart("users[username]", username));
+        loginparams.add(new NullContentTypePart("users[password]", String.valueOf(randomId)));
+        loginparams.add(new NullContentTypePart("submit", "Login"));
+         ***/
         PostMethod loginPost = new PostMethod(loginURL);
 
-        loginPost.setFollowRedirects(true);
+        // loginPost.setFollowRedirects(true);
         loginPost.addParameter("users[username]", username);
         loginPost.addParameter("users[password]", String.valueOf(randomId));
         loginPost.addParameter("submit", "Login");
-        
+
         return loginPost;
+
     }
 
-    public void doMultiPartPost(MultipartPostMethod post, String message) throws Exception
{
+    public void doMultiPartPost(PostMethod post, String message)
+            throws Exception {
         logger.finer("In doMultiPartPost()");
 
         if (httpClient == null) {
             logger.warning("HttpClient is null, this shouldn't happen");
-            httpClient = new HttpClient();
-            httpClient.setConnectionTimeout(5000);
+            HttpClient httpClient = ((ApacheHC3Transport) http).getHttpClient();
+            httpClient.getHttpConnectionManager().getParams().
+                    setConnectionTimeout(5000);
         }
 
-        post.setFollowRedirects(false);
         int status = httpClient.executeMethod(post);
-        if (status == HttpStatus.SC_MOVED_TEMPORARILY) {
+		Header locationHeader = post.getResponseHeader("location");
+		if (locationHeader != null) {
+			/*********
             // Manually follow redirect
-            GetMethod get = new GetMethod(post.getResponseHeader("Location").getValue());
+            // GetMethod get = new GetMethod(post.getResponseHeader("Location").getValue());
             httpClient.executeMethod(get);
             String buffer = get.getResponseBodyAsString();
             int idx = buffer.indexOf(message);
-            if (idx == -1 )
+            if (idx == -1) {
                 throw new Exception("Could not find success message '" + message + "' in
result body");
+            }
+			*********/
+			logger.fine("locationHeader is not null");
+			String redirectLocation = locationHeader.getValue();
+			// Release the connection after we get location
+			post.releaseConnection();
+			logger.fine("redirectLocation is " + redirectLocation);
+			http.fetchURL(redirectLocation);
         } else if (status != HttpStatus.SC_OK) {
-            throw new Exception("Multipart post did not redirect");
+            throw new IOException("Multipart post did not work, returned status code: " +
status);
         }
     }
 
-    // TODO: implement prepareAddress() for Rails form data
-    public void addAddress(MultipartPostMethod post)
-    {
+    public String[] prepareEvent() {
 
-        StringPart tmpPart = null;
-        //add the address
-        String nvp[][] = {{"address[street1]", street1()},
-                          {"address[street2]",street2()},
-                          {"address[city]", random.makeCString(4, 14)},
-                          {"address[state]", random.makeCString(2, 2).toUpperCase()},
-                          {"address[zip]", random.makeNString(5, 5)},
-                          {"address[country]", country()}};
-
-        for (int i = 0; i < nvp.length; i++) {
-            tmpPart = new StringPart(nvp[i][0], nvp[i][1]);
-            tmpPart.setContentType(null);
-            post.addPart(tmpPart);
+        String fields[] = new String[11];
+        StringBuilder buffer = new StringBuilder(256);
+        fields[0] = RandomUtil.randomText(random, 15, 20); //title
+        fields[1] = RandomUtil.randomText(random, 50, 200); //summary
+        fields[2] = RandomUtil.randomText(random, 100, 495); // description
+
+        int numTags = random.random(1, 7); // Avg is 4 tags per event
+        for (int i = 0; i < numTags; i++) {
+            tagSet.add(RandomUtil.randomTagId(random, 0.1d));
+        }
+
+        for (int tagId : tagSet) {
+            tags.append(UserName.getUserName(tagId)).append(' ');
+        }
+        tags.setLength(tags.length() - 1);
+
+        fields[10] = tags.toString();
+        tags.setLength(0);
+        tagSet.clear();
+
+        fields[3] = RandomUtil.randomPhone(random, buffer); //phone
+        fields[4] = RandomUtil.randomTimeZone(random); // timezone
+        DateFormat dateFormat = getDateFormat(); // eventtimestamp
+        String dateTime = dateFormat.format( //eventtimestamp
+                random.makeDateInInterval(BASE_DATE, 0, 540));
+        StringTokenizer t = new StringTokenizer(dateTime, "-");
+        int i = 5;
+        while (t.hasMoreTokens()) {
+            fields[i++] = t.nextToken();
         }
+        return fields;
     }
 
-    public String street1() {
-        String[] STREETEXTS = { "Blvd", "Ave", "St", "Ln", "" };
+    public String[] prepareAddress() {
+
+        String[] STREETEXTS = {"Blvd", "Ave", "St", "Ln", ""};
         StringBuilder buffer = new StringBuilder(255);
         buffer.append(random.makeNString(1, 5)).append(' '); // number
         RandomUtil.randomName(random, buffer, 1, 11); // street
         String streetExt = STREETEXTS[random.random(0, STREETEXTS.length - 1)];
-        if (streetExt.length() > 0)
+        if (streetExt.length() > 0) {
             buffer.append(' ').append(streetExt);
-    	return buffer.toString();
-    }
+        }
+        String[] fields = new String[6];
+        fields[0] = buffer.toString();
 
-    public String street2() {
         int toggle = random.random(0, 1); // street2
-        String street;
-        if (toggle > 0)
-          street = random.makeCString(5, 20);
-        else
-          street = "";
-        return street;
-    }
+        if (toggle > 0) {
+            fields[1] = random.makeCString(5, 20);
+        } else {
+            fields[1] = "";
+        }
 
-    public String country() {
-        int toggle = random.random(0, 1);
-        StringBuilder buffer = new StringBuilder(255);
-        String cntry;
+        fields[2] = random.makeCString(4, 14); // city
+        fields[3] = random.makeCString(2, 2).toUpperCase(); // state
+        fields[4] = random.makeNString(5, 5);  // zip
+
+        toggle = random.random(0, 1);
         if (toggle == 0) {
-          cntry = "USA";
+            fields[5] = "USA";
         } else {
-          cntry = RandomUtil.randomName(random, buffer, 6, 16).toString();
+            buffer.setLength(0);
+            fields[5] = RandomUtil.randomName(random, buffer, 6, 16).toString();
         }
+        return fields;
+    }
 
-    return cntry;
+    public String[] preparePerson() {
+        String fields[] = new String[8];
+        StringBuilder b = new StringBuilder(256);
+        int id = loadedUsers + personsAdded++ * ScaleFactors.activeUsers +
+                ctx.getThreadId() + 1;
+        fields[0] = UserName.getUserName(id);
+        //use the same field for repeating the password field.
+        fields[1] = String.valueOf(id);
+        fields[2] = RandomUtil.randomName(random, b, 2, 12).toString();
+        b.setLength(0);
+        fields[3] = RandomUtil.randomName(random, b, 5, 15).toString();
+        fields[4] = random.makeCString(3, 10);
+        fields[4] = fields[2] + '_' + fields[3] + '@' + fields[4] + ".com";
+        b.setLength(0);
+        fields[5] = RandomUtil.randomPhone(random, b);
+        fields[6] = random.makeAString(250, 2500);
+        fields[7] = RandomUtil.randomTimeZone(random);
+        return fields;
     }
-    
+
     static class UIDriverMetrics implements CustomMetrics {
 
         int addAttendeeCount = 0;
@@ -1020,10 +1071,11 @@
             if (total > 0) {
                 double pctAdd = 100d * addAttendeeCount / (double) total;
                 el[0].result = String.format("%.2f", pctAdd);
-                if (pctAdd >= 6d)
+                if (pctAdd >= 6d) {
                     el[0].passed = Boolean.TRUE;
-                else
+                } else {
                     el[0].passed = Boolean.FALSE;
+                }
             } else {
                 el[0].result = "";
                 el[0].passed = Boolean.FALSE;
@@ -1041,10 +1093,11 @@
             if (cnt > 0) {
                 double imagesPerPage = homePageImages / (double) cnt;
                 el[2].result = String.format("%.2f", imagesPerPage);
-                if (imagesPerPage >= 9.5d && imagesPerPage <= 10.5d)
+                if (imagesPerPage >= 9.5d && imagesPerPage <= 10.5d) {
                     el[2].passed = Boolean.TRUE;
-                else
+                } else {
                     el[2].passed = Boolean.FALSE;
+                }
             } else {
                 el[2].result = "";
                 el[2].passed = Boolean.FALSE;
@@ -1057,10 +1110,11 @@
             if (cnt > 0) {
                 double avgImgs = homePageImagesLoaded / (double) cnt;
                 el[3].result = String.format("%.2f", avgImgs);
-                if (avgImgs >= 2.5)
+                if (avgImgs >= 2.5) {
                     el[3].passed = Boolean.TRUE;
-                else
+                } else {
                     el[3].passed = Boolean.FALSE;
+                }
             } else {
                 el[3].result = "";
                 el[3].passed = Boolean.FALSE;
@@ -1072,10 +1126,11 @@
             if (cnt > 0) {
                 double avgBytes = homePageImageBytes / (double) cnt;
                 el[4].result = String.format("%.2f", avgBytes);
-                if (avgBytes >= 15000)
+                if (avgBytes >= 15000) {
                     el[4].passed = Boolean.TRUE;
-                else
+                } else {
                     el[4].passed = Boolean.FALSE;
+                }
             } else {
                 el[4].result = "";
                 el[4].passed = Boolean.FALSE;
@@ -1087,10 +1142,11 @@
             if (cnt > 0) {
                 double avgImgs = tagSearchImages / (double) cnt;
                 el[5].result = String.format("%.2f", avgImgs);
-                if (avgImgs >= 3.6d)
+                if (avgImgs >= 3.6d) {
                     el[5].passed = Boolean.TRUE;
-                else
+                } else {
                     el[5].passed = Boolean.FALSE;
+                }
             } else {
                 el[5].result = "";
                 el[5].passed = Boolean.FALSE;
@@ -1101,10 +1157,11 @@
             if (total > 0) {
                 double avgImgs = eventDetailImages / (double) total;
                 el[6].result = String.format("%.2f", avgImgs);
-                if (avgImgs >= 1d)
+                if (avgImgs >= 1d) {
                     el[6].passed = Boolean.TRUE;
-                else
+                } else {
                     el[6].passed = Boolean.FALSE;
+                }
             } else {
                 el[6].result = "";
                 el[6].passed = Boolean.FALSE;
@@ -1120,10 +1177,11 @@
             el[9].target = "&lt;= 5.25";
             double ratio = r.getScale() / r.getMetric();
             el[9].result = String.format("%.2f", ratio);
-            if (ratio <= 5.25d)
+            if (ratio <= 5.25d) {
                 el[9].passed = true;
-            else
+            } else {
                 el[9].passed = false;
+            }
             return el;
         }
 
@@ -1141,4 +1199,15 @@
             return clone;
         }
     }
+    
+    /*
+     * StringPart doesn't work for Rack 1.0.0 unless it's contentType
+     * is set to null
+     */
+    class NullContentTypePart extends StringPart {
+      public NullContentTypePart(String name, String value) {
+          super(name, value);
+          this.setContentType(null);
+      }
+    }
 }



Mime
View raw message