openMSX
FilePoolCore_test.cc
Go to the documentation of this file.
1 #include "catch.hpp"
2 
3 #include "FilePoolCore.hh"
4 #include "File.hh"
5 #include "FileOperations.hh"
6 #include "one_of.hh"
7 #include "StringOp.hh"
8 #include "Timer.hh"
9 #include <iostream>
10 #include <fstream>
11 
12 using namespace openmsx;
13 
14 static void createFile(const std::string filename, const std::string content)
15 {
16  std::ofstream of(filename);
17  of << content;
18 }
19 
20 static std::vector<std::string> readLines(const std::string& filename)
21 {
22  std::vector<std::string> result;
23  std::ifstream is(filename);
24  std::string line;
25  while (std::getline(is, line)) {
26  result.push_back(line);
27  }
28  return result;
29 }
30 
31 TEST_CASE("FilePoolCore")
32 {
33  auto tmp = FileOperations::getTempDir() + "/filepool_unittest";
36  createFile(tmp + "/a", "aaa"); // 7e240de74fb1ed08fa08d38063f6a6a91462a815
37  createFile(tmp + "/a2", "aaa"); // same content, different filename
38  createFile(tmp + "/b", "bbb"); // 5cb138284d431abd6a053a56625ec088bfb88912
39 
40  auto getDirectories = [&] {
42  result.push_back(FilePoolCore::Dir{tmp, FileType::ROM});
43  return result;
44  };
45 
46  {
47  // create pool
48  FilePoolCore pool(tmp + "/cache",
49  getDirectories,
50  [](std::string_view) { /* report progress: nothing */});
51 
52  // lookup, success
53  {
54  auto file = pool.getFile(FileType::ROM, Sha1Sum("7e240de74fb1ed08fa08d38063f6a6a91462a815"));
55  CHECK(file.is_open());
56  CHECK(file.getURL() == one_of(tmp + "/a", tmp + "/a2"));
57  }
58  // lookup, not (yet) present
59  {
60  auto file = pool.getFile(FileType::ROM, Sha1Sum("f36b4825e5db2cf7dd2d2593b3f5c24c0311d8b2"));
61  CHECK(!file.is_open());
62  }
63  // lookup, success
64  {
65  auto file = pool.getFile(FileType::ROM, Sha1Sum("5cb138284d431abd6a053a56625ec088bfb88912"));
66  CHECK(file.is_open());
67  CHECK(file.getURL() == tmp + "/b");
68  }
69  // create new file, and lookup
70  createFile(tmp + "/c", "ccc"); // f36b4825e5db2cf7dd2d2593b3f5c24c0311d8b2
71  {
72  auto file = pool.getFile(FileType::ROM, Sha1Sum("f36b4825e5db2cf7dd2d2593b3f5c24c0311d8b2"));
73  CHECK(file.is_open());
74  CHECK(file.getURL() == tmp + "/c");
75  }
76  // modify file, old no longer present, new is present
77  FileOperations::unlink(tmp + "/b");
78  Timer::sleep(1'000'000); // sleep because timestamps are only accurate to 1 second
79  createFile(tmp + "/b", "BBB"); // aa6878b1c31a9420245df1daffb7b223338737a3
80  {
81  auto file1 = pool.getFile(FileType::ROM, Sha1Sum("5cb138284d431abd6a053a56625ec088bfb88912"));
82  CHECK(!file1.is_open());
83  auto file2 = pool.getFile(FileType::ROM, Sha1Sum("aa6878b1c31a9420245df1daffb7b223338737a3"));
84  CHECK(file2.is_open());
85  CHECK(file2.getURL() == tmp + "/b");
86  }
87  // modify file, but keep same content, IOW only update timestamp
88  FileOperations::unlink(tmp + "/b");
89  Timer::sleep(1'000'000); // sleep because timestamps are only accurate to 1 second
90  createFile(tmp + "/b", "BBB"); // aa6878b1c31a9420245df1daffb7b223338737a3
91  {
92  auto file = pool.getFile(FileType::ROM, Sha1Sum("aa6878b1c31a9420245df1daffb7b223338737a3"));
93  CHECK(file.is_open());
94  CHECK(file.getURL() == tmp + "/b");
95  }
96  // remove file
97  FileOperations::unlink(tmp + "/b");
98  {
99  auto file = pool.getFile(FileType::ROM, Sha1Sum("aa6878b1c31a9420245df1daffb7b223338737a3"));
100  CHECK(!file.is_open());
101  }
102 
103  // calc sha1 of cached file
104  {
105  File file(tmp + "/a2");
106  CHECK(file.is_open());
107  auto sum = pool.getSha1Sum(file);
108  CHECK(sum == Sha1Sum("7e240de74fb1ed08fa08d38063f6a6a91462a815"));
109  }
110  // calc sha1 of new file
111  createFile(tmp + "/e", "eee");
112  {
113  File file(tmp + "/e");
114  CHECK(file.is_open());
115  auto sum = pool.getSha1Sum(file);
116  CHECK(sum == Sha1Sum("637a81ed8e8217bb01c15c67c39b43b0ab4e20f1"));
117  }
118  }
119 
120  // write 'filecache' to disk
121  auto lines = readLines(tmp + "/cache");
122  CHECK(lines.size() == 4);
123  CHECK(StringOp::startsWith(lines[0], "637a81ed8e8217bb01c15c67c39b43b0ab4e20f1"));
124  CHECK(StringOp::endsWith(lines[0], tmp + "/e"));
125  CHECK(StringOp::startsWith(lines[1], "7e240de74fb1ed08fa08d38063f6a6a91462a815"));
126  CHECK((StringOp::endsWith(lines[1], tmp + "/a") ||
127  StringOp::endsWith(lines[1], tmp + "/a2")));
128  CHECK(StringOp::startsWith(lines[2], "7e240de74fb1ed08fa08d38063f6a6a91462a815"));
129  CHECK((StringOp::endsWith(lines[2], tmp + "/a") ||
130  StringOp::endsWith(lines[2], tmp + "/a2")));
131  CHECK(StringOp::startsWith(lines[3], "f36b4825e5db2cf7dd2d2593b3f5c24c0311d8b2"));
132  CHECK(StringOp::endsWith(lines[3], tmp + "/c"));
133 
135 }
TEST_CASE("FilePoolCore")
Definition: one_of.hh:7
File getFile(FileType fileType, const Sha1Sum &sha1sum)
Search file with the given sha1sum.
std::vector< Dir > Directories
Definition: FilePoolCore.hh:44
bool is_open() const
Return true iff this file handle refers to an open file.
Definition: File.hh:63
This class represents the result of a sha1 calculation (a 160-bit value).
Definition: sha1.hh:22
CHECK(m3==m3)
bool endsWith(string_view total, string_view part)
Definition: StringOp.cc:43
bool startsWith(string_view total, string_view part)
Definition: StringOp.cc:33
string getTempDir()
Get the name of the temp directory on the system.
int deleteRecursive(zstring_view path)
Recursively delete a file or directory and (in case of a directory) all its sub-components.
void mkdirp(string path)
Acts like the unix command "mkdir -p".
int unlink(zstring_view path)
Call unlink() in a platform-independent manner.
void sleep(uint64_t us)
Sleep for the specified amount of time (in us).
Definition: Timer.cc:27
This file implemented 3 utility functions:
Definition: Autofire.cc:5
constexpr const char *const filename
auto sum(InputRange &&range)
Definition: stl.hh:293