From fe0dd83ea2325526f1d3bc174b8afb772bb41b8b Mon Sep 17 00:00:00 2001 From: jce Date: Thu, 5 Dec 2024 16:22:09 +0100 Subject: [PATCH] Normalize all the line endings --- .gitattributes | 52 +++++++ tests/test_coverity.py | 218 ++++++++++++++-------------- tests/test_doxygen.py | 154 ++++++++++---------- tests/test_in/junit_double_fail.xml | 30 ++-- tests/test_xmlrunner.py | 96 ++++++------ 5 files changed, 301 insertions(+), 249 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..c5bb2afb --- /dev/null +++ b/.gitattributes @@ -0,0 +1,52 @@ +# .gitattributes snippet to force users to use same line endings for project. +# +# Handle line endings automatically for files detected as text +# and leave all files detected as binary untouched. +* text=auto + +# +# The above will handle all files NOT found below +# https://help.github.com/articles/dealing-with-line-endings/ +# https://github.com/Danimoth/gitattributes/blob/master/Web.gitattributes + + + +# These files are text and should be normalized (Convert crlf => lf) +*.php text +*.css text +*.js text +*.json text +*.htm text +*.html text +*.xml text +*.txt text +*.ini text +*.inc text +*.pl text +*.rb text +*.py text +*.scm text +*.sql text +.htaccess text +*.sh text +*.rst text +*.md text + +# These files are binary and should be left untouched +# (binary is a macro for -text -diff) +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.mov binary +*.mp4 binary +*.mp3 binary +*.flv binary +*.fla binary +*.swf binary +*.gz binary +*.zip binary +*.7z binary +*.ttf binary +*.pyc binary diff --git a/tests/test_coverity.py b/tests/test_coverity.py index 0d869bd9..f91e40d4 100644 --- a/tests/test_coverity.py +++ b/tests/test_coverity.py @@ -1,109 +1,109 @@ -import filecmp -import os -from io import StringIO -from pathlib import Path -from unittest import TestCase, mock -from unittest.mock import patch - -from mlx.warnings import WarningsPlugin, warnings_wrapper, Finding - -TEST_IN_DIR = Path(__file__).parent / 'test_in' -TEST_OUT_DIR = Path(__file__).parent / 'test_out' - - -def ordered(obj): - if isinstance(obj, dict): - return sorted((k, ordered(v)) for k, v in obj.items()) - if isinstance(obj, list): - return sorted(ordered(x) for x in obj) - else: - return obj - - -@mock.patch.dict(os.environ, { - "MIN_UNCLASSIFIED": "8", "MAX_UNCLASSIFIED": "8", - "MIN_INTENTIONAL": "1", "MAX_INTENTIONAL": "1", - "MIN_FALSE_POSITIVE": "2", "MAX_FALSE_POSITIVE": "2", -}) -class TestCoverityWarnings(TestCase): - def setUp(self): - Finding.fingerprints = {} - self.warnings = WarningsPlugin(verbose=True) - self.warnings.activate_checker_name('coverity') - - def test_no_warning_normal_text(self): - dut = 'This should not be treated as warning' - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 0) - - def test_no_warning_but_still_command_output(self): - dut = 'src/something/src/somefile.c:82: 1. misra_violation: Essential type of the left hand operand "0U" (unsigned) is not the same as that of the right operand "1U"(signed).' - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 0) - - def test_single_warning(self): - dut = '/src/somefile.c:82: CID 113396 (#2 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 1) - self.assertIn(dut, fake_out.getvalue()) - - def test_single_warning_count_one(self): - dut1 = '/src/somefile.c:80: CID 113396 (#1 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' - dut2 = '/src/somefile.c:82: CID 113396 (#2 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut1) - self.warnings.check(dut2) - self.assertEqual(self.warnings.return_count(), 1) - self.assertIn(dut2, fake_out.getvalue()) - - def test_single_warning_real_output(self): - dut1 = '/src/somefile.c:80: CID 113396 (#1 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' - dut2 = '/src/somefile.c:82: CID 113396 (#2 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' - dut3 = 'src/something/src/somefile.c:82: 1. misra_violation: Essential type of the left hand operand "0U" (unsigned) is not the same as that of the right operand "1U"(signed).' - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut1) - self.warnings.check(dut2) - self.warnings.check(dut3) - self.assertEqual(self.warnings.return_count(), 1) - self.assertIn(dut2, fake_out.getvalue()) - - def test_code_quality_without_config(self): - filename = 'coverity_cq.json' - out_file = str(TEST_OUT_DIR / filename) - ref_file = str(TEST_IN_DIR / filename) - retval = warnings_wrapper([ - '--coverity', - '--code-quality', out_file, - str(TEST_IN_DIR / 'coverity_full.txt'), - ]) - self.assertEqual(11, retval) - self.assertTrue(filecmp.cmp(out_file, ref_file)) - - def test_code_quality_with_config_pass(self): - filename = 'coverity_cq.json' - out_file = str(TEST_OUT_DIR / filename) - ref_file = str(TEST_IN_DIR / filename) - retval = warnings_wrapper([ - '--code-quality', out_file, - '--config', str(TEST_IN_DIR / 'config_example_coverity.yml'), - str(TEST_IN_DIR / 'coverity_full.txt'), - ]) - self.assertEqual(0, retval) - self.assertTrue(filecmp.cmp(out_file, ref_file)) - - @mock.patch.dict(os.environ, { - "MIN_UNCLASSIFIED": "11", "MAX_UNCLASSIFIED": "-1", - "MIN_FALSE_POSITIVE": "0", "MAX_FALSE_POSITIVE": "1", - }) - def test_code_quality_with_config_fail(self): - filename = 'coverity_cq.json' - out_file = str(TEST_OUT_DIR / filename) - ref_file = str(TEST_IN_DIR / filename) - retval = warnings_wrapper([ - '--code-quality', out_file, - '--config', str(TEST_IN_DIR / 'config_example_coverity.yml'), - str(TEST_IN_DIR / 'coverity_full.txt'), - ]) - self.assertEqual(10, retval) # 8 + 2 not within range 6 and 7 - self.assertTrue(filecmp.cmp(out_file, ref_file)) +import filecmp +import os +from io import StringIO +from pathlib import Path +from unittest import TestCase, mock +from unittest.mock import patch + +from mlx.warnings import WarningsPlugin, warnings_wrapper, Finding + +TEST_IN_DIR = Path(__file__).parent / 'test_in' +TEST_OUT_DIR = Path(__file__).parent / 'test_out' + + +def ordered(obj): + if isinstance(obj, dict): + return sorted((k, ordered(v)) for k, v in obj.items()) + if isinstance(obj, list): + return sorted(ordered(x) for x in obj) + else: + return obj + + +@mock.patch.dict(os.environ, { + "MIN_UNCLASSIFIED": "8", "MAX_UNCLASSIFIED": "8", + "MIN_INTENTIONAL": "1", "MAX_INTENTIONAL": "1", + "MIN_FALSE_POSITIVE": "2", "MAX_FALSE_POSITIVE": "2", +}) +class TestCoverityWarnings(TestCase): + def setUp(self): + Finding.fingerprints = {} + self.warnings = WarningsPlugin(verbose=True) + self.warnings.activate_checker_name('coverity') + + def test_no_warning_normal_text(self): + dut = 'This should not be treated as warning' + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 0) + + def test_no_warning_but_still_command_output(self): + dut = 'src/something/src/somefile.c:82: 1. misra_violation: Essential type of the left hand operand "0U" (unsigned) is not the same as that of the right operand "1U"(signed).' + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 0) + + def test_single_warning(self): + dut = '/src/somefile.c:82: CID 113396 (#2 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 1) + self.assertIn(dut, fake_out.getvalue()) + + def test_single_warning_count_one(self): + dut1 = '/src/somefile.c:80: CID 113396 (#1 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' + dut2 = '/src/somefile.c:82: CID 113396 (#2 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut1) + self.warnings.check(dut2) + self.assertEqual(self.warnings.return_count(), 1) + self.assertIn(dut2, fake_out.getvalue()) + + def test_single_warning_real_output(self): + dut1 = '/src/somefile.c:80: CID 113396 (#1 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' + dut2 = '/src/somefile.c:82: CID 113396 (#2 of 2): Coding standard violation (MISRA C-2012 Rule 10.1): Unclassified, Unspecified, Undecided, owner is nobody, first detected on 2017-07-27.' + dut3 = 'src/something/src/somefile.c:82: 1. misra_violation: Essential type of the left hand operand "0U" (unsigned) is not the same as that of the right operand "1U"(signed).' + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut1) + self.warnings.check(dut2) + self.warnings.check(dut3) + self.assertEqual(self.warnings.return_count(), 1) + self.assertIn(dut2, fake_out.getvalue()) + + def test_code_quality_without_config(self): + filename = 'coverity_cq.json' + out_file = str(TEST_OUT_DIR / filename) + ref_file = str(TEST_IN_DIR / filename) + retval = warnings_wrapper([ + '--coverity', + '--code-quality', out_file, + str(TEST_IN_DIR / 'coverity_full.txt'), + ]) + self.assertEqual(11, retval) + self.assertTrue(filecmp.cmp(out_file, ref_file)) + + def test_code_quality_with_config_pass(self): + filename = 'coverity_cq.json' + out_file = str(TEST_OUT_DIR / filename) + ref_file = str(TEST_IN_DIR / filename) + retval = warnings_wrapper([ + '--code-quality', out_file, + '--config', str(TEST_IN_DIR / 'config_example_coverity.yml'), + str(TEST_IN_DIR / 'coverity_full.txt'), + ]) + self.assertEqual(0, retval) + self.assertTrue(filecmp.cmp(out_file, ref_file)) + + @mock.patch.dict(os.environ, { + "MIN_UNCLASSIFIED": "11", "MAX_UNCLASSIFIED": "-1", + "MIN_FALSE_POSITIVE": "0", "MAX_FALSE_POSITIVE": "1", + }) + def test_code_quality_with_config_fail(self): + filename = 'coverity_cq.json' + out_file = str(TEST_OUT_DIR / filename) + ref_file = str(TEST_IN_DIR / filename) + retval = warnings_wrapper([ + '--code-quality', out_file, + '--config', str(TEST_IN_DIR / 'config_example_coverity.yml'), + str(TEST_IN_DIR / 'coverity_full.txt'), + ]) + self.assertEqual(10, retval) # 8 + 2 not within range 6 and 7 + self.assertTrue(filecmp.cmp(out_file, ref_file)) diff --git a/tests/test_doxygen.py b/tests/test_doxygen.py index 95f60d11..6a7ee7d4 100644 --- a/tests/test_doxygen.py +++ b/tests/test_doxygen.py @@ -1,77 +1,77 @@ -from io import StringIO -from unittest import TestCase - -from unittest.mock import patch - -from mlx.warnings import WarningsPlugin - - -class TestDoxygenWarnings(TestCase): - def setUp(self): - self.warnings = WarningsPlugin(verbose=True) - self.warnings.activate_checker_name('doxygen') - - def test_no_warning(self): - dut = 'This should not be treated as warning' - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 0) - - def test_single_warning(self): - dut = 'testfile.c:6: warning: group test: ignoring title "Some test functions" that does not match old title "Some freaky test functions"' - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 1) - self.assertRegex(fake_out.getvalue(), dut) - - def test_single_warning_mixed(self): - dut1 = 'This1 should not be treated as warning' - dut2 = 'testfile.c:6: warning: group test: ignoring title "Some test functions" that does not match old title "Some freaky test functions"' - dut3 = 'This should not be treated as warning2' - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut1) - self.warnings.check(dut2) - self.warnings.check(dut3) - self.assertEqual(self.warnings.return_count(), 1) - self.assertRegex(fake_out.getvalue(), dut2) - - def test_multiline(self): - duterr1 = "testfile.c:6: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" - duterr2 = "testfile.c:8: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" - dut = "This1 should not be treated as warning\n" - dut += duterr1 - dut += "This should not be treated as warning2\n" - dut += duterr2 - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 2) - self.assertRegex(fake_out.getvalue(), duterr1) - self.assertRegex(fake_out.getvalue(), duterr2) - - def test_git_warning(self): - duterr1 = "testfile.c:6: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" - duterr2 = "testfile.c:8: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" - dut = "warning: notes ref refs/notes/review is invalid should not be treated as warning\n" - dut += duterr1 - dut += "This should not be treated as warning2\n" - dut += duterr2 - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 2) - self.assertRegex(fake_out.getvalue(), duterr1) - self.assertRegex(fake_out.getvalue(), duterr2) - - def test_sphinx_deprecation_warning(self): - duterr1 = "testfile.c:6: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" - dut = "/usr/local/lib/python3.5/dist-packages/sphinx/application.py:402: RemovedInSphinx20Warning: app.info() "\ - "is now deprecated. Use sphinx.util.logging instead. RemovedInSphinx20Warning)\n" - dut += duterr1 - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 1) - self.assertRegex(fake_out.getvalue(), duterr1) - - def test_doxygen_warnings_txt(self): - dut_file = 'tests/test_in/doxygen_warnings.txt' - with open(dut_file, 'r') as open_file: - self.warnings.check(open_file.read()) - self.assertEqual(self.warnings.return_count(), 22) +from io import StringIO +from unittest import TestCase + +from unittest.mock import patch + +from mlx.warnings import WarningsPlugin + + +class TestDoxygenWarnings(TestCase): + def setUp(self): + self.warnings = WarningsPlugin(verbose=True) + self.warnings.activate_checker_name('doxygen') + + def test_no_warning(self): + dut = 'This should not be treated as warning' + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 0) + + def test_single_warning(self): + dut = 'testfile.c:6: warning: group test: ignoring title "Some test functions" that does not match old title "Some freaky test functions"' + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 1) + self.assertRegex(fake_out.getvalue(), dut) + + def test_single_warning_mixed(self): + dut1 = 'This1 should not be treated as warning' + dut2 = 'testfile.c:6: warning: group test: ignoring title "Some test functions" that does not match old title "Some freaky test functions"' + dut3 = 'This should not be treated as warning2' + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut1) + self.warnings.check(dut2) + self.warnings.check(dut3) + self.assertEqual(self.warnings.return_count(), 1) + self.assertRegex(fake_out.getvalue(), dut2) + + def test_multiline(self): + duterr1 = "testfile.c:6: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" + duterr2 = "testfile.c:8: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" + dut = "This1 should not be treated as warning\n" + dut += duterr1 + dut += "This should not be treated as warning2\n" + dut += duterr2 + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 2) + self.assertRegex(fake_out.getvalue(), duterr1) + self.assertRegex(fake_out.getvalue(), duterr2) + + def test_git_warning(self): + duterr1 = "testfile.c:6: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" + duterr2 = "testfile.c:8: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" + dut = "warning: notes ref refs/notes/review is invalid should not be treated as warning\n" + dut += duterr1 + dut += "This should not be treated as warning2\n" + dut += duterr2 + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 2) + self.assertRegex(fake_out.getvalue(), duterr1) + self.assertRegex(fake_out.getvalue(), duterr2) + + def test_sphinx_deprecation_warning(self): + duterr1 = "testfile.c:6: warning: group test: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" + dut = "/usr/local/lib/python3.5/dist-packages/sphinx/application.py:402: RemovedInSphinx20Warning: app.info() "\ + "is now deprecated. Use sphinx.util.logging instead. RemovedInSphinx20Warning)\n" + dut += duterr1 + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 1) + self.assertRegex(fake_out.getvalue(), duterr1) + + def test_doxygen_warnings_txt(self): + dut_file = 'tests/test_in/doxygen_warnings.txt' + with open(dut_file, 'r') as open_file: + self.warnings.check(open_file.read()) + self.assertEqual(self.warnings.return_count(), 22) diff --git a/tests/test_in/junit_double_fail.xml b/tests/test_in/junit_double_fail.xml index e1e2611a..1db29b8d 100644 --- a/tests/test_in/junit_double_fail.xml +++ b/tests/test_in/junit_double_fail.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - This time there is more content to the failure - - - - + + + + + + + + + + + This time there is more content to the failure + + + + diff --git a/tests/test_xmlrunner.py b/tests/test_xmlrunner.py index 619e6ed0..c054ee5a 100644 --- a/tests/test_xmlrunner.py +++ b/tests/test_xmlrunner.py @@ -1,48 +1,48 @@ -from io import StringIO -from unittest import TestCase - -from unittest.mock import patch - -from mlx.warnings import WarningsPlugin - - -class TestXMLRunnerWarnings(TestCase): - def setUp(self): - self.warnings = WarningsPlugin(verbose=True) - self.warnings.activate_checker_name('xmlrunner') - - def test_no_warning(self): - dut = 'This should not be treated as warning' - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 0) - - def test_single_warning(self): - dut = 'ERROR [0.000s]: test_some_error_test (something.anything.somewhere)' - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 1) - self.assertIn(dut, fake_out.getvalue()) - - def test_single_warning_mixed(self): - dut1 = 'This1 should not be treated as warning' - dut2 = 'ERROR [0.000s]: test_some_error_test (something.anything.somewhere)' - dut3 = 'This should not be treated as warning2' - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut1) - self.warnings.check(dut2) - self.warnings.check(dut3) - self.assertEqual(self.warnings.return_count(), 1) - self.assertIn(dut2, fake_out.getvalue()) - - def test_multiline(self): - duterr1 = "ERROR [0.000s]: test_some_error_test (something.anything.somewhere) \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" - duterr2 = "ERROR [0.000s]: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" - dut = "This1 should not be treated as warning\n" - dut += duterr1 - dut += "This should not be treated as warning2\n" - dut += duterr2 - with patch('sys.stdout', new=StringIO()) as fake_out: - self.warnings.check(dut) - self.assertEqual(self.warnings.return_count(), 2) - self.assertIn(duterr1, fake_out.getvalue()) - self.assertIn(duterr2, fake_out.getvalue()) +from io import StringIO +from unittest import TestCase + +from unittest.mock import patch + +from mlx.warnings import WarningsPlugin + + +class TestXMLRunnerWarnings(TestCase): + def setUp(self): + self.warnings = WarningsPlugin(verbose=True) + self.warnings.activate_checker_name('xmlrunner') + + def test_no_warning(self): + dut = 'This should not be treated as warning' + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 0) + + def test_single_warning(self): + dut = 'ERROR [0.000s]: test_some_error_test (something.anything.somewhere)' + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 1) + self.assertIn(dut, fake_out.getvalue()) + + def test_single_warning_mixed(self): + dut1 = 'This1 should not be treated as warning' + dut2 = 'ERROR [0.000s]: test_some_error_test (something.anything.somewhere)' + dut3 = 'This should not be treated as warning2' + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut1) + self.warnings.check(dut2) + self.warnings.check(dut3) + self.assertEqual(self.warnings.return_count(), 1) + self.assertIn(dut2, fake_out.getvalue()) + + def test_multiline(self): + duterr1 = "ERROR [0.000s]: test_some_error_test (something.anything.somewhere) \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" + duterr2 = "ERROR [0.000s]: ignoring title \"Some test functions\" that does not match old title \"Some freaky test functions\"\n" + dut = "This1 should not be treated as warning\n" + dut += duterr1 + dut += "This should not be treated as warning2\n" + dut += duterr2 + with patch('sys.stdout', new=StringIO()) as fake_out: + self.warnings.check(dut) + self.assertEqual(self.warnings.return_count(), 2) + self.assertIn(duterr1, fake_out.getvalue()) + self.assertIn(duterr2, fake_out.getvalue())