diff --git a/internal/platform/implementation/g3/BUILD b/internal/platform/implementation/g3/BUILD index a7447c86..2881c276 100644 --- a/internal/platform/implementation/g3/BUILD +++ b/internal/platform/implementation/g3/BUILD @@ -121,6 +121,7 @@ cc_library( ":comm", ":crypto", # build_cleaner: keep ":types", + "//file/base:path", "//internal/platform:test_util", "//internal/platform/implementation:comm", "//internal/platform/implementation:platform", diff --git a/internal/platform/implementation/g3/platform.cc b/internal/platform/implementation/g3/platform.cc index 5b316469..10a9e767 100644 --- a/internal/platform/implementation/g3/platform.cc +++ b/internal/platform/implementation/g3/platform.cc @@ -18,6 +18,7 @@ #include #include +#include "file/base/path.h" #include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/time/time.h" @@ -60,50 +61,9 @@ namespace api { std::string ImplementationPlatform::GetDownloadPath(std::string& parent_folder, std::string& file_name) { - std::string fullPath("/tmp/"); + std::string fullPath("/tmp"); - // If parent_folder starts with a \\ or /, then strip it - while (!parent_folder.empty() && - (*parent_folder.begin() == '\\' || *parent_folder.begin() == '/')) { - parent_folder.erase(0, 1); - } - - // If parent_folder ends with a \\ or /, then strip it - while (!parent_folder.empty() && - (*parent_folder.rbegin() == '\\' || *parent_folder.rbegin() == '/')) { - parent_folder.erase(parent_folder.size() - 1); - } - - // If file_name starts with a \\, then strip it - while (!file_name.empty() && - (*file_name.begin() == '\\' || *file_name.begin() == '/')) { - file_name.erase(0, 1); - } - - // If file_name ends with a \\, then strip it - while (!file_name.empty() && - (*file_name.rbegin() == '\\' || *file_name.rbegin() == '/')) { - file_name.erase(file_name.size() - 1); - } - - std::stringstream path; - - if (parent_folder.empty() && file_name.empty()) { - path << fullPath.c_str(); - return path.str(); - } - if (parent_folder.empty()) { - path << fullPath.c_str() << "\\" << file_name.c_str(); - return path.str(); - } - if (file_name.empty()) { - path << fullPath.c_str() << "\\" << parent_folder.c_str(); - return path.str(); - } - - path << fullPath.c_str() << "\\" << parent_folder.c_str() << "\\" - << file_name.c_str(); - return path.str(); + return file::JoinPath("/tmp", file_name); } OSName ImplementationPlatform::GetCurrentOS() { return OSName::kLinux; } diff --git a/internal/platform/implementation/shared/file.cc b/internal/platform/implementation/shared/file.cc index 0d22d474..9d9d66a3 100644 --- a/internal/platform/implementation/shared/file.cc +++ b/internal/platform/implementation/shared/file.cc @@ -14,8 +14,10 @@ #include "internal/platform/implementation/shared/file.h" +#include #include #include +#include #include "absl/memory/memory.h" #include "absl/strings/string_view.h" @@ -42,10 +44,9 @@ std::unique_ptr IOFile::CreateOutputFile(const absl::string_view path) { } IOFile::IOFile(const absl::string_view file_path) - : file_(std::string(file_path.data(), file_path.size()), - std::ios::binary | std::ios::out | std::ios::trunc), - path_({file_path.data(), file_path.size()}), - total_size_(0) {} + : file_(), path_(file_path), total_size_(0) { + file_.open(path_, std::ios::binary | std::ios::out); +} ExceptionOr IOFile::Read(std::int64_t size) { if (!file_.is_open()) { diff --git a/internal/platform/implementation/shared/file.h b/internal/platform/implementation/shared/file.h index 2efcc6d4..fa96bbf5 100644 --- a/internal/platform/implementation/shared/file.h +++ b/internal/platform/implementation/shared/file.h @@ -17,6 +17,7 @@ #include #include +#include #include "absl/strings/string_view.h" #include "internal/platform/exception.h" @@ -35,9 +36,9 @@ class IOFile final : public api::InputFile, public api::OutputFile { static std::unique_ptr CreateOutputFile(const absl::string_view path); ExceptionOr Read(std::int64_t size) override; - std::string GetFilePath() const override { - return std::string(path_.data(), path_.size()); - } + + std::string GetFilePath() const override { return path_; } + std::int64_t GetTotalSize() const override { return total_size_; } Exception Close() override; diff --git a/internal/platform/implementation/shared/file_test.cc b/internal/platform/implementation/shared/file_test.cc index 367e9ff0..b4abf193 100644 --- a/internal/platform/implementation/shared/file_test.cc +++ b/internal/platform/implementation/shared/file_test.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include "file/util/temp_path.h" #include "gtest/gtest.h" @@ -133,7 +134,8 @@ TEST_F(FileTest, IOFile_Write) { ByteArray bytes2("bc"); EXPECT_EQ(io_file_output->Write(bytes1), Exception{Exception::kSuccess}); EXPECT_EQ(io_file_output->Write(bytes2), Exception{Exception::kSuccess}); - auto io_file_input = shared::IOFile::CreateInputFile(path_, GetSize()); + auto io_file_input = + shared::IOFile::CreateInputFile(io_file_output->GetFilePath(), GetSize()); AssertEquals(io_file_input->Read(kMaxSize), "abc"); } diff --git a/internal/platform/implementation/windows/platform.cc b/internal/platform/implementation/windows/platform.cc index 6cda5c07..d966fae2 100644 --- a/internal/platform/implementation/windows/platform.cc +++ b/internal/platform/implementation/windows/platform.cc @@ -49,8 +49,10 @@ namespace location { namespace nearby { namespace api { -std::string ImplementationPlatform::GetDownloadPath(std::string& parent_folder, - std::string& file_name) { + +namespace { +std::string GetDownloadPathInternal(std::string& parent_folder, + std::string& file_name) { PWSTR basePath; // Retrieves the full path of a known folder identified by the folder's @@ -69,9 +71,10 @@ std::string ImplementationPlatform::GetDownloadPath(std::string& parent_folder, // SHGetKnownFolderPath succeeds or not. size_t bufferSize; wcstombs_s(&bufferSize, NULL, 0, basePath, 0); - std::string fullpathUTF8(bufferSize, '\0'); + std::string fullpathUTF8(bufferSize - 1, '\0'); wcstombs_s(&bufferSize, fullpathUTF8.data(), bufferSize, basePath, _TRUNCATE); - std::string fullPath = fullpathUTF8; + + std::replace(fullpathUTF8.begin(), fullpathUTF8.end(), '\\', '/'); // If parent_folder starts with a \\ or /, then strip it while (!parent_folder.empty() && @@ -102,25 +105,74 @@ std::string ImplementationPlatform::GetDownloadPath(std::string& parent_folder, std::stringstream path(""); if (parent_folder.empty() && file_name.empty()) { - return fullPath; + return fullpathUTF8; } if (parent_folder.empty()) { - path << fullPath.c_str() << "\\" << file_name.c_str(); + path << fullpathUTF8.c_str() << "/" << file_name.c_str(); std::string retVal = path.str(); return retVal; } if (file_name.empty()) { - path << fullPath.c_str() << "\\" << parent_folder.c_str(); + path << fullpathUTF8.c_str() << "/" << parent_folder.c_str(); std::string retVal = path.str(); return retVal; } - path << fullPath.c_str() << "\\" << parent_folder.c_str() << "\\" + path << fullpathUTF8.c_str() << "/" << parent_folder.c_str() << "/" << file_name.c_str(); std::string retVal = path.str(); return retVal; } +// If the file already exists we add " (x)", where x is an incrementing number, +// starting at 1, using the next non-existing number, to the file name, just +// before the first dot, or at the end if no dot. The absolute path is returned. +std::string CreateOutputFileWithRename(absl::string_view path) { + auto last_separator = path.find_last_of('/'); + std::string folder(path.substr(0, last_separator)); + std::string file_name(path.substr(last_separator)); + + int count = 0; + + // Locate the first dot + auto first = file_name.find_first_of('.', 0); + + if (first == std::string::npos) { + first = file_name.size(); + } + + // Break the string at the dot. + auto file_name1 = file_name.substr(0, first); + auto file_name2 = file_name.substr(first); + + // Construct the target file name + std::string target(path); + + std::fstream file; + file.open(target, std::fstream::binary | std::fstream::in); + + // While we successfully open the file, keep incrementing the count. + while (!(file.rdstate() & std::ifstream::failbit)) { + file.close(); + target = absl::StrCat(folder, file_name1, " (", ++count, ")", file_name2); + file.clear(); + file.open(target, std::fstream::binary | std::fstream::in); + } + + // The above leaves the file open, so close it. + file.close(); + + return target; +} + +} // namespace + +std::string ImplementationPlatform::GetDownloadPath(std::string& parent_folder, + std::string& file_name) { + return CreateOutputFileWithRename( + GetDownloadPathInternal(parent_folder, file_name)); +} + OSName ImplementationPlatform::GetCurrentOS() { return OSName::kWindows; } std::unique_ptr ImplementationPlatform::CreateAtomicBoolean( diff --git a/internal/platform/implementation/windows/platform_test.cc b/internal/platform/implementation/windows/platform_test.cc index af04706a..9501f439 100644 --- a/internal/platform/implementation/windows/platform_test.cc +++ b/internal/platform/implementation/windows/platform_test.cc @@ -19,18 +19,33 @@ #include #include +#include #include "gtest/gtest.h" +namespace { +constexpr absl::string_view kFileName("/increment_file_test.txt"); +constexpr absl::string_view kFirstIterationFileName( + "/increment_file_test (1).txt"); +constexpr absl::string_view kSecondIterationFileName( + "/increment_file_test (2).txt"); +constexpr absl::string_view kThirdIterationFileName( + "/increment_file_test (3).txt"); +constexpr absl::string_view kNoDotsFileName("/incrementfiletesttxt"); +constexpr absl::string_view kOneIterationNoDotsFileName( + "/incrementfiletesttxt (1)"); +constexpr absl::string_view kMultipleDotsFileName("/increment.file.test.txt"); +constexpr absl::string_view kOneIterationMultipleDotsFileName( + "/increment (1).file.test.txt"); +} // namespace + // Can't run on google 3, I presume the SHGetKnownFolderPath // fails. #if 0 -class ImplementationPlatformTests : public testing::Test -{ +class ImplementationPlatformTests : public testing::Test { protected: // You can define per-test set-up logic as usual. - void SetUp() override - { + void SetUp() override { PWSTR basePath; SHGetKnownFolderPath( @@ -52,18 +67,19 @@ class ImplementationPlatformTests : public testing::Test size_t bufferSize; wcstombs_s(&bufferSize, NULL, 0, basePath, 0); - std::string fullpathUTF8(bufferSize, '\0'); - wcstombs_s(&bufferSize, fullpathUTF8.data(), bufferSize, basePath, + default_download_path_.resize(bufferSize - 1, '\0'); + wcstombs_s(&bufferSize, default_download_path_.data(), bufferSize, basePath, _TRUNCATE); - default_download_path_ = fullpathUTF8; + + std::replace(default_download_path_.begin(), default_download_path_.end(), + '\\', '/'); } std::string default_download_path_; }; TEST_F(ImplementationPlatformTests, - GetDownloadPathWithEmptyStringArgumentsShouldReturnBaseDownloadPath) -{ + GetDownloadPathWithEmptyStringArgumentsShouldReturnBaseDownloadPath) { // Arrange std::string parent_folder(""); std::string file_name(""); @@ -78,8 +94,7 @@ TEST_F(ImplementationPlatformTests, TEST_F(ImplementationPlatformTests, GetDownloadPathWithSlashParentFolderArgumentsShouldReturn\ -BaseDownloadPath) -{ +BaseDownloadPath) { // Arrange std::string parent_folder("/"); std::string file_name(""); @@ -94,8 +109,7 @@ BaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithBackslashParentFolderArgumentsShouldReturn\ -BaseDownloadPath) -{ +BaseDownloadPath) { // Arrange std::string parent_folder("\\"); std::string file_name(""); @@ -109,8 +123,7 @@ BaseDownloadPath) } TEST_F(ImplementationPlatformTests, - GetDownloadPathWithSlashFileNameArgumentsShouldReturnBaseDownloadPath) -{ + GetDownloadPathWithSlashFileNameArgumentsShouldReturnBaseDownloadPath) { // Arrange std::string parent_folder(""); std::string file_name("/"); @@ -125,8 +138,7 @@ TEST_F(ImplementationPlatformTests, TEST_F(ImplementationPlatformTests, GetDownloadPathWithBackslashFileNameArgumentsShouldReturn\ -BaseDownloadPath) -{ +BaseDownloadPath) { // Arrange std::string parent_folder(""); std::string file_name("\\"); @@ -144,14 +156,13 @@ BaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithParentFolderShouldReturnParentFolder\ -AppendedToBaseDownloadPath) -{ +AppendedToBaseDownloadPath) { // Arrange std::string parent_folder("test_parent_folder"); std::string file_name(""); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_parent_folder"; std::string expected = path.str(); @@ -166,14 +177,13 @@ AppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithParentFolderStartingWithSlashArgumentsShouldReturn\ -ParentFolderAppendedToBaseDownloadPath) -{ +ParentFolderAppendedToBaseDownloadPath) { // Arrange std::string parent_folder("/test_parent_folder"); std::string file_name(""); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_parent_folder"; std::string expected = path.str(); @@ -188,14 +198,13 @@ ParentFolderAppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithParentFolderStartingWithBackslashArguments\ -ShouldReturnParentFolderAppendedToBaseDownloadPath) -{ +ShouldReturnParentFolderAppendedToBaseDownloadPath) { // Arrange std::string parent_folder("\\test_parent_folder"); std::string file_name(""); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_parent_folder"; std::string expected = path.str(); @@ -210,14 +219,13 @@ ShouldReturnParentFolderAppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithParentFolderEndingWithSlashArgumentsShouldReturn\ -ParentFolderAppendedToBaseDownloadPath) -{ +ParentFolderAppendedToBaseDownloadPath) { // Arrange std::string parent_folder("test_parent_folder/"); std::string file_name(""); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_parent_folder"; std::string expected = path.str(); @@ -232,14 +240,13 @@ ParentFolderAppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithParentFolderEndingWithBackslashArguments\ -ShouldReturnParentFolderAppendedToBaseDownloadPath) -{ +ShouldReturnParentFolderAppendedToBaseDownloadPath) { // Arrange std::string parent_folder("test_parent_folder\\"); std::string file_name(""); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_parent_folder"; std::string expected = path.str(); @@ -254,14 +261,13 @@ ShouldReturnParentFolderAppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithFileNameBeginningWithSlashArgumentsShouldReturn\ -FileNameAppendedToBaseDownloadPath) -{ +FileNameAppendedToBaseDownloadPath) { // Arrange std::string parent_folder(""); std::string file_name("/test_file_name.name"); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_file_name.name"; std::string expected = path.str(); @@ -276,36 +282,32 @@ FileNameAppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithFileNameBeginningWithBackslashArgumentsShouldReturn\ -FileNameAppendedToBaseDownloadPath) -{ +FileNameAppendedToBaseDownloadPath) { // Arrange std::string parent_folder(""); std::string file_name("\\test_file_name.name"); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_file_name.name"; - std::string expected = path.str(); - // Act auto result = location::nearby::api::ImplementationPlatform::GetDownloadPath( parent_folder, file_name); // Assert - EXPECT_EQ(result, expected); + EXPECT_EQ(result, path.str().c_str()); } TEST_F(ImplementationPlatformTests, GetDownloadPathWithFileNameEndingWithSlashArgumentsShouldReturnFileName\ -AppendedToBaseDownloadPath) -{ +AppendedToBaseDownloadPath) { // Arrange std::string parent_folder(""); std::string file_name("test_file_name.name/"); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_file_name.name"; std::string expected = path.str(); @@ -320,14 +322,13 @@ AppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithFileNameEndingWithBackslashArgumentsShouldReturn\ -FileNameAppendedToBaseDownloadPath) -{ +FileNameAppendedToBaseDownloadPath) { // Arrange std::string parent_folder(""); std::string file_name("test_file_name.name\\"); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_file_name.name"; std::string expected = path.str(); @@ -342,16 +343,15 @@ FileNameAppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithParentFolderAndFileNameArgumentsShouldReturn\ -ParentFolderAndFileNameAppendedToBaseDownloadPath) -{ +ParentFolderAndFileNameAppendedToBaseDownloadPath) { // Arrange std::string parent_folder("test_parent_folder"); std::string file_name("test_file_name.name"); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_parent_folder" - << "\\" + << "/" << "test_file_name.name"; std::string expected = path.str(); @@ -366,16 +366,15 @@ ParentFolderAndFileNameAppendedToBaseDownloadPath) TEST_F(ImplementationPlatformTests, GetDownloadPathWithParentFolderEndingWithBackslashAndFileNameArguments\ -ShouldReturnParentFolderAndFileNameAppendedToBaseDownloadPath) -{ +ShouldReturnParentFolderAndFileNameAppendedToBaseDownloadPath) { // Arrange std::string parent_folder("test_parent_folder\\"); std::string file_name("test_file_name.name"); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_parent_folder" - << "\\" + << "/" << "test_file_name.name"; std::string expected = path.str(); @@ -388,19 +387,17 @@ ShouldReturnParentFolderAndFileNameAppendedToBaseDownloadPath) EXPECT_EQ(result, expected); } -TEST_F( - ImplementationPlatformTests, - GetDownloadPathWithFileNameStartingWithBackslashAndParentFolderArguments\ -ShouldReturnParentFolderAndFileNameAppendedToBaseDownloadPath) -{ +TEST_F(ImplementationPlatformTests, + GetDownloadPathWithFileNameStartingWithBackslashAndParentFolderArguments\ +ShouldReturnParentFolderAndFileNameAppendedToBaseDownloadPath) { // Arrange std::string parent_folder("test_parent_folder"); std::string file_name("\\test_file_name.name"); std::stringstream path(""); - path << default_download_path_.c_str() << "\\" + path << default_download_path_ << "/" << "test_parent_folder" - << "\\" + << "/" << "test_file_name.name"; std::string expected = path.str(); @@ -412,4 +409,279 @@ ShouldReturnParentFolderAndFileNameAppendedToBaseDownloadPath) // Assert EXPECT_EQ(result, expected); } + +TEST_F(ImplementationPlatformTests, + GetDownloadPath_FileDoesntExistReturnsFileWithPassedName) { + // Arrange + std::string file_name(kFileName); + std::string parent_folder(""); + + std::string expected(default_download_path_); + expected.append(file_name.c_str()); + + // Act + std::string actual = + location::nearby::api::ImplementationPlatform::GetDownloadPath( + parent_folder, file_name); + + // Assert + EXPECT_EQ(actual, expected); +} + +TEST_F(ImplementationPlatformTests, + GetDownloadPath_FileExistsReturnsFileWithIncrementedName) { + // Arrange + std::string file_name(kFileName); + std::string renamed_file_name(kFirstIterationFileName); + std::string parent_folder(""); + + std::string output_file_path(default_download_path_); + output_file_path.append(file_name); + + std::string expected(default_download_path_); + expected.append(renamed_file_name.c_str()); + + std::ifstream input_file; + std::ofstream output_file; + + output_file.open(output_file_path, + std::ofstream::binary | std::ofstream::out); + + ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit); + + output_file.close(); + + // Act + std::string actual = + location::nearby::api::ImplementationPlatform::GetDownloadPath( + parent_folder, file_name); + + // Assert + EXPECT_EQ(actual, expected); + + // Remove the file and check that it is removed + // File 1 + std::remove(output_file_path.c_str()); + + input_file.open(output_file_path, std::ifstream::binary | std::ifstream::in); + + ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit); +} + +TEST_F(ImplementationPlatformTests, + GetDownloadPath_MultipleFilesExistReturnsNextIncrementedFileName) { + // Arrange + std::ofstream output_file; + std::ifstream input_file; + + std::string file_name(kFileName); + std::string first_renamed_file_name(kFirstIterationFileName); + std::string second_renamed_file_name(kSecondIterationFileName); + + std::string parent_folder(""); + + std::string expected(default_download_path_); + expected.append(second_renamed_file_name.c_str()); + + std::string output_file1_path(default_download_path_); + output_file1_path.append(file_name); + + std::string output_file2_path(default_download_path_); + output_file2_path.append(first_renamed_file_name); + + // Create the test files + output_file.open(output_file1_path, + std::ofstream::binary | std::ofstream::out); + ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit); + output_file.close(); + output_file.clear(); + + output_file.open(output_file2_path, + std::ofstream::binary | std::ofstream::out); + ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit); + output_file.close(); + + // Act + std::string actual = + location::nearby::api::ImplementationPlatform::GetDownloadPath( + parent_folder, file_name); + + // Assert + EXPECT_EQ(expected, actual); + + // Remove the test files and check that it is removed + // File 1 + std::remove(output_file1_path.c_str()); + input_file.open(output_file1_path, std::ifstream::binary | std::ifstream::in); + + ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit); + + // File 2 + std::remove(output_file2_path.c_str()); + + input_file.clear(); + input_file.open(output_file2_path, std::ifstream::binary | std::ifstream::in); + + ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit); +} + +TEST_F( + ImplementationPlatformTests, + GetDownloadPath_FileNameContainsMultipleDotsReturnsIncrementBeforeFirstDot){ + // Arrange + std::ifstream input_file; + std::ofstream output_file; + + std::string file_name(kMultipleDotsFileName); + std::string renamed_file_name(kOneIterationMultipleDotsFileName); + + std::string parent_folder(""); + + std::string output_file1_path(default_download_path_); + output_file1_path.append(file_name); + + std::string output_file2_path(default_download_path_); + output_file2_path.append(renamed_file_name); + + std::string expected(default_download_path_); + expected.append(renamed_file_name); + + output_file.open(output_file1_path, + std::ofstream::binary | std::ofstream::out); + ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit); + output_file.close(); + + // Act + std::string actual = + location::nearby::api::ImplementationPlatform::GetDownloadPath( + parent_folder, file_name); + + // Assert + EXPECT_EQ(expected, actual); + + std::remove(output_file1_path.c_str()); + input_file.open(output_file1_path, std::ifstream::binary | std::ifstream::in); + + ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit); +} + +TEST_F(ImplementationPlatformTests, + GetDownloadPath_FileNameContainsNoDotsReturnsWithIncrementAtEnd) { + std::ifstream input_file; + std::ofstream output_file; + + std::string file_name(kNoDotsFileName); + std::string renamed_file_name(kOneIterationNoDotsFileName); + + std::string parent_folder(""); + + std::string output_file1_path(default_download_path_); + output_file1_path.append(file_name); + + std::string output_file2_path(default_download_path_); + output_file2_path.append(renamed_file_name); + + std::string expected(default_download_path_); + expected.append(renamed_file_name); + + output_file.open(output_file1_path, + std::ofstream::binary | std::ofstream::out); + ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit); + output_file.close(); + + // Act + std::string actual = + location::nearby::api::ImplementationPlatform::GetDownloadPath( + parent_folder, file_name); + + // Assert + EXPECT_EQ(expected, actual); + + std::remove(output_file1_path.c_str()); + input_file.open(output_file1_path, std::ifstream::binary | std::ifstream::in); + + ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit); +} + +TEST_F(ImplementationPlatformTests, + GetDownloadPath_FileNameExistsWithAHoleBetweenRenamedFiles) { + std::ifstream input_file; + std::ofstream output_file; + + std::string file_name(kFileName); + std::string file_name1(kFirstIterationFileName); + std::string file_name2(kSecondIterationFileName); + std::string file_name3(kThirdIterationFileName); + + std::string parent_folder(""); + + // Create the path for the original file name + std::string output_file_path(default_download_path_); + output_file_path.append( + file_name); // Original file name example: "increment_file_test.txt" + + // Create the path for the first iteration of the original file name + std::string output_file1_path(default_download_path_); + output_file1_path.append(file_name1); // First iteration on original file + // name example: + // "increment_file_test (1).txt" + + // Create the path for the third iteration of the original file name + std::string output_file3_path(default_download_path_); + output_file3_path.append( + file_name3); // Third iteration on original file + // name example: "increment_file_test (3).txt" + + // Create the expected result which is the second iteration of the original + // file name + std::string expected(default_download_path_); + expected.append(file_name2); // Second iteration on original file name + // example: "increment_file_test (2).txt" + + // Create the original file + output_file.open(output_file_path, + std::ofstream::binary | std::ofstream::out); + ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit); + output_file.close(); + + // Create the first iteration of the original file + output_file.clear(); + output_file.open(output_file1_path, + std::ofstream::binary | std::ofstream::out); + ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit); + output_file.close(); + + // Create the third iteration of the original file + output_file.clear(); + output_file.open(output_file3_path, + std::ofstream::binary | std::ofstream::out); + ASSERT_TRUE(output_file.rdstate() == std::ofstream::goodbit); + output_file.close(); + + // Act + // This should return the second iteration of the original file + std::string actual = + location::nearby::api::ImplementationPlatform::GetDownloadPath( + parent_folder, file_name); + + // Assert + EXPECT_EQ(expected, actual); + + // Delete the original file + std::remove(output_file_path.c_str()); + input_file.open(output_file_path, std::ifstream::binary | std::ifstream::in); + ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit); + + // Delete the first iteration of the original file + input_file.clear(); // Reset the input_file state + std::remove(output_file1_path.c_str()); + input_file.open(output_file1_path, std::ifstream::binary | std::ifstream::in); + ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit); + + // Delete the third iteration of the original file + input_file.clear(); // Reset the input_file state + std::remove(output_file3_path.c_str()); + input_file.open(output_file3_path, std::ifstream::binary | std::ifstream::in); + ASSERT_FALSE(input_file.rdstate() == std::ifstream::goodbit); +} #endif