| | |
| |
|
| | #include <gtest/gtest.h> |
| | #include <App/ApplicationDirectories.h> |
| |
|
| | #include <random> |
| | #include <fstream> |
| | #include "Base/Exception.h" |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | namespace fs = std::filesystem; |
| |
|
| | static fs::path MakeUniqueTempDir() |
| | { |
| | constexpr int maxTries = 128; |
| | const fs::path base = fs::temp_directory_path(); |
| | std::random_device rd; |
| | std::mt19937_64 gen(rd()); |
| | std::uniform_int_distribution<unsigned long long> dist; |
| |
|
| | for (int i = 0; i < maxTries; ++i) { |
| | auto name = "app_directories_test-" + std::to_string(dist(gen)); |
| | fs::path candidate = base / name; |
| | std::error_code ec; |
| | if (fs::create_directory(candidate, ec)) { |
| | return candidate; |
| | } |
| | if (ec && ec != std::make_error_code(std::errc::file_exists)) { |
| | continue; |
| | } |
| | } |
| | throw std::runtime_error("Failed to create unique temp directory"); |
| | } |
| |
|
| | |
| | class ApplicationDirectoriesTestClass: public App::ApplicationDirectories |
| | { |
| | using App::ApplicationDirectories::ApplicationDirectories; |
| |
|
| | public: |
| | void wrapAppendVersionIfPossible(const fs::path& basePath, std::vector<std::string>& subdirs) const |
| | { |
| | appendVersionIfPossible(basePath, subdirs); |
| | } |
| |
|
| | std::tuple<int, int> wrapExtractVersionFromConfigMap( |
| | const std::map<std::string, std::string>& config |
| | ) |
| | { |
| | return extractVersionFromConfigMap(config); |
| | } |
| |
|
| | static std::filesystem::path wrapSanitizePath(const std::string& pathAsString) |
| | { |
| | return sanitizePath(pathAsString); |
| | } |
| | }; |
| |
|
| | class ApplicationDirectoriesTest: public ::testing::Test |
| | { |
| | protected: |
| | void SetUp() override |
| | { |
| | _tempDir = MakeUniqueTempDir(); |
| | } |
| |
|
| | std::map<std::string, std::string> generateConfig( |
| | const std::map<std::string, std::string>& overrides |
| | ) const |
| | { |
| | std::map<std::string, std::string> config { |
| | {"AppHomePath", _tempDir.string()}, |
| | {"ExeVendor", "Vendor"}, |
| | {"ExeName", "Test"}, |
| | {"BuildVersionMajor", "4"}, |
| | {"BuildVersionMinor", "2"} |
| | }; |
| | for (const auto& override : overrides) { |
| | config[override.first] = override.second; |
| | } |
| | return config; |
| | } |
| |
|
| | std::unique_ptr<ApplicationDirectoriesTestClass> makeAppDirsForVersion(int major, int minor) |
| | { |
| | auto configuration = generateConfig( |
| | {{"BuildVersionMajor", std::to_string(major)}, |
| | {"BuildVersionMinor", std::to_string(minor)}} |
| | ); |
| | return std::make_unique<ApplicationDirectoriesTestClass>(configuration); |
| | } |
| |
|
| | fs::path makePathForVersion(const fs::path& base, int major, int minor) |
| | { |
| | return base / App::ApplicationDirectories::versionStringForPath(major, minor); |
| | } |
| |
|
| | void TearDown() override |
| | { |
| | fs::remove_all(_tempDir); |
| | } |
| |
|
| | fs::path tempDir() |
| | { |
| | return _tempDir; |
| | } |
| |
|
| | private: |
| | fs::path _tempDir; |
| | }; |
| |
|
| | namespace fs = std::filesystem; |
| |
|
| |
|
| | TEST_F(ApplicationDirectoriesTest, usingCurrentVersionConfigTrueWhenDirMatchesVersion) |
| | { |
| | |
| | constexpr int major = 3; |
| | constexpr int minor = 7; |
| | const fs::path testPath = fs::path("some_kind_of_config") |
| | / App::ApplicationDirectories::versionStringForPath(major, minor); |
| |
|
| | |
| | auto appDirs = makeAppDirsForVersion(major, minor); |
| |
|
| | |
| | EXPECT_TRUE(appDirs->usingCurrentVersionConfig(testPath)); |
| | } |
| |
|
| | TEST_F(ApplicationDirectoriesTest, usingCurrentVersionConfigFalseWhenDirDoesntMatchVersion) |
| | { |
| | |
| | constexpr int major = 3; |
| | constexpr int minor = 7; |
| | const fs::path testPath = fs::path("some_kind_of_config") |
| | / App::ApplicationDirectories::versionStringForPath(major, minor); |
| |
|
| | |
| | auto configuration = generateConfig( |
| | {{"BuildVersionMajor", std::to_string(major + 1)}, |
| | {"BuildVersionMinor", std::to_string(minor)}} |
| | ); |
| | auto appDirs = std::make_unique<App::ApplicationDirectories>(configuration); |
| |
|
| | |
| | EXPECT_FALSE(appDirs->usingCurrentVersionConfig(testPath)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, isVersionedPathMatchesCurrentMajorAndMinor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::path p = makePathForVersion(tempDir(), 5, 4); |
| | EXPECT_TRUE(appDirs->isVersionedPath(p)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, isVersionedPathMatchesLowerMinorSameMajor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::path p = makePathForVersion(tempDir(), 5, 2); |
| | EXPECT_TRUE(appDirs->isVersionedPath(p)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, isVersionedPathMatchesLowerMajorAnyMinor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::path p = makePathForVersion(tempDir(), 4, 7); |
| | EXPECT_TRUE(appDirs->isVersionedPath(p)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, isVersionedPathMatchesZeroMinorSameMajor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::path p = makePathForVersion(tempDir(), 5, 0); |
| | EXPECT_TRUE(appDirs->isVersionedPath(p)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, isVersionedPathDoesNotMatchHigherMinorSameMajor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::path p = makePathForVersion(tempDir(), 5, 5); |
| | EXPECT_FALSE(appDirs->isVersionedPath(p)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, isVersionedPathDoesNotMatchHigherMajorOrRandomName) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path higherMajor = makePathForVersion(tempDir(), 6, 1); |
| | EXPECT_FALSE(appDirs->isVersionedPath(higherMajor)); |
| |
|
| | fs::path randomName = tempDir() / "not-a-version"; |
| | EXPECT_FALSE(appDirs->isVersionedPath(randomName)); |
| | } |
| |
|
| | |
| | fs::path versionedPath(const fs::path& base, int major, int minor) |
| | { |
| | return base / App::ApplicationDirectories::versionStringForPath(major, minor); |
| | } |
| |
|
| | |
| | void touchFile(const fs::path& p) |
| | { |
| | fs::create_directories(p.parent_path()); |
| | std::ofstream ofs(p.string()); |
| | ofs << "x"; |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentAvailReturnsExactCurrentVersionIfDirectoryExists) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 5, 4)); |
| |
|
| | EXPECT_EQ( |
| | appDirs->mostRecentAvailableConfigVersion(tempDir()), |
| | App::ApplicationDirectories::versionStringForPath(5, 4) |
| | ); |
| | } |
| |
|
| | |
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentAvailPrefersSameMajorAndPicksHighestLowerMinor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 5, 1)); |
| | fs::create_directories(versionedPath(tempDir(), 5, 3)); |
| | fs::create_directories(versionedPath(tempDir(), 4, 99)); |
| |
|
| | EXPECT_EQ( |
| | appDirs->mostRecentAvailableConfigVersion(tempDir()), |
| | App::ApplicationDirectories::versionStringForPath(5, 3) |
| | ); |
| | } |
| |
|
| | |
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentAvailForLowerMajorPicksHighestAvailableMinor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 4, 3)); |
| | fs::create_directories(versionedPath(tempDir(), 4, 42)); |
| |
|
| | EXPECT_EQ( |
| | appDirs->mostRecentAvailableConfigVersion(tempDir()), |
| | App::ApplicationDirectories::versionStringForPath(4, 42) |
| | ); |
| | } |
| |
|
| | |
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentAvailSkipsFilesAndFallsBackToNextDirectory) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | touchFile(versionedPath(tempDir(), 5, 4)); |
| | fs::create_directories(versionedPath(tempDir(), 5, 3)); |
| |
|
| | EXPECT_EQ( |
| | appDirs->mostRecentAvailableConfigVersion(tempDir()), |
| | App::ApplicationDirectories::versionStringForPath(5, 3) |
| | ); |
| | } |
| |
|
| | |
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentAvailIgnoresHigherMinorThanCurrentInSameMajor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 5, 7)); |
| | fs::create_directories(versionedPath(tempDir(), 4, 1)); |
| |
|
| | EXPECT_EQ( |
| | appDirs->mostRecentAvailableConfigVersion(tempDir()), |
| | App::ApplicationDirectories::versionStringForPath(4, 1) |
| | ); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentAvailReturnsEmptyStringWhenNoVersionsPresent) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | EXPECT_EQ(appDirs->mostRecentAvailableConfigVersion(tempDir()), ""); |
| | } |
| |
|
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentConfigReturnsCurrentVersionDirectoryIfPresent) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 5, 4)); |
| |
|
| | fs::path got = appDirs->mostRecentConfigFromBase(tempDir()); |
| | EXPECT_EQ(got, versionedPath(tempDir(), 5, 4)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentConfigFallsBackToMostRecentInSameMajorWhenCurrentMissing) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | |
| | |
| | fs::create_directories(versionedPath(tempDir(), 5, 1)); |
| | fs::create_directories(versionedPath(tempDir(), 5, 3)); |
| | fs::create_directories(versionedPath(tempDir(), 4, 99)); |
| |
|
| | fs::path got = appDirs->mostRecentConfigFromBase(tempDir()); |
| | EXPECT_EQ(got, versionedPath(tempDir(), 5, 3)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentConfigSkipsFileAtCurrentVersionAndFallsBack) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | touchFile(versionedPath(tempDir(), 5, 4)); |
| | fs::create_directories(versionedPath(tempDir(), 5, 2)); |
| |
|
| | fs::path got = appDirs->mostRecentConfigFromBase(tempDir()); |
| | EXPECT_EQ(got, versionedPath(tempDir(), 5, 2)); |
| | } |
| |
|
| | |
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentConfigFallsBackToHighestVersionInLowerMajors) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | |
| | fs::create_directories(versionedPath(tempDir(), 5, 7)); |
| |
|
| | |
| | fs::create_directories(versionedPath(tempDir(), 4, 3)); |
| | fs::create_directories(versionedPath(tempDir(), 4, 90)); |
| | fs::create_directories(versionedPath(tempDir(), 3, 99)); |
| |
|
| | fs::path got = appDirs->mostRecentConfigFromBase(tempDir()); |
| | EXPECT_EQ(got, versionedPath(tempDir(), 4, 90)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, mostRecentConfigReturnsStartingPathWhenNoVersionedConfigExists) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::path got = appDirs->mostRecentConfigFromBase(tempDir()); |
| | EXPECT_EQ(got, tempDir()); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, usingCurrentVersionExactVersionDir) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 5, 4)); |
| |
|
| | EXPECT_TRUE(appDirs->usingCurrentVersionConfig(versionedPath(tempDir(), 5, 4))); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, usingCurrentVersionVersionDirWithTrailingSlash) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 5, 4)); |
| | fs::path p = versionedPath(tempDir(), 5, 4) / ""; |
| |
|
| | EXPECT_TRUE(appDirs->usingCurrentVersionConfig(p)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, usingCurrentVersionFileInsideVersionDirIsFalse) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::path filePath = versionedPath(tempDir(), 5, 4) / "config.yaml"; |
| | touchFile(filePath); |
| |
|
| | EXPECT_FALSE(appDirs->usingCurrentVersionConfig(filePath)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, usingCurrentVersionLowerVersionDirIsFalse) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 5, 3)); |
| |
|
| | EXPECT_FALSE(appDirs->usingCurrentVersionConfig(versionedPath(tempDir(), 5, 3))); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, usingCurrentVersionHigherVersionDirIsFalse) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(versionedPath(tempDir(), 6, 0)); |
| |
|
| | EXPECT_FALSE(appDirs->usingCurrentVersionConfig(versionedPath(tempDir(), 6, 0))); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, usingCurrentVersionNonVersionDirIsFalse) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | fs::create_directories(tempDir()); |
| |
|
| | EXPECT_FALSE(appDirs->usingCurrentVersionConfig(tempDir())); |
| | } |
| |
|
| | void writeFile(const fs::path& p, std::string_view contents) |
| | { |
| | fs::create_directories(p.parent_path()); |
| | std::ofstream ofs(p.string(), std::ios::binary); |
| | ofs << contents; |
| | } |
| |
|
| | std::string readFile(const fs::path& p) |
| | { |
| | std::ifstream ifs(p.string(), std::ios::binary); |
| | return {std::istreambuf_iterator<char>(ifs), {}}; |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateConfigCreatesDestinationAndCopiesFiles) |
| | { |
| | |
| | fs::path oldPath = tempDir() / "old"; |
| | fs::path newPath = tempDir() / "new"; |
| | writeFile(oldPath / "a.txt", "alpha"); |
| | writeFile(oldPath / "b.ini", "bravo"); |
| |
|
| | |
| | App::ApplicationDirectories::migrateConfig(oldPath, newPath); |
| |
|
| | |
| | ASSERT_TRUE(fs::exists(newPath)); |
| | ASSERT_TRUE(fs::is_directory(newPath)); |
| |
|
| | EXPECT_TRUE(fs::exists(newPath / "a.txt")); |
| | EXPECT_TRUE(fs::exists(newPath / "b.ini")); |
| | EXPECT_EQ(readFile(newPath / "a.txt"), "alpha"); |
| | EXPECT_EQ(readFile(newPath / "b.ini"), "bravo"); |
| |
|
| | EXPECT_TRUE(fs::exists(oldPath / "a.txt")); |
| | EXPECT_TRUE(fs::exists(oldPath / "b.ini")); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateConfigSkipsSelfWhenNewIsSubdirectoryOfOld) |
| | { |
| | |
| | fs::path oldPath = tempDir() / "container"; |
| | fs::path newPath = oldPath / "migrated"; |
| | writeFile(oldPath / "c.yaml", "charlie"); |
| | writeFile(oldPath / "d.cfg", "delta"); |
| |
|
| | |
| | App::ApplicationDirectories::migrateConfig(oldPath, newPath); |
| |
|
| | |
| | ASSERT_TRUE(fs::exists(newPath)); |
| | ASSERT_TRUE(fs::is_directory(newPath)); |
| | EXPECT_TRUE(fs::exists(newPath / "c.yaml")); |
| | EXPECT_TRUE(fs::exists(newPath / "d.cfg")); |
| |
|
| | |
| | EXPECT_FALSE(fs::exists(newPath / newPath.filename())); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateConfigEmptyOldPathJustCreatesDestination) |
| | { |
| | fs::path oldPath = tempDir() / "empty_old"; |
| | fs::path newPath = tempDir() / "dest_only"; |
| |
|
| | fs::create_directories(oldPath); |
| | App::ApplicationDirectories::migrateConfig(oldPath, newPath); |
| |
|
| | ASSERT_TRUE(fs::exists(newPath)); |
| | ASSERT_TRUE(fs::is_directory(newPath)); |
| |
|
| | |
| | bool hasEntries = (fs::directory_iterator(newPath) != fs::directory_iterator {}); |
| | EXPECT_FALSE(hasEntries); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateConfigRecursivelyCopiesDirectoriesAndFiles) |
| | { |
| | fs::path oldPath = tempDir() / "old_tree"; |
| | fs::path newPath = tempDir() / "new_tree"; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | writeFile(oldPath / "config" / "env" / "a.txt", "alpha"); |
| | fs::create_directories(oldPath / "empty_dir"); |
| |
|
| | App::ApplicationDirectories::migrateConfig(oldPath, newPath); |
| |
|
| | |
| | ASSERT_TRUE(fs::exists(newPath)); |
| | EXPECT_TRUE(fs::exists(newPath / "config")); |
| | EXPECT_TRUE(fs::exists(newPath / "config" / "env")); |
| | EXPECT_TRUE(fs::exists(newPath / "config" / "env" / "a.txt")); |
| | EXPECT_EQ(readFile(newPath / "config" / "env" / "a.txt"), "alpha"); |
| |
|
| | |
| | EXPECT_TRUE(fs::exists(newPath / "empty_dir")); |
| | EXPECT_TRUE(fs::is_directory(newPath / "empty_dir")); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateConfigNewPathSubdirRecursivelyCopiesAndSkipsSelf) |
| | { |
| | fs::path oldPath = tempDir() / "src_tree"; |
| | fs::path newPath = oldPath / "migrated"; |
| |
|
| | |
| | |
| | |
| | |
| | writeFile(oldPath / "folderA" / "child" / "f.txt", "filedata"); |
| |
|
| | App::ApplicationDirectories::migrateConfig(oldPath, newPath); |
| |
|
| | |
| | EXPECT_TRUE(fs::exists(newPath / "folderA" / "child" / "f.txt")); |
| | EXPECT_EQ(readFile(newPath / "folderA" / "child" / "f.txt"), "filedata"); |
| |
|
| | |
| | EXPECT_FALSE(fs::exists(newPath / newPath.filename())); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateAllPathsVersionedInputChoosesParentPlusCurrent) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "v_branch"; |
| | fs::path older = versionedPath(base, 5, 1); |
| | fs::create_directories(older); |
| | writeFile(older / "sentinel.txt", "s"); |
| |
|
| | std::vector<fs::path> inputs {older}; |
| | appDirs->migrateAllPaths(inputs); |
| |
|
| | fs::path expectedDest = versionedPath(base, 5, 4); |
| | EXPECT_TRUE(fs::exists(expectedDest)); |
| | EXPECT_TRUE(fs::is_directory(expectedDest)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateAllPathsNonVersionedInputAppendsCurrent) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "plain_base"; |
| | fs::create_directories(base); |
| | writeFile(base / "config.yaml", "x"); |
| |
|
| | std::vector<fs::path> inputs {base}; |
| | appDirs->migrateAllPaths(inputs); |
| |
|
| | fs::path expectedDest = versionedPath(base, 5, 4); |
| | EXPECT_TRUE(fs::exists(expectedDest)); |
| | EXPECT_TRUE(fs::is_directory(expectedDest)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateAllPathsIgnoresIfDestinationAlreadyExists_NonVersioned) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "exists_case"; |
| | fs::create_directories(base); |
| | fs::path dest = versionedPath(base, 5, 4); |
| | fs::create_directories(dest); |
| |
|
| | std::vector<fs::path> inputs {base}; |
| |
|
| | ASSERT_NO_THROW(appDirs->migrateAllPaths(inputs)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, migrateAllPathsProcessesMultipleInputs) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | |
| | fs::path baseA = tempDir() / "multiA"; |
| | fs::path olderA = versionedPath(baseA, 5, 2); |
| | fs::create_directories(olderA); |
| | writeFile(olderA / "a.txt", "a"); |
| |
|
| | |
| | fs::path baseB = tempDir() / "multiB"; |
| | fs::create_directories(baseB); |
| | writeFile(baseB / "b.txt", "b"); |
| |
|
| | std::vector<fs::path> inputs {olderA, baseB}; |
| | appDirs->migrateAllPaths(inputs); |
| |
|
| | EXPECT_TRUE(fs::exists(versionedPath(baseA, 5, 4))); |
| | EXPECT_TRUE(fs::exists(versionedPath(baseB, 5, 4))); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, appendVecAlreadyVersionedBails) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "bail_vec"; |
| | std::vector<std::string> sub { |
| | "configs", |
| | App::ApplicationDirectories::versionStringForPath(5, 2) |
| | }; |
| | fs::create_directories(base / sub[0] / sub[1]); |
| |
|
| | auto before = sub; |
| | appDirs->wrapAppendVersionIfPossible(base, sub); |
| | EXPECT_EQ(sub, before); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, appendVecBaseExistsAppendsCurrentWhenPresent) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "vec_current"; |
| | std::vector<std::string> sub {"configs"}; |
| | fs::create_directories(base / "configs"); |
| | fs::create_directories(versionedPath(base / "configs", 5, 4)); |
| |
|
| | appDirs->wrapAppendVersionIfPossible(base, sub); |
| |
|
| | ASSERT_EQ(sub.size(), 2u); |
| | EXPECT_EQ(sub.back(), App::ApplicationDirectories::versionStringForPath(5, 4)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, appendVecPicksHighestLowerMinorInSameMajor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "vec_lower_minor"; |
| | std::vector<std::string> sub {"configs"}; |
| | fs::create_directories(versionedPath(base / "configs", 5, 1)); |
| | fs::create_directories(versionedPath(base / "configs", 5, 3)); |
| | |
| | fs::create_directories(versionedPath(base / "configs", 4, 99)); |
| |
|
| | appDirs->wrapAppendVersionIfPossible(base, sub); |
| |
|
| | ASSERT_EQ(sub.size(), 2u); |
| | EXPECT_EQ(sub.back(), App::ApplicationDirectories::versionStringForPath(5, 3)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, appendVecFallsBackToLowerMajor) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "vec_lower_major"; |
| | std::vector<std::string> sub {"configs"}; |
| | fs::create_directories(versionedPath(base / "configs", 4, 90)); |
| | fs::create_directories(versionedPath(base / "configs", 3, 99)); |
| |
|
| | appDirs->wrapAppendVersionIfPossible(base, sub); |
| |
|
| | ASSERT_EQ(sub.size(), 2u); |
| | EXPECT_EQ(sub.back(), App::ApplicationDirectories::versionStringForPath(4, 90)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, appendVecNoVersionedChildrenLeavesVectorUnchanged) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "vec_noversions"; |
| | std::vector<std::string> sub {"configs"}; |
| | fs::create_directories(base / "configs"); |
| |
|
| | auto before = sub; |
| | appDirs->wrapAppendVersionIfPossible(base, sub); |
| | EXPECT_EQ(sub, before); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, appendVecBaseMissingAppendsCurrentSuffix) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| |
|
| | fs::path base = tempDir() / "vec_missing"; |
| | std::vector<std::string> sub {"configs"}; |
| |
|
| | appDirs->wrapAppendVersionIfPossible(base, sub); |
| |
|
| | ASSERT_EQ(sub.size(), 2u); |
| | EXPECT_EQ(sub.back(), App::ApplicationDirectories::versionStringForPath(5, 4)); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, extractVersionSucceedsWithPlainIntegers) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | std::map<std::string, std::string> m {{"BuildVersionMajor", "7"}, {"BuildVersionMinor", "2"}}; |
| | auto [maj, min] = appDirs->wrapExtractVersionFromConfigMap(m); |
| | EXPECT_EQ(maj, 7); |
| | EXPECT_EQ(min, 2); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, extractVersionSucceedsWithWhitespace) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | std::map<std::string, std::string> m { |
| | {"BuildVersionMajor", " 10 "}, |
| | {"BuildVersionMinor", "\t3\n"} |
| | }; |
| | auto [maj, min] = appDirs->wrapExtractVersionFromConfigMap(m); |
| | EXPECT_EQ(maj, 10); |
| | EXPECT_EQ(min, 3); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, extractVersionMissingMajorThrowsRuntimeError) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | std::map<std::string, std::string> m {{"BuildVersionMinor", "1"}}; |
| | EXPECT_THROW(appDirs->wrapExtractVersionFromConfigMap(m), Base::RuntimeError); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, extractVersionMissingMinorThrowsRuntimeError) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | std::map<std::string, std::string> m {{"BuildVersionMajor", "1"}}; |
| | EXPECT_THROW(appDirs->wrapExtractVersionFromConfigMap(m), Base::RuntimeError); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, extractVersionNonNumericThrowsRuntimeError) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | std::map<std::string, std::string> m {{"BuildVersionMajor", "abc"}, {"BuildVersionMinor", "2"}}; |
| | EXPECT_THROW(appDirs->wrapExtractVersionFromConfigMap(m), Base::RuntimeError); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, extractVersionOverflowThrowsRuntimeError) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | std::map<std::string, std::string> m { |
| | {"BuildVersionMajor", "9999999999999999999999999"}, |
| | {"BuildVersionMinor", "1"} |
| | }; |
| | EXPECT_THROW(appDirs->wrapExtractVersionFromConfigMap(m), Base::RuntimeError); |
| | } |
| |
|
| | |
| | TEST_F(ApplicationDirectoriesTest, extractVersionNegativeNumbersPassThrough) |
| | { |
| | auto appDirs = makeAppDirsForVersion(5, 4); |
| | std::map<std::string, std::string> m {{"BuildVersionMajor", "-2"}, {"BuildVersionMinor", "-7"}}; |
| | auto [maj, min] = appDirs->wrapExtractVersionFromConfigMap(m); |
| | EXPECT_EQ(maj, -2); |
| | EXPECT_EQ(min, -7); |
| | } |
| |
|
| |
|
| | TEST_F(ApplicationDirectoriesTest, sanitizeRemovesNullCharacterAtEnd) |
| | { |
| | std::string input = std::string("valid_path") + '\0' + "junk_after"; |
| | std::filesystem::path result = ApplicationDirectoriesTestClass::wrapSanitizePath(input); |
| |
|
| | EXPECT_EQ(result.string(), "valid_path"); |
| | EXPECT_EQ(result.string().find('\0'), std::string::npos); |
| | } |
| |
|
| | TEST_F(ApplicationDirectoriesTest, sanitizeReturnsUnchangedIfNoNullCharacter) |
| | { |
| | std::string input = "clean_path/without_nulls"; |
| | std::filesystem::path result = ApplicationDirectoriesTestClass::wrapSanitizePath(input); |
| |
|
| | EXPECT_EQ(result.string(), input); |
| | EXPECT_EQ(result.string().find('\0'), std::string::npos); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|