Index: extensions/browser/mojo/stash_backend_unittest.cc |
diff --git a/extensions/browser/mojo/stash_backend_unittest.cc b/extensions/browser/mojo/stash_backend_unittest.cc |
index 9d7f0947e649136444b0ad2410b16eb08db6066b..de8abf440c9ec21745e2d58900e09c9399205dd2 100644 |
--- a/extensions/browser/mojo/stash_backend_unittest.cc |
+++ b/extensions/browser/mojo/stash_backend_unittest.cc |
@@ -7,14 +7,38 @@ |
#include "base/run_loop.h" |
#include "extensions/browser/mojo/stash_backend.h" |
#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" |
namespace extensions { |
+namespace { |
+ |
+// Create a data pipe, write some data to the producer handle and return the |
+// consumer handle. |
+mojo::ScopedHandle CreateReadableHandle() { |
+ mojo::ScopedDataPipeConsumerHandle consumer_handle; |
+ mojo::ScopedDataPipeProducerHandle producer_handle; |
+ MojoCreateDataPipeOptions options = { |
+ sizeof(options), MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, 1, |
+ }; |
+ MojoResult result = |
+ mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle); |
+ EXPECT_EQ(MOJO_RESULT_OK, result); |
+ uint32_t num_bytes = 1; |
+ result = mojo::WriteDataRaw(producer_handle.get(), "a", &num_bytes, |
+ MOJO_WRITE_DATA_FLAG_NONE); |
+ EXPECT_EQ(MOJO_RESULT_OK, result); |
+ EXPECT_EQ(1u, num_bytes); |
+ return mojo::ScopedHandle::From(consumer_handle.Pass()); |
+} |
+ |
+} // namespace |
class StashServiceTest : public testing::Test, public mojo::ErrorHandler { |
public: |
enum Event { |
EVENT_NONE, |
EVENT_STASH_RETRIEVED, |
+ EVENT_HANDLE_READY, |
}; |
StashServiceTest() {} |
@@ -22,9 +46,11 @@ class StashServiceTest : public testing::Test, public mojo::ErrorHandler { |
void SetUp() override { |
expecting_error_ = false; |
expected_event_ = EVENT_NONE; |
- stash_backend_.reset(new StashBackend); |
+ stash_backend_.reset(new StashBackend(base::Bind( |
+ &StashServiceTest::OnHandleReadyToRead, base::Unretained(this)))); |
stash_backend_->BindToRequest(mojo::GetProxy(&stash_service_)); |
stash_service_.set_error_handler(this); |
+ handles_ready_ = 0; |
} |
void OnConnectionError() override { FAIL() << "Unexpected connection error"; } |
@@ -55,6 +81,11 @@ class StashServiceTest : public testing::Test, public mojo::ErrorHandler { |
stop_run_loop_.Run(); |
} |
+ void OnHandleReadyToRead() { |
+ handles_ready_++; |
+ EventReceived(EVENT_HANDLE_READY); |
+ } |
+ |
protected: |
base::MessageLoop message_loop_; |
base::Closure stop_run_loop_; |
@@ -62,6 +93,7 @@ class StashServiceTest : public testing::Test, public mojo::ErrorHandler { |
Event expected_event_; |
bool expecting_error_; |
mojo::InterfacePtr<StashService> stash_service_; |
+ int handles_ready_; |
private: |
DISALLOW_COPY_AND_ASSIGN(StashServiceTest); |
@@ -147,6 +179,94 @@ TEST_F(StashServiceTest, RetrieveWithoutStashing) { |
EXPECT_EQ(0u, stashed_objects.size()); |
} |
+TEST_F(StashServiceTest, NotifyOnReadableHandle) { |
+ mojo::Array<StashedObjectPtr> stash_entries; |
+ StashedObjectPtr stashed_object(StashedObject::New()); |
+ stashed_object->id = "test type"; |
+ stashed_object->data.push_back(0); |
+ stashed_object->monitor_handles = true; |
+ mojo::ServiceProviderPtr service_provider; |
+ |
+ // Stash the ServiceProvider request. When we make a call on |
+ // |service_provider|, the stashed handle will become readable. |
+ stashed_object->stashed_handles.push_back(mojo::ScopedHandle::From( |
+ mojo::GetProxy(&service_provider).PassMessagePipe())); |
+ |
+ stash_entries.push_back(stashed_object.Pass()); |
+ stash_service_->AddToStash(stash_entries.Pass()); |
+ |
+ mojo::MessagePipe pipe; |
+ service_provider->ConnectToService("", pipe.handle0.Pass()); |
+ |
+ WaitForEvent(EVENT_HANDLE_READY); |
+ EXPECT_EQ(1, handles_ready_); |
+} |
+ |
+TEST_F(StashServiceTest, NotifyOnReadableDataPipeHandle) { |
+ mojo::Array<StashedObjectPtr> stash_entries; |
+ StashedObjectPtr stashed_object(StashedObject::New()); |
+ stashed_object->id = "test type"; |
+ stashed_object->monitor_handles = true; |
+ |
+ MojoCreateDataPipeOptions options = { |
+ sizeof(options), MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, 1, |
+ }; |
+ mojo::ScopedDataPipeConsumerHandle consumer_handle; |
+ mojo::ScopedDataPipeProducerHandle producer_handle; |
+ uint32_t num_bytes = 1; |
+ MojoResult result = |
+ mojo::CreateDataPipe(&options, &producer_handle, &consumer_handle); |
+ ASSERT_EQ(MOJO_RESULT_OK, result); |
+ result = mojo::WriteDataRaw(producer_handle.get(), "a", &num_bytes, |
+ MOJO_WRITE_DATA_FLAG_NONE); |
+ ASSERT_EQ(MOJO_RESULT_OK, result); |
+ ASSERT_EQ(1u, num_bytes); |
+ stashed_object->stashed_handles.push_back( |
+ mojo::ScopedHandle::From(producer_handle.Pass())); |
+ stashed_object->stashed_handles.push_back( |
+ mojo::ScopedHandle::From(consumer_handle.Pass())); |
+ stashed_object->data.push_back(1); |
+ |
+ stash_entries.push_back(stashed_object.Pass()); |
+ stash_service_->AddToStash(stash_entries.Pass()); |
+ WaitForEvent(EVENT_HANDLE_READY); |
+ EXPECT_EQ(1, handles_ready_); |
+} |
+ |
+TEST_F(StashServiceTest, NotifyOncePerStashOnReadableHandles) { |
+ mojo::Array<StashedObjectPtr> stash_entries; |
+ StashedObjectPtr stashed_object(StashedObject::New()); |
+ stashed_object->id = "test type"; |
+ stashed_object->data.push_back(1); |
+ stashed_object->monitor_handles = true; |
+ stashed_object->stashed_handles.push_back(CreateReadableHandle()); |
+ stashed_object->stashed_handles.push_back(CreateReadableHandle()); |
+ stash_entries.push_back(stashed_object.Pass()); |
+ stashed_object = StashedObject::New(); |
+ stashed_object->id = "another test type"; |
+ stashed_object->data.push_back(2); |
+ stashed_object->monitor_handles = true; |
+ stashed_object->stashed_handles.push_back(CreateReadableHandle()); |
+ stashed_object->stashed_handles.push_back(CreateReadableHandle()); |
+ stash_entries.push_back(stashed_object.Pass()); |
+ stash_service_->AddToStash(stash_entries.Pass()); |
+ WaitForEvent(EVENT_HANDLE_READY); |
+ EXPECT_EQ(1, handles_ready_); |
+ |
+ stashed_object = StashedObject::New(); |
+ stashed_object->id = "yet another test type"; |
+ stashed_object->data.push_back(3); |
+ stashed_object->monitor_handles = true; |
+ stashed_object->stashed_handles.push_back(CreateReadableHandle()); |
+ stashed_object->stashed_handles.push_back(CreateReadableHandle()); |
+ stash_entries.push_back(stashed_object.Pass()); |
+ stash_service_->AddToStash(stash_entries.Pass()); |
+ |
+ stash_service_->AddToStash(RetrieveStash()); |
+ WaitForEvent(EVENT_HANDLE_READY); |
+ EXPECT_EQ(2, handles_ready_); |
+} |
+ |
// Test that a stash service discards stashed objects when the backend no longer |
// exists. |
TEST_F(StashServiceTest, ServiceWithDeletedBackend) { |