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

Side by Side Diff: chrome/browser/ui/app_list/arc_app_unittest.cc

Issue 1413153007: arc-app-launcher: Minimal support for ARC app launcher. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix WeakPtr issue. Change PostTask on PostTaskAndReplyWithResult Created 5 years, 1 month 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 2015 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 <algorithm>
6 #include <map>
7 #include <string>
8 #include <vector>
9
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/task_runner_util.h"
13 #include "chrome/browser/ui/app_list/app_list_test_util.h"
14 #include "chrome/browser/ui/app_list/arc_app_item.h"
15 #include "chrome/browser/ui/app_list/arc_app_list_prefs.h"
16 #include "chrome/browser/ui/app_list/arc_app_model_builder.h"
17 #include "chrome/browser/ui/app_list/test/fake_arc_bridge_service_for_app_launch er.h"
18 #include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "components/arc/arc_bridge_service.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 #include "ui/app_list/app_list_model.h"
24 #include "ui/gfx/image/image_skia.h"
25
26 namespace {
27
28 const struct FakeArcBridgeServiceForAppLauncher::AppInfo kFakeApps[] = {
29 {"Arc app 1", "fake.app.1", "fake.app.1.Activity"},
30 {"Arc app 2", "fake.app.2", "fake.app.2.Activity"},
31 {"Arc app 3", "fake.app.3", "fake.app.3.Activity"},
32 };
33
34 const size_t kFakeAppCnt = sizeof(kFakeApps) /
35 sizeof(FakeArcBridgeServiceForAppLauncher::AppInfo);
xiyuan 2015/11/18 03:42:16 nit: use arraysize in base/macros.h https://code.
khmel1 2015/11/18 06:10:04 Good to know, thanks!
36
37 } // namespace
38
39 class ArcAppModelBuilderTest : public AppListTestBase {
40 public:
41 ArcAppModelBuilderTest() {}
42 ~ArcAppModelBuilderTest() override {
43 // Release profile file in order to keep right sequence.
44 profile_.reset();
45 }
46
47 void SetUp() override {
48 AppListTestBase::SetUp();
49
50 // Make sure we have enough data for test.
51 static_assert(kFakeAppCnt >= 2, "Not enough data for test");
52
53 bridge_service_.reset(new FakeArcBridgeServiceForAppLauncher());
54
55 // Check initial conditions.
56 EXPECT_EQ(bridge_service_.get(), arc::ArcBridgeService::Get());
57 EXPECT_EQ(false, arc::ArcBridgeService::Get()->available());
58 EXPECT_EQ(arc::ArcBridgeService::State::STOPPED,
59 arc::ArcBridgeService::Get()->state());
60
61 CreateBuilder();
62
63 // At this point we should have ArcAppListPrefs as observer of service.
64 EXPECT_EQ(
65 true,
66 bridge_service_->HasObserver(ArcAppListPrefs::Get(profile_.get())));
67 }
68
69 void TearDown() override { ResetBuilder(); }
70
71 protected:
72 // Creates a new builder, destroying any existing one.
73 void CreateBuilder() {
74 ResetBuilder(); // Destroy any existing builder in the correct order.
75
76 model_.reset(new app_list::AppListModel);
77 controller_.reset(new test::TestAppListControllerDelegate);
78 builder_.reset(new ArcAppModelBuilder(controller_.get()));
79 builder_->InitializeWithProfile(profile_.get(), model_.get());
80 }
81
82 void ResetBuilder() {
83 builder_.reset();
84 controller_.reset();
85 model_.reset();
86 }
87
88 size_t GetModelItemCnt() const {
xiyuan 2015/11/18 03:42:16 nit: GetModelItemCnt -> GetArcItemCount to be more
khmel1 2015/11/18 06:10:04 Done.
89 size_t arc_cnt = 0;
90 const size_t cnt = model_->top_level_item_list()->item_count();
91 for (size_t i = 0; i < cnt; ++i) {
92 app_list::AppListItem* item = model_->top_level_item_list()->item_at(i);
93 if (item->GetItemType() == ArcAppItem::kItemType) {
94 ++arc_cnt;
95 }
96 }
97 return arc_cnt;
98 }
99
100 ArcAppItem* GetModelItem(size_t index) const {
xiyuan 2015/11/18 03:42:16 nit: GetModelItem -> GetArcItem
khmel1 2015/11/18 06:10:04 Done.
101 size_t arc_cnt = 0;
102 const size_t cnt = model_->top_level_item_list()->item_count();
103 ArcAppItem* arc_item = nullptr;
104 for (size_t i = 0; i < cnt; ++i) {
105 app_list::AppListItem* item = model_->top_level_item_list()->item_at(i);
106 if (item->GetItemType() == ArcAppItem::kItemType) {
107 if (arc_cnt++ == index) {
108 arc_item = reinterpret_cast<ArcAppItem*>(item);
109 break;
110 }
111 }
112 }
113 EXPECT_NE(nullptr, arc_item);
114 return arc_item;
115 }
116
117 ArcAppItem* FindModelItem(const std::string& id) const {
xiyuan 2015/11/18 03:42:16 nit: FindModelItem -> FindArcItem
khmel1 2015/11/18 06:10:04 Done.
118 const size_t cnt = GetModelItemCnt();
119 for (size_t i = 0; i < cnt; ++i) {
120 ArcAppItem* item = GetModelItem(i);
121 if (item && item->id() == id) {
122 return item;
123 }
124 }
125 return nullptr;
126 }
127
128 // Validate that prefs and model have right content.
129 void ValidateHaveApps(
130 size_t app_cnt,
131 const FakeArcBridgeServiceForAppLauncher::AppInfo* apps) {
132 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
133 const std::vector<std::string> ids = prefs->GetAppIds();
134 ASSERT_EQ(app_cnt, ids.size());
135 ASSERT_EQ(app_cnt, GetModelItemCnt());
136 // In principle, order of items is not defined.
137 for (size_t i = 0; i < app_cnt; ++i) {
138 const std::string id = apps[i].id();
139 EXPECT_NE(std::find(ids.begin(), ids.end(), id), ids.end());
140 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(ids[i]);
141 ASSERT_NE(nullptr, app_info.get());
142 EXPECT_EQ(apps[i].name, app_info->name);
143 EXPECT_EQ(apps[i].package, app_info->package);
144 EXPECT_EQ(apps[i].activity, app_info->activity);
145
146 const ArcAppItem* app_item = FindModelItem(ids[i]);
147 ASSERT_NE(nullptr, app_item);
148 EXPECT_EQ(apps[i].name, app_item->GetDisplayName());
149 }
150 }
151
152 // Validate that requested apps have required ready state and other apps have
153 // opposite state.
154 void ValidateAppReadyState(
155 size_t app_cnt,
156 const FakeArcBridgeServiceForAppLauncher::AppInfo* apps,
157 bool ready) {
158 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
159 ASSERT_NE(nullptr, prefs);
160
161 std::vector<std::string> ids = prefs->GetAppIds();
162 EXPECT_EQ(ids.size(), GetModelItemCnt());
163
164 // Process requested apps.
165 for (size_t i = 0; i < app_cnt; ++i) {
166 const std::string id = apps[i].id();
167 std::vector<std::string>::iterator it_id = std::find(ids.begin(),
168 ids.end(),
169 id);
170 ASSERT_NE(it_id, ids.end());
171 ids.erase(it_id);
172
173 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id);
174 ASSERT_NE(nullptr, app_info.get());
175 EXPECT_EQ(ready, app_info->ready);
176 const ArcAppItem* app_item = FindModelItem(id);
177 ASSERT_NE(nullptr, app_item);
178 EXPECT_EQ(ready, app_item->ready());
179 }
180
181 // Process the rest apps.
182 for (size_t i = 0; i < ids.size(); ++i) {
183 const std::string id = ids[i];
184 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id);
185 ASSERT_NE(nullptr, app_info.get());
186 EXPECT_NE(ready, app_info->ready);
187 const ArcAppItem* app_item = FindModelItem(id);
188 ASSERT_NE(nullptr, app_item);
189 EXPECT_NE(ready, app_item->ready());
190 }
191 }
192
193 scoped_ptr<app_list::AppListModel> model_;
194 scoped_ptr<test::TestAppListControllerDelegate> controller_;
195 scoped_ptr<ArcAppModelBuilder> builder_;
196 scoped_ptr<FakeArcBridgeServiceForAppLauncher> bridge_service_;
197
198 private:
199 DISALLOW_COPY_AND_ASSIGN(ArcAppModelBuilderTest);
200 };
201
202 TEST_F(ArcAppModelBuilderTest, RefreshAllOnReady) {
203 EXPECT_EQ(0, bridge_service_->refresh_apps_cnt());
204 bridge_service_->SetReady();
205 EXPECT_EQ(1, bridge_service_->refresh_apps_cnt());
206 }
207
208 TEST_F(ArcAppModelBuilderTest, RefreshAllFillsContent) {
209 ValidateHaveApps(0, nullptr);
210 bridge_service_->SetReady();
211 bridge_service_->SendRefreshApps(kFakeAppCnt, kFakeApps);
212 ValidateHaveApps(kFakeAppCnt, kFakeApps);
213 }
214
215 TEST_F(ArcAppModelBuilderTest, MultipleRefreshAll) {
216 ValidateHaveApps(0, nullptr);
217 bridge_service_->SetReady();
218 // Send info about all fake apps except last.
219 bridge_service_->SendRefreshApps(kFakeAppCnt - 1, kFakeApps);
220 // At this point all apps (except last) should exist and be ready.
221 ValidateHaveApps(kFakeAppCnt - 1, kFakeApps);
222 ValidateAppReadyState(kFakeAppCnt - 1, kFakeApps, true);
223
224 // Send info about all fake apps except first.
225 bridge_service_->SendRefreshApps(kFakeAppCnt - 1, kFakeApps + 1);
226 // At this point all apps should exist but first one should be non-ready.
227 ValidateHaveApps(kFakeAppCnt, kFakeApps);
228 ValidateAppReadyState(kFakeAppCnt - 1, kFakeApps + 1, true);
229
230 // Send info about all fake apps.
231 bridge_service_->SendRefreshApps(kFakeAppCnt, kFakeApps);
232 // At this point all apps should exist and be ready.
233 ValidateHaveApps(kFakeAppCnt, kFakeApps);
234 ValidateAppReadyState(kFakeAppCnt, kFakeApps, true);
235
236 // Send info no app available.
237 bridge_service_->SendRefreshApps(0, nullptr);
238 // At this point all apps should exist and be non-ready.
239 ValidateHaveApps(kFakeAppCnt, kFakeApps);
240 ValidateAppReadyState(kFakeAppCnt, kFakeApps, false);
241 }
242
243 TEST_F(ArcAppModelBuilderTest, StopServiceDisablesApps) {
244 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
245 ASSERT_NE(nullptr, prefs);
246
247 bridge_service_->SetReady();
248 EXPECT_EQ(static_cast<size_t>(0), GetModelItemCnt());
249 EXPECT_EQ(static_cast<size_t>(0), prefs->GetAppIds().size());
250
251 bridge_service_->SendRefreshApps(kFakeAppCnt, kFakeApps);
252 std::vector<std::string> ids = prefs->GetAppIds();
253 EXPECT_EQ(kFakeAppCnt, ids.size());
254 ValidateAppReadyState(kFakeAppCnt, kFakeApps, true);
255
256 // Stopping service does not delete items. It makes them non-ready.
257 bridge_service_->SetStopped();
258 // Ids should be the same.
259 EXPECT_EQ(ids, prefs->GetAppIds());
260 ValidateAppReadyState(kFakeAppCnt, kFakeApps, false);
261 }
262
263 TEST_F(ArcAppModelBuilderTest, LaunchApps) {
264 bridge_service_->SetReady();
265 bridge_service_->SendRefreshApps(kFakeAppCnt, kFakeApps);
266
267 // Simulate item activate.
268 ArcAppItem* item_first = FindModelItem(kFakeApps[0].id());
269 ArcAppItem* item_last = FindModelItem(kFakeApps[kFakeAppCnt - 1].id());
270 ASSERT_NE(nullptr, item_first);
271 ASSERT_NE(nullptr, item_last);
272 item_first->Activate(0);
273 item_last->Activate(0);
274 item_first->Activate(0);
275
276 const std::vector<std::string> launch_requests =
277 bridge_service_->launch_requests();
278 EXPECT_EQ(static_cast<size_t>(3), launch_requests.size());
279 EXPECT_EQ(kFakeApps[0].id(), launch_requests[0]);
280 EXPECT_EQ(kFakeApps[kFakeAppCnt - 1].id(), launch_requests[1]);
281 EXPECT_EQ(kFakeApps[0].id(), launch_requests[2]);
282 }
283
284 TEST_F(ArcAppModelBuilderTest, RequestIcons) {
285 base::MessageLoop* current = base::MessageLoop::current();
xiyuan 2015/11/18 03:42:16 New code should use base::RunLoop instead of using
khmel1 2015/11/18 06:10:04 Done.
286 // Make sure we are on UI thread.
287 ASSERT_EQ(true,
288 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
289
290 bridge_service_->SetReady();
291 bridge_service_->SendRefreshApps(kFakeAppCnt, kFakeApps);
292
293 // Validate that no icon exists at the beginning and request icon for
294 // each supported scale factor. This will start asynchronous loading.
295 uint32_t expected_mask = 0;
296 const std::vector<ui::ScaleFactor>& scale_factors =
297 ui::GetSupportedScaleFactors();
298 for (size_t i = 0; i < scale_factors.size(); ++i) {
299 const ui::ScaleFactor scale_factor = scale_factors[i];
300 expected_mask |= 1 << scale_factor;
301 for (size_t j = 0; j < kFakeAppCnt; ++j) {
302 ArcAppItem* app_item = FindModelItem(kFakeApps[j].id());
303 ASSERT_NE(nullptr, app_item);
304 const float scale = ui::GetScaleForScaleFactor(scale_factor);
305 app_item->icon().GetRepresentation(scale);
306 }
307 }
308
309 // Process pending tasks.
310 content::BrowserThread::GetBlockingPool()->FlushForTesting();
311 current->RunUntilIdle();
312
313 // At this moment we should receive all requests for icon loading.
314 const std::vector<FakeArcBridgeServiceForAppLauncher::IconRequest>&
315 icon_requests = bridge_service_->icon_requests();
316 EXPECT_EQ(scale_factors.size() * kFakeAppCnt, icon_requests.size());
317 std::map<std::string, uint32_t> app_masks;
318 for (size_t i = 0; i < icon_requests.size(); ++i) {
319 const FakeArcBridgeServiceForAppLauncher::IconRequest icon_request =
320 icon_requests[i];
321 const std::string id = ArcAppListPrefs::GetAppId(icon_request.package,
322 icon_request.activity);
323 // Make sure no double requests.
324 EXPECT_NE(app_masks[id], app_masks[id] | (1 << icon_request.scale_factor));
325 app_masks[id] |= (1 << icon_request.scale_factor);
326 }
327
328 // Validate that we have a request for each icon for each supported scale
329 // factor.
330 EXPECT_EQ(kFakeAppCnt, app_masks.size());
331 for (size_t i = 0; i < kFakeAppCnt; ++i) {
332 const std::string id = kFakeApps[i].id();
333 ASSERT_NE(app_masks.find(id), app_masks.end());
334 EXPECT_EQ(app_masks[id], expected_mask);
335 }
336 }
337
338 TEST_F(ArcAppModelBuilderTest, InstallIcon) {
339 base::MessageLoop* current = base::MessageLoop::current();
340 // Make sure we are on UI thread.
341 ASSERT_EQ(true,
342 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
343
344 bridge_service_->SetReady();
345 bridge_service_->SendRefreshApps(1, kFakeApps);
346
347 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
348 ASSERT_NE(nullptr, prefs);
349
350 const ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactors()[0];
351 const float scale = ui::GetScaleForScaleFactor(scale_factor);
352 const base::FilePath icon_path = prefs->GetIconPath(kFakeApps[0].id(),
353 scale_factor);
354 EXPECT_EQ(false, base::PathExists(icon_path));
355
356 const ArcAppItem* app_item = FindModelItem(kFakeApps[0].id());
357 EXPECT_NE(nullptr, app_item);
358 // This initiates async loading.
359 app_item->icon().GetRepresentation(scale);
360
361 // Process pending tasks.
362 content::BrowserThread::GetBlockingPool()->FlushForTesting();
363 current->RunUntilIdle();
364
365 // Now send generated icon for the app.
366 std::vector<unsigned char> png_data;
367 EXPECT_EQ(true, bridge_service_->GenerateAndSendIcon(kFakeApps[0],
368 scale_factor,
369 &png_data));
370
371 // Process pending tasks.
372 content::BrowserThread::GetBlockingPool()->FlushForTesting();
373 current->RunUntilIdle();
374
375 // Validate that icons are installed, have right content and icon is
376 // refreshed for ARC app item.
377 EXPECT_EQ(true, base::PathExists(icon_path));
378
379 std::string icon_data;
380 // Read the file from disk and compare with reference data.
381 EXPECT_EQ(true, base::ReadFileToString(icon_path, &icon_data));
382 ASSERT_EQ(icon_data.size(), png_data.size());
383 EXPECT_EQ(0, memcmp(&icon_data[0], &png_data[0], png_data.size()));
384
385 // Validating decoded content does not fit well for unit tests. Each image is
386 // decoded in separate process and under such condition this unit test takes
387 // noticeable time to complete.
388 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698