Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / mojo / stash_backend_unittest.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/bind.h"
6 #include "base/message_loop/message_loop.h"
7 #include "base/run_loop.h"
8 #include "extensions/browser/mojo/stash_backend.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace extensions {
12
13 class StashServiceTest : public testing::Test, public mojo::ErrorHandler {
14  public:
15   enum Event {
16     EVENT_NONE,
17     EVENT_STASH_RETRIEVED,
18   };
19
20   StashServiceTest() {}
21
22   void SetUp() override {
23     expecting_error_ = false;
24     expected_event_ = EVENT_NONE;
25     stash_backend_.reset(new StashBackend);
26     stash_backend_->BindToRequest(mojo::GetProxy(&stash_service_));
27     stash_service_.set_error_handler(this);
28   }
29
30   void OnConnectionError() override { FAIL() << "Unexpected connection error"; }
31
32   mojo::Array<StashedObjectPtr> RetrieveStash() {
33     mojo::Array<StashedObjectPtr> stash;
34     stash_service_->RetrieveStash(base::Bind(
35         &StashServiceTest::StashRetrieved, base::Unretained(this), &stash));
36     WaitForEvent(EVENT_STASH_RETRIEVED);
37     return stash.Pass();
38   }
39
40   void StashRetrieved(mojo::Array<StashedObjectPtr>* output,
41                       mojo::Array<StashedObjectPtr> stash) {
42     *output = stash.Pass();
43     EventReceived(EVENT_STASH_RETRIEVED);
44   }
45
46   void WaitForEvent(Event event) {
47     expected_event_ = event;
48     base::RunLoop run_loop;
49     stop_run_loop_ = run_loop.QuitClosure();
50     run_loop.Run();
51   }
52
53   void EventReceived(Event event) {
54     if (event == expected_event_ && !stop_run_loop_.is_null())
55       stop_run_loop_.Run();
56   }
57
58  protected:
59   base::MessageLoop message_loop_;
60   base::Closure stop_run_loop_;
61   scoped_ptr<StashBackend> stash_backend_;
62   Event expected_event_;
63   bool expecting_error_;
64   mojo::InterfacePtr<StashService> stash_service_;
65
66  private:
67   DISALLOW_COPY_AND_ASSIGN(StashServiceTest);
68 };
69
70 // Test that adding stashed objects in multiple calls can all be retrieved by a
71 // Retrieve call.
72 TEST_F(StashServiceTest, AddTwiceAndRetrieve) {
73   mojo::Array<StashedObjectPtr> stashed_objects;
74   StashedObjectPtr stashed_object(StashedObject::New());
75   stashed_object->id = "test type";
76   stashed_object->data.push_back(1);
77   stashed_object->stashed_handles = mojo::Array<mojo::ScopedHandle>(0);
78   stashed_objects.push_back(stashed_object.Pass());
79   stash_service_->AddToStash(stashed_objects.Pass());
80   stashed_object = StashedObject::New();
81   stashed_object->id = "test type2";
82   stashed_object->data.push_back(2);
83   stashed_object->data.push_back(3);
84   stashed_object->stashed_handles = mojo::Array<mojo::ScopedHandle>(0);
85   stashed_objects.push_back(stashed_object.Pass());
86   stash_service_->AddToStash(stashed_objects.Pass());
87   stashed_objects = RetrieveStash();
88   ASSERT_EQ(2u, stashed_objects.size());
89   EXPECT_EQ("test type", stashed_objects[0]->id);
90   EXPECT_EQ(0u, stashed_objects[0]->stashed_handles.size());
91   EXPECT_EQ(1u, stashed_objects[0]->data.size());
92   EXPECT_EQ(1, stashed_objects[0]->data[0]);
93   EXPECT_EQ("test type2", stashed_objects[1]->id);
94   EXPECT_EQ(0u, stashed_objects[1]->stashed_handles.size());
95   EXPECT_EQ(2u, stashed_objects[1]->data.size());
96   EXPECT_EQ(2, stashed_objects[1]->data[0]);
97   EXPECT_EQ(3, stashed_objects[1]->data[1]);
98 }
99
100 // Test that handles survive a round-trip through the stash.
101 TEST_F(StashServiceTest, StashAndRetrieveHandles) {
102   mojo::Array<StashedObjectPtr> stashed_objects;
103   StashedObjectPtr stashed_object(StashedObject::New());
104   stashed_object->id = "test type";
105   stashed_object->data.push_back(1);
106
107   mojo::ScopedDataPipeConsumerHandle consumer;
108   mojo::ScopedDataPipeProducerHandle producer;
109   MojoCreateDataPipeOptions options = {
110       sizeof(options), MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, 1,
111   };
112   mojo::CreateDataPipe(&options, &producer, &consumer);
113   uint32_t num_bytes = 1;
114   MojoResult result = mojo::WriteDataRaw(
115       producer.get(), "1", &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
116   ASSERT_EQ(MOJO_RESULT_OK, result);
117   ASSERT_EQ(1u, num_bytes);
118
119   stashed_object->stashed_handles.push_back(
120       mojo::ScopedHandle::From(producer.Pass()));
121   stashed_object->stashed_handles.push_back(
122       mojo::ScopedHandle::From(consumer.Pass()));
123   stashed_objects.push_back(stashed_object.Pass());
124   stash_service_->AddToStash(stashed_objects.Pass());
125   stashed_objects = RetrieveStash();
126   ASSERT_EQ(1u, stashed_objects.size());
127   EXPECT_EQ("test type", stashed_objects[0]->id);
128   ASSERT_EQ(2u, stashed_objects[0]->stashed_handles.size());
129
130   consumer = mojo::ScopedDataPipeConsumerHandle::From(
131       stashed_objects[0]->stashed_handles[1].Pass());
132   result = mojo::Wait(
133       consumer.get(), MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE);
134   ASSERT_EQ(MOJO_RESULT_OK, result);
135   char data = '\0';
136   result = mojo::ReadDataRaw(
137       consumer.get(), &data, &num_bytes, MOJO_READ_DATA_FLAG_ALL_OR_NONE);
138   ASSERT_EQ(MOJO_RESULT_OK, result);
139   ASSERT_EQ(1u, num_bytes);
140   EXPECT_EQ('1', data);
141 }
142
143 TEST_F(StashServiceTest, RetrieveWithoutStashing) {
144   mojo::Array<StashedObjectPtr> stashed_objects = RetrieveStash();
145   ASSERT_TRUE(!stashed_objects.is_null());
146   EXPECT_EQ(0u, stashed_objects.size());
147 }
148
149 // Test that a stash service discards stashed objects when the backend no longer
150 // exists.
151 TEST_F(StashServiceTest, ServiceWithDeletedBackend) {
152   stash_backend_.reset();
153   stash_service_.set_error_handler(this);
154
155   mojo::Array<StashedObjectPtr> stashed_objects;
156   StashedObjectPtr stashed_object(StashedObject::New());
157   stashed_object->id = "test type";
158   stashed_object->data.push_back(1);
159   mojo::MessagePipe message_pipe;
160   stashed_object->stashed_handles.push_back(
161       mojo::ScopedHandle::From(message_pipe.handle0.Pass()));
162   stashed_objects.push_back(stashed_object.Pass());
163   stash_service_->AddToStash(stashed_objects.Pass());
164   stashed_objects = RetrieveStash();
165   ASSERT_EQ(0u, stashed_objects.size());
166   // Check that the stashed handle has been closed.
167   MojoResult result =
168       mojo::Wait(message_pipe.handle1.get(),
169                  MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_READABLE,
170                  MOJO_DEADLINE_INDEFINITE);
171   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
172 }
173
174 }  // namespace extensions