diff options
author | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-07 00:09:08 +0000 |
---|---|---|
committer | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-07 00:09:08 +0000 |
commit | 3ab612746af9bfa1f7d502b7851330423f71c672 (patch) | |
tree | dabdc0200d609cec040c5df4f5042a88cb343e83 | |
parent | 4af886ca90a6262620eebdc9ab49b7b71b9ca33b (diff) | |
download | chromium_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.cc | 4 | ||||
-rw-r--r-- | ppapi/tests/test_case.cc | 2 | ||||
-rw-r--r-- | ppapi/tests/test_case.h | 24 | ||||
-rw-r--r-- | ppapi/tests/test_file_system.cc | 65 | ||||
-rw-r--r-- | ppapi/tests/test_flash_fullscreen.cc | 12 | ||||
-rw-r--r-- | ppapi/tests/test_flash_fullscreen.h | 6 | ||||
-rw-r--r-- | ppapi/tests/test_fullscreen.cc | 19 | ||||
-rw-r--r-- | ppapi/tests/test_fullscreen.h | 6 | ||||
-rw-r--r-- | ppapi/tests/test_network_monitor_private.cc | 28 | ||||
-rw-r--r-- | ppapi/tests/test_url_loader.cc | 238 | ||||
-rw-r--r-- | ppapi/tests/test_url_request.cc | 34 | ||||
-rw-r--r-- | ppapi/tests/test_utils.cc | 119 | ||||
-rw-r--r-- | ppapi/tests/test_utils.h | 126 | ||||
-rw-r--r-- | ppapi/tests/test_websocket.cc | 38 |
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)); |