1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/tests/TestFile.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,524 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "prio.h" 1.10 +#include "prsystem.h" 1.11 + 1.12 +#include "TestHarness.h" 1.13 + 1.14 +#include "nsIFile.h" 1.15 +#include "nsDirectoryServiceDefs.h" 1.16 +#include "nsDirectoryServiceUtils.h" 1.17 + 1.18 +static const char* gFunction = "main"; 1.19 + 1.20 +static bool VerifyResult(nsresult aRV, const char* aMsg) 1.21 +{ 1.22 + if (NS_FAILED(aRV)) { 1.23 + fail("%s %s, rv=%x", gFunction, aMsg, aRV); 1.24 + return false; 1.25 + } 1.26 + return true; 1.27 +} 1.28 + 1.29 +static already_AddRefed<nsIFile> NewFile(nsIFile* aBase) 1.30 +{ 1.31 + nsresult rv; 1.32 + nsCOMPtr<nsIFile> file = 1.33 + do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv); 1.34 + VerifyResult(rv, "Creating nsIFile"); 1.35 + rv = file->InitWithFile(aBase); 1.36 + VerifyResult(rv, "InitWithFile"); 1.37 + return file.forget(); 1.38 +} 1.39 + 1.40 +static nsCString FixName(const char* aName) 1.41 +{ 1.42 + nsCString name; 1.43 + for (uint32_t i = 0; aName[i]; ++i) { 1.44 + char ch = aName[i]; 1.45 + // PR_GetPathSeparator returns the wrong value on Mac so don't use it 1.46 +#if defined(XP_WIN) 1.47 + if (ch == '/') { 1.48 + ch = '\\'; 1.49 + } 1.50 +#endif 1.51 + name.Append(ch); 1.52 + } 1.53 + return name; 1.54 +} 1.55 + 1.56 +// Test nsIFile::AppendNative, verifying that aName is not a valid file name 1.57 +static bool TestInvalidFileName(nsIFile* aBase, const char* aName) 1.58 +{ 1.59 + gFunction = "TestInvalidFileName"; 1.60 + nsCOMPtr<nsIFile> file = NewFile(aBase); 1.61 + if (!file) 1.62 + return false; 1.63 + 1.64 + nsCString name = FixName(aName); 1.65 + nsresult rv = file->AppendNative(name); 1.66 + if (NS_SUCCEEDED(rv)) { 1.67 + fail("%s AppendNative with invalid filename %s", gFunction, name.get()); 1.68 + return false; 1.69 + } 1.70 + 1.71 + return true; 1.72 +} 1.73 + 1.74 +// Test nsIFile::Create, verifying that the file exists and did not exist before, 1.75 +// and leaving it there for future tests 1.76 +static bool TestCreate(nsIFile* aBase, const char* aName, int32_t aType, int32_t aPerm) 1.77 +{ 1.78 + gFunction = "TestCreate"; 1.79 + nsCOMPtr<nsIFile> file = NewFile(aBase); 1.80 + if (!file) 1.81 + return false; 1.82 + 1.83 + nsCString name = FixName(aName); 1.84 + nsresult rv = file->AppendNative(name); 1.85 + if (!VerifyResult(rv, "AppendNative")) 1.86 + return false; 1.87 + 1.88 + bool exists; 1.89 + rv = file->Exists(&exists); 1.90 + if (!VerifyResult(rv, "Exists (before)")) 1.91 + return false; 1.92 + if (exists) { 1.93 + fail("%s File %s already exists", gFunction, name.get()); 1.94 + return false; 1.95 + } 1.96 + 1.97 + rv = file->Create(aType, aPerm); 1.98 + if (!VerifyResult(rv, "Create")) 1.99 + return false; 1.100 + 1.101 + rv = file->Exists(&exists); 1.102 + if (!VerifyResult(rv, "Exists (after)")) 1.103 + return false; 1.104 + if (!exists) { 1.105 + fail("%s File %s was not created", gFunction, name.get()); 1.106 + return false; 1.107 + } 1.108 + 1.109 + return true; 1.110 +} 1.111 + 1.112 +// Test nsIFile::CreateUnique, verifying that the new file exists and if it existed before, 1.113 +// the new file has a different name. 1.114 +// The new file is left in place. 1.115 +static bool TestCreateUnique(nsIFile* aBase, const char* aName, int32_t aType, int32_t aPerm) 1.116 +{ 1.117 + gFunction = "TestCreateUnique"; 1.118 + nsCOMPtr<nsIFile> file = NewFile(aBase); 1.119 + if (!file) 1.120 + return false; 1.121 + 1.122 + nsCString name = FixName(aName); 1.123 + nsresult rv = file->AppendNative(name); 1.124 + if (!VerifyResult(rv, "AppendNative")) 1.125 + return false; 1.126 + 1.127 + bool existsBefore; 1.128 + rv = file->Exists(&existsBefore); 1.129 + if (!VerifyResult(rv, "Exists (before)")) 1.130 + return false; 1.131 + 1.132 + rv = file->CreateUnique(aType, aPerm); 1.133 + if (!VerifyResult(rv, "Create")) 1.134 + return false; 1.135 + 1.136 + bool existsAfter; 1.137 + rv = file->Exists(&existsAfter); 1.138 + if (!VerifyResult(rv, "Exists (after)")) 1.139 + return false; 1.140 + if (!existsAfter) { 1.141 + fail("%s File %s was not created", gFunction, name.get()); 1.142 + return false; 1.143 + } 1.144 + 1.145 + if (existsBefore) { 1.146 + nsAutoCString leafName; 1.147 + rv = file->GetNativeLeafName(leafName); 1.148 + if (!VerifyResult(rv, "GetNativeLeafName")) 1.149 + return false; 1.150 + if (leafName.Equals(name)) { 1.151 + fail("%s File %s was not given a new name by CreateUnique", gFunction, name.get()); 1.152 + return false; 1.153 + } 1.154 + } 1.155 + 1.156 + return true; 1.157 +} 1.158 + 1.159 +// Test nsIFile::OpenNSPRFileDesc with DELETE_ON_CLOSE, verifying that the file exists 1.160 +// and did not exist before, and leaving it there for future tests 1.161 +static bool TestDeleteOnClose(nsIFile* aBase, const char* aName, int32_t aFlags, int32_t aPerm) 1.162 +{ 1.163 + gFunction = "TestDeleteOnClose"; 1.164 + nsCOMPtr<nsIFile> file = NewFile(aBase); 1.165 + if (!file) 1.166 + return false; 1.167 + 1.168 + nsCString name = FixName(aName); 1.169 + nsresult rv = file->AppendNative(name); 1.170 + if (!VerifyResult(rv, "AppendNative")) 1.171 + return false; 1.172 + 1.173 + bool exists; 1.174 + rv = file->Exists(&exists); 1.175 + if (!VerifyResult(rv, "Exists (before)")) 1.176 + return false; 1.177 + if (exists) { 1.178 + fail("%s File %s already exists", gFunction, name.get()); 1.179 + return false; 1.180 + } 1.181 + 1.182 + PRFileDesc* fileDesc; 1.183 + rv = file->OpenNSPRFileDesc(aFlags | nsIFile::DELETE_ON_CLOSE, aPerm, &fileDesc); 1.184 + if (!VerifyResult(rv, "OpenNSPRFileDesc")) 1.185 + return false; 1.186 + PRStatus status = PR_Close(fileDesc); 1.187 + if (status != PR_SUCCESS) { 1.188 + fail("%s File %s could not be closed", gFunction, name.get()); 1.189 + return false; 1.190 + } 1.191 + 1.192 + rv = file->Exists(&exists); 1.193 + if (!VerifyResult(rv, "Exists (after)")) 1.194 + return false; 1.195 + if (exists) { 1.196 + fail("%s File %s was not removed on close!", gFunction, name.get()); 1.197 + return false; 1.198 + } 1.199 + 1.200 + return true; 1.201 +} 1.202 + 1.203 +// Test nsIFile::Remove, verifying that the file does not exist and did before 1.204 +static bool TestRemove(nsIFile* aBase, const char* aName, bool aRecursive) 1.205 +{ 1.206 + gFunction = "TestDelete"; 1.207 + nsCOMPtr<nsIFile> file = NewFile(aBase); 1.208 + if (!file) 1.209 + return false; 1.210 + 1.211 + nsCString name = FixName(aName); 1.212 + nsresult rv = file->AppendNative(name); 1.213 + if (!VerifyResult(rv, "AppendNative")) 1.214 + return false; 1.215 + 1.216 + bool exists; 1.217 + rv = file->Exists(&exists); 1.218 + if (!VerifyResult(rv, "Exists (before)")) 1.219 + return false; 1.220 + if (!exists) { 1.221 + fail("%s File %s does not exist", gFunction, name.get()); 1.222 + return false; 1.223 + } 1.224 + 1.225 + rv = file->Remove(aRecursive); 1.226 + if (!VerifyResult(rv, "Remove")) 1.227 + return false; 1.228 + 1.229 + rv = file->Exists(&exists); 1.230 + if (!VerifyResult(rv, "Exists (after)")) 1.231 + return false; 1.232 + if (exists) { 1.233 + fail("%s File %s was not removed", gFunction, name.get()); 1.234 + return false; 1.235 + } 1.236 + 1.237 + return true; 1.238 +} 1.239 + 1.240 +// Test nsIFile::MoveToNative, verifying that the file did not exist at the new location 1.241 +// before and does afterward, and that it does not exist at the old location anymore 1.242 +static bool TestMove(nsIFile* aBase, nsIFile* aDestDir, const char* aName, const char* aNewName) 1.243 +{ 1.244 + gFunction = "TestMove"; 1.245 + nsCOMPtr<nsIFile> file = NewFile(aBase); 1.246 + if (!file) 1.247 + return false; 1.248 + 1.249 + nsCString name = FixName(aName); 1.250 + nsresult rv = file->AppendNative(name); 1.251 + if (!VerifyResult(rv, "AppendNative")) 1.252 + return false; 1.253 + 1.254 + bool exists; 1.255 + rv = file->Exists(&exists); 1.256 + if (!VerifyResult(rv, "Exists (before)")) 1.257 + return false; 1.258 + if (!exists) { 1.259 + fail("%s File %s does not exist", gFunction, name.get()); 1.260 + return false; 1.261 + } 1.262 + 1.263 + nsCOMPtr<nsIFile> newFile = NewFile(file); 1.264 + nsCString newName = FixName(aNewName); 1.265 + rv = newFile->MoveToNative(aDestDir, newName); 1.266 + if (!VerifyResult(rv, "MoveToNative")) 1.267 + return false; 1.268 + 1.269 + rv = file->Exists(&exists); 1.270 + if (!VerifyResult(rv, "Exists (after)")) 1.271 + return false; 1.272 + if (exists) { 1.273 + fail("%s File %s was not moved", gFunction, name.get()); 1.274 + return false; 1.275 + } 1.276 + 1.277 + file = NewFile(aDestDir); 1.278 + if (!file) 1.279 + return false; 1.280 + rv = file->AppendNative(newName); 1.281 + if (!VerifyResult(rv, "AppendNative")) 1.282 + return false; 1.283 + bool equal; 1.284 + rv = file->Equals(newFile, &equal); 1.285 + if (!VerifyResult(rv, "Equals")) 1.286 + return false; 1.287 + if (!equal) { 1.288 + fail("%s file object was not updated to destination", gFunction); 1.289 + return false; 1.290 + } 1.291 + 1.292 + rv = file->Exists(&exists); 1.293 + if (!VerifyResult(rv, "Exists (new after)")) 1.294 + return false; 1.295 + if (!exists) { 1.296 + fail("%s Destination file %s was not created", gFunction, newName.get()); 1.297 + return false; 1.298 + } 1.299 + 1.300 + return true; 1.301 +} 1.302 + 1.303 +// Test nsIFile::CopyToNative, verifying that the file did not exist at the new location 1.304 +// before and does afterward, and that it does exist at the old location too 1.305 +static bool TestCopy(nsIFile* aBase, nsIFile* aDestDir, const char* aName, const char* aNewName) 1.306 +{ 1.307 + gFunction = "TestCopy"; 1.308 + nsCOMPtr<nsIFile> file = NewFile(aBase); 1.309 + if (!file) 1.310 + return false; 1.311 + 1.312 + nsCString name = FixName(aName); 1.313 + nsresult rv = file->AppendNative(name); 1.314 + if (!VerifyResult(rv, "AppendNative")) 1.315 + return false; 1.316 + 1.317 + bool exists; 1.318 + rv = file->Exists(&exists); 1.319 + if (!VerifyResult(rv, "Exists (before)")) 1.320 + return false; 1.321 + if (!exists) { 1.322 + fail("%s File %s does not exist", gFunction, name.get()); 1.323 + return false; 1.324 + } 1.325 + 1.326 + nsCOMPtr<nsIFile> newFile = NewFile(file); 1.327 + nsCString newName = FixName(aNewName); 1.328 + rv = newFile->CopyToNative(aDestDir, newName); 1.329 + if (!VerifyResult(rv, "MoveToNative")) 1.330 + return false; 1.331 + bool equal; 1.332 + rv = file->Equals(newFile, &equal); 1.333 + if (!VerifyResult(rv, "Equals")) 1.334 + return false; 1.335 + if (!equal) { 1.336 + fail("%s file object updated unexpectedly", gFunction); 1.337 + return false; 1.338 + } 1.339 + 1.340 + rv = file->Exists(&exists); 1.341 + if (!VerifyResult(rv, "Exists (after)")) 1.342 + return false; 1.343 + if (!exists) { 1.344 + fail("%s File %s was removed", gFunction, name.get()); 1.345 + return false; 1.346 + } 1.347 + 1.348 + file = NewFile(aDestDir); 1.349 + if (!file) 1.350 + return false; 1.351 + rv = file->AppendNative(newName); 1.352 + if (!VerifyResult(rv, "AppendNative")) 1.353 + return false; 1.354 + 1.355 + rv = file->Exists(&exists); 1.356 + if (!VerifyResult(rv, "Exists (new after)")) 1.357 + return false; 1.358 + if (!exists) { 1.359 + fail("%s Destination file %s was not created", gFunction, newName.get()); 1.360 + return false; 1.361 + } 1.362 + 1.363 + return true; 1.364 +} 1.365 + 1.366 +// Test nsIFile::GetParent 1.367 +static bool TestParent(nsIFile* aBase, nsIFile* aStart) 1.368 +{ 1.369 + gFunction = "TestParent"; 1.370 + nsCOMPtr<nsIFile> file = NewFile(aStart); 1.371 + if (!file) 1.372 + return false; 1.373 + 1.374 + nsCOMPtr<nsIFile> parent; 1.375 + nsresult rv = file->GetParent(getter_AddRefs(parent)); 1.376 + VerifyResult(rv, "GetParent"); 1.377 + 1.378 + bool equal; 1.379 + rv = parent->Equals(aBase, &equal); 1.380 + VerifyResult(rv, "Equals"); 1.381 + if (!equal) { 1.382 + fail("%s Incorrect parent", gFunction); 1.383 + return false; 1.384 + } 1.385 + 1.386 + return true; 1.387 +} 1.388 + 1.389 +// Test nsIFile::Normalize and native path setting/getting 1.390 +static bool TestNormalizeNativePath(nsIFile* aBase, nsIFile* aStart) 1.391 +{ 1.392 + gFunction = "TestNormalizeNativePath"; 1.393 + nsCOMPtr<nsIFile> file = NewFile(aStart); 1.394 + if (!file) 1.395 + return false; 1.396 + 1.397 + nsAutoCString path; 1.398 + nsresult rv = file->GetNativePath(path); 1.399 + VerifyResult(rv, "GetNativePath"); 1.400 + path.Append(FixName("/./..")); 1.401 + rv = file->InitWithNativePath(path); 1.402 + VerifyResult(rv, "InitWithNativePath"); 1.403 + rv = file->Normalize(); 1.404 + VerifyResult(rv, "Normalize"); 1.405 + rv = file->GetNativePath(path); 1.406 + VerifyResult(rv, "GetNativePath (after normalization)"); 1.407 + 1.408 + nsAutoCString basePath; 1.409 + rv = aBase->GetNativePath(basePath); 1.410 + VerifyResult(rv, "GetNativePath (base)"); 1.411 + 1.412 + if (!path.Equals(basePath)) { 1.413 + fail("%s Incorrect normalization"); 1.414 + return false; 1.415 + } 1.416 + 1.417 + return true; 1.418 +} 1.419 + 1.420 +int main(int argc, char** argv) 1.421 +{ 1.422 + ScopedXPCOM xpcom("nsLocalFile"); 1.423 + if (xpcom.failed()) 1.424 + return 1; 1.425 + 1.426 + nsCOMPtr<nsIFile> base; 1.427 + nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(base)); 1.428 + if (!VerifyResult(rv, "Getting temp directory")) 1.429 + return 1; 1.430 + rv = base->AppendNative(nsDependentCString("mozfiletests")); 1.431 + if (!VerifyResult(rv, "Appending mozfiletests to temp directory name")) 1.432 + return 1; 1.433 + // Remove the directory in case tests failed and left it behind. 1.434 + // don't check result since it might not be there 1.435 + base->Remove(true); 1.436 + 1.437 + // Now create the working directory we're going to use 1.438 + rv = base->Create(nsIFile::DIRECTORY_TYPE, 0700); 1.439 + if (!VerifyResult(rv, "Creating temp directory")) 1.440 + return 1; 1.441 + // Now we can safely normalize the path 1.442 + rv = base->Normalize(); 1.443 + if (!VerifyResult(rv, "Normalizing temp directory name")) 1.444 + return 1; 1.445 + 1.446 + // Initialize subdir object for later use 1.447 + nsCOMPtr<nsIFile> subdir = NewFile(base); 1.448 + if (!subdir) 1.449 + return 1; 1.450 + rv = subdir->AppendNative(nsDependentCString("subdir")); 1.451 + if (!VerifyResult(rv, "Appending 'subdir' to test dir name")) 1.452 + return 1; 1.453 + 1.454 + passed("Setup"); 1.455 + 1.456 + // Test path parsing 1.457 + if (TestInvalidFileName(base, "a/b")) { 1.458 + passed("AppendNative with invalid file name"); 1.459 + } 1.460 + if (TestParent(base, subdir)) { 1.461 + passed("GetParent"); 1.462 + } 1.463 + 1.464 + // Test file creation 1.465 + if (TestCreate(base, "file.txt", nsIFile::NORMAL_FILE_TYPE, 0600)) { 1.466 + passed("Create file"); 1.467 + } 1.468 + if (TestRemove(base, "file.txt", false)) { 1.469 + passed("Remove file"); 1.470 + } 1.471 + 1.472 + // Test directory creation 1.473 + if (TestCreate(base, "subdir", nsIFile::DIRECTORY_TYPE, 0700)) { 1.474 + passed("Create directory"); 1.475 + } 1.476 + 1.477 + // Test move and copy in the base directory 1.478 + if (TestCreate(base, "file.txt", nsIFile::NORMAL_FILE_TYPE, 0600) && 1.479 + TestMove(base, base, "file.txt", "file2.txt")) { 1.480 + passed("MoveTo rename file"); 1.481 + } 1.482 + if (TestCopy(base, base, "file2.txt", "file3.txt")) { 1.483 + passed("CopyTo copy file"); 1.484 + } 1.485 + // Test moving across directories 1.486 + if (TestMove(base, subdir, "file2.txt", "file2.txt")) { 1.487 + passed("MoveTo move file"); 1.488 + } 1.489 + // Test moving across directories and renaming at the same time 1.490 + if (TestMove(subdir, base, "file2.txt", "file4.txt")) { 1.491 + passed("MoveTo move and rename file"); 1.492 + } 1.493 + // Test copying across directoreis 1.494 + if (TestCopy(base, subdir, "file4.txt", "file5.txt")) { 1.495 + passed("CopyTo copy file across directories"); 1.496 + } 1.497 + 1.498 + // Run normalization tests while the directory exists 1.499 + if (TestNormalizeNativePath(base, subdir)) { 1.500 + passed("Normalize with native paths"); 1.501 + } 1.502 + 1.503 + // Test recursive directory removal 1.504 + if (TestRemove(base, "subdir", true)) { 1.505 + passed("Remove directory"); 1.506 + } 1.507 + 1.508 + if (TestCreateUnique(base, "foo", nsIFile::NORMAL_FILE_TYPE, 0600) && 1.509 + TestCreateUnique(base, "foo", nsIFile::NORMAL_FILE_TYPE, 0600)) { 1.510 + passed("CreateUnique file"); 1.511 + } 1.512 + if (TestCreateUnique(base, "bar.xx", nsIFile::DIRECTORY_TYPE, 0700) && 1.513 + TestCreateUnique(base, "bar.xx", nsIFile::DIRECTORY_TYPE, 0700)) { 1.514 + passed("CreateUnique directory"); 1.515 + } 1.516 + 1.517 + if (TestDeleteOnClose(base, "file7.txt", PR_RDWR | PR_CREATE_FILE, 0600)) { 1.518 + passed("OpenNSPRFileDesc DELETE_ON_CLOSE"); 1.519 + } 1.520 + 1.521 + gFunction = "main"; 1.522 + // Clean up temporary stuff 1.523 + rv = base->Remove(true); 1.524 + VerifyResult(rv, "Cleaning up temp directory"); 1.525 + 1.526 + return gFailCount > 0; 1.527 +}