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

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

Powered by Google App Engine
This is Rietveld 408576698