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
SetUpTestSuite()17 static void SetUpTestSuite()
18 {
19 ASSERT_FALSE(std::filesystem::exists(directory));
20 }
21
TearDown()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
TEST_F(TestPersistentJsonStorage,storesJsonData)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
TEST_F(TestPersistentJsonStorage,emptyListWhenNoReportsCreated)52 TEST_F(TestPersistentJsonStorage, emptyListWhenNoReportsCreated)
53 {
54 EXPECT_THAT(sut.list(), SizeIs(0u));
55 }
56
TEST_F(TestPersistentJsonStorage,listSavedReports)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
TEST_F(TestPersistentJsonStorage,listSavedReportsWithoutRemovedOnes)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
TEST_F(TestPersistentJsonStorage,removesStoredJson)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
TEST_F(TestPersistentJsonStorage,returnsFalseWhenDeletingNonExistingFile)107 TEST_F(TestPersistentJsonStorage, returnsFalseWhenDeletingNonExistingFile)
108 {
109 ASSERT_THAT(sut.remove(fileName), Eq(false));
110 }
111
TEST_F(TestPersistentJsonStorage,returnsNulloptWhenFileDoesntExist)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
setupSymlinksTestFileSymlink120 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
setupSymlinksTestDirectorySymlink135 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:
TestPersistentJsonStorageWithSymlink()152 TestPersistentJsonStorageWithSymlink()
153 {
154 std::ofstream file(dummyReportPath);
155 file << "{}";
156 file.close();
157
158 linkPath = T::setupSymlinks(dummyReportPath, directory);
159 }
160
SetUpTestSuite()161 static void SetUpTestSuite()
162 {
163 TestPersistentJsonStorage::SetUpTestSuite();
164 ASSERT_FALSE(std::filesystem::exists(dummyReportPath));
165 }
166
TearDown()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
TYPED_TEST(TestPersistentJsonStorageWithSymlink,symlinksAreNotListed)188 TYPED_TEST(TestPersistentJsonStorageWithSymlink, symlinksAreNotListed)
189 {
190 ASSERT_THAT(TestPersistentJsonStorage::sut.list(), UnorderedElementsAre());
191 }
192
TYPED_TEST(TestPersistentJsonStorageWithSymlink,throwsWhenStoreTargetIsSymlink)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
TYPED_TEST(TestPersistentJsonStorageWithSymlink,returnsNulloptWhenFileIsSymlink)202 TYPED_TEST(TestPersistentJsonStorageWithSymlink,
203 returnsNulloptWhenFileIsSymlink)
204 {
205 ASSERT_THAT(TestPersistentJsonStorage::sut.load(TestFixture::linkPath),
206 Eq(std::nullopt));
207 }
208
TYPED_TEST(TestPersistentJsonStorageWithSymlink,returnsFalseWhenTryingToDeleteSymlink)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