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

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 comment 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/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_app_item.h"
16 #include "chrome/browser/ui/app_list/arc_app_list_prefs.h"
17 #include "chrome/browser/ui/app_list/arc_app_model_builder.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 "components/arc/test/fake_arc_bridge_service.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "ui/app_list/app_list_model.h"
25 #include "ui/gfx/image/image_skia.h"
26
27 namespace {
28
29 const struct FakeArcBridgeService::AppInfo kFakeApps[] = {
30 {"Arc app 1", "fake.app.1", "fake.app.1.Activity"},
31 {"Arc app 2", "fake.app.2", "fake.app.2.Activity"},
32 {"Arc app 3", "fake.app.3", "fake.app.3.Activity"},
33 };
34
35 const size_t kFakeAppCount = arraysize(kFakeApps);
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(kFakeAppCount >= 2, "Not enough data for test");
52
53 bridge_service_.reset(new FakeArcBridgeService());
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 GetArcItemCount() const {
89 size_t arc_count = 0;
90 const size_t count = model_->top_level_item_list()->item_count();
91 for (size_t i = 0; i < count; ++i) {
92 app_list::AppListItem* item = model_->top_level_item_list()->item_at(i);
93 if (item->GetItemType() == ArcAppItem::kItemType) {
94 ++arc_count;
95 }
96 }
97 return arc_count;
98 }
99
100 ArcAppItem* GetArcItem(size_t index) const {
101 size_t arc_count = 0;
102 const size_t count = model_->top_level_item_list()->item_count();
103 ArcAppItem* arc_item = nullptr;
104 for (size_t i = 0; i < count; ++i) {
105 app_list::AppListItem* item = model_->top_level_item_list()->item_at(i);
106 if (item->GetItemType() == ArcAppItem::kItemType) {
107 if (arc_count++ == 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* FindArcItem(const std::string& id) const {
118 const size_t count = GetArcItemCount();
119 for (size_t i = 0; i < count; ++i) {
120 ArcAppItem* item = GetArcItem(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(size_t app_count,
130 const FakeArcBridgeService::AppInfo* apps) {
131 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
132 const std::vector<std::string> ids = prefs->GetAppIds();
133 ASSERT_EQ(app_count, ids.size());
134 ASSERT_EQ(app_count, GetArcItemCount());
135 // In principle, order of items is not defined.
136 for (size_t i = 0; i < app_count; ++i) {
137 const std::string id = apps[i].id();
138 EXPECT_NE(std::find(ids.begin(), ids.end(), id), ids.end());
139 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(ids[i]);
140 ASSERT_NE(nullptr, app_info.get());
141 EXPECT_EQ(apps[i].name, app_info->name);
142 EXPECT_EQ(apps[i].package, app_info->package);
143 EXPECT_EQ(apps[i].activity, app_info->activity);
144
145 const ArcAppItem* app_item = FindArcItem(ids[i]);
146 ASSERT_NE(nullptr, app_item);
147 EXPECT_EQ(apps[i].name, app_item->GetDisplayName());
148 }
149 }
150
151 // Validate that requested apps have required ready state and other apps have
152 // opposite state.
153 void ValidateAppReadyState(size_t app_count,
154 const FakeArcBridgeService::AppInfo* apps,
155 bool ready) {
156 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
157 ASSERT_NE(nullptr, prefs);
158
159 std::vector<std::string> ids = prefs->GetAppIds();
160 EXPECT_EQ(ids.size(), GetArcItemCount());
161
162 // Process requested apps.
163 for (size_t i = 0; i < app_count; ++i) {
164 const std::string id = apps[i].id();
165 std::vector<std::string>::iterator it_id = std::find(ids.begin(),
166 ids.end(),
167 id);
168 ASSERT_NE(it_id, ids.end());
169 ids.erase(it_id);
170
171 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id);
172 ASSERT_NE(nullptr, app_info.get());
173 EXPECT_EQ(ready, app_info->ready);
174 const ArcAppItem* app_item = FindArcItem(id);
175 ASSERT_NE(nullptr, app_item);
176 EXPECT_EQ(ready, app_item->ready());
177 }
178
179 // Process the rest of the apps.
180 for (size_t i = 0; i < ids.size(); ++i) {
181 const std::string id = ids[i];
182 scoped_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(id);
183 ASSERT_NE(nullptr, app_info.get());
184 EXPECT_NE(ready, app_info->ready);
185 const ArcAppItem* app_item = FindArcItem(id);
186 ASSERT_NE(nullptr, app_item);
187 EXPECT_NE(ready, app_item->ready());
188 }
189 }
190
191 scoped_ptr<app_list::AppListModel> model_;
192 scoped_ptr<test::TestAppListControllerDelegate> controller_;
193 scoped_ptr<ArcAppModelBuilder> builder_;
194 scoped_ptr<FakeArcBridgeService> bridge_service_;
195
196 private:
197 DISALLOW_COPY_AND_ASSIGN(ArcAppModelBuilderTest);
198 };
199
200 TEST_F(ArcAppModelBuilderTest, RefreshAllOnReady) {
201 EXPECT_EQ(0, bridge_service_->refresh_apps_count());
202 bridge_service_->SetReady();
203 EXPECT_EQ(1, bridge_service_->refresh_apps_count());
204 }
205
206 TEST_F(ArcAppModelBuilderTest, RefreshAllFillsContent) {
207 ValidateHaveApps(0, nullptr);
208 bridge_service_->SetReady();
209 bridge_service_->SendRefreshApps(kFakeAppCount, kFakeApps);
210 ValidateHaveApps(kFakeAppCount, kFakeApps);
211 }
212
213 TEST_F(ArcAppModelBuilderTest, MultipleRefreshAll) {
214 ValidateHaveApps(0, nullptr);
215 bridge_service_->SetReady();
216 // Send info about all fake apps except last.
217 bridge_service_->SendRefreshApps(kFakeAppCount - 1, kFakeApps);
218 // At this point all apps (except last) should exist and be ready.
219 ValidateHaveApps(kFakeAppCount - 1, kFakeApps);
220 ValidateAppReadyState(kFakeAppCount - 1, kFakeApps, true);
221
222 // Send info about all fake apps except first.
223 bridge_service_->SendRefreshApps(kFakeAppCount - 1, kFakeApps + 1);
224 // At this point all apps should exist but first one should be non-ready.
225 ValidateHaveApps(kFakeAppCount, kFakeApps);
226 ValidateAppReadyState(kFakeAppCount - 1, kFakeApps + 1, true);
227
228 // Send info about all fake apps.
229 bridge_service_->SendRefreshApps(kFakeAppCount, kFakeApps);
230 // At this point all apps should exist and be ready.
231 ValidateHaveApps(kFakeAppCount, kFakeApps);
232 ValidateAppReadyState(kFakeAppCount, kFakeApps, true);
233
234 // Send info no app available.
235 bridge_service_->SendRefreshApps(0, nullptr);
236 // At this point all apps should exist and be non-ready.
237 ValidateHaveApps(kFakeAppCount, kFakeApps);
238 ValidateAppReadyState(kFakeAppCount, kFakeApps, false);
239 }
240
241 TEST_F(ArcAppModelBuilderTest, StopServiceDisablesApps) {
242 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
243 ASSERT_NE(nullptr, prefs);
244
245 bridge_service_->SetReady();
246 EXPECT_EQ(static_cast<size_t>(0), GetArcItemCount());
247 EXPECT_EQ(static_cast<size_t>(0), prefs->GetAppIds().size());
248
249 bridge_service_->SendRefreshApps(kFakeAppCount, kFakeApps);
250 std::vector<std::string> ids = prefs->GetAppIds();
251 EXPECT_EQ(kFakeAppCount, ids.size());
252 ValidateAppReadyState(kFakeAppCount, kFakeApps, true);
253
254 // Stopping service does not delete items. It makes them non-ready.
255 bridge_service_->SetStopped();
256 // Ids should be the same.
257 EXPECT_EQ(ids, prefs->GetAppIds());
258 ValidateAppReadyState(kFakeAppCount, kFakeApps, false);
259 }
260
261 TEST_F(ArcAppModelBuilderTest, LaunchApps) {
262 bridge_service_->SetReady();
263 bridge_service_->SendRefreshApps(kFakeAppCount, kFakeApps);
264
265 // Simulate item activate.
266 ArcAppItem* item_first = FindArcItem(kFakeApps[0].id());
267 ArcAppItem* item_last = FindArcItem(kFakeApps[kFakeAppCount - 1].id());
268 ASSERT_NE(nullptr, item_first);
269 ASSERT_NE(nullptr, item_last);
270 item_first->Activate(0);
271 item_last->Activate(0);
272 item_first->Activate(0);
273
274 const std::vector<std::string> launch_requests =
275 bridge_service_->launch_requests();
276 EXPECT_EQ(static_cast<size_t>(3), launch_requests.size());
277 EXPECT_EQ(kFakeApps[0].id(), launch_requests[0]);
278 EXPECT_EQ(kFakeApps[kFakeAppCount - 1].id(), launch_requests[1]);
279 EXPECT_EQ(kFakeApps[0].id(), launch_requests[2]);
280 }
281
282 TEST_F(ArcAppModelBuilderTest, RequestIcons) {
283 // Make sure we are on UI thread.
284 ASSERT_EQ(true,
285 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
286
287 bridge_service_->SetReady();
288 bridge_service_->SendRefreshApps(kFakeAppCount, kFakeApps);
289
290 // Validate that no icon exists at the beginning and request icon for
291 // each supported scale factor. This will start asynchronous loading.
292 uint32_t expected_mask = 0;
293 const std::vector<ui::ScaleFactor>& scale_factors =
294 ui::GetSupportedScaleFactors();
295 for (size_t i = 0; i < scale_factors.size(); ++i) {
296 const ui::ScaleFactor scale_factor = scale_factors[i];
297 expected_mask |= 1 << scale_factor;
298 for (size_t j = 0; j < kFakeAppCount; ++j) {
299 ArcAppItem* app_item = FindArcItem(kFakeApps[j].id());
300 ASSERT_NE(nullptr, app_item);
301 const float scale = ui::GetScaleForScaleFactor(scale_factor);
302 app_item->icon().GetRepresentation(scale);
303 }
304 }
305
306 // Process pending tasks.
307 content::BrowserThread::GetBlockingPool()->FlushForTesting();
308 base::RunLoop().RunUntilIdle();
309
310 // At this moment we should receive all requests for icon loading.
311 const std::vector<FakeArcBridgeService::IconRequest>& icon_requests =
312 bridge_service_->icon_requests();
313 EXPECT_EQ(scale_factors.size() * kFakeAppCount, icon_requests.size());
314 std::map<std::string, uint32_t> app_masks;
315 for (size_t i = 0; i < icon_requests.size(); ++i) {
316 const FakeArcBridgeService::IconRequest icon_request = icon_requests[i];
317 const std::string id = ArcAppListPrefs::GetAppId(icon_request.package,
318 icon_request.activity);
319 // Make sure no double requests.
320 EXPECT_NE(app_masks[id], app_masks[id] | (1 << icon_request.scale_factor));
321 app_masks[id] |= (1 << icon_request.scale_factor);
322 }
323
324 // Validate that we have a request for each icon for each supported scale
325 // factor.
326 EXPECT_EQ(kFakeAppCount, app_masks.size());
327 for (size_t i = 0; i < kFakeAppCount; ++i) {
328 const std::string id = kFakeApps[i].id();
329 ASSERT_NE(app_masks.find(id), app_masks.end());
330 EXPECT_EQ(app_masks[id], expected_mask);
331 }
332 }
333
334 TEST_F(ArcAppModelBuilderTest, InstallIcon) {
335 // Make sure we are on UI thread.
336 ASSERT_EQ(true,
337 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
338
339 bridge_service_->SetReady();
340 bridge_service_->SendRefreshApps(1, kFakeApps);
341
342 ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_.get());
343 ASSERT_NE(nullptr, prefs);
344
345 const ui::ScaleFactor scale_factor = ui::GetSupportedScaleFactors()[0];
346 const float scale = ui::GetScaleForScaleFactor(scale_factor);
347 const base::FilePath icon_path = prefs->GetIconPath(kFakeApps[0].id(),
348 scale_factor);
349 EXPECT_EQ(false, base::PathExists(icon_path));
350
351 const ArcAppItem* app_item = FindArcItem(kFakeApps[0].id());
352 EXPECT_NE(nullptr, app_item);
353 // This initiates async loading.
354 app_item->icon().GetRepresentation(scale);
355
356 // Process pending tasks.
357 content::BrowserThread::GetBlockingPool()->FlushForTesting();
358 base::RunLoop().RunUntilIdle();
359
360 // Now send generated icon for the app.
361 std::vector<unsigned char> png_data;
362 EXPECT_EQ(true, bridge_service_->GenerateAndSendIcon(kFakeApps[0],
363 scale_factor,
364 &png_data));
365
366 // Process pending tasks.
367 content::BrowserThread::GetBlockingPool()->FlushForTesting();
368 base::RunLoop().RunUntilIdle();
369
370 // Validate that icons are installed, have right content and icon is
371 // refreshed for ARC app item.
372 EXPECT_EQ(true, base::PathExists(icon_path));
373
374 std::string icon_data;
375 // Read the file from disk and compare with reference data.
376 EXPECT_EQ(true, base::ReadFileToString(icon_path, &icon_data));
377 ASSERT_EQ(icon_data.size(), png_data.size());
378 EXPECT_EQ(0, memcmp(&icon_data[0], &png_data[0], png_data.size()));
379
380 // Validating decoded content does not fit well for unit tests. Each image is
381 // decoded in separate process and under such condition this unit test takes
382 // noticeable time to complete.
383 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698