From 3354346a7336f5b25d71ec509a45c13fde7fbbce Mon Sep 17 00:00:00 2001 From: Magnus Jacobsson Date: Tue, 5 Jul 2022 19:22:31 +0200 Subject: [PATCH] add new simple test_engines test Upcoming commits in this series will make changes to gvFreeLayout and we want to ensure that those changes don't introduce any memory leaks when run with ASan, since gvFreeLayout calls layout-specific cleanup functions. This test is run in CI with ASan leak detection enabled. It currently fails because of a memory leak in the osage layout. Towards https://gitlab.com/graphviz/graphviz/-/issues/1800. --- tests/CMakeLists.txt | 2 ++ tests/test_engines.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 tests/test_engines.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7ba4b6e04..242d1c322 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -67,6 +67,8 @@ macro(CREATE_TEST testname) endmacro() CREATE_TEST(AGraph_construction) +CREATE_TEST(engines) +set_tests_properties(test_engines PROPERTIES WILL_FAIL true) CREATE_TEST(GVContext_construction) CREATE_TEST(GVContext_render_svg) CREATE_TEST(GVLayout_construction) diff --git a/tests/test_engines.cpp b/tests/test_engines.cpp new file mode 100644 index 000000000..24b08982f --- /dev/null +++ b/tests/test_engines.cpp @@ -0,0 +1,81 @@ +#include + +#include +#include + +#include +#include + +#include "svg_analyzer.h" + +TEST_CASE( + "simple directed and undirected graph with different layout engines") { + const auto directed_graph = GENERATE(false, true); + + const std::string graph_type = directed_graph ? "digraph" : "graph"; + const std::string edge_op = directed_graph ? "->" : "--"; + + std::string dot = fmt::format("{} {{a {} b}}", graph_type, edge_op); + INFO(fmt::format("DOT source: {}", dot)); + + auto g = agmemread(dot.c_str()); + REQUIRE(g != nullptr); + + const std::string engine = GENERATE("dot", // + "neato", // + "fdp", // + "sfdp", // + "circo", // + "twopi", // + "osage", // + "patchwork" // + ); + INFO("Layout engine: " + engine); + + auto gvc = gvContextPlugins(lt_preloaded_symbols, false); + + { + const auto rc = gvLayout(gvc, g, engine.c_str()); + REQUIRE(rc == 0); + } + + char *result = nullptr; + unsigned length = 0; + { + const auto rc = gvRenderData(gvc, g, "svg", &result, &length); + REQUIRE(rc == 0); + } + REQUIRE(result != nullptr); + REQUIRE(length > 0); + + SVGAnalyzer svg_analyzer{result}; + + const std::size_t num_nodes = 2; + const std::size_t num_edges = engine == "patchwork" ? 0 : 1; + const std::size_t num_arrowheads = directed_graph ? num_edges : 0; + + const std::size_t num_svgs = 1; + const std::size_t num_groups = 1 + num_nodes + num_edges; + const std::size_t num_ellipses = engine == "patchwork" ? 0 : num_nodes; + const std::size_t num_polygons = + 1 + (engine == "patchwork" ? num_nodes : 0) + num_arrowheads; + const std::size_t num_paths = num_edges; + const std::size_t num_titles = num_nodes + num_edges; + + CHECK(svg_analyzer.num_svgs() == num_svgs); + CHECK(svg_analyzer.num_groups() == num_groups); + CHECK(svg_analyzer.num_circles() == 0); + CHECK(svg_analyzer.num_ellipses() == num_ellipses); + CHECK(svg_analyzer.num_lines() == 0); + CHECK(svg_analyzer.num_paths() == num_paths); + CHECK(svg_analyzer.num_polygons() == num_polygons); + CHECK(svg_analyzer.num_polylines() == 0); + CHECK(svg_analyzer.num_rects() == 0); + CHECK(svg_analyzer.num_titles() == num_titles); + CHECK(svg_analyzer.num_unknowns() == 0); + + gvFreeRenderData(result); + gvFreeLayout(gvc, g); + agclose(g); + gvFreeContext(gvc); +} -- 2.40.0