receipt.cpp (7202B)
1 #include "helper.hpp" 2 3 #include <receipt.hpp> 4 5 #include <index.hpp> 6 7 using Catch::Matchers::ContainsSubstring; 8 using Catch::Matchers::EndsWith; 9 10 static const char *M = "[receipt]"; 11 12 TEST_CASE("non-empty receipt", M) { 13 Receipt r; 14 REQUIRE(r.empty()); 15 16 SECTION("install") { 17 IndexPtr ri = std::make_shared<Index>("Index Name"); 18 Category cat("Category Name", ri.get()); 19 Package pkg(Package::ScriptType, "Package Name", &cat); 20 Version ver("1.0", &pkg); 21 r.addInstall(&ver, {}); 22 } 23 24 SECTION("removal") 25 r.addRemoval(Path("hello/world")); 26 27 SECTION("export") 28 r.addExport(Path("hello/world")); 29 30 SECTION("error") 31 r.addError({"message", "context"}); 32 33 REQUIRE_FALSE(r.empty()); 34 } 35 36 TEST_CASE("set receipt flags", M) { 37 Receipt r; 38 REQUIRE(r.flags() == Receipt::NoFlag); 39 Receipt::Flag expected; 40 41 SECTION("install") { 42 IndexPtr ri = std::make_shared<Index>("Index Name"); 43 Category cat("Category Name", ri.get()); 44 Package pkg(Package::ScriptType, "Package Name", &cat); 45 Version ver("1.0", &pkg); 46 r.addInstall(&ver, {}); 47 48 CHECK(r.test(Receipt::InstalledOrRemoved)); 49 CHECK_FALSE(r.test(Receipt::PackageChangedFlag)); 50 expected = Receipt::InstalledFlag; 51 } 52 53 SECTION("removal") { 54 r.addRemoval(Path("hello/world")); 55 CHECK(r.test(Receipt::InstalledOrRemoved)); 56 CHECK_FALSE(r.test(Receipt::PackageChangedFlag)); 57 expected = Receipt::RemovedFlag; 58 } 59 60 SECTION("export") { 61 r.addExport(Path("hello/world")); 62 CHECK_FALSE(r.test(Receipt::InstalledOrRemoved)); 63 expected = Receipt::ExportedFlag; 64 } 65 66 SECTION("error") { 67 r.addError({"message", "context"}); 68 CHECK_FALSE(r.test(Receipt::PackageChangedFlag)); 69 expected = Receipt::ErrorFlag; 70 } 71 72 REQUIRE(r.test(expected)); 73 REQUIRE_FALSE(r.test(Receipt::NoFlag)); 74 REQUIRE(r.flags() == expected); 75 } 76 77 TEST_CASE("set restart needed flag", M) { 78 IndexPtr ri = std::make_shared<Index>("Index Name"); 79 Category cat("Category Name", ri.get()); 80 Package script(Package::ScriptType, "Package Name", &cat); 81 Package ext(Package::ExtensionType, "Package Name", &cat); 82 Version scriptVer("1.0", &script); 83 Version extVer("1.0", &ext); 84 85 Receipt r; 86 REQUIRE_FALSE(r.test(Receipt::RestartNeededFlag)); 87 88 r.addInstall(&scriptVer, {}); 89 REQUIRE_FALSE(r.test(Receipt::RestartNeededFlag)); 90 91 r.addInstall(&extVer, {}); 92 REQUIRE(r.test(Receipt::RestartNeededFlag)); 93 } 94 95 TEST_CASE("set index changed flag", M) { 96 Receipt r; 97 REQUIRE_FALSE(r.test(Receipt::IndexChangedFlag)); 98 REQUIRE_FALSE(r.test(Receipt::RefreshBrowser)); 99 100 r.setIndexChanged(); 101 REQUIRE(r.test(Receipt::IndexChangedFlag)); 102 REQUIRE(r.test(Receipt::RefreshBrowser)); 103 } 104 105 TEST_CASE("set package changed flag", M) { 106 Receipt r; 107 REQUIRE_FALSE(r.test(Receipt::PackageChangedFlag)); 108 109 r.setPackageChanged(); 110 REQUIRE(r.test(Receipt::PackageChangedFlag)); 111 REQUIRE(r.test(Receipt::RefreshBrowser)); 112 REQUIRE_FALSE(r.test(Receipt::InstalledOrRemoved)); 113 } 114 115 TEST_CASE("format receipt page title", M) { 116 SECTION("singular") { 117 ReceiptPage page{std::vector<int>{1}, "Singular", "Plural"}; 118 REQUIRE(page.title() == "Singular (1)"); 119 } 120 121 SECTION("plural") { 122 ReceiptPage page{std::vector<int>{1, 2, 3}, "Singular", "Plural"}; 123 REQUIRE(page.title() == "Plural (3)"); 124 } 125 126 SECTION("zero is plural") { 127 ReceiptPage page{std::vector<int>{}, "Singular", "Plural"}; 128 REQUIRE(page.title() == "Plural (0)"); 129 } 130 131 SECTION("no plural") { 132 ReceiptPage page{std::vector<int>{1, 2, 3}, "Fallback"}; 133 REQUIRE(page.title() == "Fallback (3)"); 134 } 135 136 SECTION("thousand divider") { 137 ReceiptPage page{std::vector<int>(42'000, 42), "Singular", "Plural"}; 138 REQUIRE(page.title() == "Plural (42,000)"); 139 } 140 } 141 142 TEST_CASE("format receipt page contents", M) { 143 ReceiptPage page{std::vector<int>{1, 2, 3}, "", ""}; 144 REQUIRE(page.contents() == "1\r\n2\r\n3"); 145 } 146 147 TEST_CASE("format install ticket", M) { 148 IndexPtr ri = std::make_shared<Index>("Index Name"); 149 Category cat("Category Name", ri.get()); 150 Package pkg(Package::ScriptType, "Package Name", &cat); 151 152 Version *v1 = new Version("1.0", &pkg); 153 v1->addSource(new Source({}, "https://google.com", v1)); 154 pkg.addVersion(v1); 155 156 Version *v2 = new Version("2.0", &pkg); 157 v2->addSource(new Source({}, "https://google.com", v2)); 158 pkg.addVersion(v2); 159 160 Version *v3 = new Version("3.0", &pkg); 161 v3->addSource(new Source({}, "https://google.com", v3)); 162 pkg.addVersion(v3); 163 164 std::ostringstream stream; 165 Registry::Entry entry{1}; 166 167 SECTION("contains fullname") { 168 stream << InstallTicket{v3, {}}; 169 REQUIRE_THAT(stream.str(), ContainsSubstring(pkg.fullName())); 170 } 171 172 SECTION("prepend newline if stream nonempty") { 173 stream << "something"; 174 stream << InstallTicket{v3, {}}; 175 REQUIRE_THAT(stream.str(), ContainsSubstring("something\r\n")); 176 } 177 178 SECTION("installed from scratch") { 179 stream << InstallTicket{v2, {}}; 180 REQUIRE_THAT(stream.str(), ContainsSubstring("[new]") && 181 !ContainsSubstring("v1.0\r\n") && ContainsSubstring("v2.0\r\n") && !ContainsSubstring("v3.0\r\n")); 182 } 183 184 SECTION("reinstalled") { 185 entry.version = VersionName("2.0"); 186 stream << InstallTicket{v2, entry}; 187 REQUIRE_THAT(stream.str(), ContainsSubstring("[reinstalled]") && 188 !ContainsSubstring("v1.0\r\n") && ContainsSubstring("v2.0\r\n") && !ContainsSubstring("v3.0\r\n")); 189 } 190 191 SECTION("update") { 192 entry.version = VersionName("1.0"); 193 stream << InstallTicket{v3, entry}; 194 REQUIRE_THAT(stream.str(), ContainsSubstring("[v1.0 -> v3.0]") && 195 !ContainsSubstring("v1.0\r\n") && ContainsSubstring("\r\nv3.0\r\n No changelog\r\nv2.0")); 196 REQUIRE_THAT(stream.str(), !EndsWith("\r\n")); 197 } 198 199 SECTION("downgrade") { 200 entry.version = VersionName("3.0"); 201 stream << InstallTicket{v1, entry}; 202 REQUIRE_THAT(stream.str(), ContainsSubstring("[v3.0 -> v1.0]") && 203 ContainsSubstring("v1.0\r\n") && !ContainsSubstring("v2.0\r\n") && !ContainsSubstring("v3.0\r\n")); 204 } 205 } 206 207 TEST_CASE("sort InstallTickets (case insensitive)", M) { 208 IndexPtr ri = std::make_shared<Index>("Index Name"); 209 Category cat("Category Name", ri.get()); 210 Package pkg1(Package::ScriptType, "a test", &cat); 211 Version ver1("1.0", &pkg1); 212 213 Package pkg2(Package::ScriptType, "Uppercase Name", &cat); 214 Version ver2("1.0", &pkg2); 215 216 Package pkg3(Package::ScriptType, "unused name", &cat); 217 pkg3.setDescription("z is the last letter"); 218 Version ver3("1.0", &pkg3); 219 220 REQUIRE(InstallTicket(&ver1, {}) < InstallTicket(&ver2, {})); 221 REQUIRE(InstallTicket(&ver2, {}) < InstallTicket(&ver3, {})); 222 REQUIRE_FALSE(InstallTicket(&ver1, {}) < InstallTicket(&ver1, {})); 223 REQUIRE_FALSE(InstallTicket(&ver2, {}) < InstallTicket(&ver1, {})); 224 225 Receipt r; 226 r.addInstall(&ver1, {}); // a test 227 r.addInstall(&ver3, {}); // z is the last letter 228 r.addInstall(&ver1, {}); // a test (duplicate) 229 r.addInstall(&ver2, {}); // Uppercase Name 230 const std::string page = r.installedPage().contents(); 231 REQUIRE(page.find(pkg1.name()) < page.find(pkg2.name())); 232 REQUIRE(page.find(pkg2.name()) < page.find(pkg3.name())); 233 234 // duplicates should still be preserved 235 REQUIRE(page.find(pkg1.name()) < page.rfind(pkg1.name())); 236 }