From 07459fd0e0db1d488748726d1f4accd9bac18646 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Tue, 5 Jan 2021 17:02:34 -0500 Subject: [PATCH] fix(test): clobber libxml2's global error handler before every test to check that we're setting error handlers everywhere we need to. Related to #2168 --- ext/nokogiri/nokogiri.c | 3 +++ ext/nokogiri/test_global_handlers.c | 41 +++++++++++++++++++++++++++++ test/helper.rb | 14 ++++++++++ 3 files changed, 58 insertions(+) create mode 100644 ext/nokogiri/test_global_handlers.c diff --git a/ext/nokogiri/nokogiri.c b/ext/nokogiri/nokogiri.c index 963253ad96..70ad541684 100644 --- a/ext/nokogiri/nokogiri.c +++ b/ext/nokogiri/nokogiri.c @@ -1,5 +1,7 @@ #include +void init_test_global_handlers(); /* in lieu of test_global_handlers.h */ + VALUE mNokogiri ; VALUE mNokogiriXml ; VALUE mNokogiriHtml ; @@ -132,4 +134,5 @@ void Init_nokogiri() init_xml_relax_ng(); init_nokogiri_io(); init_xml_encoding_handler(); + init_test_global_handlers(); } diff --git a/ext/nokogiri/test_global_handlers.c b/ext/nokogiri/test_global_handlers.c new file mode 100644 index 0000000000..09d3b7e400 --- /dev/null +++ b/ext/nokogiri/test_global_handlers.c @@ -0,0 +1,41 @@ +#include +#include "libxml/xmlerror.h" + +static VALUE foreign_error_handler_block = Qnil; + +static void foreign_error_handler(void* user_data, xmlErrorPtr c_error) +{ + rb_funcall(foreign_error_handler_block, rb_intern("call"), 0); +} + +/* + * call-seq: + * __foreign_error_handler { ... } -> nil + * + * Override libxml2's global error handlers to call the block. This method thus has very little + * value except to test that Nokogiri is properly setting error handlers elsewhere in the code. See + * test/helper.rb for how this is being used. + */ +static VALUE +rb_foreign_error_handler(VALUE klass) +{ + rb_need_block(); + foreign_error_handler_block = rb_block_proc(); + xmlSetStructuredErrorFunc(NULL, foreign_error_handler); + return Qnil; +} + +/* + * Document-module: Nokogiri::Test + * + * The Nokogiri::Test module should only be used for testing Nokogiri. + * Do NOT use this outside of the Nokogiri test suite. + */ +void +init_test_global_handlers() +{ + VALUE mNokogiri = rb_define_module("Nokogiri"); + VALUE mNokogiriTest = rb_define_module_under(mNokogiri, "Test"); + + rb_define_singleton_method(mNokogiriTest, "__foreign_error_handler", rb_foreign_error_handler, 0); +} diff --git a/test/helper.rb b/test/helper.rb index fc380878f2..bd08bccc4c 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -58,7 +58,16 @@ class TestCase < MiniTest::Spec XSLT_FILE = File.join(ASSETS_DIR, 'staff.xslt') XPATH_FILE = File.join(ASSETS_DIR, 'slow-xpath.xml') + def setup + @fake_error_handler_called = false + Nokogiri::Test.__foreign_error_handler do + @fake_error_handler_called = true + end if Nokogiri.uses_libxml? + end + def teardown + refute(@fake_error_handler_called, "the fake error handler should never get called") if Nokogiri.uses_libxml? + if ENV['NOKOGIRI_GC'] STDOUT.putc '!' if RUBY_PLATFORM =~ /java/ @@ -135,6 +144,11 @@ class Doc < XML::SAX::Document attr_reader :xmldecls attr_reader :processing_instructions + def initialize + @errors = [] + super + end + def xmldecl version, encoding, standalone @xmldecls = [version, encoding, standalone].compact super