Match whole path components in DevicePathToDriveLetterPath().  Add tests.

+rvargas, who understands the code
+brettw, who is in OWNERS

BUG=109577
TEST=FileUtilTest.DevicePathToDriveLetter


Review URL: http://codereview.chromium.org/9167004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117986 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: 71b7da7dbd4ed7fa4e28e23a796bd203601613aa
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index 0cade2a..ee73ef3 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -580,6 +580,76 @@
                                             &normalized_path));
 }
 
+TEST_F(FileUtilTest, DevicePathToDriveLetter) {
+  // Get a drive letter.
+  std::wstring real_drive_letter = temp_dir_.path().value().substr(0, 2);
+  if (!isalpha(real_drive_letter[0]) || ':' != real_drive_letter[1]) {
+    LOG(ERROR) << "Can't get a drive letter to test with.";
+    return;
+  }
+
+  // Get the NT style path to that drive.
+  wchar_t device_path[MAX_PATH] = {'\0'};
+  ASSERT_TRUE(
+      ::QueryDosDevice(real_drive_letter.c_str(), device_path, MAX_PATH));
+  FilePath actual_device_path(device_path);
+  FilePath win32_path;
+
+  // Run DevicePathToDriveLetterPath() on the NT style path we got from
+  // QueryDosDevice().  Expect the drive letter we started with.
+  ASSERT_TRUE(file_util::DevicePathToDriveLetterPath(actual_device_path,
+                                                     &win32_path));
+  ASSERT_EQ(real_drive_letter, win32_path.value());
+
+  // Add some directories to the path.  Expect those extra path componenets
+  // to be preserved.
+  FilePath kRelativePath(FPL("dir1\\dir2\\file.txt"));
+  ASSERT_TRUE(file_util::DevicePathToDriveLetterPath(
+      actual_device_path.Append(kRelativePath),
+      &win32_path));
+  EXPECT_EQ(FilePath(real_drive_letter + L"\\").Append(kRelativePath).value(),
+            win32_path.value());
+
+  // Deform the real path so that it is invalid by removing the last four
+  // characters.  The way windows names devices that are hard disks
+  // (\Device\HardDiskVolume${NUMBER}) guarantees that the string is longer
+  // than three characters.  The only way the truncated string could be a
+  // real drive is if more than 10^3 disks are mounted:
+  // \Device\HardDiskVolume10000 would be truncated to \Device\HardDiskVolume1
+  // Check that DevicePathToDriveLetterPath fails.
+  int path_length = actual_device_path.value().length();
+  int new_length = path_length - 4;
+  ASSERT_LT(0, new_length);
+  FilePath prefix_of_real_device_path(
+      actual_device_path.value().substr(0, new_length));
+  ASSERT_FALSE(file_util::DevicePathToDriveLetterPath(
+      prefix_of_real_device_path,
+      &win32_path));
+
+  ASSERT_FALSE(file_util::DevicePathToDriveLetterPath(
+      prefix_of_real_device_path.Append(kRelativePath),
+      &win32_path));
+
+  // Deform the real path so that it is invalid by adding some characters. For
+  // example, if C: maps to \Device\HardDiskVolume8, then we simulate a
+  // request for the drive letter whose native path is
+  // \Device\HardDiskVolume812345 .  We assume such a device does not exist,
+  // because drives are numbered in order and mounting 112345 hard disks will
+  // never happen.
+  const FilePath::StringType kExtraChars = FPL("12345");
+
+  FilePath real_device_path_plus_numbers(
+      actual_device_path.value() + kExtraChars);
+
+  ASSERT_FALSE(file_util::DevicePathToDriveLetterPath(
+      real_device_path_plus_numbers,
+      &win32_path));
+
+  ASSERT_FALSE(file_util::DevicePathToDriveLetterPath(
+      real_device_path_plus_numbers.Append(kRelativePath),
+      &win32_path));
+}
+
 TEST_F(FileUtilTest, GetPlatformFileInfoForDirectory) {
   FilePath empty_dir = temp_dir_.path().Append(FPL("gpfi_test"));
   ASSERT_TRUE(file_util::CreateDirectory(empty_dir));