blob: 1d6bd789bfab00cd272d88549ffed1d47bf396e5 [file] [log] [blame]
Sergei Datsenko3554b9e42018-12-18 05:49:111// Copyright 2018 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 "chromeos/components/drivefs/drivefs_search.h"
6
7#include "base/run_loop.h"
8#include "base/test/bind_test_util.h"
Gabriel Charetteb69fcd42019-08-23 02:13:299#include "base/test/scoped_task_environment.h"
Sergei Datsenko3554b9e42018-12-18 05:49:1110#include "base/test/simple_test_clock.h"
Takuto Ikuta8cfb4892019-01-24 01:04:0511#include "chromeos/components/drivefs/mojom/drivefs.mojom-test-utils.h"
Sergei Datsenko3554b9e42018-12-18 05:49:1112#include "mojo/public/cpp/bindings/binding.h"
Robbie McElrathb0acd132019-02-05 18:11:3713#include "services/network/test/test_network_connection_tracker.h"
Sergei Datsenko3554b9e42018-12-18 05:49:1114#include "testing/gmock/include/gmock/gmock.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace drivefs {
18namespace {
19
20using testing::_;
21
22class MockDriveFs : public mojom::DriveFsInterceptorForTesting,
23 public mojom::SearchQuery {
24 public:
25 MockDriveFs() : search_binding_(this) {}
26
27 DriveFs* GetForwardingInterface() override {
28 NOTREACHED();
29 return nullptr;
30 }
31
32 MOCK_CONST_METHOD1(OnStartSearchQuery, void(const mojom::QueryParameters&));
33 void StartSearchQuery(mojom::SearchQueryRequest query,
34 mojom::QueryParametersPtr query_params) override {
35 if (search_binding_.is_bound())
36 search_binding_.Unbind();
37 OnStartSearchQuery(*query_params);
38 search_binding_.Bind(std::move(query));
39 }
40
41 MOCK_METHOD1(OnGetNextPage,
42 drive::FileError(
43 base::Optional<std::vector<mojom::QueryItemPtr>>* items));
44
45 void GetNextPage(GetNextPageCallback callback) override {
46 base::Optional<std::vector<mojom::QueryItemPtr>> items;
47 auto error = OnGetNextPage(&items);
48 std::move(callback).Run(error, std::move(items));
49 }
50
51 private:
52 mojo::Binding<mojom::SearchQuery> search_binding_;
53 DISALLOW_COPY_AND_ASSIGN(MockDriveFs);
54};
55
56class DriveFsSearchTest : public testing::Test {
57 public:
Robbie McElrathb0acd132019-02-05 18:11:3758 DriveFsSearchTest()
59 : network_connection_tracker_(
60 network::TestNetworkConnectionTracker::CreateInstance()) {
61 clock_.SetNow(base::Time::Now());
62 }
Sergei Datsenko3554b9e42018-12-18 05:49:1163
64 protected:
Gabriel Charette694c3c332019-08-19 14:53:0565 base::test::TaskEnvironment task_environment_;
Robbie McElrathb0acd132019-02-05 18:11:3766 std::unique_ptr<network::TestNetworkConnectionTracker>
67 network_connection_tracker_;
Sergei Datsenko3554b9e42018-12-18 05:49:1168 MockDriveFs mock_drivefs_;
69 base::SimpleTestClock clock_;
70};
71
72} // namespace
73
74ACTION_P(PopulateSearch, count) {
75 if (count < 0)
76 return;
77 std::vector<mojom::QueryItemPtr> items;
78 for (int i = 0; i < count; ++i) {
79 items.emplace_back(mojom::QueryItem::New());
80 items.back()->metadata = mojom::FileMetadata::New();
81 items.back()->metadata->capabilities = mojom::Capabilities::New();
82 }
83 *arg0 = std::move(items);
84}
85
86MATCHER_P5(MatchQuery, source, text, title, shared, offline, "") {
87 if (arg.query_source != source)
88 return false;
89 if (text != nullptr) {
90 if (!arg.text_content || *arg.text_content != base::StringPiece(text))
91 return false;
92 } else {
93 if (arg.text_content)
94 return false;
95 }
96 if (title != nullptr) {
97 if (!arg.title || *arg.title != base::StringPiece(title))
98 return false;
99 } else {
100 if (arg.title)
101 return false;
102 }
103 return arg.shared_with_me == shared && arg.available_offline == offline;
Nico Weber1ed20762019-02-25 19:37:58104}
Sergei Datsenko3554b9e42018-12-18 05:49:11105
106TEST_F(DriveFsSearchTest, Search) {
Robbie McElrathb0acd132019-02-05 18:11:37107 DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
108 &clock_);
Sergei Datsenko3554b9e42018-12-18 05:49:11109
110 EXPECT_CALL(mock_drivefs_, OnStartSearchQuery(_));
111 EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
112 .WillOnce(testing::DoAll(
113 PopulateSearch(3), testing::Return(drive::FileError::FILE_ERROR_OK)));
114
115 mojom::QueryParametersPtr params = mojom::QueryParameters::New();
116 params->query_source = mojom::QueryParameters::QuerySource::kLocalOnly;
117
118 bool called = false;
119 mojom::QueryParameters::QuerySource source = search.PerformSearch(
120 std::move(params),
121 base::BindLambdaForTesting(
122 [&called](drive::FileError err,
123 base::Optional<std::vector<mojom::QueryItemPtr>> items) {
124 called = true;
125 EXPECT_EQ(drive::FileError::FILE_ERROR_OK, err);
126 EXPECT_EQ(3u, items->size());
127 }));
128 EXPECT_EQ(mojom::QueryParameters::QuerySource::kLocalOnly, source);
129 base::RunLoop().RunUntilIdle();
130 EXPECT_TRUE(called);
131}
132
133TEST_F(DriveFsSearchTest, Search_Fail) {
Robbie McElrathb0acd132019-02-05 18:11:37134 DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
135 &clock_);
Sergei Datsenko3554b9e42018-12-18 05:49:11136
137 EXPECT_CALL(mock_drivefs_, OnStartSearchQuery(_));
138 EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
139 .WillOnce(testing::Return(drive::FileError::FILE_ERROR_ACCESS_DENIED));
140
141 mojom::QueryParametersPtr params = mojom::QueryParameters::New();
142 params->query_source = mojom::QueryParameters::QuerySource::kCloudOnly;
143
144 bool called = false;
145 mojom::QueryParameters::QuerySource source = search.PerformSearch(
146 std::move(params),
147 base::BindLambdaForTesting(
148 [&called](drive::FileError err,
149 base::Optional<std::vector<mojom::QueryItemPtr>> items) {
150 called = true;
151 EXPECT_EQ(drive::FileError::FILE_ERROR_ACCESS_DENIED, err);
152 }));
153 EXPECT_EQ(mojom::QueryParameters::QuerySource::kCloudOnly, source);
154 base::RunLoop().RunUntilIdle();
155 EXPECT_TRUE(called);
156}
157
158TEST_F(DriveFsSearchTest, Search_OnlineToOffline) {
Robbie McElrathb0acd132019-02-05 18:11:37159 DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
160 &clock_);
Sergei Datsenko3554b9e42018-12-18 05:49:11161
Robbie McElrathb0acd132019-02-05 18:11:37162 network_connection_tracker_->SetConnectionType(
163 network::mojom::ConnectionType::CONNECTION_NONE);
Sergei Datsenko3554b9e42018-12-18 05:49:11164
165 EXPECT_CALL(mock_drivefs_, OnStartSearchQuery(_));
166 EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
167 .WillOnce(testing::DoAll(
168 PopulateSearch(3), testing::Return(drive::FileError::FILE_ERROR_OK)));
169
170 mojom::QueryParametersPtr params = mojom::QueryParameters::New();
171 params->query_source = mojom::QueryParameters::QuerySource::kCloudOnly;
172
173 bool called = false;
174 mojom::QueryParameters::QuerySource source = search.PerformSearch(
175 std::move(params),
176 base::BindLambdaForTesting(
177 [&called](drive::FileError err,
178 base::Optional<std::vector<mojom::QueryItemPtr>> items) {
179 called = true;
180 EXPECT_EQ(drive::FileError::FILE_ERROR_OK, err);
181 EXPECT_EQ(3u, items->size());
182 }));
183 EXPECT_EQ(mojom::QueryParameters::QuerySource::kLocalOnly, source);
184 base::RunLoop().RunUntilIdle();
185 EXPECT_TRUE(called);
186}
187
188TEST_F(DriveFsSearchTest, Search_OnlineToOfflineFallback) {
Robbie McElrathb0acd132019-02-05 18:11:37189 DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
190 &clock_);
Sergei Datsenko3554b9e42018-12-18 05:49:11191
192 EXPECT_CALL(mock_drivefs_,
193 OnStartSearchQuery(
194 MatchQuery(mojom::QueryParameters::QuerySource::kCloudOnly,
195 "foobar", nullptr, false, false)));
196 EXPECT_CALL(mock_drivefs_,
197 OnStartSearchQuery(
198 MatchQuery(mojom::QueryParameters::QuerySource::kLocalOnly,
199 nullptr, "foobar", false, false)));
200
201 EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
202 .WillOnce(testing::Return(drive::FileError::FILE_ERROR_NO_CONNECTION))
203 .WillOnce(testing::DoAll(
204 PopulateSearch(3), testing::Return(drive::FileError::FILE_ERROR_OK)));
205
206 mojom::QueryParametersPtr params = mojom::QueryParameters::New();
207 params->query_source = mojom::QueryParameters::QuerySource::kCloudOnly;
208 params->text_content = "foobar";
209
210 bool called = false;
211 mojom::QueryParameters::QuerySource source = search.PerformSearch(
212 std::move(params),
213 base::BindLambdaForTesting(
214 [&called](drive::FileError err,
215 base::Optional<std::vector<mojom::QueryItemPtr>> items) {
216 called = true;
217 EXPECT_EQ(drive::FileError::FILE_ERROR_OK, err);
218 EXPECT_EQ(3u, items->size());
219 }));
220 EXPECT_EQ(mojom::QueryParameters::QuerySource::kCloudOnly, source);
221 base::RunLoop().RunUntilIdle();
222 EXPECT_TRUE(called);
223}
224
225TEST_F(DriveFsSearchTest, Search_SharedWithMeCaching) {
Robbie McElrathb0acd132019-02-05 18:11:37226 DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
227 &clock_);
Sergei Datsenko3554b9e42018-12-18 05:49:11228
229 EXPECT_CALL(mock_drivefs_,
230 OnStartSearchQuery(
231 MatchQuery(mojom::QueryParameters::QuerySource::kCloudOnly,
232 nullptr, nullptr, true, false)))
233 .Times(2);
234 EXPECT_CALL(mock_drivefs_,
235 OnStartSearchQuery(
236 MatchQuery(mojom::QueryParameters::QuerySource::kLocalOnly,
237 nullptr, nullptr, true, false)))
238 .Times(1);
239
240 EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
241 .WillOnce(testing::DoAll(
242 PopulateSearch(3), testing::Return(drive::FileError::FILE_ERROR_OK)))
243 .WillOnce(testing::DoAll(
244 PopulateSearch(3), testing::Return(drive::FileError::FILE_ERROR_OK)))
245 .WillOnce(testing::DoAll(
246 PopulateSearch(3), testing::Return(drive::FileError::FILE_ERROR_OK)));
247
248 mojom::QueryParametersPtr params = mojom::QueryParameters::New();
249 params->query_source = mojom::QueryParameters::QuerySource::kCloudOnly;
250 params->shared_with_me = true;
251
252 bool called = false;
253 mojom::QueryParameters::QuerySource source = search.PerformSearch(
254 std::move(params),
255 base::BindLambdaForTesting(
256 [&called](drive::FileError err,
257 base::Optional<std::vector<mojom::QueryItemPtr>> items) {
258 called = true;
259 EXPECT_EQ(drive::FileError::FILE_ERROR_OK, err);
260 EXPECT_EQ(3u, items->size());
261 }));
262 EXPECT_EQ(mojom::QueryParameters::QuerySource::kCloudOnly, source);
263 base::RunLoop().RunUntilIdle();
264 EXPECT_TRUE(called);
265
266 params = mojom::QueryParameters::New();
267 params->query_source = mojom::QueryParameters::QuerySource::kCloudOnly;
268 params->shared_with_me = true;
269
270 called = false;
271 source = search.PerformSearch(
272 std::move(params),
273 base::BindLambdaForTesting(
274 [&called](drive::FileError err,
275 base::Optional<std::vector<mojom::QueryItemPtr>> items) {
276 called = true;
277 EXPECT_EQ(drive::FileError::FILE_ERROR_OK, err);
278 EXPECT_EQ(3u, items->size());
279 }));
280 EXPECT_EQ(mojom::QueryParameters::QuerySource::kLocalOnly, source);
281 base::RunLoop().RunUntilIdle();
282 EXPECT_TRUE(called);
283
284 // Time has passed...
285 clock_.Advance(base::TimeDelta::FromHours(1));
286
287 params = mojom::QueryParameters::New();
288 params->query_source = mojom::QueryParameters::QuerySource::kCloudOnly;
289 params->shared_with_me = true;
290
291 called = false;
292 source = search.PerformSearch(
293 std::move(params),
294 base::BindLambdaForTesting(
295 [&called](drive::FileError err,
296 base::Optional<std::vector<mojom::QueryItemPtr>> items) {
297 called = true;
298 EXPECT_EQ(drive::FileError::FILE_ERROR_OK, err);
299 EXPECT_EQ(3u, items->size());
300 }));
301 EXPECT_EQ(mojom::QueryParameters::QuerySource::kCloudOnly, source);
302 base::RunLoop().RunUntilIdle();
303 EXPECT_TRUE(called);
304}
305
Sergei Datsenko79e4ac52018-12-18 07:17:33306TEST_F(DriveFsSearchTest, Search_NoErrorCaching) {
Robbie McElrathb0acd132019-02-05 18:11:37307 DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
308 &clock_);
Sergei Datsenko79e4ac52018-12-18 07:17:33309
310 EXPECT_CALL(mock_drivefs_,
311 OnStartSearchQuery(
312 MatchQuery(mojom::QueryParameters::QuerySource::kCloudOnly,
313 nullptr, nullptr, true, false)))
314 .Times(2);
315 EXPECT_CALL(mock_drivefs_,
316 OnStartSearchQuery(
317 MatchQuery(mojom::QueryParameters::QuerySource::kLocalOnly,
318 nullptr, nullptr, true, false)))
319 .Times(0);
320
321 EXPECT_CALL(mock_drivefs_, OnGetNextPage(_))
322 .WillOnce(
323 testing::DoAll(PopulateSearch(0),
324 testing::Return(drive::FileError::FILE_ERROR_FAILED)))
325 .WillOnce(testing::DoAll(
326 PopulateSearch(3), testing::Return(drive::FileError::FILE_ERROR_OK)));
327
328 mojom::QueryParametersPtr params = mojom::QueryParameters::New();
329 params->query_source = mojom::QueryParameters::QuerySource::kCloudOnly;
330 params->shared_with_me = true;
331
332 bool called = false;
333 mojom::QueryParameters::QuerySource source = search.PerformSearch(
334 std::move(params),
335 base::BindLambdaForTesting(
336 [&called](drive::FileError err,
337 base::Optional<std::vector<mojom::QueryItemPtr>>) {
338 called = true;
339 EXPECT_EQ(drive::FileError::FILE_ERROR_FAILED, err);
340 }));
341 EXPECT_EQ(mojom::QueryParameters::QuerySource::kCloudOnly, source);
342 base::RunLoop().RunUntilIdle();
343 EXPECT_TRUE(called);
344
345 params = mojom::QueryParameters::New();
346 params->query_source = mojom::QueryParameters::QuerySource::kCloudOnly;
347 params->shared_with_me = true;
348
349 // As previous call failed this one will go to the cloud again.
350 called = false;
351 source = search.PerformSearch(
352 std::move(params),
353 base::BindLambdaForTesting(
354 [&called](drive::FileError err,
355 base::Optional<std::vector<mojom::QueryItemPtr>> items) {
356 called = true;
357 EXPECT_EQ(drive::FileError::FILE_ERROR_OK, err);
358 EXPECT_EQ(3u, items->size());
359 }));
360 EXPECT_EQ(mojom::QueryParameters::QuerySource::kCloudOnly, source);
361 base::RunLoop().RunUntilIdle();
362 EXPECT_TRUE(called);
363}
364
Sergei Datsenko3554b9e42018-12-18 05:49:11365} // namespace drivefs