shell_util_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright (c) 2012 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 "chrome/installer/util/shell_util.h"
6
7#include <vector>
8
9#include "base/base_paths.h"
10#include "base/base_paths_win.h"
11#include "base/files/file_enumerator.h"
12#include "base/files/file_util.h"
13#include "base/files/scoped_temp_dir.h"
14#include "base/md5.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/strings/string16.h"
17#include "base/strings/string_util.h"
18#include "base/synchronization/cancellation_flag.h"
19#include "base/test/scoped_path_override.h"
20#include "base/test/test_shortcut_win.h"
21#include "base/win/shortcut.h"
22#include "base/win/windows_version.h"
23#include "chrome/installer/util/browser_distribution.h"
24#include "chrome/installer/util/product.h"
25#include "chrome/installer/util/util_constants.h"
26#include "testing/gtest/include/gtest/gtest.h"
27
28namespace {
29
30const wchar_t kManganeseExe[] = L"manganese.exe";
31const wchar_t kIronExe[] = L"iron.exe";
32const wchar_t kOtherIco[] = L"other.ico";
33
34// TODO(huangs): Separate this into generic shortcut tests and Chrome-specific
35// tests. Specifically, we should not overly rely on getting shortcut properties
36// from product_->AddDefaultShortcutProperties().
37class ShellUtilShortcutTest : public testing::Test {
38 protected:
39  ShellUtilShortcutTest() : test_properties_(ShellUtil::CURRENT_USER) {}
40
41  virtual void SetUp() OVERRIDE {
42    dist_ = BrowserDistribution::GetDistribution();
43    ASSERT_TRUE(dist_ != NULL);
44    product_.reset(new installer::Product(dist_));
45
46    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
47    chrome_exe_ = temp_dir_.path().Append(installer::kChromeExe);
48    EXPECT_EQ(0, base::WriteFile(chrome_exe_, "", 0));
49
50    manganese_exe_ = temp_dir_.path().Append(kManganeseExe);
51    EXPECT_EQ(0, base::WriteFile(manganese_exe_, "", 0));
52
53    iron_exe_ = temp_dir_.path().Append(kIronExe);
54    EXPECT_EQ(0, base::WriteFile(iron_exe_, "", 0));
55
56    other_ico_ = temp_dir_.path().Append(kOtherIco);
57    EXPECT_EQ(0, base::WriteFile(other_ico_, "", 0));
58
59    ASSERT_TRUE(fake_user_desktop_.CreateUniqueTempDir());
60    ASSERT_TRUE(fake_common_desktop_.CreateUniqueTempDir());
61    ASSERT_TRUE(fake_user_quick_launch_.CreateUniqueTempDir());
62    ASSERT_TRUE(fake_default_user_quick_launch_.CreateUniqueTempDir());
63    ASSERT_TRUE(fake_start_menu_.CreateUniqueTempDir());
64    ASSERT_TRUE(fake_common_start_menu_.CreateUniqueTempDir());
65    user_desktop_override_.reset(
66        new base::ScopedPathOverride(base::DIR_USER_DESKTOP,
67                                     fake_user_desktop_.path()));
68    common_desktop_override_.reset(
69        new base::ScopedPathOverride(base::DIR_COMMON_DESKTOP,
70                                     fake_common_desktop_.path()));
71    user_quick_launch_override_.reset(
72        new base::ScopedPathOverride(base::DIR_USER_QUICK_LAUNCH,
73                                     fake_user_quick_launch_.path()));
74    start_menu_override_.reset(
75        new base::ScopedPathOverride(base::DIR_START_MENU,
76                                     fake_start_menu_.path()));
77    common_start_menu_override_.reset(
78        new base::ScopedPathOverride(base::DIR_COMMON_START_MENU,
79                                     fake_common_start_menu_.path()));
80
81    base::FilePath icon_path;
82    base::CreateTemporaryFileInDir(temp_dir_.path(), &icon_path);
83    test_properties_.set_target(chrome_exe_);
84    test_properties_.set_arguments(L"--test --chrome");
85    test_properties_.set_description(L"Makes polar bears dance.");
86    test_properties_.set_icon(icon_path, 7);
87    test_properties_.set_app_id(L"Polar.Bear");
88    test_properties_.set_dual_mode(true);
89  }
90
91  // Returns the expected path of a test shortcut. Returns an empty FilePath on
92  // failure.
93  base::FilePath GetExpectedShortcutPath(
94      ShellUtil::ShortcutLocation location,
95      BrowserDistribution* dist,
96      const ShellUtil::ShortcutProperties& properties) {
97    base::FilePath expected_path;
98    switch (location) {
99      case ShellUtil::SHORTCUT_LOCATION_DESKTOP:
100        expected_path = (properties.level == ShellUtil::CURRENT_USER) ?
101            fake_user_desktop_.path() : fake_common_desktop_.path();
102        break;
103      case ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH:
104        expected_path = fake_user_quick_launch_.path();
105        break;
106      case ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR:
107        expected_path = (properties.level == ShellUtil::CURRENT_USER) ?
108            fake_start_menu_.path() : fake_common_start_menu_.path();
109        expected_path = expected_path.Append(
110            dist_->GetStartMenuShortcutSubfolder(
111                BrowserDistribution::SUBFOLDER_CHROME));
112        break;
113      default:
114        ADD_FAILURE() << "Unknown location";
115        return base::FilePath();
116    }
117
118    base::string16 shortcut_name = properties.has_shortcut_name() ?
119        properties.shortcut_name :
120        dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME);
121    shortcut_name.append(installer::kLnkExt);
122    return expected_path.Append(shortcut_name);
123  }
124
125  // Validates that the shortcut at |location| matches |properties| (and
126  // implicit default properties) for |dist|.
127  // Note: This method doesn't verify the |pin_to_taskbar| property as it
128  // implies real (non-mocked) state which is flaky to test.
129  void ValidateChromeShortcut(
130      ShellUtil::ShortcutLocation location,
131      BrowserDistribution* dist,
132      const ShellUtil::ShortcutProperties& properties) {
133    base::FilePath expected_path(
134        GetExpectedShortcutPath(location, dist, properties));
135
136    base::win::ShortcutProperties expected_properties;
137    if (properties.has_target()) {
138      expected_properties.set_target(properties.target);
139      expected_properties.set_working_dir(properties.target.DirName());
140    } else {
141      expected_properties.set_target(chrome_exe_);
142      expected_properties.set_working_dir(chrome_exe_.DirName());
143    }
144
145    if (properties.has_arguments())
146      expected_properties.set_arguments(properties.arguments);
147    else
148      expected_properties.set_arguments(base::string16());
149
150    if (properties.has_description())
151      expected_properties.set_description(properties.description);
152    else
153      expected_properties.set_description(dist->GetAppDescription());
154
155    if (properties.has_icon()) {
156      expected_properties.set_icon(properties.icon, properties.icon_index);
157    } else {
158      int icon_index = dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME);
159      expected_properties.set_icon(chrome_exe_, icon_index);
160    }
161
162    if (properties.has_app_id()) {
163      expected_properties.set_app_id(properties.app_id);
164    } else {
165      // Tests are always seen as user-level installs in ShellUtil.
166      expected_properties.set_app_id(ShellUtil::GetBrowserModelId(dist, true));
167    }
168
169    if (properties.has_dual_mode())
170      expected_properties.set_dual_mode(properties.dual_mode);
171    else
172      expected_properties.set_dual_mode(false);
173
174    base::win::ValidateShortcut(expected_path, expected_properties);
175  }
176
177  BrowserDistribution* dist_;
178  scoped_ptr<installer::Product> product_;
179
180  // A ShellUtil::ShortcutProperties object with common properties set already.
181  ShellUtil::ShortcutProperties test_properties_;
182
183  base::ScopedTempDir temp_dir_;
184  base::ScopedTempDir fake_user_desktop_;
185  base::ScopedTempDir fake_common_desktop_;
186  base::ScopedTempDir fake_user_quick_launch_;
187  base::ScopedTempDir fake_default_user_quick_launch_;
188  base::ScopedTempDir fake_start_menu_;
189  base::ScopedTempDir fake_common_start_menu_;
190  scoped_ptr<base::ScopedPathOverride> user_desktop_override_;
191  scoped_ptr<base::ScopedPathOverride> common_desktop_override_;
192  scoped_ptr<base::ScopedPathOverride> user_quick_launch_override_;
193  scoped_ptr<base::ScopedPathOverride> start_menu_override_;
194  scoped_ptr<base::ScopedPathOverride> common_start_menu_override_;
195
196  base::FilePath chrome_exe_;
197  base::FilePath manganese_exe_;
198  base::FilePath iron_exe_;
199  base::FilePath other_ico_;
200};
201
202}  // namespace
203
204TEST_F(ShellUtilShortcutTest, GetShortcutPath) {
205  base::FilePath path;
206
207  ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
208                             ShellUtil::CURRENT_USER, &path);
209  EXPECT_EQ(fake_user_desktop_.path(), path);
210
211  ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
212                             ShellUtil::SYSTEM_LEVEL, &path);
213  EXPECT_EQ(fake_common_desktop_.path(), path);
214
215  ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_,
216                             ShellUtil::CURRENT_USER, &path);
217  EXPECT_EQ(fake_user_quick_launch_.path(), path);
218
219  base::string16 start_menu_subfolder =
220      dist_->GetStartMenuShortcutSubfolder(
221          BrowserDistribution::SUBFOLDER_CHROME);
222  ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
223                             dist_, ShellUtil::CURRENT_USER, &path);
224  EXPECT_EQ(fake_start_menu_.path().Append(start_menu_subfolder),
225            path);
226
227  ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
228                             dist_, ShellUtil::SYSTEM_LEVEL, &path);
229  EXPECT_EQ(fake_common_start_menu_.path().Append(start_menu_subfolder),
230            path);
231}
232
233TEST_F(ShellUtilShortcutTest, CreateChromeExeShortcutWithDefaultProperties) {
234  ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
235  product_->AddDefaultShortcutProperties(chrome_exe_, &properties);
236  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
237                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, properties,
238                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
239  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
240                         properties);
241}
242
243TEST_F(ShellUtilShortcutTest, CreateStartMenuShortcutWithAllProperties) {
244  test_properties_.set_shortcut_name(L"Bobo le shortcut");
245  test_properties_.level = ShellUtil::SYSTEM_LEVEL;
246  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
247                  ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
248                  dist_, test_properties_,
249                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
250  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
251                         dist_, test_properties_);
252}
253
254TEST_F(ShellUtilShortcutTest, ReplaceSystemLevelDesktopShortcut) {
255  test_properties_.level = ShellUtil::SYSTEM_LEVEL;
256  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
257                  ShellUtil::SHORTCUT_LOCATION_DESKTOP,
258                  dist_, test_properties_,
259                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
260
261  ShellUtil::ShortcutProperties new_properties(ShellUtil::SYSTEM_LEVEL);
262  product_->AddDefaultShortcutProperties(chrome_exe_, &new_properties);
263  new_properties.set_description(L"New description");
264  new_properties.set_arguments(L"--new-arguments");
265  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
266                  ShellUtil::SHORTCUT_LOCATION_DESKTOP,
267                  dist_, new_properties,
268                  ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING));
269
270  // Expect the properties set in |new_properties| to be set as above and
271  // properties that don't have a default value to be set back to their default
272  // (as validated in ValidateChromeShortcut()) or unset if they don't .
273  ShellUtil::ShortcutProperties expected_properties(new_properties);
274  expected_properties.set_dual_mode(false);
275
276  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
277                         expected_properties);
278}
279
280TEST_F(ShellUtilShortcutTest, UpdateQuickLaunchShortcutArguments) {
281  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
282                  ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH,
283                  dist_, test_properties_,
284                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
285
286  // Only changing one property, don't need all the defaults.
287  ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER);
288  updated_properties.set_arguments(L"--updated --arguments");
289  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
290                  ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH,
291                  dist_, updated_properties,
292                  ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING));
293
294  // Expect the properties set in |updated_properties| to be set as above and
295  // all other properties to remain unchanged.
296  ShellUtil::ShortcutProperties expected_properties(test_properties_);
297  expected_properties.set_arguments(updated_properties.arguments);
298
299  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_,
300                         expected_properties);
301}
302
303TEST_F(ShellUtilShortcutTest, UpdateAddDualModeToStartMenuShortcut) {
304  ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
305  product_->AddDefaultShortcutProperties(chrome_exe_, &properties);
306  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
307                  ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_,
308                  properties, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
309
310  ShellUtil::ShortcutProperties added_properties(ShellUtil::CURRENT_USER);
311  added_properties.set_dual_mode(true);
312  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
313                  ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_,
314                  added_properties, ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING));
315
316  ShellUtil::ShortcutProperties expected_properties(properties);
317  expected_properties.set_dual_mode(true);
318
319  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
320                         dist_, expected_properties);
321}
322
323TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevel) {
324  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
325                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
326                  ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL));
327  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
328                         test_properties_);
329}
330
331TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelWithSystemLevelPresent) {
332  base::string16 shortcut_name(
333      dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
334      installer::kLnkExt);
335
336  test_properties_.level = ShellUtil::SYSTEM_LEVEL;
337  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
338                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
339                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
340  ASSERT_TRUE(base::PathExists(
341      fake_common_desktop_.path().Append(shortcut_name)));
342
343  test_properties_.level = ShellUtil::CURRENT_USER;
344  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
345                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
346                  ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL));
347  ASSERT_FALSE(base::PathExists(
348      fake_user_desktop_.path().Append(shortcut_name)));
349}
350
351TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelStartMenu) {
352  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
353                  ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
354                  dist_, test_properties_,
355                  ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL));
356  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
357                         dist_, test_properties_);
358}
359
360TEST_F(ShellUtilShortcutTest, CreateAlwaysUserWithSystemLevelPresent) {
361  base::string16 shortcut_name(
362      dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
363      installer::kLnkExt);
364
365  test_properties_.level = ShellUtil::SYSTEM_LEVEL;
366  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
367                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
368                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
369  ASSERT_TRUE(base::PathExists(
370      fake_common_desktop_.path().Append(shortcut_name)));
371
372  test_properties_.level = ShellUtil::CURRENT_USER;
373  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
374                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
375                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
376  ASSERT_TRUE(base::PathExists(
377      fake_user_desktop_.path().Append(shortcut_name)));
378}
379
380TEST_F(ShellUtilShortcutTest, RemoveChromeShortcut) {
381  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
382                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
383                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
384  base::FilePath shortcut_path = GetExpectedShortcutPath(
385      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
386  ASSERT_TRUE(base::PathExists(shortcut_path));
387
388  ASSERT_TRUE(ShellUtil::RemoveShortcuts(
389      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
390      chrome_exe_));
391  ASSERT_FALSE(base::PathExists(shortcut_path));
392  ASSERT_TRUE(base::PathExists(shortcut_path.DirName()));
393}
394
395TEST_F(ShellUtilShortcutTest, RemoveSystemLevelChromeShortcut) {
396  test_properties_.level = ShellUtil::SYSTEM_LEVEL;
397  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
398                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
399                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
400  base::FilePath shortcut_path = GetExpectedShortcutPath(
401      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
402  ASSERT_TRUE(base::PathExists(shortcut_path));
403
404  ASSERT_TRUE(ShellUtil::RemoveShortcuts(
405      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::SYSTEM_LEVEL,
406      chrome_exe_));
407  ASSERT_FALSE(base::PathExists(shortcut_path));
408  ASSERT_TRUE(base::PathExists(shortcut_path.DirName()));
409}
410
411TEST_F(ShellUtilShortcutTest, RemoveMultipleChromeShortcuts) {
412  // Shortcut 1: targets "chrome.exe"; no arguments.
413  test_properties_.set_shortcut_name(L"Chrome 1");
414  test_properties_.set_arguments(L"");
415  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
416                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
417                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
418  base::FilePath shortcut1_path = GetExpectedShortcutPath(
419      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
420  ASSERT_TRUE(base::PathExists(shortcut1_path));
421
422  // Shortcut 2: targets "chrome.exe"; has arguments; icon set to "other.ico".
423  test_properties_.set_shortcut_name(L"Chrome 2");
424  test_properties_.set_arguments(L"--profile-directory=\"Profile 2\"");
425  test_properties_.set_icon(other_ico_, 0);
426  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
427                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
428                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
429  base::FilePath shortcut2_path = GetExpectedShortcutPath(
430      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
431  ASSERT_TRUE(base::PathExists(shortcut2_path));
432
433  // Shortcut 3: targets "iron.exe"; has arguments; icon set to "chrome.exe".
434  test_properties_.set_shortcut_name(L"Iron 3");
435  test_properties_.set_target(iron_exe_);
436  test_properties_.set_icon(chrome_exe_, 3);
437  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
438                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
439                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
440  base::FilePath shortcut3_path = GetExpectedShortcutPath(
441      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
442  ASSERT_TRUE(base::PathExists(shortcut3_path));
443
444  // Remove shortcuts that target "chrome.exe".
445  ASSERT_TRUE(ShellUtil::RemoveShortcuts(
446      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
447      chrome_exe_));
448  ASSERT_FALSE(base::PathExists(shortcut1_path));
449  ASSERT_FALSE(base::PathExists(shortcut2_path));
450  ASSERT_TRUE(base::PathExists(shortcut3_path));
451  ASSERT_TRUE(base::PathExists(shortcut1_path.DirName()));
452}
453
454TEST_F(ShellUtilShortcutTest, RetargetShortcutsWithArgs) {
455  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
456                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
457                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
458  ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
459      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_)));
460
461  base::FilePath new_exe = manganese_exe_;
462  // Relies on the fact that |test_properties_| has non-empty arguments.
463  ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs(
464      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
465      chrome_exe_, new_exe));
466
467  ShellUtil::ShortcutProperties expected_properties(test_properties_);
468  expected_properties.set_target(new_exe);
469  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
470                         expected_properties);
471}
472
473TEST_F(ShellUtilShortcutTest, RetargetSystemLevelChromeShortcutsWithArgs) {
474  test_properties_.level = ShellUtil::SYSTEM_LEVEL;
475  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
476                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
477                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
478  ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
479      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_)));
480
481  base::FilePath new_exe = manganese_exe_;
482  // Relies on the fact that |test_properties_| has non-empty arguments.
483  ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs(
484      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::SYSTEM_LEVEL,
485      chrome_exe_, new_exe));
486
487  ShellUtil::ShortcutProperties expected_properties(test_properties_);
488  expected_properties.set_target(new_exe);
489  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
490                         expected_properties);
491}
492
493TEST_F(ShellUtilShortcutTest, RetargetChromeShortcutsWithArgsEmpty) {
494  // Shortcut 1: targets "chrome.exe"; no arguments.
495  test_properties_.set_shortcut_name(L"Chrome 1");
496  test_properties_.set_arguments(L"");
497  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
498                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
499                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
500  ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
501      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_)));
502  ShellUtil::ShortcutProperties expected_properties1(test_properties_);
503
504  // Shortcut 2: targets "chrome.exe"; has arguments.
505  test_properties_.set_shortcut_name(L"Chrome 2");
506  test_properties_.set_arguments(L"--profile-directory=\"Profile 2\"");
507  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
508                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
509                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
510  ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
511      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_)));
512  ShellUtil::ShortcutProperties expected_properties2(test_properties_);
513
514  // Retarget shortcuts: replace "chrome.exe" with "manganese.exe". Only
515  // shortcuts with non-empty arguments (i.e., shortcut 2) gets updated.
516  base::FilePath new_exe = manganese_exe_;
517  ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs(
518      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
519      chrome_exe_, new_exe));
520
521  // Verify shortcut 1: no change.
522  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
523                         expected_properties1);
524
525  // Verify shortcut 2: target => "manganese.exe".
526  expected_properties2.set_target(new_exe);
527  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
528                         expected_properties2);
529}
530
531TEST_F(ShellUtilShortcutTest, RetargetChromeShortcutsWithArgsIcon) {
532  const int kTestIconIndex1 = 3;
533  const int kTestIconIndex2 = 5;
534  const int kTestIconIndex3 = 8;
535
536  // Shortcut 1: targets "chrome.exe"; icon same as target.
537  test_properties_.set_shortcut_name(L"Chrome 1");
538  test_properties_.set_icon(test_properties_.target, kTestIconIndex1);
539  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
540                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
541                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
542  ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
543      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_)));
544  ShellUtil::ShortcutProperties expected_properties1(test_properties_);
545
546  // Shortcut 2: targets "chrome.exe"; icon set to "other.ico".
547  test_properties_.set_shortcut_name(L"Chrome 2");
548  test_properties_.set_icon(other_ico_, kTestIconIndex2);
549  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
550                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
551                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
552  ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
553      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_)));
554  ShellUtil::ShortcutProperties expected_properties2(test_properties_);
555
556  // Shortcut 3: targets "iron.exe"; icon set to "chrome.exe".
557  test_properties_.set_target(iron_exe_);
558  test_properties_.set_shortcut_name(L"Iron 3");
559  test_properties_.set_icon(chrome_exe_, kTestIconIndex3);
560  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
561                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
562                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
563  ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
564      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_)));
565  ShellUtil::ShortcutProperties expected_properties3(test_properties_);
566
567  // Retarget shortcuts: replace "chrome.exe" with "manganese.exe".
568  // Relies on the fact that |test_properties_| has non-empty arguments.
569  base::FilePath new_exe = manganese_exe_;
570  ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs(
571      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
572      chrome_exe_, new_exe));
573
574  // Verify shortcut 1: target & icon => "manganese.exe", kept same icon index.
575  expected_properties1.set_target(new_exe);
576  expected_properties1.set_icon(new_exe, kTestIconIndex1);
577  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
578                         expected_properties1);
579
580  // Verify shortcut 2: target => "manganese.exe", kept icon.
581  expected_properties2.set_target(new_exe);
582  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
583                         expected_properties2);
584
585  // Verify shortcut 3: no change, since target doesn't match.
586  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
587                         expected_properties3);
588}
589
590TEST_F(ShellUtilShortcutTest, ClearShortcutArguments) {
591  // Shortcut 1: targets "chrome.exe"; no arguments.
592  test_properties_.set_shortcut_name(L"Chrome 1");
593  test_properties_.set_arguments(L"");
594  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
595                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
596                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
597  base::FilePath shortcut1_path = GetExpectedShortcutPath(
598      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
599  ASSERT_TRUE(base::PathExists(shortcut1_path));
600  ShellUtil::ShortcutProperties expected_properties1(test_properties_);
601
602  // Shortcut 2: targets "chrome.exe"; has 1 whitelisted argument.
603  test_properties_.set_shortcut_name(L"Chrome 2");
604  test_properties_.set_arguments(L"--profile-directory=\"Profile 2\"");
605  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
606                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
607                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
608  base::FilePath shortcut2_path = GetExpectedShortcutPath(
609      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
610  ASSERT_TRUE(base::PathExists(shortcut2_path));
611  ShellUtil::ShortcutProperties expected_properties2(test_properties_);
612
613  // Shortcut 3: targets "chrome.exe"; has an unknown argument.
614  test_properties_.set_shortcut_name(L"Chrome 3");
615  test_properties_.set_arguments(L"foo.com");
616  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
617                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
618                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
619  base::FilePath shortcut3_path = GetExpectedShortcutPath(
620      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
621  ASSERT_TRUE(base::PathExists(shortcut3_path));
622  ShellUtil::ShortcutProperties expected_properties3(test_properties_);
623
624  // Shortcut 4: targets "chrome.exe"; has both unknown and known arguments.
625  test_properties_.set_shortcut_name(L"Chrome 4");
626  test_properties_.set_arguments(L"foo.com --show-app-list");
627  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
628                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
629                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
630  base::FilePath shortcut4_path = GetExpectedShortcutPath(
631      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_);
632  ASSERT_TRUE(base::PathExists(shortcut4_path));
633  ShellUtil::ShortcutProperties expected_properties4(test_properties_);
634
635  // List the shortcuts.
636  std::vector<std::pair<base::FilePath, base::string16> > shortcuts;
637  EXPECT_TRUE(ShellUtil::ShortcutListMaybeRemoveUnknownArgs(
638      ShellUtil::SHORTCUT_LOCATION_DESKTOP,
639      dist_,
640      ShellUtil::CURRENT_USER,
641      chrome_exe_,
642      false,
643      NULL,
644      &shortcuts));
645  ASSERT_EQ(2u, shortcuts.size());
646  std::pair<base::FilePath, base::string16> shortcut3 =
647      shortcuts[0].first == shortcut3_path ? shortcuts[0] : shortcuts[1];
648  std::pair<base::FilePath, base::string16> shortcut4 =
649      shortcuts[0].first == shortcut4_path ? shortcuts[0] : shortcuts[1];
650  EXPECT_EQ(shortcut3_path, shortcut3.first);
651  EXPECT_EQ(L"foo.com", shortcut3.second);
652  EXPECT_EQ(shortcut4_path, shortcut4.first);
653  EXPECT_EQ(L"foo.com --show-app-list", shortcut4.second);
654
655  // Clear shortcuts.
656  shortcuts.clear();
657  EXPECT_TRUE(ShellUtil::ShortcutListMaybeRemoveUnknownArgs(
658      ShellUtil::SHORTCUT_LOCATION_DESKTOP,
659      dist_,
660      ShellUtil::CURRENT_USER,
661      chrome_exe_,
662      true,
663      NULL,
664      &shortcuts));
665  ASSERT_EQ(2u, shortcuts.size());
666  shortcut3 = shortcuts[0].first == shortcut3_path ? shortcuts[0] :
667                                                     shortcuts[1];
668  shortcut4 = shortcuts[0].first == shortcut4_path ? shortcuts[0] :
669                                                     shortcuts[1];
670  EXPECT_EQ(shortcut3_path, shortcut3.first);
671  EXPECT_EQ(L"foo.com", shortcut3.second);
672  EXPECT_EQ(shortcut4_path, shortcut4.first);
673  EXPECT_EQ(L"foo.com --show-app-list", shortcut4.second);
674
675  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
676                         expected_properties1);
677  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
678                         expected_properties2);
679  expected_properties3.set_arguments(base::string16());
680  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
681                         expected_properties3);
682  expected_properties4.set_arguments(L"--show-app-list");
683  ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
684                         expected_properties4);
685}
686
687TEST_F(ShellUtilShortcutTest, CreateMultipleStartMenuShortcutsAndRemoveFolder) {
688  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
689                  ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
690                  dist_, test_properties_,
691                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
692  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
693                  ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR,
694                  dist_, test_properties_,
695                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
696  test_properties_.set_shortcut_name(L"A second shortcut");
697  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
698                  ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
699                  dist_, test_properties_,
700                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
701  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
702                  ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR,
703                  dist_, test_properties_,
704                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
705
706  base::FilePath chrome_shortcut_folder(
707      fake_start_menu_.path().Append(
708          dist_->GetStartMenuShortcutSubfolder(
709              BrowserDistribution::SUBFOLDER_CHROME)));
710  base::FilePath chrome_apps_shortcut_folder(
711      fake_start_menu_.path().Append(
712          dist_->GetStartMenuShortcutSubfolder(
713              BrowserDistribution::SUBFOLDER_APPS)));
714
715  base::FileEnumerator chrome_file_counter(chrome_shortcut_folder, false,
716                                           base::FileEnumerator::FILES);
717  int count = 0;
718  while (!chrome_file_counter.Next().empty())
719    ++count;
720  EXPECT_EQ(2, count);
721
722  base::FileEnumerator chrome_apps_file_counter(chrome_apps_shortcut_folder,
723                                                false,
724                                                base::FileEnumerator::FILES);
725  count = 0;
726  while (!chrome_apps_file_counter.Next().empty())
727    ++count;
728  EXPECT_EQ(2, count);
729
730  ASSERT_TRUE(base::PathExists(chrome_shortcut_folder));
731  ASSERT_TRUE(ShellUtil::RemoveShortcuts(
732      ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_,
733      ShellUtil::CURRENT_USER, chrome_exe_));
734  ASSERT_FALSE(base::PathExists(chrome_shortcut_folder));
735
736  ASSERT_TRUE(base::PathExists(chrome_apps_shortcut_folder));
737  ASSERT_TRUE(ShellUtil::RemoveShortcuts(
738      ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, dist_,
739      ShellUtil::CURRENT_USER, chrome_exe_));
740  ASSERT_FALSE(base::PathExists(chrome_apps_shortcut_folder));
741}
742
743TEST_F(ShellUtilShortcutTest,
744       DeleteStartMenuRootShortcutWithoutRemovingFolder) {
745  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
746                  ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT,
747                  dist_, test_properties_,
748                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
749
750  base::string16 shortcut_name(
751      dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
752      installer::kLnkExt);
753  base::FilePath shortcut_path(
754      fake_start_menu_.path().Append(shortcut_name));
755
756  ASSERT_TRUE(base::PathExists(fake_start_menu_.path()));
757  ASSERT_TRUE(base::PathExists(shortcut_path));
758  ASSERT_TRUE(ShellUtil::RemoveShortcuts(
759      ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, dist_,
760      ShellUtil::CURRENT_USER, chrome_exe_));
761  // The shortcut should be removed but the "Start Menu" root directory should
762  // remain.
763  ASSERT_TRUE(base::PathExists(fake_start_menu_.path()));
764  ASSERT_FALSE(base::PathExists(shortcut_path));
765}
766
767TEST_F(ShellUtilShortcutTest, DontRemoveChromeShortcutIfPointsToAnotherChrome) {
768  base::ScopedTempDir other_exe_dir;
769  ASSERT_TRUE(other_exe_dir.CreateUniqueTempDir());
770  base::FilePath other_chrome_exe =
771      other_exe_dir.path().Append(installer::kChromeExe);
772  EXPECT_EQ(0, base::WriteFile(other_chrome_exe, "", 0));
773
774  test_properties_.set_target(other_chrome_exe);
775  ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
776                  ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
777                  ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
778
779  base::string16 shortcut_name(
780      dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
781      installer::kLnkExt);
782  base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name));
783  ASSERT_TRUE(base::PathExists(shortcut_path));
784
785  // The shortcut shouldn't be removed as it was installed pointing to
786  // |other_chrome_exe| and RemoveChromeShortcut() is being told that the
787  // removed shortcut should point to |chrome_exe_|.
788  ASSERT_TRUE(ShellUtil::RemoveShortcuts(
789      ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
790      chrome_exe_));
791  ASSERT_TRUE(base::PathExists(shortcut_path));
792  ASSERT_TRUE(base::PathExists(shortcut_path.DirName()));
793}
794
795TEST(ShellUtilTest, BuildAppModelIdBasic) {
796  std::vector<base::string16> components;
797  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
798  const base::string16 base_app_id(dist->GetBaseAppId());
799  components.push_back(base_app_id);
800  ASSERT_EQ(base_app_id, ShellUtil::BuildAppModelId(components));
801}
802
803TEST(ShellUtilTest, BuildAppModelIdManySmall) {
804  std::vector<base::string16> components;
805  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
806  const base::string16 suffixed_app_id(dist->GetBaseAppId().append(L".gab"));
807  components.push_back(suffixed_app_id);
808  components.push_back(L"Default");
809  components.push_back(L"Test");
810  ASSERT_EQ(suffixed_app_id + L".Default.Test",
811            ShellUtil::BuildAppModelId(components));
812}
813
814TEST(ShellUtilTest, BuildAppModelIdLongUsernameNormalProfile) {
815  std::vector<base::string16> components;
816  const base::string16 long_appname(
817      L"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_"
818      L"that_goes_over_64_characters");
819  components.push_back(long_appname);
820  components.push_back(L"Default");
821  ASSERT_EQ(L"Chrome.a_user_wer_64_characters.Default",
822            ShellUtil::BuildAppModelId(components));
823}
824
825TEST(ShellUtilTest, BuildAppModelIdLongEverything) {
826  std::vector<base::string16> components;
827  const base::string16 long_appname(L"Chrome.a_user_who_has_a_crazy_long_name_"
828                                    L"with_some_weird@symbols_in_"
829                                    L"it_" L"that_goes_over_64_characters");
830  components.push_back(long_appname);
831  components.push_back(
832      L"A_crazy_profile_name_not_even_sure_whether_that_is_possible");
833  const base::string16 constructed_app_id(
834      ShellUtil::BuildAppModelId(components));
835  ASSERT_LE(constructed_app_id.length(), installer::kMaxAppModelIdLength);
836  ASSERT_EQ(L"Chrome.a_user_wer_64_characters.A_crazy_profilethat_is_possible",
837            constructed_app_id);
838}
839
840TEST(ShellUtilTest, GetUserSpecificRegistrySuffix) {
841  base::string16 suffix;
842  ASSERT_TRUE(ShellUtil::GetUserSpecificRegistrySuffix(&suffix));
843  ASSERT_TRUE(StartsWith(suffix, L".", true));
844  ASSERT_EQ(27, suffix.length());
845  ASSERT_TRUE(base::ContainsOnlyChars(suffix.substr(1),
846                                      L"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"));
847}
848
849TEST(ShellUtilTest, GetOldUserSpecificRegistrySuffix) {
850  base::string16 suffix;
851  ASSERT_TRUE(ShellUtil::GetOldUserSpecificRegistrySuffix(&suffix));
852  ASSERT_TRUE(StartsWith(suffix, L".", true));
853
854  wchar_t user_name[256];
855  DWORD size = arraysize(user_name);
856  ASSERT_NE(0, ::GetUserName(user_name, &size));
857  ASSERT_GE(size, 1U);
858  ASSERT_STREQ(user_name, suffix.substr(1).c_str());
859}
860
861TEST(ShellUtilTest, ByteArrayToBase32) {
862  // Tests from http://tools.ietf.org/html/rfc4648#section-10.
863  const unsigned char test_array[] = { 'f', 'o', 'o', 'b', 'a', 'r' };
864
865  const base::string16 expected[] = { L"", L"MY", L"MZXQ", L"MZXW6", L"MZXW6YQ",
866                                L"MZXW6YTB", L"MZXW6YTBOI"};
867
868  // Run the tests, with one more letter in the input every pass.
869  for (int i = 0; i < arraysize(expected); ++i) {
870    ASSERT_EQ(expected[i],
871              ShellUtil::ByteArrayToBase32(test_array, i));
872  }
873}
874