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

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

Powered by Google App Engine
This is Rietveld 408576698