Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(627)

Side by Side Diff: content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc

Issue 2784003002: [IndexedDB] Mojo testing harness. (Closed)
Patch Set: Working! Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 "content/browser/indexed_db/indexed_db_dispatcher_host.h"
6
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/run_loop.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/utf_offset_string_conversions.h"
13 #include "base/test/test_simple_task_runner.h"
14 #include "content/browser/browser_thread_impl.h"
15 #include "content/browser/indexed_db/indexed_db_callbacks.h"
16 #include "content/browser/indexed_db/indexed_db_context_impl.h"
17 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
18 #include "content/browser/indexed_db/indexed_db_factory.h"
19 #include "content/browser/indexed_db/indexed_db_pending_connection.h"
20 #include "content/browser/indexed_db/mock_mojo_indexed_db_callbacks.h"
21 #include "content/browser/indexed_db/mock_mojo_indexed_db_database_callbacks.h"
22 #include "content/common/indexed_db/indexed_db.mojom.h"
23 #include "content/public/test/test_browser_context.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
26 #include "mojo/public/cpp/bindings/strong_associated_binding.h"
27 #include "net/url_request/url_request_test_util.h"
28 #include "storage/browser/test/mock_quota_manager_proxy.h"
29 #include "storage/browser/test/mock_special_storage_policy.h"
30 #include "testing/gmock/include/gmock/gmock.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "url/origin.h"
33
34 using indexed_db::mojom::Callbacks;
35 using indexed_db::mojom::CallbacksAssociatedPtrInfo;
36 using indexed_db::mojom::DatabaseAssociatedPtr;
37 using indexed_db::mojom::DatabaseAssociatedRequest;
38 using indexed_db::mojom::DatabaseCallbacks;
39 using indexed_db::mojom::DatabaseCallbacksAssociatedPtrInfo;
40 using indexed_db::mojom::FactoryAssociatedPtr;
41 using indexed_db::mojom::FactoryAssociatedRequest;
42 using indexed_db::mojom::KeyPath;
43 using mojo::StrongAssociatedBindingPtr;
44 using testing::_;
45
46 namespace content {
47 namespace {
48
49 ACTION_TEMPLATE(MoveArg,
50 HAS_1_TEMPLATE_PARAMS(int, k),
51 AND_1_VALUE_PARAMS(out)) {
52 *out = std::move(*::testing::get<k>(args));
53 };
54
55 MATCHER_P(IsAssociatedInterfacePtrInfoValid,
56 tf,
57 std::string(negation ? "isn't" : "is") + " " +
58 std::string(tf ? "valid" : "invalid")) {
59 return tf == arg->is_valid();
60 }
61
62 static const char kDatabaseName[] = "db";
63 static const char kOrigin[] = "https://www.example.com";
64 static const int kFakeProcessId = 2;
65
66 base::FilePath CreateAndReturnTempDir(base::ScopedTempDir* temp_dir) {
67 CHECK(temp_dir->CreateUniqueTempDir());
68 return temp_dir->GetPath();
69 }
70
71 // Represents a transaction from the renderer side.
72 struct TestTransaction {
73 TestTransaction(DatabaseAssociatedPtr* database, int64_t transaction_id)
74 : database(database), transaction_id(transaction_id) {}
75 TestTransaction(TestTransaction&& other) = default;
76
77 void EnqueueCreateObjectStore(int64_t object_store_id,
78 base::string16 name,
79 const content::IndexedDBKeyPath& key_path,
80 bool auto_increment) {
81 (*database)->CreateObjectStore(transaction_id, object_store_id, name,
82 key_path, auto_increment);
83 }
84
85 void ExpectTxnComplete(
86 MockMojoIndexedDBDatabaseCallbacks* connection_callbacks) {
87 EXPECT_CALL(*connection_callbacks, Complete(transaction_id)).Times(1);
88 }
89
90 void EnqueueCommit() { (*database)->Commit(transaction_id); }
91
92 DatabaseAssociatedPtr* database;
Reilly Grant (use Gerrit) 2017/05/11 02:12:01 It's hard to tell what is going on in the methods
Ken Rockot(use gerrit already) 2017/05/11 17:21:03 This could be a raw mojom::Database*. No need to h
93 int64_t transaction_id;
94
95 private:
96 DISALLOW_COPY_AND_ASSIGN(TestTransaction);
97 };
98
99 // Represents a database connection from the renderer side.
100 struct TestDatabaseConnection {
101 TestDatabaseConnection(url::Origin origin,
102 base::string16 db_name,
103 int64_t version,
104 int64_t upgrade_txn_id)
105 : origin(std::move(origin)),
106 db_name(std::move(db_name)),
107 version(version),
108 upgrade_txn_id(upgrade_txn_id){};
109 TestDatabaseConnection(TestDatabaseConnection&& other) = default;
110
111 ~TestDatabaseConnection() {
112 if (open_callbacks_strong_ptr)
113 open_callbacks_strong_ptr->Close();
114 if (connection_callbacks_strong_ptr)
115 connection_callbacks_strong_ptr->Close();
116 }
117
118 // The factory has to be flushed or the io thread run for the message to be
119 // sent.
120 void QueueOpenRequestAndCreateCallbacks(FactoryAssociatedPtr* factory) {
121 ASSERT_FALSE(connection_openned) << "Connection already opened.";
122 connection_openned = true;
123
124 CallbacksAssociatedPtrInfo callbacks_ptr_info;
125 DatabaseCallbacksAssociatedPtrInfo database_callbacks_ptr_info;
126
127 auto callbacks_request = ::mojo::MakeRequest(&callbacks_ptr_info);
128 auto database_callbacks_request =
129 ::mojo::MakeRequest(&database_callbacks_ptr_info);
130
131 open_callbacks = new testing::StrictMock<MockMojoIndexedDBCallbacks>();
132 connection_callbacks =
133 new testing::StrictMock<MockMojoIndexedDBDatabaseCallbacks>();
134
135 open_callbacks_strong_ptr = ::mojo::MakeStrongAssociatedBinding(
136 base::WrapUnique(open_callbacks), std::move(callbacks_request));
137 connection_callbacks_strong_ptr = ::mojo::MakeStrongAssociatedBinding(
138 base::WrapUnique(connection_callbacks),
139 std::move(database_callbacks_request));
140
141 (*factory)->Open(std::move(callbacks_ptr_info),
142 std::move(database_callbacks_ptr_info), origin, db_name,
143 version, upgrade_txn_id);
Reilly Grant (use Gerrit) 2017/05/11 02:12:01 First, I suggest adding a method to mojo::Associat
Ken Rockot(use gerrit already) 2017/05/11 17:21:03 Guess to be safe my reply should have been inline,
144 }
145
146 void ExpectUpgradeCall(int64_t old_version) {
147 EXPECT_FALSE(database_info_.is_valid());
148 EXPECT_CALL(*open_callbacks,
149 MockedUpgradeNeeded(IsAssociatedInterfacePtrInfoValid(true),
150 old_version, blink::kWebIDBDataLossNone,
151 std::string(""), _))
152 .WillOnce(testing::DoAll(MoveArg<0>(&database_info_),
153 testing::SaveArg<4>(&metadata)));
154 }
155
156 void ExpectDatabaseSuccess(bool with_database) {
157 if (with_database) {
158 EXPECT_CALL(
159 *open_callbacks,
160 MockedSuccessDatabase(IsAssociatedInterfacePtrInfoValid(true), _))
161 .WillOnce(testing::DoAll(MoveArg<0>(&database_info_),
162 testing::SaveArg<1>(&metadata)));
163 } else {
164 EXPECT_CALL(
165 *open_callbacks,
166 MockedSuccessDatabase(IsAssociatedInterfacePtrInfoValid(false), _));
167 }
168 }
169
170 void ValidateMetadata() {
171 EXPECT_EQ(metadata.name, db_name);
172 EXPECT_EQ(metadata.version, version);
173 }
174
175 void CreateDatabasePtr() {
176 ASSERT_TRUE(database_info_.is_valid());
177 database.Bind(std::move(database_info_));
178 }
179
180 url::Origin origin;
181 base::string16 db_name;
182 int64_t version;
183 int64_t upgrade_txn_id;
184
185 DatabaseAssociatedPtr database;
186 IndexedDBDatabaseMetadata metadata;
187
188 // Callbacks given to the 'open' call - used for upgrading & recieving the db.
189 MockMojoIndexedDBCallbacks* open_callbacks = nullptr;
190 // Callbacks given to the 'open' call for interacting with connection.
191 MockMojoIndexedDBDatabaseCallbacks* connection_callbacks = nullptr;
192
193 bool connection_openned = false;
194 StrongAssociatedBindingPtr<Callbacks> open_callbacks_strong_ptr;
Ken Rockot(use gerrit already) 2017/05/11 17:21:03 If you actually have to explicitly close these str
dmurph 2017/05/12 01:22:06 Thanks!
195 StrongAssociatedBindingPtr<DatabaseCallbacks> connection_callbacks_strong_ptr;
196
197 private:
198 ::indexed_db::mojom::DatabaseAssociatedPtrInfo database_info_;
199
200 DISALLOW_COPY_AND_ASSIGN(TestDatabaseConnection);
201 };
202
203 } // namespace
204
205 class IndexedDBDispatcherHostTest : public testing::Test {
206 public:
207 IndexedDBDispatcherHostTest()
208 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
209 db_task_runner_(new base::TestSimpleTaskRunner()),
210 request_context_getter_(
211 new net::TestURLRequestContextGetter(db_task_runner_)),
212 special_storage_policy_(new MockSpecialStoragePolicy()),
213 quota_manager_proxy_(new MockQuotaManagerProxy(nullptr, nullptr)),
214 context_impl_(
215 new IndexedDBContextImpl(CreateAndReturnTempDir(&temp_dir_),
216 special_storage_policy_.get(),
217 quota_manager_proxy_.get(),
218 db_task_runner_.get())),
219 blob_storage_(ChromeBlobStorageContext::GetFor(&browser_context_)),
220 host_(new IndexedDBDispatcherHost(kFakeProcessId,
221 request_context_getter_.get(),
222 context_impl_.get(),
223 blob_storage_.get())) {
224 base::RunLoop().RunUntilIdle();
Ken Rockot(use gerrit already) 2017/05/11 17:21:03 Please never use RunUntilIdle unless you are expli
dmurph 2017/05/12 01:22:06 I need to do this because I need to run the IO thr
225 }
226
227 void TearDown() override {
228 host_.reset();
229 base::RunLoop().RunUntilIdle();
Ken Rockot(use gerrit already) 2017/05/11 17:21:03 Again with the RunUntilIdle() - flakiness danger z
dmurph 2017/05/12 01:22:06 These are temp, above is not though.
230 db_task_runner_->RunUntilIdle();
231 base::RunLoop().RunUntilIdle();
232 // We leak files if this doesn't return true.
233 ASSERT_TRUE(temp_dir_.Delete());
234 }
235
236 void SetUp() override {
237 FactoryAssociatedRequest request =
238 ::mojo::MakeIsolatedRequest(&idb_mojo_factory_);
239 host_->AddBinding(std::move(request));
240 }
241
242 protected:
243 TestBrowserThreadBundle thread_bundle_;
244 TestBrowserContext browser_context_;
245
246 base::ScopedTempDir temp_dir_;
247 scoped_refptr<base::TestSimpleTaskRunner> db_task_runner_;
248 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
249 scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
250 scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
251 scoped_refptr<IndexedDBContextImpl> context_impl_;
252 scoped_refptr<ChromeBlobStorageContext> blob_storage_;
253 std::unique_ptr<IndexedDBDispatcherHost, BrowserThread::DeleteOnIOThread>
254 host_;
255 FactoryAssociatedPtr idb_mojo_factory_;
256
257 DISALLOW_COPY_AND_ASSIGN(IndexedDBDispatcherHostTest);
258 };
259
260 TEST_F(IndexedDBDispatcherHostTest, TestCloseConnectionBeforeUpgrade) {
261 TestDatabaseConnection connection(url::Origin(GURL(kOrigin)),
262 base::UTF8ToUTF16(kDatabaseName), 1, 1);
263
264 // Queue open request message.
265 connection.QueueOpenRequestAndCreateCallbacks(&idb_mojo_factory_);
266
267 // Create mock expectation.
268 connection.ExpectUpgradeCall(IndexedDBDatabaseMetadata::NO_VERSION);
269
270 // Send message.
271 idb_mojo_factory_.FlushForTesting();
272
273 // Run database tasks and io tasks to send message back.
274 db_task_runner_->RunUntilIdle();
275 base::RunLoop().RunUntilIdle();
276
277 connection.ValidateMetadata();
278 }
279
280 TEST_F(IndexedDBDispatcherHostTest, TestOpenConnectionAndUpgrade) {
281 TestDatabaseConnection connection(url::Origin(GURL(kOrigin)),
282 base::UTF8ToUTF16(kDatabaseName), 1, 1);
283
284 // Open DB.
285 connection.QueueOpenRequestAndCreateCallbacks(&idb_mojo_factory_);
286 connection.ExpectUpgradeCall(IndexedDBDatabaseMetadata::NO_VERSION);
287 idb_mojo_factory_.FlushForTesting();
288 db_task_runner_->RunUntilIdle();
289 base::RunLoop().RunUntilIdle();
290 connection.ValidateMetadata();
291 connection.CreateDatabasePtr();
292
293 // Create object store.
294 TestTransaction txn(&connection.database, 1);
295 txn.EnqueueCreateObjectStore(10, base::UTF8ToUTF16(kDatabaseName),
296 content::IndexedDBKeyPath(), false);
297 txn.EnqueueCommit();
298 txn.ExpectTxnComplete(connection.connection_callbacks);
299 connection.ExpectDatabaseSuccess(/* with_database */ false);
300
301 connection.database.FlushForTesting();
302 db_task_runner_->RunUntilIdle();
303 base::RunLoop().RunUntilIdle();
304 }
305
306 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698