aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2025-06-11 14:21:41 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2025-06-11 14:21:41 -0400
commitf867196566c8aa51fd8b18dc5956daeea49e7518 (patch)
tree6ac9e1d4acf478fff80124c213a7e4dc31d74e25
parent1c5e99ce8744c166d82cb96bbb2d58392b5fb8d7 (diff)
downloadgcc-f867196566c8aa51fd8b18dc5956daeea49e7518.zip
gcc-f867196566c8aa51fd8b18dc5956daeea49e7518.tar.gz
gcc-f867196566c8aa51fd8b18dc5956daeea49e7518.tar.bz2
diagnostics: add selftests for html_token_printer [PR116792]
No functional change intended. gcc/ChangeLog: PR other/116792 * diagnostic-format-html.cc: Include "selftest-xml.h". (html_builder::make_element_for_diagnostic): Move... (class html_token_printer): ...from local to the function to the global namespace. (struct selftest::token_printer_test): New. (selftest::test_token_printer): New. (selftest::test_simple_log): Simplify using ASSERT_XML_PRINT_EQ. (selftest::test_metadata): Likewise. (selftest::diagnostic_format_html_cc_tests): Run the new test. * selftest-xml.h: New file. * xml.cc: Include "selftest-xml.h". (selftest::assert_xml_print_eq): New. (selftest::test_no_dtd): Simplify using ASSERT_XML_PRINT_EQ. (selftest::test_printer): Likewise. (selftest::test_attribute_ordering): Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
-rw-r--r--gcc/diagnostic-format-html.cc219
-rw-r--r--gcc/selftest-xml.h50
-rw-r--r--gcc/xml.cc29
3 files changed, 198 insertions, 100 deletions
diff --git a/gcc/diagnostic-format-html.cc b/gcc/diagnostic-format-html.cc
index 22bf6b9..45d0881 100644
--- a/gcc/diagnostic-format-html.cc
+++ b/gcc/diagnostic-format-html.cc
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "xml.h"
#include "xml-printer.h"
#include "json.h"
+#include "selftest-xml.h"
// struct html_generation_options
@@ -729,6 +730,82 @@ add_labelled_value (xml::printer &xp,
xp.pop_tag ("div");
}
+class html_token_printer : public token_printer
+{
+public:
+ html_token_printer (xml::element &parent_element)
+ /* Ideally pp_token_lists that reach a token_printer should be
+ "balanced", but for now they can have mismatching pp_tokens
+ e.g. a begin_color without an end_color (PR other/120610).
+ Give html_token_printer its own xml::printer as a firewall to
+ limit the scope of the mismatches in the HTML. */
+ : m_xp (parent_element,
+ /* Similarly we don't check that the popped tags match. */
+ false)
+ {
+ }
+ void print_tokens (pretty_printer */*pp*/,
+ const pp_token_list &tokens) final override
+ {
+ /* Implement print_tokens by adding child elements to
+ m_parent_element. */
+ for (auto iter = tokens.m_first; iter; iter = iter->m_next)
+ switch (iter->m_kind)
+ {
+ default:
+ gcc_unreachable ();
+
+ case pp_token::kind::text:
+ {
+ pp_token_text *sub = as_a <pp_token_text *> (iter);
+ /* The value might be in the obstack, so we may need to
+ copy it. */
+ m_xp.add_text (sub->m_value.get ());
+ }
+ break;
+
+ case pp_token::kind::begin_color:
+ {
+ pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter);
+ gcc_assert (sub->m_value.get ());
+ m_xp.push_tag_with_class ("span", sub->m_value.get ());
+ }
+ break;
+
+ case pp_token::kind::end_color:
+ m_xp.pop_tag ("span");
+ break;
+
+ case pp_token::kind::begin_quote:
+ {
+ m_xp.add_text (open_quote);
+ m_xp.push_tag_with_class ("span", "gcc-quoted-text");
+ }
+ break;
+ case pp_token::kind::end_quote:
+ {
+ m_xp.pop_tag ("span");
+ m_xp.add_text (close_quote);
+ }
+ break;
+
+ case pp_token::kind::begin_url:
+ {
+ pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
+ m_xp.push_tag ("a", true);
+ m_xp.set_attr ("href", sub->m_value.get ());
+ }
+ break;
+ case pp_token::kind::end_url:
+ m_xp.pop_tag ("a");
+ break;
+ }
+ }
+
+private:
+ xml::printer m_xp;
+};
+
/* Make a <div class="gcc-diagnostic"> for DIAGNOSTIC.
If ALERT is true, make it be a PatternFly alert (see
@@ -744,82 +821,6 @@ html_builder::make_element_for_diagnostic (const diagnostic_info &diagnostic,
diagnostic_t orig_diag_kind,
bool alert)
{
- class html_token_printer : public token_printer
- {
- public:
- html_token_printer (xml::element &parent_element)
- /* Ideally pp_token_lists that reach a token_printer should be
- "balanced", but for now they can have mismatching pp_tokens
- e.g. a begin_color without an end_color (PR other/120610).
- Give html_token_printer its own xml::printer as a firewall to
- limit the scope of the mismatches in the HTML. */
- : m_xp (parent_element,
- /* Similarly we don't check that the popped tags match. */
- false)
- {
- }
- void print_tokens (pretty_printer */*pp*/,
- const pp_token_list &tokens) final override
- {
- /* Implement print_tokens by adding child elements to
- m_parent_element. */
- for (auto iter = tokens.m_first; iter; iter = iter->m_next)
- switch (iter->m_kind)
- {
- default:
- gcc_unreachable ();
-
- case pp_token::kind::text:
- {
- pp_token_text *sub = as_a <pp_token_text *> (iter);
- /* The value might be in the obstack, so we may need to
- copy it. */
- m_xp.add_text (sub->m_value.get ());
- }
- break;
-
- case pp_token::kind::begin_color:
- {
- pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter);
- gcc_assert (sub->m_value.get ());
- m_xp.push_tag_with_class ("span", sub->m_value.get ());
- }
- break;
-
- case pp_token::kind::end_color:
- m_xp.pop_tag ("span");
- break;
-
- case pp_token::kind::begin_quote:
- {
- m_xp.add_text (open_quote);
- m_xp.push_tag_with_class ("span", "gcc-quoted-text");
- }
- break;
- case pp_token::kind::end_quote:
- {
- m_xp.pop_tag ("span");
- m_xp.add_text (close_quote);
- }
- break;
-
- case pp_token::kind::begin_url:
- {
- pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
- m_xp.push_tag ("a", true);
- m_xp.set_attr ("href", sub->m_value.get ());
- }
- break;
- case pp_token::kind::end_url:
- m_xp.pop_tag ("a");
- break;
- }
- }
-
- private:
- xml::printer m_xp;
- };
-
const int diag_idx = m_next_diag_id++;
std::string diag_id;
{
@@ -1329,6 +1330,53 @@ make_html_sink (diagnostic_context &context,
namespace selftest {
+/* Helper for writing tests of html_token_printer.
+ Printing to m_pp will appear as HTML within m_top_element, a <div>. */
+
+struct token_printer_test
+{
+ token_printer_test ()
+ : m_top_element ("div", true),
+ m_tok_printer (m_top_element)
+ {
+ m_pp.set_token_printer (&m_tok_printer);
+ }
+
+ xml::element m_top_element;
+ html_token_printer m_tok_printer;
+ pretty_printer m_pp;
+};
+
+static void
+test_token_printer ()
+{
+ {
+ token_printer_test t;
+ pp_printf (&t.m_pp, "hello world");
+ ASSERT_XML_PRINT_EQ
+ (t.m_top_element,
+ "<div>hello world</div>\n");
+ }
+
+ {
+ token_printer_test t;
+ pp_printf (&t.m_pp, "%qs: %qs", "foo", "bar");
+ ASSERT_XML_PRINT_EQ
+ (t.m_top_element,
+ "<div>"
+ "`"
+ "<span class=\"gcc-quoted-text\">"
+ "foo"
+ "</span>"
+ "&apos;: `"
+ "<span class=\"gcc-quoted-text\">"
+ "bar"
+ "</span>"
+ "&apos;"
+ "</div>\n");
+ }
+}
+
/* A subclass of html_output_format for writing selftests.
The XML output is cached internally, rather than written
out to a file. */
@@ -1394,10 +1442,8 @@ test_simple_log ()
const xml::document &doc = dc.get_document ();
- pretty_printer pp;
- doc.write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (doc,
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE html\n"
" PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
@@ -1427,10 +1473,8 @@ test_metadata ()
diagnostic_metadata metadata;
metadata.add_cwe (415);
auto element = b.make_element_for_metadata (metadata);
- pretty_printer pp;
- element->write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (*element,
"<span class=\"gcc-metadata\">"
"<span class=\"gcc-metadata-item\">"
"["
@@ -1448,10 +1492,8 @@ test_metadata ()
"http://example.com");
metadata.add_rule (rule);
auto element = b.make_element_for_metadata (metadata);
- pretty_printer pp;
- element->write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (*element,
"<span class=\"gcc-metadata\">"
"<span class=\"gcc-metadata-item\">"
"["
@@ -1470,6 +1512,7 @@ void
diagnostic_format_html_cc_tests ()
{
auto_fix_quotes fix_quotes;
+ test_token_printer ();
test_simple_log ();
test_metadata ();
}
diff --git a/gcc/selftest-xml.h b/gcc/selftest-xml.h
new file mode 100644
index 0000000..fd5c0af
--- /dev/null
+++ b/gcc/selftest-xml.h
@@ -0,0 +1,50 @@
+/* Selftest support for XML.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_SELFTEST_XML_H
+#define GCC_SELFTEST_XML_H
+
+#include "xml.h"
+
+/* The selftest code should entirely disappear in a production
+ configuration, hence we guard all of it with #if CHECKING_P. */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Assert that NODE written with indentation as xml source
+ equals EXPECTED_VALUE.
+ Use LOC for any failures. */
+
+void
+assert_xml_print_eq (const location &loc,
+ const xml::node &node,
+ const char *expected_value);
+#define ASSERT_XML_PRINT_EQ(XML_NODE, EXPECTED_VALUE) \
+ assert_xml_print_eq ((SELFTEST_LOCATION), \
+ (XML_NODE), \
+ (EXPECTED_VALUE))
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+#endif /* GCC_SELFTEST_XML_H */
diff --git a/gcc/xml.cc b/gcc/xml.cc
index 9077c1a..a23298b 100644
--- a/gcc/xml.cc
+++ b/gcc/xml.cc
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "xml-printer.h"
#include "pretty-print.h"
#include "selftest.h"
+#include "selftest-xml.h"
namespace xml {
@@ -316,14 +317,22 @@ printer::dump () const
namespace selftest {
+void
+assert_xml_print_eq (const location &loc,
+ const xml::node &node,
+ const char *expected_value)
+{
+ pretty_printer pp;
+ node.write_as_xml (&pp, 0, true);
+ ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected_value);
+}
+
static void
test_no_dtd ()
{
xml::document doc;
- pretty_printer pp;
- doc.write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (doc,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
}
@@ -343,10 +352,8 @@ test_printer ()
xp.pop_tag ("bar");
xp.pop_tag ("foo");
- pretty_printer pp;
- top.write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (top,
"<top>\n"
" <foo>\n"
" hello\n"
@@ -378,10 +385,8 @@ test_attribute_ordering ()
xp.set_attr ("naseby", "1645");
xp.pop_tag ("alphabetical");
- pretty_printer pp;
- top.write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (top,
"<top>\n"
" <chronological maldon=\"991\" hastings=\"1066\" edgehill=\"1642\" naseby=\"1645\"/>\n"
" <alphabetical edgehill=\"1642\" hastings=\"1066\" maldon=\"991\" naseby=\"1645\"/>\n"