--- /dev/null
+#include <assert.h>
+#include <graphviz/cgraph.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(void) {
+
+ int ret = EXIT_SUCCESS;
+
+#define ERR(args...) \
+ do { \
+ fprintf(stderr, "%s:%d: ", __FILE__, __LINE__); \
+ fprintf(stderr, args); \
+ ret = EXIT_FAILURE; \
+ } while (0)
+
+ // create a new, empty graph
+ Agraph_t *g = agopen("foo", Agdirected, NULL);
+ assert(g != NULL);
+
+ // create a new reference counted string in this graph’s dictionary
+ char bar[] = "bar";
+ char *ag_bar1 = agstrdup(g, bar);
+ assert(ag_bar1 != NULL);
+
+ // this should not be considered an HTML-like string
+ if (aghtmlstr(ag_bar1))
+ ERR("agstrdup result incorrectly considered HTML-like\n");
+
+ // create an HTML-like string with the same content
+ char *ag_bar2 = agstrdup_html(g, bar);
+ assert(ag_bar2 != NULL);
+
+ // this should be considered an HTML-like string
+ if (!aghtmlstr(ag_bar2))
+ ERR("agstrdup_html result incorrectly not considered HTML-like\n");
+
+ // note whether ag_bar1 and ag_bar2 are actually the same pointer, so help
+ // anyone debugging this test case
+ printf("ag_bar1 == %p, ag_bar2 == %p\n", ag_bar1, ag_bar2);
+
+ // attempt the same sequence of steps but in reverse to make sure the HTML bit
+ // is not incorrectly shared in the other direction either
+
+ char baz[] = "baz";
+ char *ag_baz1 = agstrdup_html(g, baz);
+ assert(ag_baz1 != NULL);
+
+ if (!aghtmlstr(ag_baz1))
+ ERR("agstrdup_html result incorrectly not considered HTML-like\n");
+
+ char *ag_baz2 = agstrdup(g, baz);
+ assert(ag_baz2 != NULL);
+
+ if (aghtmlstr(ag_baz2))
+ ERR("agstrdup result incorrectly considered HTML-like\n");
+
+ printf("ag_baz1 == %p, ag_baz2 == %p\n", ag_baz1, ag_baz2);
+
+ agclose(g);
+
+ return ret;
+}
# this bug has been reintroduced
subprocess.check_call(["dot", "-Tpng", "-o", os.devnull, input])
+@pytest.mark.xfail(strict=True)
+@pytest.mark.parametrize("html_like_first", (False, True))
+def test_2089(html_like_first: bool): # FIXME
+ """
+ HTML-like and non-HTML-like strings should peacefully coexist
+ https://gitlab.com/graphviz/graphviz/-/issues/2089
+ """
+
+ # a graph using an HTML-like string and a non-HTML-like string
+ if html_like_first:
+ graph = 'graph {\n' \
+ ' a[label=<foo>];\n' \
+ ' b[label="foo"];\n' \
+ '}'
+ else:
+ graph = 'graph {\n' \
+ ' a[label="foo"];\n' \
+ ' b[label=<foo>];\n' \
+ '}'
+
+ # normalize the graph
+ p = subprocess.Popen(["dot", "-Tdot"], stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, universal_newlines=True)
+ canonical, _ = p.communicate(graph)
+
+ assert p.returncode == 0
+
+ assert 'label=foo' in canonical, "non-HTML-like label not found"
+ assert "label=<foo>" in canonical, "HTML-like label not found"
+
+@pytest.mark.xfail(strict=True) # FIXME
+def test_2089_2():
+ """
+ HTML-like and non-HTML-like strings should peacefully coexist
+ https://gitlab.com/graphviz/graphviz/-/issues/2089
+ """
+
+ # find co-located test source
+ c_src = (Path(__file__).parent / "2089.c").resolve()
+ assert c_src.exists(), "missing test case"
+
+ # run it
+ ret, stdout, stderr = run_c(c_src, link=["cgraph"])
+ sys.stdout.write(stdout)
+ sys.stderr.write(stderr)
+ assert ret == 0
+
def test_package_version():
"""
The graphviz_version.h header should define a non-empty PACKAGE_VERSION