You are viewing a plain text version of this content. The canonical link for it is here.
Posted to olio-commits@incubator.apache.org by ws...@apache.org on 2009/01/28 18:30:44 UTC

svn commit: r738580 - in /incubator/olio/workload/rails/trunk/src/com/sun/web20: driver/UIDriver.java util/RandomUtil.java

Author: wsobel
Date: Wed Jan 28 18:30:44 2009
New Revision: 738580

URL: http://svn.apache.org/viewvc?rev=738580&view=rev
Log:
OLIO-36: Applied patches to Rails driver to fix session management issue (Mandy Waite)

Modified:
    incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java
    incubator/olio/workload/rails/trunk/src/com/sun/web20/util/RandomUtil.java

Modified: incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java?rev=738580&r1=738579&r2=738580&view=diff
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java (original)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/driver/UIDriver.java Wed Jan 28 18:30:44 2009
@@ -40,6 +40,10 @@
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.logging.Logger;
+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.Part;
 
 @BenchmarkDefinition (
     name    = "Web20Bench",
@@ -59,11 +63,11 @@
     operations = { "HomePage", "Login", "TagSearch", "EventDetail", "PersonDetail", "AddPerson", "AddEvent" },
 
     mix = { @Row({  0, 10, 50, 35,  0, 5,  0 }), // Home Page
-            @Row({  0,  0, 60, 20,  0, 0, 20 }), // Login
+            @Row({  0,  0, 30, 20, 20, 0, 30 }), // Login
             @Row({ 20,  5, 40, 30,  0, 5,  0 }), // Tag Search
             @Row({ 70, 20,  0,  0,  0, 5,  0 }), // Event Detail
             @Row({  0,  0,  0, 30, 10, 0, 30 }), // Person Detail
-            @Row({ 30, 65,  0,  0, 15, 0,  0 }), // Add Person
+            @Row({ 30, 65,  0,  0,  0, 0,  0 }), // Add Person
             @Row({  0,  0, 25, 75, 15, 0,  0 })  // Add Event
           }
 )
@@ -302,6 +306,15 @@
         "/images/main_nav_hover_bg.gif"
     };
 
+    /* Custom metric targets */
+    public static final double EVENT_VIEWS_WHERE_ATTENDEE_ATTENDED_TARGET = 8d;
+    public static final double AVG_IMAGE_REFS_PER_HOMEPAGE_TARGET = 10d;
+    public static final double AVG_IMAGES_LOADED_PER_HOMEPAGE_TARGET = 3d;
+    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());
@@ -338,6 +351,8 @@
     private int imagesLoaded = 0;
     private String tagCloudURL;
 
+    private HttpClient httpClient;
+
     public UIDriver() throws XPathExpressionException {
         ctx = DriverContext.getContext();
         int scale = ctx.getScale();
@@ -420,6 +435,8 @@
 
         isLoggedOn = false;
         isCached = cached();
+        httpClient = new HttpClient();
+        httpClient.setConnectionTimeout(5000);
     }
 
     @BenchmarkOperation (
@@ -458,39 +475,50 @@
     @BenchmarkOperation (
         name    = "Login",
         max90th = 1,
-        timing  = Timing.AUTO
+        timing  = Timing.MANUAL
     )
     public void doLogin() throws IOException, Exception {
+
+        httpClient = new HttpClient();
         logger.finer("In doLogin");
         int randomId = 0; //use as password
         username = null;
 
-        if (!isLoggedOn) {
+        if (isLoggedOn) {
+            //already logged in --> logout,then log in again
+            doLogout();
+        }
+
+        // http.fetchURL(loginURL);
+        // HttpClient _httpClient = new HttpClient();
+        // _httpClient.setConnectionTimeout(5000);
+
+        // httpClient = _httpClient;
+
             randomId = selectUserID();
             username = UserName.getUserName(randomId);
             logger.fine("Logging in as " + username + ", " + randomId);
-            http.readURL(loginURL, constructLoginPost(randomId), loginHeaders);
-            // This redirects to home.
-            http.fetchURL(homepageURL);
-            int loginIdx = http.getResponseBuffer().indexOf("Login:");
+        PostMethod loginPost = constructLoginPost(randomId);
+
+        ctx.recordTime();
+
+        httpClient.executeMethod(loginPost);
+
+        // Should redirect automatically but doesn't seem to
+        GetMethod loginGet = new GetMethod(homepageURL);
+        httpClient.executeMethod(loginGet);
+
+        ctx.recordTime();
+
+        int loginIdx = loginGet.getResponseBodyAsString().indexOf("Login:");
             if (loginIdx != -1)
                 throw new Exception(" Found login prompt at index " + loginIdx); 
             
-            /*if (http.getResponseBuffer().indexOf("Login:") != 1216) {
-                logger.finest(http.getResponseBuffer().toString());
-                //throw new RuntimeException("Index of LOGIN = " +http.getResponseBuffer().indexOf("Login:") );
-                //logger.info(http.getResponseBuffer().toString());
-                throw new RuntimeException("Login as " + username + ", " +
-                                                        randomId + " failed.");
-            }*/
-            //logger.fine("Login successful as " + username + ", " + randomId);
+        logger.fine("Login successful as " + username + ", " + randomId);
             isLoggedOn=true;
-        } else {
-            //already logged in --> logout,then log in again
-            doLogout();
-            doLogin();
+  
+
         }
-    }
 
 
     @BenchmarkOperation (
@@ -501,11 +529,11 @@
     public void doLogout() throws IOException {
         if (isLoggedOn){
             logger.finer("Logging off = " + isLoggedOn);
-            http.fetchURL(logoutURL);
+            httpClient.executeMethod(new GetMethod(logoutURL));
             cachedURLs.clear();
             isCached = cached();
             isLoggedOn=false;
-            http = new HttpTransport(); // clear all state
+            // httpClient = new HttpClient(); // clear all state
         }
     }
 
@@ -539,14 +567,20 @@
         timing  = Timing.MANUAL
     )
     public void doAddEvent() throws IOException {
-        logger.finer("doAddEvent");
+        logger.finer("entering doAddEvent()");
+        if(!isLoggedOn)
+            throw new IOException("User not logged when trying to add an event");
+
         ctx.recordTime();
-        http.readURL(addEventURL);
         loadStatics(addEventStatics);
 
         MultipartPostMethod post = new MultipartPostMethod(addEventResultURL);
-        if(isLoggedOn) {
+        GetMethod eventForm = new GetMethod(addEventURL);
+
+        // TODO: Implement prepareEvent() for Rails form data
 		    StringBuilder buffer = new StringBuilder(256);
+        post.addParameter("commit", "Create");
+        // post.addParameter("controller", "events");
 		    post.addParameter("event[title]", RandomUtil.randomText(random, 15, 20));
 		    post.addParameter("event[summary]", RandomUtil.randomText(random, 50, 200));
             post.addParameter("event[description]", RandomUtil.randomText(random, 100, 495));
@@ -557,15 +591,27 @@
             post.addParameter("event[event_timestamp(4i)]", "20");
             post.addParameter("event[event_timestamp(5i)]", "10");
 
-            // We do the images last, not to split the fields into parts
-            post.addParameter("event[image]", eventImg);
-            post.addParameter("event[document]", eventPdf);
-            post.addParameter("tag_list", random.makeCString(4, 14));
+        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);
+        post.addParameter("tag_list", "tag1");
 
             addAddress(post);
             
+        // GET the new event form within a user session
+        httpClient.executeMethod(eventForm);
+        String responseBuffer = eventForm.getResponseBodyAsString();
+        if (responseBuffer.length() == 0)
+             throw new IOException("Received empty response");
+
+        // Parse the authenticity_token from the response
+        String token = parseAuthToken(responseBuffer);
+
+        post.addParameter("authenticity_token", token);
+        
             doMultiPartPost(post);
-        }
         
         ctx.recordTime();
         ++driverMetrics.addEventTotal;
@@ -581,12 +627,11 @@
         if (isLoggedOn)
             doLogout();
 
-        ctx.recordTime();
+        ctx.recordTime(); // Start critical section
         http.readURL(addPersonURL);
-        loadStatics(addPersonStatics);
-
         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 +
@@ -609,11 +654,14 @@
         post.addParameter("user[summary]", RandomUtil.randomText(random, 50, 200));
         post.addParameter("user[timezone]", RandomUtil.randomTimeZone(random));
         
-        // Images
-        post.addParameter("user_image", personImg);        
+        Part imagePart = new FilePart("user_image", personImg, "image/jpeg", null);
+        post.addPart(imagePart);
         
         addAddress(post);
+
+        loadStatics(addPersonStatics);
         doMultiPartPost(post);
+
         ctx.recordTime();
         ++driverMetrics.addPersonTotal;
     }
@@ -666,17 +714,19 @@
     @BenchmarkOperation (
         name = "PersonDetail",
         max90th = 2,
-        timing = Timing.AUTO
+        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();
         if (isLoggedOn) {
             int id = random.random(1, ScaleFactors.users);
-            http.fetchURL(personDetailURL + id);
-            StringBuilder responseBuffer = http.getResponseBuffer();
+            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");
 
@@ -696,18 +746,45 @@
             logger.warning("Trying to view user, but not logged in");
             http.fetchURL(homepageURL);
         }
+        ctx.recordTime();
     }
 
     public void doAddAttendee() throws IOException {
         //can only add yourself (one attendee) to party
-        http.readURL(addAttendeeURL + selectedEvent + "/attend", "");
+        PostMethod attendeePost = new PostMethod(addAttendeeURL + selectedEvent + "/attend");
+        int status = httpClient.executeMethod(attendeePost);
+                
+        switch (status) {
+            case HttpStatus.SC_ACCEPTED:
+                logger.finer("Status = SC_ACCEPTED");
+                break;
+            case HttpStatus.SC_MOVED_TEMPORARILY:
+                logger.finer("Status = SC_MOVED_TEMPORARILY");
+                // System.out.println(post.getResponseBodyAsString());
+                // for (Header header: post.getResponseHeaders()) {
+                //     logger.info(header.getName() + ":" + header.getValue());
+                // }
+                httpClient.executeMethod(new GetMethod(attendeePost.getResponseHeader("Location").getValue()));
+                break;
+            case HttpStatus.SC_OK:
+                logger.finer("Status = SC_OK");
+                break;
+            default:
+                String statusHeaderStr = attendeePost.getResponseHeader("Status").getValue();
+                logger.finer("Status = " + statusHeaderStr);
+        }
+        if (status != HttpStatus.SC_OK && status != HttpStatus.SC_MOVED_TEMPORARILY) {
+            throw new IOException("GET operation failed");
+        }
+
         // http.readURL(updatePageURL, "list=attendees");
     }
 
     public Set<String> parseImages(StringBuilder buffer) {
         LinkedHashSet<String> urlSet = new LinkedHashSet<String>();
-        String elStart = "<img ";
-        String attrStart = " src=\"";
+        //String elStart = "<img ";
+        String elStart = "background: ";
+        String attrStart = " url(";
         int elStartLen = elStart.length() - 1; // Don't include the trailing space
         int attrStartLen = attrStart.length();
         int idx = 0;
@@ -719,10 +796,11 @@
             if (idx == -1)
                 break;
             idx += elStartLen;
-            int endIdx = buffer.indexOf("/>", idx);
+            int endIdx = buffer.indexOf(")", idx) + 1; // +1 to include the '('
             if (endIdx == -1)
                 break;
             String elText = buffer.substring(idx, endIdx);
+            logger.finest(elText);
             idx = endIdx + 1;
 
             // Find the attribute
@@ -731,34 +809,67 @@
                 logger.finer("No img src attribute. Weird! " + elText);
                 continue;
             }
-            endIdx = elText.indexOf("\"", idx2 + attrStartLen);
+            endIdx = elText.indexOf(")", idx2 + attrStartLen);
             if (endIdx == -1) {
                 logger.warning("No img src attribute ending. Weird! " + elText);
                 continue;
             }
 
             String link = elText.substring(idx2 + attrStartLen, endIdx);
-            if (link.startsWith("fileService.")) {
+            if (link.startsWith("/filestore")) {
                 String url = baseURL + '/' + link;
 
-                logger.finest("Adding " + url + " from idx " + idx);
+                logger.finer("Adding " + url + " from idx " + idx);
                 urlSet.add(url);
             }
         }
         return urlSet;
     }
 
+    private String parseAuthToken(String responseBuffer) throws IOException {
+
+        int idx = responseBuffer.indexOf("authenticity_token");
+
+        if (idx == -1)
+            throw new IOException("Trying to add event but authenticity token not found");
+
+        int endIdx = responseBuffer.indexOf("\" />", idx);
+
+        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)
+            throw new IOException("Invalid authenticity_token element. Buffer(100 chars) = " +
+                    responseBuffer.substring(idx, idx + 100));
+
+        String token = splitStr[1];
+
+        logger.finer("authenticity_token = " + token);
+
+        return token;
+
+    }
+
     private void loadImages(Set<String> images) throws IOException {
+        logger.finer("loadImages()");
+        logger.finest("No. images = " + images.size());
+
         if (images != null)
             for (String image : images)
                 // Loads image only if not cached, means we can add to cache.
                 if (cachedURLs.add(image)) {
-                    logger.finer("Loading image " + image);
+                    logger.finest("Loading image " + image);
                     imgBytes += http.readURL(image);
                     ++imagesLoaded;
                 } else {
-                    logger.finer("Image already cached: Not loading " + image);
+                    logger.finest("Image already cached: Not loading " + image);
                 }
+        else
+            logger.finest("images == null");
     }
 
     private boolean cached() {
@@ -814,20 +925,53 @@
         return returnList;
     }
 
-    private String constructLoginPost(int randomId) {
-        return "users[username]=" + username + "&users[password]=" +
-                String.valueOf(randomId) + "&submit=Login";
+    private PostMethod constructLoginPost(int randomId) {
+        PostMethod loginPost = new PostMethod(loginURL);
+
+        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) throws IOException {
+        logger.finer("In doMultiPartPost()");
 
-        HttpClient client = new HttpClient();
-        client.setConnectionTimeout(5000);
-        int status = client.executeMethod(post);
-        if(status != HttpStatus.SC_OK)
+        if (httpClient == null) {
+            logger.warning("HttpClient is null, this shouldn't happen");
+            httpClient = new HttpClient();
+            httpClient.setConnectionTimeout(5000);
+        }
+
+        post.setFollowRedirects(false);
+        int status = httpClient.executeMethod(post);
+        switch (status) {
+            case HttpStatus.SC_ACCEPTED:
+                logger.finer("Status = SC_ACCEPTED");
+                break;
+            case HttpStatus.SC_MOVED_TEMPORARILY:
+                logger.finer("Status = SC_MOVED_TEMPORARILY");
+                // System.out.println(post.getResponseBodyAsString());
+                // for (Header header: post.getResponseHeaders()) {
+                //     logger.info(header.getName() + ":" + header.getValue());
+                // }
+                httpClient.executeMethod(new GetMethod(post.getResponseHeader("Location").getValue()));
+                break;
+            case HttpStatus.SC_OK:
+                logger.finer("Status = SC_OK");
+                break;
+            default:
+                String statusHeaderStr = post.getResponseHeader("Status").getValue();
+                logger.finer("Status = " + statusHeaderStr);
+        }
+        if (status != HttpStatus.SC_OK && status != HttpStatus.SC_MOVED_TEMPORARILY) {
             throw new IOException("Multipart Post did not work");
     }
+    }
 
+    // TODO: implement prepareAddress() for Rails form data
     public void addAddress(MultipartPostMethod post)
     {
         //add the address
@@ -988,7 +1132,7 @@
             if (total > 0) {
                 double avgImgs = eventDetailImages / (double) total;
                 el[6].result = String.format("%.2f", avgImgs);
-                if (avgImgs >= 9d)
+                if (avgImgs >= 1d)
                     el[6].passed = Boolean.TRUE;
                 else
                     el[6].passed = Boolean.FALSE;

Modified: incubator/olio/workload/rails/trunk/src/com/sun/web20/util/RandomUtil.java
URL: http://svn.apache.org/viewvc/incubator/olio/workload/rails/trunk/src/com/sun/web20/util/RandomUtil.java?rev=738580&r1=738579&r2=738580&view=diff
==============================================================================
--- incubator/olio/workload/rails/trunk/src/com/sun/web20/util/RandomUtil.java (original)
+++ incubator/olio/workload/rails/trunk/src/com/sun/web20/util/RandomUtil.java Wed Jan 28 18:30:44 2009
@@ -174,21 +174,21 @@
         "W-SU", "WET", "Zulu"};
 
 
-    // Phone comes as +1 888 999 0000 or +77 66 999 0000 for non-US.
+    // Phone is 0018889990000 or 0077669990000 for non-US (no spaces for Rails app)
     // 50% of the time, do US, 50% non-us.
     public static String randomPhone(Random r, StringBuilder b) {
         String v = r.makeNString(1, 2);
         if (v.length() == 1) {
-            b.append("+1 ");
+            b.append("001"); // removed space
             v = r.makeNString(3, 3);
-            b.append(v).append(' ');
+            b.append(v); // removed space
         } else {
-            b.append("+").append(v);
+            b.append("00").append(v);
             v = r.makeNString(2, 2);
-            b.append(' ').append(v).append(' ');
+            b.append(v); //removed spaces
         }
         v = r.makeNString(3, 3);
-        b.append(v).append(' ');
+        b.append(v); // removed space
         v = r.makeNString(4, 4);
         b.append(v);
         return b.toString();
@@ -291,6 +291,7 @@
         String search1 = "<a href=\"/events/";
         int idx = 0;
         HashSet<String> eventIdSet = new HashSet<String>();
+        String eventItem = "";
         for (;;) {
             idx = eventListPage.indexOf(search1, idx);
             if (idx == -1)
@@ -300,6 +301,9 @@
             int endIdx = eventListPage.indexOf("\"", idx);
             if (endIdx == -1)
                 break;
+
+            eventItem = eventListPage.substring(idx, endIdx).trim();
+            if (!eventItem.contains("tagged") && !eventItem.contains("new") )
             eventIdSet.add(eventListPage.substring(idx, endIdx).trim());
             idx = endIdx;
         }