1// Copyright (c) 2014 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 "ui/base/win/open_file_name_win.h" 6 7#include "base/files/file_path.h" 8#include "testing/gtest/include/gtest/gtest.h" 9 10namespace { 11const HWND kHwnd = reinterpret_cast<HWND>(0xDEADBEEF); 12const DWORD kFlags = OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ENABLESIZING; 13 14void SetResult(const base::string16& result, ui::win::OpenFileName* ofn) { 15 if (ofn->GetOPENFILENAME()->nMaxFile <= result.size()) { 16 ADD_FAILURE() << "filename buffer insufficient."; 17 return; 18 } 19 if (!result.size()) { 20 ofn->GetOPENFILENAME()->lpstrFile[0] = 0; 21 } else { 22 // Because the result has embedded nulls, we must memcpy. 23 memcpy(ofn->GetOPENFILENAME()->lpstrFile, 24 result.c_str(), 25 (result.size() + 1) * sizeof(result[0])); 26 } 27} 28 29void CheckFilters( 30 const std::vector<Tuple2<base::string16, base::string16> >& expected, 31 const std::vector<Tuple2<base::string16, base::string16> >& actual) { 32 if (expected.size() != actual.size()) { 33 ADD_FAILURE() << "filter count mismatch. Got " << actual.size() 34 << " expected " << expected.size() << "."; 35 return; 36 } 37 38 for (size_t i = 0; i < expected.size(); ++i) { 39 EXPECT_EQ(expected[i].a, actual[i].a) << "Mismatch at index " << i; 40 EXPECT_EQ(expected[i].b, actual[i].b) << "Mismatch at index " << i; 41 } 42} 43 44void CheckFilterString(const base::string16& expected, 45 const ui::win::OpenFileName& ofn) { 46 if (!ofn.GetOPENFILENAME()->lpstrFilter) { 47 ADD_FAILURE() << "Filter string is NULL."; 48 return; 49 } 50 if (expected.size() == 0) { 51 EXPECT_EQ(0, ofn.GetOPENFILENAME()->lpstrFilter[0]); 52 } else { 53 EXPECT_EQ(0, 54 memcmp(expected.c_str(), 55 ofn.GetOPENFILENAME()->lpstrFilter, 56 expected.size() + 1 * sizeof(expected[0]))); 57 } 58} 59 60void CheckResult(const base::string16& expected, 61 const ui::win::OpenFileName& ofn) { 62 if (!ofn.GetOPENFILENAME()->lpstrFile) { 63 ADD_FAILURE() << "File string is NULL."; 64 return; 65 } 66 if (expected.size() == 0) { 67 EXPECT_EQ(0, ofn.GetOPENFILENAME()->lpstrFile[0]); 68 } else { 69 EXPECT_EQ(0, 70 memcmp(expected.c_str(), 71 ofn.GetOPENFILENAME()->lpstrFile, 72 expected.size() + 1 * sizeof(expected[0]))); 73 } 74} 75 76} // namespace 77 78TEST(OpenFileNameTest, Initialization) { 79 ui::win::OpenFileName ofn(kHwnd, kFlags); 80 EXPECT_EQ(kHwnd, ofn.GetOPENFILENAME()->hwndOwner); 81 EXPECT_EQ(kFlags, ofn.GetOPENFILENAME()->Flags); 82 EXPECT_EQ(sizeof(OPENFILENAME), ofn.GetOPENFILENAME()->lStructSize); 83 ASSERT_TRUE(ofn.GetOPENFILENAME()->lpstrFile); 84 ASSERT_GT(ofn.GetOPENFILENAME()->nMaxFile, 0u); 85 EXPECT_EQ(0, ofn.GetOPENFILENAME()->lpstrFile[0]); 86} 87 88TEST(OpenFileNameTest, SetInitialSelection) { 89 const base::FilePath kDirectory(L"C:\\directory\\child_directory"); 90 const base::FilePath kFile(L"file_name.ext"); 91 ui::win::OpenFileName ofn(kHwnd, kFlags); 92 ofn.SetInitialSelection(kDirectory, kFile); 93 EXPECT_EQ(kDirectory, base::FilePath(ofn.GetOPENFILENAME()->lpstrInitialDir)); 94 EXPECT_EQ(kFile, base::FilePath(ofn.GetOPENFILENAME()->lpstrFile)); 95 96 ofn.SetInitialSelection(kDirectory, base::FilePath()); 97 EXPECT_EQ(kDirectory, base::FilePath(ofn.GetOPENFILENAME()->lpstrInitialDir)); 98 // Filename buffer will still be a valid pointer, to receive a result. 99 ASSERT_TRUE(ofn.GetOPENFILENAME()->lpstrFile); 100 EXPECT_EQ(base::FilePath(), base::FilePath(ofn.GetOPENFILENAME()->lpstrFile)); 101 102 ofn.SetInitialSelection(base::FilePath(), base::FilePath()); 103 // No initial directory will lead to a NULL buffer. 104 ASSERT_FALSE(ofn.GetOPENFILENAME()->lpstrInitialDir); 105 ASSERT_TRUE(ofn.GetOPENFILENAME()->lpstrFile); 106 EXPECT_EQ(base::FilePath(), base::FilePath(ofn.GetOPENFILENAME()->lpstrFile)); 107 108 // Make sure that both values are cleared when directory is missing. 109 ofn.SetInitialSelection(kDirectory, kFile); 110 EXPECT_EQ(kDirectory, base::FilePath(ofn.GetOPENFILENAME()->lpstrInitialDir)); 111 EXPECT_EQ(kFile, base::FilePath(ofn.GetOPENFILENAME()->lpstrFile)); 112 ofn.SetInitialSelection(base::FilePath(), base::FilePath()); 113 ASSERT_FALSE(ofn.GetOPENFILENAME()->lpstrInitialDir); 114 ASSERT_TRUE(ofn.GetOPENFILENAME()->lpstrFile); 115 EXPECT_EQ(base::FilePath(), base::FilePath(ofn.GetOPENFILENAME()->lpstrFile)); 116 117 // File is ignored in absence of a directory. 118 ofn.SetInitialSelection(base::FilePath(), kFile); 119 ASSERT_FALSE(ofn.GetOPENFILENAME()->lpstrInitialDir); 120 ASSERT_TRUE(ofn.GetOPENFILENAME()->lpstrFile); 121 EXPECT_EQ(base::FilePath(), base::FilePath(ofn.GetOPENFILENAME()->lpstrFile)); 122} 123 124TEST(OpenFileNameTest, GetSingleResult) { 125 const base::string16 kNull(L"\0", 1); 126 ui::win::OpenFileName ofn(kHwnd, kFlags); 127 base::FilePath result; 128 129 SetResult(L"C:\\dir\\file" + kNull, &ofn); 130 result = ofn.GetSingleResult(); 131 EXPECT_EQ(base::FilePath(L"C:\\dir\\file"), result); 132 133 SetResult(L"C:\\dir" + kNull + L"file" + kNull, &ofn); 134 result = ofn.GetSingleResult(); 135 EXPECT_EQ(base::FilePath(L"C:\\dir\\file"), result); 136 137 SetResult(L"C:\\dir" + kNull + L"file" + kNull + L"otherfile" + kNull, &ofn); 138 result = ofn.GetSingleResult(); 139 EXPECT_EQ(base::FilePath(), result); 140 141 SetResult(L"", &ofn); 142 result = ofn.GetSingleResult(); 143 EXPECT_EQ(base::FilePath(), result); 144} 145 146TEST(OpenFileNameTest, GetResult) { 147 const base::string16 kNull(L"\0", 1); 148 149 ui::win::OpenFileName ofn(kHwnd, kFlags); 150 base::FilePath directory; 151 std::vector<base::FilePath> filenames; 152 153 SetResult(L"C:\\dir\\file" + kNull, &ofn); 154 ofn.GetResult(&directory, &filenames); 155 EXPECT_EQ(base::FilePath(L"C:\\dir"), directory); 156 ASSERT_EQ(1u, filenames.size()); 157 EXPECT_EQ(base::FilePath(L"file"), filenames[0]); 158 159 directory.clear(); 160 filenames.clear(); 161 162 SetResult(L"C:\\dir" + kNull + L"file" + kNull, &ofn); 163 ofn.GetResult(&directory, &filenames); 164 EXPECT_EQ(base::FilePath(L"C:\\dir"), directory); 165 ASSERT_EQ(1u, filenames.size()); 166 EXPECT_EQ(base::FilePath(L"file"), filenames[0]); 167 168 directory.clear(); 169 filenames.clear(); 170 171 SetResult(L"C:\\dir" + kNull + L"file" + kNull + L"otherfile" + kNull, &ofn); 172 ofn.GetResult(&directory, &filenames); 173 EXPECT_EQ(base::FilePath(L"C:\\dir"), directory); 174 ASSERT_EQ(2u, filenames.size()); 175 EXPECT_EQ(base::FilePath(L"file"), filenames[0]); 176 EXPECT_EQ(base::FilePath(L"otherfile"), filenames[1]); 177 178 directory.clear(); 179 filenames.clear(); 180 181 SetResult(L"", &ofn); 182 ofn.GetResult(&directory, &filenames); 183 EXPECT_EQ(base::FilePath(), directory); 184 ASSERT_EQ(0u, filenames.size()); 185} 186 187TEST(OpenFileNameTest, SetAndGetFilters) { 188 const base::string16 kNull(L"\0", 1); 189 190 ui::win::OpenFileName ofn(kHwnd, kFlags); 191 std::vector<Tuple2<base::string16, base::string16> > filters; 192 ofn.SetFilters(filters); 193 EXPECT_FALSE(ofn.GetOPENFILENAME()->lpstrFilter); 194 CheckFilters(filters, 195 ui::win::OpenFileName::GetFilters(ofn.GetOPENFILENAME())); 196 197 filters.push_back(MakeTuple(base::string16(L"a"), base::string16(L"b"))); 198 ofn.SetFilters(filters); 199 CheckFilterString(L"a" + kNull + L"b" + kNull, ofn); 200 CheckFilters(filters, 201 ui::win::OpenFileName::GetFilters(ofn.GetOPENFILENAME())); 202 203 filters.push_back(MakeTuple(base::string16(L"X"), base::string16(L"Y"))); 204 ofn.SetFilters(filters); 205 CheckFilterString(L"a" + kNull + L"b" + kNull + L"X" + kNull + L"Y" + kNull, 206 ofn); 207 CheckFilters(filters, 208 ui::win::OpenFileName::GetFilters(ofn.GetOPENFILENAME())); 209} 210 211TEST(OpenFileNameTest, SetResult) { 212 const base::string16 kNull(L"\0", 1); 213 214 ui::win::OpenFileName ofn(kHwnd, kFlags); 215 base::FilePath directory; 216 std::vector<base::FilePath> filenames; 217 218 ui::win::OpenFileName::SetResult(directory, filenames, ofn.GetOPENFILENAME()); 219 CheckResult(L"", ofn); 220 221 directory = base::FilePath(L"C:\\dir"); 222 filenames.push_back(base::FilePath(L"file")); 223 ui::win::OpenFileName::SetResult(directory, filenames, ofn.GetOPENFILENAME()); 224 CheckResult(L"C:\\dir\\file" + kNull, ofn); 225 226 filenames.push_back(base::FilePath(L"otherfile")); 227 ui::win::OpenFileName::SetResult(directory, filenames, ofn.GetOPENFILENAME()); 228 CheckResult(L"C:\\dir" + kNull + L"file" + kNull + L"otherfile" + kNull, ofn); 229 230 base::char16 short_buffer[10] = L""; 231 232 ofn.GetOPENFILENAME()->lpstrFile = short_buffer; 233 ofn.GetOPENFILENAME()->nMaxFile = arraysize(short_buffer); 234 ui::win::OpenFileName::SetResult(directory, filenames, ofn.GetOPENFILENAME()); 235 CheckResult(L"", ofn); 236} 237