pairinteraction
A Rydberg Interaction Calculator
ParquetManager.test.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 Pairinteraction Developers
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
5
8
9#include <doctest/doctest.h>
10#include <duckdb.hpp>
11#include <filesystem>
12#include <fstream>
13#include <miniz.h>
14#include <nlohmann/json.hpp>
15
16namespace pairinteraction {
18public:
19 std::future<GitHubDownloader::Result>
20 download(const std::string &remote_url, const std::string & /*if_modified_since*/ = "",
21 bool /*use_octet_stream*/ = false) const override {
23 result.status_code = 200;
24 result.rate_limit.remaining = 60;
25 result.rate_limit.reset_time = 2147483647;
26
27 if (remote_url == "/test/repo/path") {
28 // This is the repo path request, return JSON with assets
29 nlohmann::json assets = nlohmann::json::array();
30 nlohmann::json asset;
31 asset["name"] = "misc_v1.2.zip";
32 asset["url"] = "https://api.github.com/test/path/misc_v1.2.zip";
33 assets.push_back(asset);
34 nlohmann::json response;
35 response["assets"] = assets;
36 result.body = response.dump();
37 } else if (remote_url == "/rate_limit") {
38 // This is the rate limit request
39 result.body = "";
40 } else {
41 // This is the file download request
42 std::string content = "updated_file_content";
43 std::string filename = "misc_v1.2/wigner.parquet";
44
45 mz_zip_archive zip_archive{};
46 size_t zip_size = 0;
47 void *zip_data = nullptr;
48
49 mz_zip_writer_init_heap(&zip_archive, 0, 0);
50 mz_zip_writer_add_mem(&zip_archive, filename.c_str(), content.data(), content.size(),
51 MZ_BEST_SPEED);
52 mz_zip_writer_finalize_heap_archive(&zip_archive, &zip_data, &zip_size);
53
54 result.body = std::string(static_cast<char *>(zip_data), zip_size);
55
56 mz_free(zip_data);
57 mz_zip_writer_end(&zip_archive);
58 }
59
60 return std::async(std::launch::deferred, [result]() { return result; });
61 }
62};
63
64TEST_CASE("ParquetManager functionality with mocked downloader") {
65 MockDownloader downloader;
66 auto test_dir = std::filesystem::temp_directory_path() / "pairinteraction_test_db";
67 std::filesystem::create_directories(test_dir / "tables" / "misc_v1.0");
68 std::filesystem::create_directories(test_dir / "tables" / "misc_v1.1");
69 std::ofstream(test_dir / "tables" / "misc_v1.0" / "wigner.parquet").close();
70 std::ofstream(test_dir / "tables" / "misc_v1.1" / "wigner.parquet").close();
71 duckdb::DuckDB db(nullptr);
72 duckdb::Connection con(db);
73
74 SUBCASE("Check missing table") {
75 std::vector<std::string> repo_paths;
76 ParquetManager manager(test_dir, downloader, repo_paths, con, false);
77 manager.scan_local();
78 manager.scan_remote();
79
80 CHECK_THROWS_WITH_AS(manager.get_path("misc", "missing_table"),
81 "Table misc_missing_table not found.", std::runtime_error);
82 }
83
84 SUBCASE("Check version parsing") {
85 std::vector<std::string> repo_paths;
86 ParquetManager manager(test_dir, downloader, repo_paths, con, false);
87 manager.scan_local();
88 manager.scan_remote();
89
90 std::string expected = (test_dir / "tables" / "misc_v1.1" / "wigner.parquet").string();
91 CHECK(manager.get_path("misc", "wigner") == expected);
92 }
93
94 SUBCASE("Check update table") {
95 std::vector<std::string> repo_paths = {"/test/repo/path"};
96 ParquetManager manager(test_dir, downloader, repo_paths, con, false);
97 manager.scan_local();
98 manager.scan_remote();
99
100 std::string expected = (test_dir / "tables" / "misc_v1.2" / "wigner.parquet").string();
101 CHECK(manager.get_path("misc", "wigner") == expected);
102
103 std::ifstream in(expected, std::ios::binary);
104 std::stringstream buffer;
105 buffer << in.rdbuf();
106 CHECK(buffer.str() == "updated_file_content");
107 }
108
109 std::filesystem::remove_all(test_dir);
110}
111
112DOCTEST_TEST_CASE("ParquetManager functionality with github downloader") {
113 if (!Database::get_global_instance().get_download_missing()) {
114 DOCTEST_MESSAGE("Skipping test because download_missing is false.");
115 return;
116 }
117 GitHubDownloader downloader;
118 duckdb::DuckDB db(nullptr);
119 duckdb::Connection con(db);
120
121 std::vector<std::string> repo_paths = {"/repos/pairinteraction/database-sqdt/releases/latest",
122 "/repos/pairinteraction/database-mqdt/releases/latest"};
123 ParquetManager manager(Database::get_global_instance().get_database_dir(), downloader,
124 repo_paths, con, Database::get_global_instance().get_use_cache());
125 manager.scan_local();
126 manager.scan_remote();
127
128 std::string info = manager.get_versions_info();
129
130 // Check that all species are present
131 std::vector<std::string> should_contain = {
132 "Cs", "K", "Li", "Na",
133 "Rb", "Sr87_mqdt", "Sr88_singlet", "Sr88_triplet",
134 "Sr88_mqdt", "Yb171_mqdt", "Yb173_mqdt", "Yb174_mqdt",
135 "misc"};
136 for (const auto &substr : should_contain) {
137 DOCTEST_CHECK(info.find(substr) != std::string::npos);
138 }
139}
140
141} // namespace pairinteraction
nlohmann::json json
static Database & get_global_instance()
Definition: Database.cpp:1068
std::future< GitHubDownloader::Result > download(const std::string &remote_url, const std::string &="", bool=false) const override
std::string get_versions_info() const
std::string get_path(const std::string &key, const std::string &table)
TEST_CASE("ParquetManager functionality with mocked downloader")
DOCTEST_TEST_CASE("create a basis for strontium 88")