1 #include <catch2/catch_test_macros.hpp>
3 #include <polysolve/Utils.hpp>
23 bool load_json(
const std::string& json_file,
json& out)
25 std::ifstream file(json_file);
27 if (!file.is_open())
return false;
35 bool contains_results(
const json& in_args)
37 if (!in_args.contains(
"tests")) {
41 const auto& tests = in_args[
"tests"];
42 for (
const auto& type : {
"meshes",
"vertices",
"edges",
"faces",
"tetrahedra"}) {
43 if (!(tests.contains(type) && (tests[type].is_number() || tests[type].is_array()))) {
45 "Test must have type {} = {} and test is an (array type = {} or number type {})",
48 tests[type].is_number(),
49 tests[type].is_array());
56 bool missing_tests_data(
const json& j)
58 return !j.contains(
"tests") || !j.at(
"tests").contains(
"meshes");
64 if (!load_json(json_file, in_args)) {
65 wmtk::logger().error(
"unable to open {} file", json_file);
69 in_args[
"root_path"] = json_file;
74 if (!compute_validation) {
75 if (missing_tests_data(in_args)) {
76 wmtk::logger().error(
"JSON file missing \"tests\" or meshes key.");
80 REQUIRE(contains_results(in_args));
84 const std::vector<std::string> meshes = in_args[
"tests"][
"meshes"];
86 if (in_args[
"tests"].contains(
"skip_check") && in_args[
"tests"][
"skip_check"]) {
91 const auto vertices = in_args[
"tests"][
"vertices"];
92 const auto edges = in_args[
"tests"][
"edges"];
93 const auto faces = in_args[
"tests"][
"faces"];
94 const auto tetrahedra = in_args[
"tests"][
"tetrahedra"];
95 if (meshes.size() !=
vertices.size() || meshes.size() !=
edges.size() ||
96 meshes.size() !=
faces.
size() || meshes.size() != tetrahedra.size()) {
98 "JSON size missmatch between meshes and vertices, edges, faces, or tetrahedra.");
102 for (int64_t i = 0; i < meshes.size(); ++i) {
103 const std::shared_ptr<Mesh> mesh = cache.read_mesh(meshes[i]);
105 const int64_t expected_vertices =
vertices[i];
106 const int64_t expected_edges =
edges[i];
107 const int64_t expected_faces =
faces[i];
108 const int64_t expected_tetrahedra = tetrahedra[i];
115 if (n_vertices != expected_vertices) {
117 "Violating Authenticate in mesh `{}` for vertices {} != {}",
123 if (n_edges != expected_edges) {
125 "Violating Authenticate in mesh `{}` for edges {} != {}",
131 if (n_faces != expected_faces) {
133 "Violating Authenticate in mesh `{}` for faces {} != {}",
139 if (n_tetrahedra != expected_tetrahedra) {
141 "Violating Authenticate in mesh `{}` for tetrahedra {} != {}",
144 expected_tetrahedra);
151 if (contains_results(in_args)) {
153 "JSON file contains results even though the test was run in `computation "
154 "mode`. Set DO_VALIDATION to false to compare with saved results or remove "
155 "results from JSON to re-compute them.");
161 const std::vector<std::string> meshes = cache.mesh_names();
162 in_args[
"tests"][
"meshes"] = meshes;
164 std::vector<int64_t> expected_vertices, expected_edges, expected_faces, expected_tetrahedra;
166 for (int64_t i = 0; i < meshes.size(); ++i) {
167 const std::shared_ptr<Mesh> mesh = cache.read_mesh(meshes[i]);
175 expected_vertices.push_back(n_vertices);
176 expected_edges.push_back(n_edges);
177 expected_faces.push_back(n_faces);
178 expected_tetrahedra.push_back(n_tetrahedra);
181 in_args[
"tests"][
"vertices"] = expected_vertices;
182 in_args[
"tests"][
"edges"] = expected_edges;
183 in_args[
"tests"][
"faces"] = expected_faces;
184 in_args[
"tests"][
"tetrahedra"] = expected_tetrahedra;
185 in_args.erase(
"root_path");
186 in_args.erase(
"settings");
188 std::ofstream file(json_file);
197 std::string tagsrun =
"[integration]";
199 std::string tagsrun =
"[.][integration]";
203 #define WMTK_INTEGRATION_BODY(NAME, DO_VALIDATION) \
205 std::string path = std::string("unit_test/") + NAME + ".json"; \
206 bool compute_validation = DO_VALIDATION; \
207 wmtk::logger().info("Processing {}", NAME); \
208 auto flag = authenticate_json(WMTK_DATA_DIR "/" + path, compute_validation); \
209 REQUIRE(flag == IntegrationTestResult::Success); \
212 #define WMTK_INTEGRATION(NAME, DO_VALIDATION) \
213 TEST_CASE(std::string("integration_") + NAME, tagsrun) \
214 WMTK_INTEGRATION_BODY(NAME, DO_VALIDATION)
234 TEST_CASE(
"integration_benchmark",
"[.][benchmark][integration]")
236 double total_time = 0;
241 auto run = [&](
const std::string& name) {
244 POLYSOLVE_SCOPED_STOPWATCH(
"Benchmark " + name, time,
logger());
253 POLYSOLVE_SCOPED_STOPWATCH(
"Benchmark total time", total_time,
logger());
254 run(
"wildmeshing_3d");
255 run(
"isotropic_remeshing_mm_timing");
257 js[
"total_time"] = total_time;
258 js[
"geometric_mean_time"] =
std::pow(prod, 1.0 / count);
260 fmt::print(
"{}\n", js.dump());
TEST_CASE("integration_benchmark", "[.][benchmark][integration]")
#define WMTK_INTEGRATION(NAME, DO_VALIDATION)
#define WMTK_INTEGRATION_BODY(NAME, DO_VALIDATION)
wmtk::io::Cache run_components(const nlohmann::json &json_input_file, bool strict)
std::vector< Tuple > vertices(const Mesh &m, const Simplex &simplex)
std::vector< Tuple > edges(const Mesh &m, const Simplex &simplex)
SimplexCollection faces(const Mesh &mesh, const Simplex &simplex, const bool sort_and_clean)
Returns all faces of a simplex.
void set_random_seed(uint64_t val)
spdlog::logger & logger()
Retrieves the current logger.
Rational pow(const Rational &x, int p)