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

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

Powered by Google App Engine
This is Rietveld 408576698