1 #include "helpers.hpp" 2 #include "persistent_json_storage.hpp" 3 4 #include <fstream> 5 6 #include "gmock/gmock.h" 7 #include "gtest/gtest.h" 8 9 using namespace testing; 10 11 class TestPersistentJsonStorage : public Test 12 { 13 public: 14 using FilePath = interfaces::JsonStorage::FilePath; 15 using DirectoryPath = interfaces::JsonStorage::DirectoryPath; 16 17 static void SetUpTestSuite() 18 { 19 ASSERT_FALSE(std::filesystem::exists(directory)); 20 } 21 22 void TearDown() override 23 { 24 if (std::filesystem::exists(directory)) 25 { 26 std::filesystem::remove_all(directory); 27 } 28 } 29 30 const FilePath fileName = FilePath("report/1/file.txt"); 31 32 static const DirectoryPath directory; 33 PersistentJsonStorage sut{directory}; 34 }; 35 36 const interfaces::JsonStorage::DirectoryPath 37 TestPersistentJsonStorage::directory = 38 interfaces::JsonStorage::DirectoryPath( 39 std::filesystem::temp_directory_path() / "telemetry-tests"); 40 41 TEST_F(TestPersistentJsonStorage, storesJsonData) 42 { 43 nlohmann::json data = nlohmann::json::object(); 44 data["name"] = "kevin"; 45 data["lastname"] = "mc calister"; 46 47 sut.store(fileName, data); 48 49 ASSERT_THAT(sut.load(fileName), Eq(data)); 50 } 51 52 TEST_F(TestPersistentJsonStorage, emptyListWhenNoReportsCreated) 53 { 54 EXPECT_THAT(sut.list(), SizeIs(0u)); 55 } 56 57 TEST_F(TestPersistentJsonStorage, listSavedReports) 58 { 59 sut.store(FilePath("report/domain-1/name-1/conf-1.json"), 60 nlohmann::json("data-1a")); 61 sut.store(FilePath("report/domain-1/name-2/conf-1.json"), 62 nlohmann::json("data-2a")); 63 sut.store(FilePath("report/domain-1/name-2/conf-2.json"), 64 nlohmann::json("data-2b")); 65 sut.store(FilePath("report/domain-2/name-1/conf-1.json"), 66 nlohmann::json("data-3a")); 67 68 EXPECT_THAT( 69 sut.list(), 70 UnorderedElementsAre(FilePath("report/domain-1/name-1/conf-1.json"), 71 FilePath("report/domain-1/name-2/conf-1.json"), 72 FilePath("report/domain-1/name-2/conf-2.json"), 73 FilePath("report/domain-2/name-1/conf-1.json"))); 74 } 75 76 TEST_F(TestPersistentJsonStorage, listSavedReportsWithoutRemovedOnes) 77 { 78 sut.store(FilePath("report/domain-1/name-1/conf-1.json"), 79 nlohmann::json("data-1a")); 80 sut.store(FilePath("report/domain-1/name-2/conf-1.json"), 81 nlohmann::json("data-2a")); 82 sut.store(FilePath("report/domain-1/name-2/conf-2.json"), 83 nlohmann::json("data-2b")); 84 sut.store(FilePath("report/domain-2/name-1/conf-1.json"), 85 nlohmann::json("data-3a")); 86 sut.remove(FilePath("report/domain-1/name-1/conf-1.json")); 87 sut.remove(FilePath("report/domain-1/name-2/conf-2.json")); 88 89 EXPECT_THAT( 90 sut.list(), 91 UnorderedElementsAre(FilePath("report/domain-1/name-2/conf-1.json"), 92 FilePath("report/domain-2/name-1/conf-1.json"))); 93 } 94 95 TEST_F(TestPersistentJsonStorage, removesStoredJson) 96 { 97 nlohmann::json data = nlohmann::json::object(); 98 data["name"] = "kevin"; 99 data["lastname"] = "mc calister"; 100 101 sut.store(fileName, data); 102 103 ASSERT_THAT(sut.remove(fileName), Eq(true)); 104 ASSERT_THAT(sut.load(fileName), Eq(std::nullopt)); 105 } 106 107 TEST_F(TestPersistentJsonStorage, returnsFalseWhenDeletingNonExistingFile) 108 { 109 ASSERT_THAT(sut.remove(fileName), Eq(false)); 110 } 111 112 TEST_F(TestPersistentJsonStorage, returnsNulloptWhenFileDoesntExist) 113 { 114 ASSERT_THAT(sut.load(fileName), Eq(std::nullopt)); 115 } 116 117 struct TestFileSymlink 118 { 119 static interfaces::JsonStorage::FilePath 120 setupSymlinks(const std::filesystem::path& originalFile, 121 const interfaces::JsonStorage::DirectoryPath& directory) 122 { 123 auto linkPath = std::filesystem::path(directory) / 124 "report/symlink.json"; 125 std::filesystem::create_directories(std::filesystem::path(directory) / 126 "report"); 127 std::filesystem::create_symlink(originalFile, linkPath); 128 return interfaces::JsonStorage::FilePath(linkPath); 129 } 130 }; 131 132 struct TestDirectorySymlink 133 { 134 static interfaces::JsonStorage::FilePath 135 setupSymlinks(const std::filesystem::path& originalFile, 136 const interfaces::JsonStorage::DirectoryPath& directory) 137 { 138 auto linkPath = std::filesystem::path(directory) / "reportLink"; 139 std::filesystem::create_directories(std::filesystem::path(directory) / 140 "report"); 141 std::filesystem::create_directory_symlink(originalFile.parent_path(), 142 linkPath); 143 return interfaces::JsonStorage::FilePath(linkPath / 144 originalFile.filename()); 145 } 146 }; 147 148 template <typename T> 149 class TestPersistentJsonStorageWithSymlink : public TestPersistentJsonStorage 150 { 151 public: 152 TestPersistentJsonStorageWithSymlink() 153 { 154 std::ofstream file(dummyReportPath); 155 file << "{}"; 156 file.close(); 157 158 linkPath = T::setupSymlinks(dummyReportPath, directory); 159 } 160 161 static void SetUpTestSuite() 162 { 163 TestPersistentJsonStorage::SetUpTestSuite(); 164 ASSERT_FALSE(std::filesystem::exists(dummyReportPath)); 165 } 166 167 void TearDown() override 168 { 169 TestPersistentJsonStorage::TearDown(); 170 if (std::filesystem::exists(dummyReportPath)) 171 { 172 std::filesystem::remove(dummyReportPath); 173 } 174 } 175 176 static const std::filesystem::path dummyReportPath; 177 interfaces::JsonStorage::FilePath linkPath; 178 }; 179 180 template <typename T> 181 const std::filesystem::path 182 TestPersistentJsonStorageWithSymlink<T>::dummyReportPath = 183 std::filesystem::temp_directory_path() / "report.json"; 184 185 using SymlinkTypes = Types<TestFileSymlink, TestDirectorySymlink>; 186 TYPED_TEST_SUITE(TestPersistentJsonStorageWithSymlink, SymlinkTypes); 187 188 TYPED_TEST(TestPersistentJsonStorageWithSymlink, symlinksAreNotListed) 189 { 190 ASSERT_THAT(TestPersistentJsonStorage::sut.list(), UnorderedElementsAre()); 191 } 192 193 TYPED_TEST(TestPersistentJsonStorageWithSymlink, throwsWhenStoreTargetIsSymlink) 194 { 195 ASSERT_THROW(TestPersistentJsonStorage::sut.store(TestFixture::linkPath, 196 nlohmann::json("data")), 197 std::runtime_error); 198 199 ASSERT_THAT(TestPersistentJsonStorage::sut.list(), UnorderedElementsAre()); 200 } 201 202 TYPED_TEST(TestPersistentJsonStorageWithSymlink, 203 returnsNulloptWhenFileIsSymlink) 204 { 205 ASSERT_THAT(TestPersistentJsonStorage::sut.load(TestFixture::linkPath), 206 Eq(std::nullopt)); 207 } 208 209 TYPED_TEST(TestPersistentJsonStorageWithSymlink, 210 returnsFalseWhenTryingToDeleteSymlink) 211 { 212 EXPECT_THAT(TestPersistentJsonStorage::sut.remove(TestFixture::linkPath), 213 Eq(false)); 214 EXPECT_TRUE(std::filesystem::exists(TestFixture::linkPath)); 215 EXPECT_TRUE(std::filesystem::exists(TestFixture::dummyReportPath)); 216 } 217