summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-07 00:09:08 +0000
committerdmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-07 00:09:08 +0000
commit3ab612746af9bfa1f7d502b7851330423f71c672 (patch)
treedabdc0200d609cec040c5df4f5042a88cb343e83
parent4af886ca90a6262620eebdc9ab49b7b71b9ca33b (diff)
downloadchromium_src-3ab612746af9bfa1f7d502b7851330423f71c672.zip
chromium_src-3ab612746af9bfa1f7d502b7851330423f71c672.tar.gz
chromium_src-3ab612746af9bfa1f7d502b7851330423f71c672.tar.bz2
PPAPI: Refactor ppapi test callbacks to ease testing blocking callbacks.
There are really 3 changes to test_utils: - Change "force_async_" to "callback_type_" so that we can represent REQUIRED, OPTIONAL, _and_ BLOCKING. (I left backwards compatibility with force_async_ and will follow up to change them all after this CL). - Add a new form of WaitForResult and a new CHECK_CALLBACK_BEHAVIOR macro. This simplifies checking that the callback ran as expected (i.e., asynchronous or not). test_url_loader.cc in this CL is a good example of the new form. (My intent is to remove the existing WaitForResult in the aforementioned follow-up CL). - Add TestCompletionCallback::GetCallback. This is a minor thing, but it means we can get rid of a bunch of ugly "static_cast<pp::CompletionCallback>" in the tests (see test_websocket.cc for an example of that). BUG=92909 TEST= Review URL: http://codereview.chromium.org/9937001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131215 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ppapi/proxy/ppb_network_monitor_private_proxy.cc4
-rw-r--r--ppapi/tests/test_case.cc2
-rw-r--r--ppapi/tests/test_case.h24
-rw-r--r--ppapi/tests/test_file_system.cc65
-rw-r--r--ppapi/tests/test_flash_fullscreen.cc12
-rw-r--r--ppapi/tests/test_flash_fullscreen.h6
-rw-r--r--ppapi/tests/test_fullscreen.cc19
-rw-r--r--ppapi/tests/test_fullscreen.h6
-rw-r--r--ppapi/tests/test_network_monitor_private.cc28
-rw-r--r--ppapi/tests/test_url_loader.cc238
-rw-r--r--ppapi/tests/test_url_request.cc34
-rw-r--r--ppapi/tests/test_utils.cc119
-rw-r--r--ppapi/tests/test_utils.h126
-rw-r--r--ppapi/tests/test_websocket.cc38
14 files changed, 423 insertions, 298 deletions
diff --git a/ppapi/proxy/ppb_network_monitor_private_proxy.cc b/ppapi/proxy/ppb_network_monitor_private_proxy.cc
index 26252ac..865dc87 100644
--- a/ppapi/proxy/ppb_network_monitor_private_proxy.cc
+++ b/ppapi/proxy/ppb_network_monitor_private_proxy.cc
@@ -98,9 +98,9 @@ PP_Resource PPB_NetworkMonitor_Private_Proxy::CreateProxyResource(
// here.
proxy->current_list_ = NULL;
} else if (proxy->current_list_.get()) {
- MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ MessageLoop::current()->PostTask(FROM_HERE, RunWhileLocked(base::Bind(
&NetworkMonitor::OnNetworkListReceived,
- result->AsWeakPtr(), proxy->current_list_));
+ result->AsWeakPtr(), proxy->current_list_)));
}
return result->GetReference();
diff --git a/ppapi/tests/test_case.cc b/ppapi/tests/test_case.cc
index 0100ded..26f6d40 100644
--- a/ppapi/tests/test_case.cc
+++ b/ppapi/tests/test_case.cc
@@ -12,7 +12,7 @@
TestCase::TestCase(TestingInstance* instance)
: instance_(instance),
testing_interface_(NULL),
- force_async_(false) {
+ callback_type_(PP_REQUIRED) {
// Get the testing_interface_ if it is available, so that we can do Resource
// and Var checks on shutdown (see CheckResourcesAndVars). If it is not
// available, testing_interface_ will be NULL. Some tests do not require it.
diff --git a/ppapi/tests/test_case.h b/ppapi/tests/test_case.h
index b4815a1..2973084 100644
--- a/ppapi/tests/test_case.h
+++ b/ppapi/tests/test_case.h
@@ -14,6 +14,7 @@
#include "ppapi/c/dev/ppb_testing_dev.h"
#include "ppapi/cpp/dev/scrollbar_dev.h"
#include "ppapi/cpp/view.h"
+#include "ppapi/tests/test_utils.h"
#if (defined __native_client__)
#include "ppapi/cpp/var.h"
@@ -108,13 +109,28 @@ class TestCase {
// Pointer to the instance that owns us.
TestingInstance* instance_;
+ protected:
// NULL unless InitTestingInterface is called.
const PPB_Testing_Dev* testing_interface_;
- // Force asynchronous completion of any operation taking a callback.
+ // TODO(dmichael): Remove this, it's for temporary backwards compatibility so
+ // I don't have to change all the tests at once.
bool force_async_;
+ void set_callback_type(CallbackType callback_type) {
+ callback_type_ = callback_type;
+ // TODO(dmichael): Remove this; see comment on force_async_.
+ force_async_ = (callback_type_ == PP_REQUIRED);
+ }
+ CallbackType callback_type() const {
+ return callback_type_;
+ }
+
private:
+ // Passed when creating completion callbacks in some tests. This determines
+ // what kind of callback we use for the test.
+ CallbackType callback_type_;
+
// Var ids that should be ignored when checking for leaks on shutdown.
std::set<int64_t> ignored_leaked_vars_;
@@ -167,7 +183,7 @@ class TestCaseFactory {
// test |name|.
#define RUN_TEST(name, test_filter) \
if (MatchesFilter(#name, test_filter)) { \
- force_async_ = false; \
+ set_callback_type(PP_OPTIONAL); \
std::string error_message = Test##name(); \
if (error_message.empty()) \
error_message = CheckResourcesAndVars(); \
@@ -176,7 +192,7 @@ class TestCaseFactory {
#define RUN_TEST_WITH_REFERENCE_CHECK(name, test_filter) \
if (MatchesFilter(#name, test_filter)) { \
- force_async_ = false; \
+ set_callback_type(PP_OPTIONAL); \
uint32_t objects = testing_interface_->GetLiveObjectsForInstance( \
instance_->pp_instance()); \
std::string error_message = Test##name(); \
@@ -192,7 +208,7 @@ class TestCaseFactory {
// asynchronously on success or error.
#define RUN_TEST_FORCEASYNC(name, test_filter) \
if (MatchesFilter(#name"ForceAsync", test_filter)) { \
- force_async_ = true; \
+ set_callback_type(PP_REQUIRED); \
instance_->LogTest(#name"ForceAsync", Test##name()); \
}
diff --git a/ppapi/tests/test_file_system.cc b/ppapi/tests/test_file_system.cc
index 8c05d42..3874295 100644
--- a/ppapi/tests/test_file_system.cc
+++ b/ppapi/tests/test_file_system.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -27,64 +27,43 @@ std::string TestFileSystem::TestOpen() {
// Open.
pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
- int32_t rv = file_system.Open(1024, callback);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("FileSystem::Open", rv);
+ callback.WaitForResult(file_system.Open(1024, callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
// Open aborted (see the DirectoryReader test for comments).
- callback.reset_run_count();
- rv = pp::FileSystem(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY)
- .Open(1024, callback);
- if (callback.run_count() > 0)
- return "FileSystem::Open ran callback synchronously.";
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("FileSystem::Open force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING) {
- rv = callback.WaitForResult();
- if (rv != PP_ERROR_ABORTED)
- return "FileSystem::Open not aborted.";
- } else if (rv != PP_OK) {
- return ReportError("FileSystem::Open", rv);
+ int32_t rv = 0;
+ {
+ rv = pp::FileSystem(instance_,
+ PP_FILESYSTEMTYPE_LOCALTEMPORARY).Open(1024, callback);
}
+ callback.WaitForAbortResult(rv);
+ CHECK_CALLBACK_BEHAVIOR(callback);
PASS();
}
std::string TestFileSystem::TestMultipleOpens() {
- // Should not allow multiple opens, no matter the first open has completed or
- // not.
+ // Should not allow multiple opens, regardless of whether or not the first
+ // open has completed.
TestCompletionCallback callback_1(instance_->pp_instance(), force_async_);
pp::FileSystem file_system(instance_, PP_FILESYSTEMTYPE_LOCALTEMPORARY);
int32_t rv_1 = file_system.Open(1024, callback_1);
- if (callback_1.run_count() > 0)
- return "FileSystem::Open1 ran callback synchronously.";
- if (force_async_ && rv_1 != PP_OK_COMPLETIONPENDING)
- return ReportError("FileSystem::Open1 force_async", rv_1);
TestCompletionCallback callback_2(instance_->pp_instance(), force_async_);
- int32_t rv_2 = file_system.Open(1024, callback_2);
- if (force_async_ && rv_2 != PP_OK_COMPLETIONPENDING)
- return ReportError("FileSystem::Open2 force_async", rv_2);
- if (rv_2 == PP_OK_COMPLETIONPENDING)
- rv_2 = callback_2.WaitForResult();
- if (rv_2 == PP_OK)
- return "FileSystem::Open2 should not allow multiple opens.";
+ callback_2.WaitForResult(file_system.Open(1024, callback_2));
+ CHECK_CALLBACK_BEHAVIOR(callback_2);
+ // FileSystem should not allow multiple opens.
+ ASSERT_NE(PP_OK, callback_2.result());
- if (rv_1 == PP_OK_COMPLETIONPENDING)
- rv_1 = callback_1.WaitForResult();
- if (rv_1 != PP_OK)
- return ReportError("FileSystem::Open1", rv_1);
+ callback_1.WaitForResult(rv_1);
+ CHECK_CALLBACK_BEHAVIOR(callback_1);
+ ASSERT_EQ(PP_OK, callback_1.result());
TestCompletionCallback callback_3(instance_->pp_instance(), force_async_);
- int32_t rv_3 = file_system.Open(1024, callback_3);
- if (force_async_ && rv_3 != PP_OK_COMPLETIONPENDING)
- return ReportError("FileSystem::Open3 force_async", rv_3);
- if (rv_3 == PP_OK_COMPLETIONPENDING)
- rv_3 = callback_3.WaitForResult();
- if (rv_3 == PP_OK)
- return "FileSystem::Open3 should not allow multiple opens.";
+ callback_3.WaitForResult(file_system.Open(1024, callback_3));
+ CHECK_CALLBACK_BEHAVIOR(callback_3);
+ ASSERT_NE(PP_OK, callback_3.result());
PASS();
}
diff --git a/ppapi/tests/test_flash_fullscreen.cc b/ppapi/tests/test_flash_fullscreen.cc
index b724fef..819ffab 100644
--- a/ppapi/tests/test_flash_fullscreen.cc
+++ b/ppapi/tests/test_flash_fullscreen.cc
@@ -40,8 +40,8 @@ TestFlashFullscreen::TestFlashFullscreen(TestingInstance* instance)
screen_mode_(instance),
fullscreen_pending_(false),
normal_pending_(false),
- fullscreen_callback_(instance->pp_instance()),
- normal_callback_(instance->pp_instance()) {
+ fullscreen_event_(instance->pp_instance()),
+ normal_event_(instance->pp_instance()) {
screen_mode_.GetScreenSize(&screen_size_);
}
@@ -86,7 +86,7 @@ std::string TestFlashFullscreen::TestNormalToFullscreenToNormal() {
}
// DidChangeView() will call the callback once in fullscreen mode.
- fullscreen_callback_.WaitForResult();
+ fullscreen_event_.Wait();
if (fullscreen_pending_)
return "fullscreen_pending_ has not been reset";
if (!screen_mode_.IsFullscreen())
@@ -116,7 +116,7 @@ std::string TestFlashFullscreen::TestNormalToFullscreenToNormal() {
if (testing_interface_->IsOutOfProcess()) {
if (!screen_mode_.IsFullscreen())
return ReportError("IsFullscreen() in normal transition", false);
- normal_callback_.WaitForResult();
+ normal_event_.Wait();
if (normal_pending_)
return "normal_pending_ has not been reset";
}
@@ -140,11 +140,11 @@ void TestFlashFullscreen::DidChangeView(const pp::View& view) {
pp::Rect clip = view.GetClipRect();
if (fullscreen_pending_ && IsFullscreenView(position, clip, screen_size_)) {
fullscreen_pending_ = false;
- pp::Module::Get()->core()->CallOnMainThread(0, fullscreen_callback_);
+ fullscreen_event_.Signal();
} else if (normal_pending_ &&
!IsFullscreenView(position, clip, screen_size_)) {
normal_pending_ = false;
if (testing_interface_->IsOutOfProcess())
- pp::Module::Get()->core()->CallOnMainThread(0, normal_callback_);
+ normal_event_.Signal();
}
}
diff --git a/ppapi/tests/test_flash_fullscreen.h b/ppapi/tests/test_flash_fullscreen.h
index b02ff2a..d9f742f 100644
--- a/ppapi/tests/test_flash_fullscreen.h
+++ b/ppapi/tests/test_flash_fullscreen.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -34,8 +34,8 @@ class TestFlashFullscreen : public TestCase {
bool fullscreen_pending_;
bool normal_pending_;
- TestCompletionCallback fullscreen_callback_;
- TestCompletionCallback normal_callback_;
+ NestedEvent fullscreen_event_;
+ NestedEvent normal_event_;
};
#endif // PPAPI_TESTS_TEST_FLASH_FULLSCREEN_H_
diff --git a/ppapi/tests/test_fullscreen.cc b/ppapi/tests/test_fullscreen.cc
index 2a6edcd..2fddbdf 100644
--- a/ppapi/tests/test_fullscreen.cc
+++ b/ppapi/tests/test_fullscreen.cc
@@ -56,9 +56,8 @@ TestFullscreen::TestFullscreen(TestingInstance* instance)
painted_color_(0),
fullscreen_pending_(false),
normal_pending_(false),
- set_fullscreen_true_callback_(instance->pp_instance()),
- fullscreen_callback_(instance->pp_instance()),
- normal_callback_(instance->pp_instance()) {
+ fullscreen_event_(instance->pp_instance()),
+ normal_event_(instance->pp_instance()) {
screen_mode_.GetScreenSize(&screen_size_);
}
@@ -115,7 +114,7 @@ std::string TestFullscreen::TestNormalToFullscreenToNormal() {
instance_->RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
SimulateUserGesture();
// DidChangeView() will call the callback once in fullscreen mode.
- fullscreen_callback_.WaitForResult();
+ fullscreen_event_.Wait();
if (GotError())
return Error();
if (fullscreen_pending_)
@@ -135,8 +134,8 @@ std::string TestFullscreen::TestNormalToFullscreenToNormal() {
normal_pending_ = true;
if (!screen_mode_.SetFullscreen(false))
return ReportError("SetFullscreen(false) in fullscreen", false);
- // DidChangeView() will call the callback once out of fullscreen mode.
- normal_callback_.WaitForResult();
+ // DidChangeView() will signal once out of fullscreen mode.
+ normal_event_.Wait();
if (GotError())
return Error();
if (normal_pending_)
@@ -174,20 +173,20 @@ void TestFullscreen::SimulateUserGesture() {
void TestFullscreen::FailFullscreenTest(const std::string& error) {
error_ = error;
- pp::Module::Get()->core()->CallOnMainThread(0, fullscreen_callback_);
+ fullscreen_event_.Signal();
}
void TestFullscreen::FailNormalTest(const std::string& error) {
error_ = error;
- pp::Module::Get()->core()->CallOnMainThread(0, normal_callback_);
+ normal_event_.Signal();
}
void TestFullscreen::PassFullscreenTest() {
- pp::Module::Get()->core()->CallOnMainThread(0, fullscreen_callback_);
+ fullscreen_event_.Signal();
}
void TestFullscreen::PassNormalTest() {
- pp::Module::Get()->core()->CallOnMainThread(0, normal_callback_);
+ normal_event_.Signal();
}
// Transition to fullscreen can only happen when processing a user gesture.
diff --git a/ppapi/tests/test_fullscreen.h b/ppapi/tests/test_fullscreen.h
index 4b355ca..bfe2e27 100644
--- a/ppapi/tests/test_fullscreen.h
+++ b/ppapi/tests/test_fullscreen.h
@@ -57,9 +57,9 @@ class TestFullscreen : public TestCase {
bool fullscreen_pending_;
bool normal_pending_;
pp::Graphics2D graphics2d_;
- TestCompletionCallback set_fullscreen_true_callback_;
- TestCompletionCallback fullscreen_callback_;
- TestCompletionCallback normal_callback_;
+
+ NestedEvent fullscreen_event_;
+ NestedEvent normal_event_;
};
#endif // PAPPI_TESTS_TEST_FULLSCREEN_H_
diff --git a/ppapi/tests/test_network_monitor_private.cc b/ppapi/tests/test_network_monitor_private.cc
index 6583cc4..7757dee 100644
--- a/ppapi/tests/test_network_monitor_private.cc
+++ b/ppapi/tests/test_network_monitor_private.cc
@@ -21,8 +21,8 @@ namespace {
struct CallbackData {
explicit CallbackData(PP_Instance instance)
- : call_counter(0),
- completion_callback(instance),
+ : event(instance),
+ call_counter(0),
list_resource(0),
delete_monitor(false),
monitor(NULL) {
@@ -31,8 +31,8 @@ struct CallbackData {
if (list_resource)
pp::Module::Get()->core()->ReleaseResource(list_resource);
}
+ NestedEvent event;
int call_counter;
- TestCompletionCallback completion_callback;
PP_Resource list_resource;
bool delete_monitor;
pp::NetworkMonitorPrivate* monitor;
@@ -49,9 +49,9 @@ void TestCallback(void* user_data, PP_Resource network_list) {
if (data->delete_monitor)
delete data->monitor;
- // Invoke completion callback only for the first change notification.
+
if (data->call_counter == 1)
- static_cast<pp::CompletionCallback>(data->completion_callback).Run(PP_OK);
+ data->event.Signal();
}
@@ -59,15 +59,15 @@ class TestNetworkListObserver : public pp::NetworkListObserverPrivate {
public:
explicit TestNetworkListObserver(const pp::InstanceHandle& instance)
: pp::NetworkListObserverPrivate(instance),
- completion_callback(instance.pp_instance()) {
+ event(instance.pp_instance()) {
}
virtual void OnNetworkListChanged(const pp::NetworkListPrivate& list) {
current_list = list;
- static_cast<pp::CompletionCallback>(completion_callback).Run(PP_OK);
+ event.Signal();
}
pp::NetworkListPrivate current_list;
- TestCompletionCallback completion_callback;
+ NestedEvent event;
};
} // namespace
@@ -80,7 +80,7 @@ bool TestNetworkMonitorPrivate::Init() {
if (!pp::NetworkMonitorPrivate::IsAvailable())
return false;
- return true;
+ return CheckTestingInterface();
}
void TestNetworkMonitorPrivate::RunTests(const std::string& filter) {
@@ -180,7 +180,7 @@ std::string TestNetworkMonitorPrivate::TestBasic() {
pp::NetworkMonitorPrivate network_monitor(
instance_, &TestCallback, &callback_data);
- ASSERT_EQ(callback_data.completion_callback.WaitForResult(), PP_OK);
+ callback_data.event.Wait();
ASSERT_EQ(callback_data.call_counter, 1);
ASSERT_SUBTEST_SUCCESS(
@@ -194,7 +194,7 @@ std::string TestNetworkMonitorPrivate::Test2Monitors() {
pp::NetworkMonitorPrivate network_monitor(
instance_, &TestCallback, &callback_data);
- ASSERT_EQ(callback_data.completion_callback.WaitForResult(), PP_OK);
+ callback_data.event.Wait();
ASSERT_EQ(callback_data.call_counter, 1);
ASSERT_SUBTEST_SUCCESS(
@@ -204,7 +204,7 @@ std::string TestNetworkMonitorPrivate::Test2Monitors() {
pp::NetworkMonitorPrivate network_monitor_2(
instance_, &TestCallback, &callback_data_2);
- ASSERT_EQ(callback_data_2.completion_callback.WaitForResult(), PP_OK);
+ callback_data_2.event.Wait();
ASSERT_EQ(callback_data_2.call_counter, 1);
ASSERT_SUBTEST_SUCCESS(
@@ -221,7 +221,7 @@ std::string TestNetworkMonitorPrivate::TestDeleteInCallback() {
callback_data.delete_monitor = true;
callback_data.monitor = network_monitor;
- ASSERT_EQ(callback_data.completion_callback.WaitForResult(), PP_OK);
+ callback_data.event.Wait();
ASSERT_EQ(callback_data.call_counter, 1);
ASSERT_SUBTEST_SUCCESS(
@@ -232,7 +232,7 @@ std::string TestNetworkMonitorPrivate::TestDeleteInCallback() {
std::string TestNetworkMonitorPrivate::TestListObserver() {
TestNetworkListObserver observer(instance_);
- ASSERT_EQ(observer.completion_callback.WaitForResult(), PP_OK);
+ observer.event.Wait();
ASSERT_SUBTEST_SUCCESS(VerifyNetworkList(observer.current_list));
PASS();
}
diff --git a/ppapi/tests/test_url_loader.cc b/ppapi/tests/test_url_loader.cc
index 984fee0..15ea546 100644
--- a/ppapi/tests/test_url_loader.cc
+++ b/ppapi/tests/test_url_loader.cc
@@ -40,15 +40,15 @@ int32_t WriteEntireBuffer(PP_Instance instance,
int32_t size = data.size();
while (write_offset < offset + size) {
- int32_t rv = file_io->Write(write_offset, &buf[write_offset - offset],
- size - write_offset + offset, callback);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv < 0)
- return rv;
- if (rv == 0)
+ callback.WaitForResult(file_io->Write(write_offset,
+ &buf[write_offset - offset],
+ size - write_offset + offset,
+ callback));
+ if (callback.result() < 0)
+ return callback.result();
+ if (callback.result() == 0)
return PP_ERROR_FAILED;
- write_offset += rv;
+ write_offset += callback.result();
}
return PP_OK;
@@ -122,22 +122,18 @@ void TestURLLoader::RunTests(const std::string& filter) {
std::string TestURLLoader::ReadEntireFile(pp::FileIO* file_io,
std::string* data) {
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
char buf[256];
int64_t offset = 0;
for (;;) {
- int32_t rv = file_io->Read(offset, buf, sizeof(buf), callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("FileIO::Read force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv < 0)
- return ReportError("FileIO::Read", rv);
- if (rv == 0)
+ callback.WaitForResult(file_io->Read(offset, buf, sizeof(buf), callback));
+ if (callback.result() < 0)
+ return ReportError("FileIO::Read", callback.result());
+ if (callback.result() == 0)
break;
- offset += rv;
- data->append(buf, rv);
+ offset += callback.result();
+ data->append(buf, callback.result());
}
PASS();
@@ -145,20 +141,17 @@ std::string TestURLLoader::ReadEntireFile(pp::FileIO* file_io,
std::string TestURLLoader::ReadEntireResponseBody(pp::URLLoader* loader,
std::string* body) {
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
char buf[2]; // Small so that multiple reads are needed.
for (;;) {
- int32_t rv = loader->ReadResponseBody(buf, sizeof(buf), callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::ReadResponseBody force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv < 0)
- return ReportError("URLLoader::ReadResponseBody", rv);
- if (rv == 0)
+ callback.WaitForResult(
+ loader->ReadResponseBody(buf, sizeof(buf), callback));
+ if (callback.result() < 0)
+ return ReportError("URLLoader::ReadResponseBody", callback.result());
+ if (callback.result() == 0)
break;
- body->append(buf, rv);
+ body->append(buf, callback.result());
}
PASS();
@@ -167,16 +160,12 @@ std::string TestURLLoader::ReadEntireResponseBody(pp::URLLoader* loader,
std::string TestURLLoader::LoadAndCompareBody(
const pp::URLRequestInfo& request,
const std::string& expected_body) {
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
pp::URLLoader loader(instance_);
- int32_t rv = loader.Open(request, callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::Open force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("URLLoader::Open", rv);
+ callback.WaitForResult(loader.Open(request, callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
pp::URLResponseInfo response_info(loader.GetResponseInfo());
if (response_info.is_null())
@@ -200,46 +189,42 @@ std::string TestURLLoader::LoadAndCompareBody(
int32_t TestURLLoader::OpenFileSystem(pp::FileSystem* file_system,
std::string* message) {
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
- int32_t rv = file_system->Open(1024, callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING) {
- message->assign("FileSystem::Open force_async");
- return rv;
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
+ callback.WaitForResult(file_system->Open(1024, callback));
+ if (callback.failed()) {
+ message->assign(callback.errors());
+ return callback.result();
}
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK) {
+ if (callback.result() != PP_OK) {
message->assign("FileSystem::Open");
- return rv;
+ return callback.result();
}
- return rv;
+ return callback.result();
}
int32_t TestURLLoader::PrepareFileForPost(
const pp::FileRef& file_ref,
const std::string& data,
std::string* message) {
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
pp::FileIO file_io(instance_);
- int32_t rv = file_io.Open(file_ref,
- PP_FILEOPENFLAG_CREATE |
- PP_FILEOPENFLAG_TRUNCATE |
- PP_FILEOPENFLAG_WRITE,
- callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING) {
- message->assign("FileIO::Open force_async");
- return rv;
+ callback.WaitForResult(file_io.Open(file_ref,
+ PP_FILEOPENFLAG_CREATE |
+ PP_FILEOPENFLAG_TRUNCATE |
+ PP_FILEOPENFLAG_WRITE,
+ callback));
+ if (callback.failed()) {
+ message->assign(callback.errors());
+ return callback.result();
}
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK) {
- message->assign("FileIO::Open");
- return rv;
+ if (callback.result() != PP_OK) {
+ message->assign("FileIO::Open failed.");
+ return callback.result();
}
- rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0, data);
+ int32_t rv = WriteEntireBuffer(instance_->pp_instance(), &file_io, 0, data);
if (rv != PP_OK) {
- message->assign("FileIO::Write");
+ message->assign("FileIO::Write failed.");
return rv;
}
@@ -309,15 +294,9 @@ int32_t TestURLLoader::Open(const pp::URLRequestInfo& request,
pp::URLLoader loader(instance_);
if (trusted)
url_loader_trusted_interface_->GrantUniversalAccess(loader.pp_resource());
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
- int32_t rv = loader.Open(request, callback);
-
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- else if (force_async_)
- ReportError("URLLoader::Open force_async", rv);
-
- return rv;
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
+ callback.WaitForResult(loader.Open(request, callback));
+ return callback.result();
}
std::string TestURLLoader::TestBasicGET() {
@@ -437,16 +416,12 @@ std::string TestURLLoader::TestStreamToFile() {
request.SetURL("test_url_loader_data/hello.txt");
request.SetStreamToFile(true);
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
pp::URLLoader loader(instance_);
- int32_t rv = loader.Open(request, callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::Open force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("URLLoader::Open", rv);
+ callback.WaitForResult(loader.Open(request, callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
pp::URLResponseInfo response_info(loader.GetResponseInfo());
if (response_info.is_null())
@@ -459,23 +434,14 @@ std::string TestURLLoader::TestStreamToFile() {
if (body.is_null())
return "URLResponseInfo::GetBody returned null";
- rv = loader.FinishStreamingToFile(callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::FinishStreamingToFile force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("URLLoader::FinishStreamingToFile", rv);
+ callback.WaitForResult(loader.FinishStreamingToFile(callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
- // FileIO is not yet supported by ppapi/proxy.
pp::FileIO reader(instance_);
- rv = reader.Open(body, PP_FILEOPENFLAG_READ, callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("FileIO::Open force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("FileIO::Open", rv);
+ callback.WaitForResult(reader.Open(body, PP_FILEOPENFLAG_READ, callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
std::string data;
std::string error = ReadEntireFile(&reader, &data);
@@ -726,16 +692,12 @@ std::string TestURLLoader::TestAuditURLRedirect() {
request.SetURL(redirect_prefix.append(redirect_url));
request.SetFollowRedirects(false);
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
pp::URLLoader loader(instance_);
- int32_t rv = loader.Open(request, callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::Open force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("URLLoader::Open", rv);
+ callback.WaitForResult(loader.Open(request, callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
// Checks that the response indicates a redirect, and that the URL
// is correct.
@@ -747,15 +709,9 @@ std::string TestURLLoader::TestAuditURLRedirect() {
return "Response status should be 301";
// Test that the paused loader can be resumed.
- TestCompletionCallback redirect_callback(instance_->pp_instance(),
- force_async_);
- rv = loader.FollowRedirect(redirect_callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::FollowRedirect force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = redirect_callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("URLLoader::FollowRedirect", rv);
+ callback.WaitForResult(loader.FollowRedirect(callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
std::string body;
std::string error = ReadEntireResponseBody(&loader, &body);
if (!error.empty())
@@ -771,56 +727,34 @@ std::string TestURLLoader::TestAbortCalls() {
pp::URLRequestInfo request(instance_);
request.SetURL("test_url_loader_data/hello.txt");
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
int32_t rv;
// Abort |Open()|.
{
- callback.reset_run_count();
rv = pp::URLLoader(instance_).Open(request, callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::Open force_async", rv);
- if (callback.run_count() > 0)
- return "URLLoader::Open ran callback synchronously.";
- if (rv == PP_OK_COMPLETIONPENDING) {
- rv = callback.WaitForResult();
- if (rv != PP_ERROR_ABORTED)
- return "URLLoader::Open not aborted.";
- } else if (rv != PP_OK) {
- return ReportError("URLLoader::Open", rv);
- }
}
+ callback.WaitForAbortResult(rv);
+ CHECK_CALLBACK_BEHAVIOR(callback);
// Abort |ReadResponseBody()|.
{
char buf[2] = { 0 };
{
pp::URLLoader loader(instance_);
- rv = loader.Open(request, callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::Open force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("URLLoader::Open", rv);
-
- callback.reset_run_count();
+ callback.WaitForResult(loader.Open(request, callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
+
rv = loader.ReadResponseBody(buf, sizeof(buf), callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::ReadResponseBody force_async", rv);
} // Destroy |loader|.
+ callback.WaitForAbortResult(rv);
+ CHECK_CALLBACK_BEHAVIOR(callback);
if (rv == PP_OK_COMPLETIONPENDING) {
- // Save a copy and make sure |buf| doesn't get written to.
- char buf_copy[2];
- memcpy(&buf_copy, &buf, sizeof(buf));
- rv = callback.WaitForResult();
- if (rv != PP_ERROR_ABORTED)
- return "URLLoader::ReadResponseBody not aborted.";
- if (memcmp(&buf_copy, &buf, sizeof(buf)) != 0)
+ if (buf[0] || buf[1]) {
return "URLLoader::ReadResponseBody wrote data after resource "
"destruction.";
- } else if (rv != PP_OK) {
- return ReportError("URLLoader::ReadResponseBody", rv);
+ }
}
}
@@ -834,16 +768,12 @@ std::string TestURLLoader::TestUntendedLoad() {
pp::URLRequestInfo request(instance_);
request.SetURL("test_url_loader_data/hello.txt");
request.SetRecordDownloadProgress(true);
- TestCompletionCallback callback(instance_->pp_instance(), force_async_);
+ TestCompletionCallback callback(instance_->pp_instance(), callback_type());
pp::URLLoader loader(instance_);
- int32_t rv = loader.Open(request, callback);
- if (force_async_ && rv != PP_OK_COMPLETIONPENDING)
- return ReportError("URLLoader::Open force_async", rv);
- if (rv == PP_OK_COMPLETIONPENDING)
- rv = callback.WaitForResult();
- if (rv != PP_OK)
- return ReportError("URLLoader::Open", rv);
+ callback.WaitForResult(loader.Open(request, callback));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
// We received the response callback. Yield until the network code has called
// the loader's didReceiveData and didFinishLoading methods before we give it
@@ -867,7 +797,7 @@ std::string TestURLLoader::TestUntendedLoad() {
if (!error.empty())
return error;
if (body != "hello\n")
- return ReportError("Couldn't read data", rv);
+ return ReportError("Couldn't read data", callback.result());
PASS();
}
diff --git a/ppapi/tests/test_url_request.cc b/ppapi/tests/test_url_request.cc
index d8b280c..e0902f0 100644
--- a/ppapi/tests/test_url_request.cc
+++ b/ppapi/tests/test_url_request.cc
@@ -274,14 +274,12 @@ std::string TestURLRequest::TestSetProperty() {
std::string TestURLRequest::LoadAndCompareBody(
PP_Resource url_request, const std::string& expected_body) {
- TestCompletionCallback test_callback(instance_->pp_instance(), true);
- pp::CompletionCallback callback =
- static_cast<pp::CompletionCallback>(test_callback);
- int32_t result = ppb_url_loader_interface_->Open(
- url_loader_, url_request, callback.pp_completion_callback());
- ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
- result = test_callback.WaitForResult();
- ASSERT_EQ(PP_OK, result);
+ TestCompletionCallback callback(instance_->pp_instance(), PP_REQUIRED);
+ callback.WaitForResult(ppb_url_loader_interface_->Open(
+ url_loader_, url_request,
+ callback.GetCallback().pp_completion_callback()));
+ CHECK_CALLBACK_BEHAVIOR(callback);
+ ASSERT_EQ(PP_OK, callback.result());
std::string error;
PP_Resource url_response =
@@ -298,19 +296,17 @@ std::string TestURLRequest::LoadAndCompareBody(
for (; error.empty();) { // Read the entire body in this loop.
const size_t kBufferSize = 32;
char buf[kBufferSize];
- result = ppb_url_loader_interface_->ReadResponseBody(
+ callback.WaitForResult(ppb_url_loader_interface_->ReadResponseBody(
url_loader_, buf, kBufferSize,
- callback.pp_completion_callback());
- if (PP_OK_COMPLETIONPENDING != result) {
- error = ReportError("PPB_URLLoader::ReadResponseBody()", result);
+ callback.GetCallback().pp_completion_callback()));
+ if (callback.failed())
+ error.assign(callback.errors());
+ else if (callback.result() < PP_OK)
+ error.assign(ReportError("PPB_URLLoader::ReadResponseBody()",
+ callback.result()));
+ if (callback.result() <= PP_OK || callback.failed())
break;
- }
- result = test_callback.WaitForResult();
- if (result < PP_OK)
- error = ReportError("PPB_URLLoader::ReadResponseBody()", result);
- if (result <= PP_OK)
- break;
- actual_body.append(buf, result);
+ actual_body.append(buf, callback.result());
}
if (actual_body != expected_body)
error = "PPB_URLLoader::ReadResponseBody() read unexpected response";
diff --git a/ppapi/tests/test_utils.cc b/ppapi/tests/test_utils.cc
index 449b64c..7405e93 100644
--- a/ppapi/tests/test_utils.cc
+++ b/ppapi/tests/test_utils.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -71,51 +71,146 @@ bool GetLocalHostPort(PP_Instance instance, std::string* host, uint16_t* port) {
return true;
}
+void NestedEvent::Wait() {
+ // Don't allow nesting more than once; it doesn't work with the code as-is,
+ // and probably is a bad idea most of the time anyway.
+ PP_DCHECK(!waiting_);
+ if (signalled_)
+ return;
+ waiting_ = true;
+ while (!signalled_)
+ GetTestingInterface()->RunMessageLoop(instance_);
+ waiting_ = false;
+}
+
+void NestedEvent::Signal() {
+ signalled_ = true;
+ if (waiting_)
+ GetTestingInterface()->QuitMessageLoop(instance_);
+}
+
TestCompletionCallback::TestCompletionCallback(PP_Instance instance)
- : have_result_(false),
+ : wait_for_result_called_(false),
+ have_result_(false),
result_(PP_OK_COMPLETIONPENDING),
- force_async_(false),
+ // TODO(dmichael): The default should probably be PP_REQUIRED, but this is
+ // what the tests currently expect.
+ callback_type_(PP_OPTIONAL),
post_quit_task_(false),
- run_count_(0),
instance_(instance) {
}
TestCompletionCallback::TestCompletionCallback(PP_Instance instance,
bool force_async)
- : have_result_(false),
+ : wait_for_result_called_(false),
+ have_result_(false),
+ result_(PP_OK_COMPLETIONPENDING),
+ callback_type_(force_async ? PP_REQUIRED : PP_OPTIONAL),
+ post_quit_task_(false),
+ instance_(instance) {
+}
+
+TestCompletionCallback::TestCompletionCallback(PP_Instance instance,
+ CallbackType callback_type)
+ : wait_for_result_called_(false),
+ have_result_(false),
result_(PP_OK_COMPLETIONPENDING),
- force_async_(force_async),
+ callback_type_(callback_type),
post_quit_task_(false),
- run_count_(0),
instance_(instance) {
}
int32_t TestCompletionCallback::WaitForResult() {
+ PP_DCHECK(!wait_for_result_called_);
+ wait_for_result_called_ = true;
+ errors_.clear();
if (!have_result_) {
- result_ = PP_OK_COMPLETIONPENDING; // Reset
post_quit_task_ = true;
GetTestingInterface()->RunMessageLoop(instance_);
}
- have_result_ = false;
return result_;
}
-TestCompletionCallback::operator pp::CompletionCallback() const {
- int32_t flags = (force_async_ ? 0 : PP_COMPLETIONCALLBACK_FLAG_OPTIONAL);
+void TestCompletionCallback::WaitForResult(int32_t result) {
+ PP_DCHECK(!wait_for_result_called_);
+ wait_for_result_called_ = true;
+ errors_.clear();
+ if (result == PP_OK_COMPLETIONPENDING) {
+ if (!have_result_) {
+ post_quit_task_ = true;
+ GetTestingInterface()->RunMessageLoop(instance_);
+ }
+ if (callback_type_ == PP_BLOCKING) {
+ errors_.assign(
+ ReportError("TestCompletionCallback: Call did not run synchronously "
+ "when passed a blocking completion callback!",
+ result_));
+ return;
+ }
+ } else {
+ result_ = result;
+ have_result_ = true;
+ if (callback_type_ == PP_REQUIRED) {
+ errors_.assign(
+ ReportError("TestCompletionCallback: Call ran synchronously when "
+ "passed a required completion callback!",
+ result_));
+ return;
+ }
+ }
+ PP_DCHECK(have_result_ == true);
+}
+
+void TestCompletionCallback::WaitForAbortResult(int32_t result) {
+ WaitForResult(result);
+ int32_t final_result = result_;
+ if (result == PP_OK_COMPLETIONPENDING) {
+ if (final_result != PP_ERROR_ABORTED) {
+ errors_.assign(
+ ReportError("TestCompletionCallback: Expected PP_ERROR_ABORTED or "
+ "PP_OK. Ran asynchronously.",
+ final_result));
+ return;
+ }
+ } else if (result != PP_OK) {
+ errors_.assign(
+ ReportError("TestCompletionCallback: Expected PP_ERROR_ABORTED or"
+ "PP_OK. Ran synchronously.",
+ result));
+ return;
+ }
+}
+
+pp::CompletionCallback TestCompletionCallback::GetCallback() {
+ Reset();
+ int32_t flags = 0;
+ if (callback_type_ == PP_BLOCKING)
+ return pp::CompletionCallback();
+ else if (callback_type_ == PP_OPTIONAL)
+ flags = PP_COMPLETIONCALLBACK_FLAG_OPTIONAL;
return pp::CompletionCallback(&TestCompletionCallback::Handler,
const_cast<TestCompletionCallback*>(this),
flags);
}
+void TestCompletionCallback::Reset() {
+ wait_for_result_called_ = false;
+ result_ = PP_OK_COMPLETIONPENDING;
+ have_result_ = false;
+ post_quit_task_ = false;
+ errors_.clear();
+}
+
// static
void TestCompletionCallback::Handler(void* user_data, int32_t result) {
TestCompletionCallback* callback =
static_cast<TestCompletionCallback*>(user_data);
+ PP_DCHECK(!callback->have_result_);
callback->result_ = result;
callback->have_result_ = true;
- callback->run_count_++;
if (callback->post_quit_task_) {
callback->post_quit_task_ = false;
GetTestingInterface()->QuitMessageLoop(callback->instance_);
}
}
+
diff --git a/ppapi/tests/test_utils.h b/ppapi/tests/test_utils.h
index 8cff24e..1e2ec36 100644
--- a/ppapi/tests/test_utils.h
+++ b/ppapi/tests/test_utils.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -11,6 +11,7 @@
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/cpp/completion_callback.h"
+#include "ppapi/utility/completion_callback_factory.h"
// Timeout to wait for some action to complete.
extern const int kActionTimeoutMs;
@@ -20,36 +21,149 @@ std::string ReportError(const char* method, int32_t error);
void PlatformSleep(int duration_ms);
bool GetLocalHostPort(PP_Instance instance, std::string* host, uint16_t* port);
+// NestedEvent allows you to run a nested MessageLoop and wait for a particular
+// event to complete. For example, you can use it to wait for a callback on a
+// PPP interface, which will "Signal" the event and make the loop quit.
+// "Wait()" will return immediately if it has already been signalled. Otherwise,
+// it will run a nested message loop (using PPB_Testing.RunMessageLoop) and will
+// return only after it has been signalled.
+// Example:
+// std::string TestFullscreen::TestNormalToFullscreen() {
+// pp::Fullscreen screen_mode(instance);
+// screen_mode.SetFullscreen(true);
+// SimulateUserGesture();
+// // Let DidChangeView run in a nested message loop.
+// nested_event_.Wait();
+// Pass();
+// }
+//
+// void TestFullscreen::DidChangeView(const pp::View& view) {
+// nested_event_.Signal();
+// }
+class NestedEvent {
+ public:
+ explicit NestedEvent(PP_Instance instance)
+ : instance_(instance), waiting_(false), signalled_(false) {
+ }
+ // Run a nested message loop and wait until Signal() is called. If Signal()
+ // has already been called, return immediately without running a nested loop.
+ void Wait();
+ // Signal the NestedEvent. If Wait() has been called, quit the message loop.
+ void Signal();
+ private:
+ PP_Instance instance_;
+ bool waiting_;
+ bool signalled_;
+ // Disable copy and assign.
+ NestedEvent(const NestedEvent&);
+ NestedEvent& operator=(const NestedEvent&);
+};
+
+enum CallbackType { PP_REQUIRED, PP_OPTIONAL, PP_BLOCKING };
class TestCompletionCallback {
public:
- TestCompletionCallback(PP_Instance instance);
+ explicit TestCompletionCallback(PP_Instance instance);
+ // TODO(dmichael): Remove this constructor.
TestCompletionCallback(PP_Instance instance, bool force_async);
+ TestCompletionCallback(PP_Instance instance, CallbackType callback_type);
+
// Waits for the callback to be called and returns the
// result. Returns immediately if the callback was previously called
// and the result wasn't returned (i.e. each result value received
// by the callback is returned by WaitForResult() once and only
- // once).
+ // once). DEPRECATED: Please use the one below.
+ // TODO(dmichael): Remove this one when all the tests are updated.
int32_t WaitForResult();
- operator pp::CompletionCallback() const;
+ // Wait for a result, given the return from the call which took this callback
+ // as a parameter. If |result| is PP_OK_COMPLETIONPENDING, WaitForResult will
+ // block until its callback has been invoked (in some cases, this will already
+ // have happened, and WaitForCallback can return immediately).
+ // For any other values, WaitForResult will simply set its internal "result_"
+ // field. To retrieve the final result of the operation (i.e., the result
+ // the callback has run, if necessary), call result(). You can call result()
+ // as many times as necessary until a new pp::CompletionCallback is retrieved.
+ //
+ // In some cases, you may want to check that the callback was invoked in the
+ // expected way (i.e., if the callback was "Required", then it should be
+ // invoked asynchronously). Within the body of a test (where returning a non-
+ // empty string indicates test failure), you can use the
+ // CHECK_CALLBACK_BEHAVIOR(callback) macro. From within a helper function,
+ // you can use failed() and errors().
+ //
+ // Example usage within a test:
+ // callback.WaitForResult(foo.DoSomething(callback));
+ // CHECK_CALLBACK_BEHAVIOR(callback);
+ // ASSERT_EQ(PP_OK, callback.result());
+ //
+ // Example usage within a helper function:
+ // void HelperFunction(std::string* error_message) {
+ // callback.WaitForResult(foo.DoSomething(callback));
+ // if (callback.failed())
+ // error_message->assign(callback.errors());
+ // }
+ void WaitForResult(int32_t result);
+ // Used when you expect to receive either synchronous completion with PP_OK
+ // or a PP_ERROR_ABORTED asynchronously.
+ // Example usage:
+ // int32_t result = 0;
+ // {
+ // pp::URLLoader temp(instance_);
+ // result = temp.Open(request, callback);
+ // }
+ // callback.WaitForAbortResult(result);
+ // CHECK_CALLBACK_BEHAVIOR(callback);
+ void WaitForAbortResult(int32_t result);
+
+ // Retrieve a pp::CompletionCallback for use in testing. This Reset()s the
+ // TestCompletionCallback.
+ pp::CompletionCallback GetCallback();
+ operator pp::CompletionCallback() {
+ return GetCallback();
+ }
+
+ // TODO(dmichael): Remove run_count when all tests are updated. Most cases
+ // that use this can simply use CHECK_CALLBACK_BEHAVIOR.
unsigned run_count() const { return run_count_; }
+ // TODO(dmichael): Remove this; tests should use Reset() instead.
void reset_run_count() { run_count_ = 0; }
+ bool failed() { return !errors_.empty(); }
+ const std::string& errors() { return errors_; }
+
int32_t result() const { return result_; }
+ // Reset so that this callback can be used again.
+ void Reset();
+
private:
static void Handler(void* user_data, int32_t result);
+ // Used to check that WaitForResult is only called once for each usage of the
+ // callback.
+ bool wait_for_result_called_;
+ // Indicates whether we have already been invoked.
bool have_result_;
+ // The last result received (or PP_OK_COMPLETIONCALLBACK if none).
int32_t result_;
- bool force_async_;
+ CallbackType callback_type_;
bool post_quit_task_;
+ std::string errors_;
unsigned run_count_;
PP_Instance instance_;
};
+// Verifies that the callback didn't record any errors. If the callback is run
+// in an unexpected way (e.g., if it's invoked asynchronously when the call
+// should have blocked), this returns an appropriate error string.
+#define CHECK_CALLBACK_BEHAVIOR(callback) \
+do { \
+ if ((callback).failed()) \
+ return (callback).errors(); \
+} while (false)
+
/*
* A set of macros to use for platform detection. These were largely copied
* from chromium's build_config.h.
@@ -71,7 +185,7 @@ class TestCompletionCallback {
#elif defined(__sun)
#define PPAPI_OS_SOLARIS 1
#else
-#error Please add support for your platform in ppapi/c/pp_macros.h.
+#error Please add support for your platform in ppapi/tests/test_utils.h
#endif
/* These are used to determine POSIX-like implementations vs Windows. */
diff --git a/ppapi/tests/test_websocket.cc b/ppapi/tests/test_websocket.cc
index 69502a1..636bcae 100644
--- a/ppapi/tests/test_websocket.cc
+++ b/ppapi/tests/test_websocket.cc
@@ -282,7 +282,7 @@ PP_Resource TestWebSocket::Connect(const std::string& url,
}
*result = websocket_interface_->Connect(
ws, url_var, protocols, protocol_count,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ReleaseVar(url_var);
if (protocol.size())
ReleaseVar(protocols[0]);
@@ -356,12 +356,12 @@ std::string TestWebSocket::TestInvalidConnect() {
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
int32_t result = websocket_interface_->Connect(
ws, PP_MakeUndefined(), protocols, 1U,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
result = websocket_interface_->Connect(
ws, PP_MakeUndefined(), protocols, 1U,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_ERROR_INPROGRESS, result);
core_interface_->ReleaseResource(ws);
@@ -393,7 +393,7 @@ std::string TestWebSocket::TestProtocols() {
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
int32_t result = websocket_interface_->Connect(
ws, url, bad_protocols, 2U,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
if (result == PP_OK_COMPLETIONPENDING)
result = callback.WaitForResult();
ASSERT_EQ(PP_ERROR_BADARGUMENT, result);
@@ -452,7 +452,7 @@ std::string TestWebSocket::TestInvalidClose() {
PP_Resource ws = websocket_interface_->Create(instance_->pp_instance());
int32_t result = websocket_interface_->Close(
ws, PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_ERROR_FAILED, result);
core_interface_->ReleaseResource(ws);
@@ -461,7 +461,7 @@ std::string TestWebSocket::TestInvalidClose() {
ASSERT_TRUE(ws);
ASSERT_EQ(PP_OK, result);
result = websocket_interface_->Close(ws, 1U, reason,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_ERROR_NOACCESS, result);
core_interface_->ReleaseResource(ws);
@@ -484,7 +484,7 @@ std::string TestWebSocket::TestValidClose() {
ASSERT_EQ(PP_OK, result);
result = websocket_interface_->Close(ws,
PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
result = callback.WaitForResult();
ASSERT_EQ(PP_OK, result);
@@ -495,12 +495,11 @@ std::string TestWebSocket::TestValidClose() {
// successfully.
ws = websocket_interface_->Create(instance_->pp_instance());
result = websocket_interface_->Connect(ws, url, protocols, 0U,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
result = websocket_interface_->Close(ws,
PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- static_cast<pp::CompletionCallback>(
- another_callback).pp_completion_callback());
+ another_callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
result = callback.WaitForResult();
ASSERT_EQ(PP_ERROR_ABORTED, result);
@@ -516,12 +515,11 @@ std::string TestWebSocket::TestValidClose() {
ASSERT_EQ(PP_OK, result);
result = websocket_interface_->Close(ws,
PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
result = websocket_interface_->Close(ws,
PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- static_cast<pp::CompletionCallback>(
- another_callback).pp_completion_callback());
+ another_callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_ERROR_INPROGRESS, result);
result = callback.WaitForResult();
ASSERT_EQ(PP_OK, result);
@@ -533,12 +531,11 @@ std::string TestWebSocket::TestValidClose() {
ASSERT_EQ(PP_OK, result);
PP_Var receive_message_var;
result = websocket_interface_->ReceiveMessage(ws, &receive_message_var,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
result = websocket_interface_->Close(ws,
PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- static_cast<pp::CompletionCallback>(
- another_callback).pp_completion_callback());
+ another_callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
result = callback.WaitForResult();
ASSERT_EQ(PP_ERROR_ABORTED, result);
@@ -594,7 +591,7 @@ std::string TestWebSocket::TestTextSendReceive() {
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
PP_Var received_message;
result = websocket_interface_->ReceiveMessage(ws, &received_message,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_FALSE(result != PP_OK && result != PP_OK_COMPLETIONPENDING);
if (result == PP_OK_COMPLETIONPENDING)
result = callback.WaitForResult();
@@ -626,7 +623,7 @@ std::string TestWebSocket::TestBinarySendReceive() {
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
PP_Var received_message;
result = websocket_interface_->ReceiveMessage(ws, &received_message,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_TRUE(result == PP_OK || result == PP_OK_COMPLETIONPENDING);
if (result == PP_OK_COMPLETIONPENDING)
result = callback.WaitForResult();
@@ -668,8 +665,7 @@ std::string TestWebSocket::TestStressedSendReceive() {
TestCompletionCallback callback(instance_->pp_instance(), force_async_);
PP_Var received_message;
int32_t result = websocket_interface_->ReceiveMessage(
- ws, &received_message, static_cast<pp::CompletionCallback>(
- callback).pp_completion_callback());
+ ws, &received_message, callback.GetCallback().pp_completion_callback());
ASSERT_TRUE(result == PP_OK || result == PP_OK_COMPLETIONPENDING);
if (result == PP_OK_COMPLETIONPENDING)
result = callback.WaitForResult();
@@ -715,7 +711,7 @@ std::string TestWebSocket::TestBufferedAmount() {
TestCompletionCallback callback(instance_->pp_instance());
result = websocket_interface_->Close(ws,
PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE, reason,
- static_cast<pp::CompletionCallback>(callback).pp_completion_callback());
+ callback.GetCallback().pp_completion_callback());
ASSERT_EQ(PP_OK_COMPLETIONPENDING, result);
ASSERT_EQ(PP_WEBSOCKETREADYSTATE_CLOSING,
websocket_interface_->GetReadyState(ws));