#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_STORAGE_SOURCE 1 #include "Nuclex/Storage/FileSystem/Path.h" #include namespace Nuclex { namespace Storage { namespace FileSystem { // ------------------------------------------------------------------------------------------- // TEST(PathTest, DetectsAbsolutePaths) { EXPECT_FALSE(Path::IsAbsolute(std::string())); EXPECT_FALSE(Path::IsAbsolute(u8".")); EXPECT_FALSE(Path::IsAbsolute(u8"..")); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_TRUE(Path::IsAbsolute(u8"\\")); EXPECT_TRUE(Path::IsAbsolute(u8"\\games")); EXPECT_TRUE(Path::IsAbsolute(u8"\\\\Server")); EXPECT_TRUE(Path::IsAbsolute(u8"C:\\")); EXPECT_FALSE(Path::IsAbsolute(u8"C:")); EXPECT_FALSE(Path::IsAbsolute(u8"~weird")); EXPECT_FALSE(Path::IsAbsolute(u8"~.weird")); EXPECT_FALSE(Path::IsAbsolute(u8"~/weird")); EXPECT_FALSE(Path::IsAbsolute(u8"~")); #else EXPECT_FALSE(Path::IsAbsolute(u8"\\")); EXPECT_FALSE(Path::IsAbsolute(u8"\\games")); EXPECT_FALSE(Path::IsAbsolute(u8"\\\\Server")); EXPECT_FALSE(Path::IsAbsolute(u8"C:\\")); EXPECT_FALSE(Path::IsAbsolute(u8"C:")); EXPECT_FALSE(Path::IsAbsolute(u8"~weird")); EXPECT_FALSE(Path::IsAbsolute(u8"~.weird")); EXPECT_TRUE(Path::IsAbsolute(u8"~/weird")); EXPECT_TRUE(Path::IsAbsolute(u8"~")); #endif EXPECT_TRUE(Path::IsAbsolute(u8"/")); EXPECT_TRUE(Path::IsAbsolute(u8"/games")); EXPECT_FALSE(Path::IsAbsolute(u8"home")); EXPECT_FALSE(Path::IsAbsolute(u8"file:")); // malformed EXPECT_FALSE(Path::IsAbsolute(u8"file:/")); // malformed EXPECT_FALSE(Path::IsAbsolute(u8"file://")); // empty EXPECT_TRUE(Path::IsAbsolute(u8"file:///")); EXPECT_TRUE(Path::IsAbsolute(u8"file://C:/")); EXPECT_TRUE(Path::IsAbsolute(u8"https://www.example.com")); EXPECT_FALSE(Path::IsAbsolute(u8":///test")); // missing scheme } // ------------------------------------------------------------------------------------------- // TEST(PathTest, DetectsRelativePaths) { EXPECT_TRUE(Path::IsRelative(std::string())); EXPECT_TRUE(Path::IsRelative(u8".")); EXPECT_TRUE(Path::IsRelative(u8"..")); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_FALSE(Path::IsRelative(u8"\\")); EXPECT_FALSE(Path::IsRelative(u8"\\games")); EXPECT_FALSE(Path::IsRelative(u8"\\\\Server")); EXPECT_FALSE(Path::IsRelative(u8"C:\\")); EXPECT_TRUE(Path::IsRelative(u8"C:")); EXPECT_TRUE(Path::IsRelative(u8"~weird")); EXPECT_TRUE(Path::IsRelative(u8"~.weird")); EXPECT_TRUE(Path::IsRelative(u8"~/weird")); EXPECT_TRUE(Path::IsRelative(u8"~")); #else EXPECT_TRUE(Path::IsRelative(u8"\\")); EXPECT_TRUE(Path::IsRelative(u8"\\games")); EXPECT_TRUE(Path::IsRelative(u8"\\\\Server")); EXPECT_TRUE(Path::IsRelative(u8"C:\\")); EXPECT_TRUE(Path::IsRelative(u8"C:")); EXPECT_TRUE(Path::IsRelative(u8"~weird")); EXPECT_TRUE(Path::IsRelative(u8"~.weird")); EXPECT_FALSE(Path::IsRelative(u8"~/weird")); EXPECT_FALSE(Path::IsRelative(u8"~")); #endif EXPECT_FALSE(Path::IsRelative(u8"/")); EXPECT_FALSE(Path::IsRelative(u8"/games")); EXPECT_TRUE(Path::IsRelative(u8"home")); EXPECT_TRUE(Path::IsRelative(u8"file:")); // malformed EXPECT_TRUE(Path::IsRelative(u8"file:/")); // malformed EXPECT_TRUE(Path::IsRelative(u8"file://")); // empty EXPECT_FALSE(Path::IsRelative(u8"file:///")); EXPECT_FALSE(Path::IsRelative(u8"file://C:/")); EXPECT_FALSE(Path::IsRelative(u8"https://www.example.com")); EXPECT_TRUE(Path::IsRelative(u8":///test")); // missing scheme } // ------------------------------------------------------------------------------------------- // TEST(PathTest, StemOfPathCanBeDetermined) { EXPECT_EQ(Path::GetStem(u8"some-directory"), std::string()); EXPECT_EQ(Path::GetStem(u8"/absolute/path"), std::string(u8"/")); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_EQ(Path::GetStem(u8"\\windows\\absolute"), std::string(u8"\\")); EXPECT_EQ(Path::GetStem(u8"C:\\games"), std::string(u8"C:\\")); EXPECT_EQ(Path::GetStem(u8"C:games"), std::string(u8"C:")); #else EXPECT_EQ(Path::GetStem(u8"\\windows\\absolute"), std::string()); // Backslashes and EXPECT_EQ(Path::GetStem(u8"C:\\games"), std::string()); // drive letters are meaningless EXPECT_EQ(Path::GetStem(u8"C:games"), std::string()); // if the system is not Windows #endif EXPECT_EQ(Path::GetStem(u8"file:///my-file.txt"), std::string(u8"file:///")); EXPECT_EQ(Path::GetStem(u8"file://my-file.txt"), std::string(u8"file://")); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, FilenameExtractionHandlesEmptyStrings) { EXPECT_EQ(Path::GetFilename(std::string()), std::string()); EXPECT_EQ(Path::GetFilename(std::string(), false), std::string()); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, FilenameCanBeExtractedFromPath) { EXPECT_EQ(Path::GetFilename(u8"my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8".file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"~file"), std::string(u8"~file")); EXPECT_EQ(Path::GetFilename(u8"~.file"), std::string(u8"~.file")); EXPECT_EQ(Path::GetFilename(u8".~file"), std::string(u8".~file")); EXPECT_EQ(Path::GetFilename(u8"my-directory/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"my-directory.txt/"), std::string()); EXPECT_EQ(Path::GetFilename(u8".directory/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"my-directory/my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"my-directory/my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"my-directory/.file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"file://my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"file:///my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"file://my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"file:///my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"file://.file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"file:///.file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"file://my-dir/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"file:///my-dir/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"file://my-dir.txt/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"file:///my-dir.txt/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"file://.dir/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"file:///.dir/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"file://my-dir/my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"file:///my-dir/my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"file://my-dir/my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"file:///my-dir/my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"file://my-dir/.file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"file:///my-dir/.file"), std::string(u8".file")); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, FilenameCanBeExtractedFromPlatformDependentPath) { EXPECT_EQ(Path::GetFilename(u8"C:my-directory/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"C:my-directory.txt/"), std::string()); EXPECT_EQ(Path::GetFilename(u8"C:.directory/"), std::string()); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_EQ(Path::GetFilename(u8"C:my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"C:my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"C:.file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"C:\\.file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"C:my-directory\\my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"C:my-directory\\my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"C:my-directory\\.file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-directory\\my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-directory\\my-file.txt"), std::string(u8"my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-directory\\.file"), std::string(u8".file")); EXPECT_EQ(Path::GetFilename(u8"C:my-directory\\"), std::string()); EXPECT_EQ(Path::GetFilename(u8"C:my-directory.txt\\"), std::string()); EXPECT_EQ(Path::GetFilename(u8"C:.directory\\"), std::string()); EXPECT_EQ(Path::GetFilename(u8"C:\\my-directory\\"), std::string()); EXPECT_EQ(Path::GetFilename(u8"C:\\my-directory.txt\\"), std::string()); EXPECT_EQ(Path::GetFilename(u8"C:\\.directory\\"), std::string()); EXPECT_EQ(Path::GetFilename(u8"~my-file"), std::string(u8"~my-file")); EXPECT_EQ(Path::GetFilename(u8"~/my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"~\\my-file"), std::string(u8"my-file")); #else EXPECT_EQ(Path::GetFilename(u8"C:my-file"), std::string(u8"C:my-file")); EXPECT_EQ(Path::GetFilename(u8"C:my-file.txt"), std::string(u8"C:my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"C:.file"), std::string(u8"C:.file")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-file"), std::string(u8"C:\\my-file")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-file.txt"), std::string(u8"C:\\my-file.txt")); EXPECT_EQ(Path::GetFilename(u8"C:\\.file"), std::string(u8"C:\\.file")); EXPECT_EQ(Path::GetFilename(u8"C:my-dir\\my-file"), std::string(u8"C:my-dir\\my-file")); EXPECT_EQ(Path::GetFilename(u8"C:my-dir\\file.txt"), std::string(u8"C:my-dir\\file.txt")); EXPECT_EQ(Path::GetFilename(u8"C:my-dir\\.file"), std::string(u8"C:my-dir\\.file")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-dir\\my-file"), std::string(u8"C:\\my-dir\\my-file")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-dir\\file.txt"), std::string(u8"C:\\my-dir\\file.txt")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-dir\\.file"), std::string(u8"C:\\my-dir\\.file")); EXPECT_EQ(Path::GetFilename(u8"C:my-directory\\"), std::string(u8"C:my-directory\\")); EXPECT_EQ(Path::GetFilename(u8"C:my-directory.txt\\"), std::string(u8"C:my-directory.txt\\")); EXPECT_EQ(Path::GetFilename(u8"C:.directory\\"), std::string(u8"C:.directory\\")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-directory\\"), std::string(u8"C:\\my-directory\\")); EXPECT_EQ(Path::GetFilename(u8"C:\\my-dir.txt\\"), std::string(u8"C:\\my-dir.txt\\")); EXPECT_EQ(Path::GetFilename(u8"C:\\.directory\\"), std::string(u8"C:\\.directory\\")); EXPECT_EQ(Path::GetFilename(u8"~my-file"), std::string(u8"~my-file")); EXPECT_EQ(Path::GetFilename(u8"~/my-file"), std::string(u8"my-file")); EXPECT_EQ(Path::GetFilename(u8"~\\my-file"), std::string(u8"~\\my-file")); #endif } // ------------------------------------------------------------------------------------------- // TEST(PathTest, FilenameCanBeExtractedWithoutExtension) { EXPECT_EQ(Path::GetFilename(u8"hello.txt", false), std::string(u8"hello")); EXPECT_EQ(Path::GetFilename(u8"hello", false), std::string(u8"hello")); EXPECT_EQ(Path::GetFilename(u8".hello", false), std::string(u8".hello")); EXPECT_EQ(Path::GetFilename(u8"~hello", false), std::string(u8"~hello")); EXPECT_EQ(Path::GetFilename(u8"~.hello", false), std::string(u8"~")); EXPECT_EQ(Path::GetFilename(u8".~hello", false), std::string(u8".~hello")); EXPECT_EQ(Path::GetFilename(u8"file:///.hello/world.txt", false), std::string(u8"world")); EXPECT_EQ(Path::GetFilename(u8"file:///.hello/world", false), std::string(u8"world")); EXPECT_EQ(Path::GetFilename(u8"file:///hello/.world", false), std::string(u8".world")); EXPECT_EQ(Path::GetFilename(u8"file:///hello.txt/world", false), std::string(u8"world")); EXPECT_EQ(Path::GetFilename(u8"hello.tar.gz", false), std::string(u8"hello")); EXPECT_EQ(Path::GetFilename(u8".hello.tar.gz", false), std::string(u8".hello")); // Let's get looney EXPECT_EQ(Path::GetFilename(u8"/.config/.tar.gz", false), std::string(u8".tar")); EXPECT_EQ(Path::GetFilename(std::string(), false), std::string()); EXPECT_EQ(Path::GetFilename(u8"/", false), std::string()); EXPECT_EQ(Path::GetFilename(u8".", false), std::string(u8".")); EXPECT_EQ(Path::GetFilename(u8"./", false), std::string()); EXPECT_EQ(Path::GetFilename(u8"/.", false), std::string(u8".")); EXPECT_EQ(Path::GetFilename(u8"/a.", false), std::string(u8"a")); EXPECT_EQ(Path::GetFilename(u8"/.b", false), std::string(u8".b")); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, ExtensionCanBeExtracted) { EXPECT_EQ(Path::GetExtension(u8"hello.txt"), std::string(u8"txt")); EXPECT_EQ(Path::GetExtension(u8"hello"), std::string()); EXPECT_EQ(Path::GetExtension(u8".hello"), std::string()); EXPECT_EQ(Path::GetExtension(u8"~hello"), std::string()); EXPECT_EQ(Path::GetExtension(u8"~.hello"), std::string(u8"hello")); EXPECT_EQ(Path::GetExtension(u8".~hello"), std::string()); EXPECT_EQ(Path::GetExtension(u8"file:///.hello/world.txt"), std::string(u8"txt")); EXPECT_EQ(Path::GetExtension(u8"file:///.hello/world"), std::string()); EXPECT_EQ(Path::GetExtension(u8"file:///hello/.world"), std::string()); EXPECT_EQ(Path::GetExtension(u8"file:///hello.txt/world"), std::string()); EXPECT_EQ(Path::GetExtension(u8"hello.tar.gz"), std::string(u8"tar.gz")); EXPECT_EQ(Path::GetExtension(u8".hello.tar.gz"), std::string(u8"tar.gz")); // Let's get looney EXPECT_EQ(Path::GetExtension(u8"/.config/.tar.gz"), std::string(u8"gz")); EXPECT_EQ(Path::GetExtension(std::string()), std::string()); EXPECT_EQ(Path::GetExtension(u8"/"), std::string()); EXPECT_EQ(Path::GetExtension(u8"."), std::string()); EXPECT_EQ(Path::GetExtension(u8"./"), std::string()); EXPECT_EQ(Path::GetExtension(u8"/."), std::string()); EXPECT_EQ(Path::GetExtension(u8"/a."), std::string()); EXPECT_EQ(Path::GetExtension(u8"/.b"), std::string()); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, PathsCanBeNormalized) { EXPECT_EQ( Path::Normalize(std::string(u8"file:///path/that/is/not/../normalized/.")), std::string(u8"file:///path/that/is/normalized") ); EXPECT_EQ( Path::Normalize(std::string(u8"file:///path/with//redundant///slashes////")), std::string(u8"file:///path/with/redundant/slashes") ); EXPECT_EQ( Path::Normalize(std::string(u8"file:///../path/../../nope")), std::string(u8"file:///../../nope") ); EXPECT_EQ( Path::Normalize(std::string(u8"test/../../")), std::string(u8"..") ); EXPECT_EQ( Path::Normalize(std::string(u8".")), std::string(u8"") ); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_EQ( Path::Normalize(std::string(u8"\\")), std::string(u8"\\") ); #else EXPECT_EQ( Path::Normalize(std::string(u8"/")), std::string(u8"/") ); #endif } // ------------------------------------------------------------------------------------------- // TEST(PathTest, PathNormalizationHandlesEmptyStrings) { EXPECT_EQ(Path::Normalize(std::string()), std::string()); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, RealPathCanBeResolved) { std::string realPath = Path::Resolve(u8"."); EXPECT_GE(realPath.length(), 1); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, JoinHandlesEmptyPaths) { std::string result = Path::Join(u8"hello", std::string()); EXPECT_EQ(result, u8"hello"); result = Path::Join(std::string(), u8"world"); EXPECT_EQ(result, u8"world"); result = Path::Join(std::string(), std::string()); EXPECT_EQ(result, std::string()); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, TwoPathsCanBeJoined) { std::string result = Path::Join(u8"hello", u8"world"); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_EQ(result, u8"hello\\world"); #else EXPECT_EQ(result, u8"hello/world"); #endif } // ------------------------------------------------------------------------------------------- // #if 0 TEST(PathTest, MoreThanTwoPathsCanBeJoined) { std::string result = Path::Join(u8"hello", u8"world", u8"this", u8"is", u8"a", u8"test"); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_EQ(result, u8"hello\\world\\this\\is\\a\\test"); #else EXPECT_EQ(result, u8"hello/world/this/is/a/test"); #endif } #endif // ------------------------------------------------------------------------------------------- // TEST(PathTest, CombiningEmptyPathWithOtherYieldsOther) { #if defined(NUCLEX_STORAGE_WIN32) std::string other(u8"my\\directory"); #else std::string other(u8"my/directory"); #endif std::string result = Path::Combine(std::string(), other); EXPECT_EQ(result, other); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, CombiningBasePathWithEmptyYieldsBase) { #if defined(NUCLEX_STORAGE_WIN32) std::string base(u8"my\\directory"); #else std::string base(u8"my/directory"); #endif std::string result = Path::Combine(base, std::string()); EXPECT_EQ(result, base); } // ------------------------------------------------------------------------------------------- // TEST(PathTest, CombinedPathsCanHaveTrailingSlashes) { #if defined(NUCLEX_STORAGE_WIN32) std::string base(u8"my\\directory\\"); std::string other(u8"other\\directory\\"); #else std::string base(u8"my/directory/"); std::string other(u8"other/directory/"); #endif std::string result = Path::Combine(base, other); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_EQ(result, u8"my\\directory\\other\\directory"); #else EXPECT_EQ(result, u8"my/directory/other/directory"); #endif } // ------------------------------------------------------------------------------------------- // TEST(PathTest, SimplePathsCanBeCombined) { #if defined(NUCLEX_STORAGE_WIN32) std::string base(u8"my\\directory"); std::string other(u8"other\\directory"); #else std::string base(u8"my/directory"); std::string other(u8"other/directory"); #endif std::string result = Path::Combine(base, other); #if defined(NUCLEX_STORAGE_WIN32) EXPECT_EQ(result, u8"my\\directory\\other\\directory"); #else EXPECT_EQ(result, u8"my/directory/other/directory"); #endif } // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Storage::FileSystem