Hello andreip,

I'd like you to do a code review.  Please execute
        g4 diff -c 8228410

or point your web browser to
        http://mondrian/8228410

to review the following code:

Change 8228410 by [EMAIL PROTECTED] on 2008/09/10 15:34:55 *pending*

        Adds unit tests for AsyncTask requests with and without cookies.
        
        This was first added in CL 7897750 but was rolled back in 7915293 due 
to problems on Safari. The new version uses an asynchronous JavaScript function 
call to avoid this.
        
        *** Original change description ***
        
        Automated g4 rollback of changelist 7897750.
        
        *** Reason for rollback ***
        
          Original CL causes Unit tests to wedge on Safari.
        
        *** Original change description ***
        
        Adds unit tests for AsyncTask requests with and without cookies.
        
        R=andreip
        [EMAIL PROTECTED]
        DELTA=333  (333 added, 0 deleted, 0 changed)
        OCL=8228410

Affected files ...

... //depot/googleclient/gears/opensource/gears/Makefile#182 edit
... //depot/googleclient/gears/opensource/gears/base/common/serialization.h#5 
edit
... //depot/googleclient/gears/opensource/gears/cctests/test.cc#81 edit
... //depot/googleclient/gears/opensource/gears/cctests/test.h#24 edit
... 
//depot/googleclient/gears/opensource/gears/localserver/common/async_task_test.cc#2
 add
... 
//depot/googleclient/gears/opensource/gears/localserver/common/async_task_test.h#2
 add
... //depot/googleclient/gears/opensource/gears/test/runner/testwebserver.py#7 
edit
... 
//depot/googleclient/gears/opensource/gears/test/testcases/internal_tests.js#35 
edit
... 
//depot/googleclient/gears/opensource/gears/test/testcases/serve_if_cookies_absent.txt#2
 add
... 
//depot/googleclient/gears/opensource/gears/test/testcases/serve_if_cookies_present.txt#2
 add
... //depot/googleclient/gears/opensource/gears/test/testcases/set_cookie.txt#2 
add

333 delta lines: 333 added, 0 deleted, 0 changed

Also consider running:
        g4 lint -c 8228410

which verifies that the changelist doesn't introduce new style violations.

If you can't do the review, please let me know as soon as possible.  During
your review, please ensure that all new code has corresponding unit tests and
that existing unit tests are updated appropriately.  Visit
http://www/eng/code_review.html for more information.

This is a semiautomated message from "g4 mail".  Complaints or suggestions?
Mail [EMAIL PROTECTED]
Change 8228410 by [EMAIL PROTECTED] on 2008/09/10 15:34:55 *pending*

        Adds unit tests for AsyncTask requests with and without cookies.
        
        This was first added in CL 7897750 but was rolled back in 7915293 due 
to problems on Safari. The new version uses an asynchronous JavaScript function 
call to avoid this.
        
        *** Original change description ***
        
        Automated g4 rollback of changelist 7897750.
        
        *** Reason for rollback ***
        
          Original CL causes Unit tests to wedge on Safari.
        
        *** Original change description ***
        
        Adds unit tests for AsyncTask requests with and without cookies.

Affected files ...

... //depot/googleclient/gears/opensource/gears/Makefile#182 edit
... //depot/googleclient/gears/opensource/gears/base/common/serialization.h#5 
edit
... //depot/googleclient/gears/opensource/gears/cctests/test.cc#81 edit
... //depot/googleclient/gears/opensource/gears/cctests/test.h#24 edit
... 
//depot/googleclient/gears/opensource/gears/localserver/common/async_task_test.cc#2
 add
... 
//depot/googleclient/gears/opensource/gears/localserver/common/async_task_test.h#2
 add
... //depot/googleclient/gears/opensource/gears/test/runner/testwebserver.py#7 
edit
... 
//depot/googleclient/gears/opensource/gears/test/testcases/internal_tests.js#35 
edit
... 
//depot/googleclient/gears/opensource/gears/test/testcases/serve_if_cookies_absent.txt#2
 add
... 
//depot/googleclient/gears/opensource/gears/test/testcases/serve_if_cookies_present.txt#2
 add
... //depot/googleclient/gears/opensource/gears/test/testcases/set_cookie.txt#2 
add

==== //depot/googleclient/gears/opensource/gears/Makefile#182 - 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/Makefile ====
# action=edit type=text
--- googleclient/gears/opensource/gears/Makefile        2008-09-11 
14:58:12.000000000 +0100
+++ googleclient/gears/opensource/gears/Makefile        2008-09-11 
12:02:39.000000000 +0100
@@ -2039,6 +2039,7 @@
                $(NULL)
 
 $(BROWSER)_CPPSRCS += \
+               async_task_test.cc \
                blob_store.cc \
                capture_task.cc \
                file_store.cc \
==== //depot/googleclient/gears/opensource/gears/base/common/serialization.h#5 
- 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/base/common/serialization.h
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/base/common/serialization.h     
2008-09-11 14:58:12.000000000 +0100
+++ googleclient/gears/opensource/gears/base/common/serialization.h     
2008-09-10 17:15:11.000000000 +0100
@@ -45,6 +45,7 @@
   SERIALIZABLE_NOTIFICATION,
   SERIALIZABLE_GEOLOCATION,
   SERIALIZABLE_DESKTOP,
+  SERIALIZABLE_ASYNC_TASK_POST_COOKIES_TEST,
 
   // The following value can not be changed for cross-version compatibility.
   SERIALIZABLE_DESKTOP_NOTIFICATION = 1000,
==== //depot/googleclient/gears/opensource/gears/cctests/test.cc#81 - 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/cctests/test.cc ====
# action=edit type=text
--- googleclient/gears/opensource/gears/cctests/test.cc 2008-09-11 
14:58:12.000000000 +0100
+++ googleclient/gears/opensource/gears/cctests/test.cc 2008-09-11 
12:05:18.000000000 +0100
@@ -34,6 +34,7 @@
 #include "gears/base/common/js_runner.h"
 #include "gears/base/common/paths.h"
 #include "gears/base/common/string_utils.h"
+#include "gears/base/common/url_utils.h"  // For ResolveAndNormalize()
 #include "gears/blob/blob.h"
 #include "gears/blob/buffer_blob.h"
 #include "gears/desktop/desktop_test.h"
@@ -104,6 +105,8 @@
   RegisterMethod("testNotifier", &GearsTest::TestNotifier);
 #endif  // OS_ANDROID
 #endif  // OFFICIAL_BUILD
+  RegisterMethod("testAsyncTaskPostCookies",
+                 &GearsTest::TestAsyncTaskPostCookies);
 }
 
 #ifdef WIN32
@@ -140,6 +143,7 @@
 #else
 #include "gears/media/audio_recorder_test.h"
 #endif
+#include "gears/localserver/common/async_task_test.h"
 #include "gears/localserver/common/http_cookies.h"
 #include "gears/localserver/common/http_request.h"
 #include "gears/localserver/common/localserver_db.h"
@@ -2301,4 +2305,37 @@
 }
 #endif  // OFFICIAL_BUILD
 
+void GearsTest::TestAsyncTaskPostCookies(JsCallContext *context) {
+  // Note that GetArguments allocates a new JsRootedCallback.
+  std::string16 url;
+  bool send_cookies;
+  JsRootedCallback *callback;
+  JsArgument argv[] = {
+    { JSPARAM_REQUIRED, JSPARAM_STRING16, &url },
+    { JSPARAM_REQUIRED, JSPARAM_BOOL, &send_cookies },
+    { JSPARAM_REQUIRED, JSPARAM_FUNCTION, &callback },
+  };
+ 
+  if (!context->GetArguments(ARRAYSIZE(argv), argv)) {
+    assert(context->is_exception_set());
+    return;
+  }
+
+  std::string16 absolute_url;
+  if (!ResolveAndNormalize(EnvPageLocationUrl().c_str(),
+                           url.c_str(),
+                           &absolute_url)) {
+    context->SetException(STRING16(L"Could not resolve URL."));
+    return;
+  }
+
+  // async_task deletes itself once it has made its callback, or if
+  // MakePostRequest fails.
+  AsyncTaskTest *async_task = new AsyncTaskTest(absolute_url, send_cookies,
+                                                callback, GetJsRunner());
+  if (!async_task->MakePostRequest()) {
+    context->SetException(STRING16(L"Failed to make POST request."));
+  }
+}
+
 #endif  // USING_CCTESTS
==== //depot/googleclient/gears/opensource/gears/cctests/test.h#24 - 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/cctests/test.h ====
# action=edit type=text
--- googleclient/gears/opensource/gears/cctests/test.h  2008-08-07 
20:06:59.000000000 +0100
+++ googleclient/gears/opensource/gears/cctests/test.h  2008-09-10 
17:10:57.000000000 +0100
@@ -203,6 +203,10 @@
   void TestNotifier(JsCallContext *context);
 #endif  // OFFICIAL_BUILD
 
+  // IN: string url, bool send_cookies, function callback
+  // OUT: nothing
+  void TestAsyncTaskPostCookies(JsCallContext *context);
+
  private:
   // The tick count used by the perf timer.
   int64 start_ticks_;
==== 
//depot/googleclient/gears/opensource/gears/localserver/common/async_task_test.cc#2
 - 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/localserver/common/async_task_test.cc
 ====
# action=add type=text
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ googleclient/gears/opensource/gears/localserver/common/async_task_test.cc   
2008-09-11 13:55:44.000000000 +0100
@@ -0,0 +1,151 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//  1. Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright 
notice,
+//     this list of conditions and the following disclaimer in the 
documentation
+//     and/or other materials provided with the distribution.
+//  3. Neither the name of Google Inc. nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#if USING_CCTESTS
+
+#include "gears/localserver/common/async_task_test.h"
+
+#include "gears/base/common/js_types.h"  // For JsRootedCallback
+#include "gears/base/common/js_runner.h"
+#include "gears/blob/blob_interface.h"
+#include "gears/blob/buffer_blob.h"
+
+static const char16 *kRequestCompleteObserverTopic =
+    STRING16(L"request complete");
+
+// Data class for use with MessageService.
+class AsyncTaskNotificationData : public NotificationData {
+ public:
+  AsyncTaskNotificationData(int status_code) : status_code_(status_code) {}
+  virtual ~AsyncTaskNotificationData() {}
+
+  friend class AsyncTaskTest;
+
+ private:
+  // NotificationData implementation.
+  //
+  // We do not wish our messages to be delivered across process boundaries. To
+  // achieve this, we use an unregistered class ID. On receipt of an IPC
+  // message, InboundQueue::ReadOneMessage will attempt to deserialize the
+  // message data using CreateAndReadObject. This will fail silently because no
+  // factory function is registered for our class ID and Deserialize will not 
be
+  // called.
+  virtual SerializableClassId GetSerializableClassId() const {
+    return SERIALIZABLE_ASYNC_TASK_POST_COOKIES_TEST;
+  }
+  virtual bool Serialize(Serializer * /* out */) const {
+    // The serialized message is not used.
+    return true;
+  }
+  virtual bool Deserialize(Deserializer * /* in */) {
+    // This method should never be called.
+    assert(false);
+    return false;
+  }
+
+  int status_code_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(AsyncTaskNotificationData);
+};
+
+AsyncTaskTest::AsyncTaskTest(const std::string16 &url,
+                             bool send_cookies,
+                             JsRootedCallback *callback,
+                             JsRunnerInterface *js_runner)
+    : AsyncTask(NULL),
+      url_(url),
+      send_cookies_(send_cookies),
+      callback_(callback),
+      js_runner_(js_runner) {
+}
+
+bool AsyncTaskTest::MakePostRequest() {
+  MessageService::GetInstance()->AddObserver(this,
+                                             kRequestCompleteObserverTopic);
+  if (!Init() || !Start()) {
+    MessageService::GetInstance()->RemoveObserver(
+        this, kRequestCompleteObserverTopic);
+    DeleteWhenDone();
+    return false;
+  }
+  return true;
+}
+
+// AsyncTask implementation.
+void AsyncTaskTest::Run() {
+  WebCacheDB::PayloadInfo payload;
+  // TODO(andreip): remove this once WebCacheDB::PayloadInfo.data is a Blob.
+  scoped_refptr<BlobInterface> payload_data;
+  // The testwebserver can't handle POST requests with empty bodies.
+  scoped_refptr<BlobInterface> post_body(new BufferBlob("test\n\r", 6));
+  bool result = HttpPost(url_.c_str(),
+                         false,            // Not capturing, follow redirects
+                         NULL,             // reason_header_value
+                         NULL,             // mod_since_date
+                         NULL,             // required_cookie
+                         !send_cookies_,   // disable_browser_cookies
+                         post_body.get(),
+                         &payload,
+                         &payload_data,
+                         NULL,             // was_redirected
+                         NULL,             // full_redirect_url
+                         NULL);            // error_message
+  int status_code = result ? payload.status_code : 0;
+
+  // Marshall to JavaScript thread to make the callback.
+  MessageService::GetInstance()->NotifyObservers(
+      kRequestCompleteObserverTopic,
+      new AsyncTaskNotificationData(status_code));
+}
+
+// MessageObserverInterface implementation.
+void AsyncTaskTest::OnNotify(MessageService *service,
+                             const char16 *topic,
+                             const NotificationData *data) {
+  assert(data);
+
+  if (char16_wmemcmp(kRequestCompleteObserverTopic,
+                     topic,
+                     char16_wcslen(topic)) != 0) {
+    return;
+  }
+
+  int status_code =
+      reinterpret_cast<const AsyncTaskNotificationData*>(data)->status_code_;
+
+  // We unregister as an observer before making the callback so that we don't
+  // receive extra messages triggered by code in the callback.
+  MessageService::GetInstance()->RemoveObserver(this,
+                                                kRequestCompleteObserverTopic);
+
+  assert(callback_.get());
+  assert(js_runner_);
+  JsParamToSend argv[] = { { JSPARAM_INT, &status_code } };
+  js_runner_->InvokeCallback(callback_.get(), ARRAYSIZE(argv), argv, NULL);
+
+  DeleteWhenDone();
+}
+
+#endif  // USING_CCTESTS
==== 
//depot/googleclient/gears/opensource/gears/localserver/common/async_task_test.h#2
 - 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/localserver/common/async_task_test.h
 ====
# action=add type=text
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ googleclient/gears/opensource/gears/localserver/common/async_task_test.h    
2008-09-11 12:16:52.000000000 +0100
@@ -0,0 +1,71 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+//  1. Redistributions of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//  2. Redistributions in binary form must reproduce the above copyright 
notice,
+//     this list of conditions and the following disclaimer in the 
documentation
+//     and/or other materials provided with the distribution.
+//  3. Neither the name of Google Inc. nor the names of its contributors may be
+//     used to endorse or promote products derived from this software without
+//     specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GEARS_LOCALSERVER_COMMON_ASYNC_TASK_TEST_H__
+#define GEARS_LOCALSERVER_COMMON_ASYNC_TASK_TEST_H__
+
+#if USING_CCTESTS
+
+class JsRootedToken;
+typedef JsRootedToken JsRootedCallback;
+class JsRunnerInterface;
+
+#include "gears/base/common/message_service.h"
+#include "gears/localserver/common/async_task.h"
+
+class AsyncTaskTest
+    : public AsyncTask,
+      public MessageObserverInterface {
+ public:
+  AsyncTaskTest(const std::string16 &url,
+                bool send_cookies,
+                JsRootedCallback *callback,
+                JsRunnerInterface *js_runner);
+
+  bool MakePostRequest();
+
+ private:
+  // Private destructor. Instance deletes itself.
+  ~AsyncTaskTest() {}
+
+  // AsyncTask implementation.
+  virtual void Run();
+  
+  // MessageObserverInterface implementation.
+  virtual void OnNotify(MessageService *service,
+                        const char16 *topic,
+                        const NotificationData *data);
+
+  std::string16 url_;
+  bool send_cookies_;
+  scoped_ptr<JsRootedCallback> callback_;
+  JsRunnerInterface *js_runner_;
+
+  DISALLOW_EVIL_CONSTRUCTORS(AsyncTaskTest);
+};
+
+#endif  // USING_CCTESTS
+
+#endif  // GEARS_LOCALSERVER_COMMON_ASYNC_TASK_TEST_H__
==== //depot/googleclient/gears/opensource/gears/test/runner/testwebserver.py#7 
- 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/test/runner/testwebserver.py
 ====
# action=edit type=xtext
--- googleclient/gears/opensource/gears/test/runner/testwebserver.py    
2008-09-08 17:41:54.000000000 +0100
+++ googleclient/gears/opensource/gears/test/runner/testwebserver.py    
2008-09-11 12:06:19.000000000 +0100
@@ -130,9 +130,28 @@
     self.rfile = cStringIO.StringIO(''.join(popall(self.incoming)))
     self.rfile.seek(0)
     self.do_POST()
-     
-      
+
+
+  def can_serve(self):
+    # The AyncTask unit tests rely on conditionally serving files based on the
+    # presence of cookies in the request. Here we check whether we can serve
+    # these files.
+    if self.path.endswith('serve_if_cookies_absent.txt'):
+      if self.headers.getheader('Cookie') != '':
+        return False
+    elif self.path.endswith('serve_if_cookies_present.txt'):
+      if self.headers.getheader('Cookie') == '':
+        return False
+    return True
+
+
   def do_POST(self):
+    can_serve = True
+    if self.can_serve() == False:
+      self.send_error(404)
+      self.outgoing.append(None)
+      return
+
     qspos = self.path.find('?')
     if qspos >= 0:
       # Added query to allow test server to run redirects at POST, and the 
==== 
//depot/googleclient/gears/opensource/gears/test/testcases/internal_tests.js#35 
- 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/test/testcases/internal_tests.js
 ====
# action=edit type=text
--- googleclient/gears/opensource/gears/test/testcases/internal_tests.js        
2008-09-11 14:58:13.000000000 +0100
+++ googleclient/gears/opensource/gears/test/testcases/internal_tests.js        
2008-09-11 11:51:24.000000000 +0100
@@ -662,6 +662,55 @@
   }
 }
 
+function testAsyncTaskPostCookies() {
+  if (isUsingCCTests) {
+    var setCookieUrl = "/testcases/set_cookie.txt";
+    var serveIfCookiesPresentUrl = "/testcases/serve_if_cookies_present.txt";
+    var serveIfCookiesAbsentUrl = "/testcases/serve_if_cookies_absent.txt";
+    var testIndex = 0;
+
+    function runNextTest(returnCode) {
+      var previousIndex = testIndex;
+      testIndex++;
+      switch (previousIndex) {
+        case 0:
+          internalTests.testAsyncTaskPostCookies(serveIfCookiesPresentUrl,
+                                                 true,
+                                                 runNextTest);
+          break;
+        case 1:
+          assertEqual(200, returnCode,
+                      'Expected 200 for request with cookies.');
+          internalTests.testAsyncTaskPostCookies(serveIfCookiesPresentUrl,
+                                                 false, runNextTest);
+          break;
+        case 2:
+          assertEqual(404, returnCode,
+                      'Expected 200 for request without cookies.');
+          internalTests.testAsyncTaskPostCookies(serveIfCookiesAbsentUrl,
+                                                 true, runNextTest);
+          break;
+        case 3:
+          assertEqual(404, returnCode,
+                      'Expected 404 for request with cookies.');
+          internalTests.testAsyncTaskPostCookies(serveIfCookiesAbsentUrl,
+                                                 false, runNextTest);
+          break;
+        case 4:
+          assertEqual(200, returnCode,
+                      'Expected 200 for request without cookies.');
+          completeAsync();
+          break;
+        default:
+          throw new Error("Unexpected test index.");
+      }
+    }
+
+    startAsync();
+    runNextTest();
+  }
+}
+
 // Helper functions
 
 function createTestArray(length) {
==== 
//depot/googleclient/gears/opensource/gears/test/testcases/serve_if_cookies_absent.txt#2
 - 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/test/testcases/serve_if_cookies_absent.txt
 ====
# action=add type=text
==== 
//depot/googleclient/gears/opensource/gears/test/testcases/serve_if_cookies_present.txt#2
 - 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/test/testcases/serve_if_cookies_present.txt
 ====
# action=add type=text
==== 
//depot/googleclient/gears/opensource/gears/test/testcases/set_cookie.txt#2 - 
c:\MyDocs\Gears4/googleclient/gears/opensource/gears/test/testcases/set_cookie.txt
 ====
# action=add type=text

Reply via email to