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
12using namespace openmsx;
13
14static void createFile(const std::string filename, const std::string content)
15{
16 std::ofstream of(filename);
17 of << content;
18}
19
20static 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
31TEST_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(lines[0].starts_with("637a81ed8e8217bb01c15c67c39b43b0ab4e20f1"));
124 CHECK(lines[0].ends_with(tmp + "/e"));
125 CHECK(lines[1].starts_with("7e240de74fb1ed08fa08d38063f6a6a91462a815"));
126 CHECK((lines[1].ends_with(tmp + "/a") ||
127 lines[1].ends_with(tmp + "/a2")));
128 CHECK(lines[2].starts_with("7e240de74fb1ed08fa08d38063f6a6a91462a815"));
129 CHECK((lines[2].ends_with(tmp + "/a") ||
130 lines[2].ends_with(tmp + "/a2")));
131 CHECK(lines[3].starts_with("f36b4825e5db2cf7dd2d2593b3f5c24c0311d8b2"));
132 CHECK(lines[3].ends_with(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:23
CHECK(m3==m3)
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:9
auto sum(InputRange &&range, Proj proj={})
Definition: stl.hh:236