Skip to content

test: Fix 'make cov' with clang#19709

Merged
maflcko merged 1 commit into
bitcoin:masterfrom
hebasto:200813-lcov
Aug 14, 2020
Merged

test: Fix 'make cov' with clang#19709
maflcko merged 1 commit into
bitcoin:masterfrom
hebasto:200813-lcov

Conversation

@hebasto

@hebasto hebasto commented Aug 13, 2020

Copy link
Copy Markdown
Member

This is a follow up of #19688.

With this PR it is possible to do the following:

$ ./autogen.sh
$ ./configure --enable-lcov CC=clang CXX=clang++
$ make
$ make cov

Currently, on master (8a85377), make cov fails to Processing src/test/test_bitcoin-util_tests.gcda.

@practicalswift

Copy link
Copy Markdown
Contributor

@hebasto What is the root cause of this issue? :)

@hebasto

hebasto commented Aug 13, 2020

Copy link
Copy Markdown
Member Author

@practicalswift

@hebasto What is the root cause of this issue? :)

I don't know (( See #19709 (comment)

I can just describe a pattern on which Boost Test suite and Clang's llvm-cov are incompatible: BOOST_CHECK() macro argument calls some function more then once.

@DrahtBot DrahtBot added the Tests label Aug 13, 2020
@laanwj

laanwj commented Aug 13, 2020

Copy link
Copy Markdown
Member

@hebasto What is the root cause of this issue? :)

That's pretty important to figure out imo, we can't just randomly perturb the test code to make a tool happy.
(also so that people maintaining the code in the future know what to take into account)

@fjahr

fjahr commented Aug 13, 2020

Copy link
Copy Markdown
Contributor

Agree we should know what is going on but since I have had this issue locally I have gone ahead and tested it. So, I am tACK this PR cherry-picked on top of #19688 modulo an explanation of why this failed previously. Thanks for fixing this!

@hebasto

hebasto commented Aug 13, 2020

Copy link
Copy Markdown
Member Author

@practicalswift @laanwj @fjahr

What is the root cause of this issue? :)

Thank you for forcing me to find the root of this issue!

BOOST_TEST - Limitations & workaround:

... compound statements containing any logical composition ||, &&... should be surrounded by parenthesis

To solve this issues some variants of the patch are available:

  • as suggested by Boost docs:
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -559,11 +559,10 @@ BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
                 && test_args.m_settings.ro_config[""].count("h")
                 && test_args.m_settings.ro_config[""].count("i")
                );
-    BOOST_CHECK(test_args.m_settings.ro_config["sec1"].count("ccc")
-                && test_args.m_settings.ro_config["sec1"].count("h")
-                && test_args.m_settings.ro_config["sec2"].count("ccc")
-                && test_args.m_settings.ro_config["sec2"].count("iii")
+    BOOST_CHECK(((test_args.m_settings.ro_config["sec1"].count("ccc")
+                && test_args.m_settings.ro_config["sec1"].count("h"))
+                && test_args.m_settings.ro_config["sec2"].count("ccc"))
+                && test_args.m_settings.ro_config["sec2"].count("iii")
                );
 
     BOOST_CHECK(test_args.IsArgSet("-a")
                 && test_args.IsArgSet("-b")
  • using a local variable:
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -559,11 +559,10 @@ BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
                 && test_args.m_settings.ro_config[""].count("h")
                 && test_args.m_settings.ro_config[""].count("i")
                );
-    BOOST_CHECK(test_args.m_settings.ro_config["sec1"].count("ccc")
-                && test_args.m_settings.ro_config["sec1"].count("h")
-                && test_args.m_settings.ro_config["sec2"].count("ccc")
-                && test_args.m_settings.ro_config["sec2"].count("iii")
-               );
+    bool test_value = test_args.m_settings.ro_config["sec1"].count("ccc")
+                && test_args.m_settings.ro_config["sec1"].count("h")
+                && test_args.m_settings.ro_config["sec2"].count("ccc")
+                && test_args.m_settings.ro_config["sec2"].count("iii");
+    BOOST_CHECK(test_value);
 
     BOOST_CHECK(test_args.IsArgSet("-a")
                 && test_args.IsArgSet("-b")
  • as suggested in this PR:
--- a/src/test/util_tests.cpp
+++ b/src/test/util_tests.cpp
@@ -559,11 +559,10 @@ BOOST_AUTO_TEST_CASE(util_ReadConfigStream)
                 && test_args.m_settings.ro_config[""].count("h")
                 && test_args.m_settings.ro_config[""].count("i")
                );
-    BOOST_CHECK(test_args.m_settings.ro_config["sec1"].count("ccc")
-                && test_args.m_settings.ro_config["sec1"].count("h")
-                && test_args.m_settings.ro_config["sec2"].count("ccc")
-                && test_args.m_settings.ro_config["sec2"].count("iii")
-               );
+    BOOST_CHECK(test_args.m_settings.ro_config["sec1"].count("ccc"));
+    BOOST_CHECK(test_args.m_settings.ro_config["sec1"].count("h"));
+    BOOST_CHECK(test_args.m_settings.ro_config["sec2"].count("ccc"));
+    BOOST_CHECK(test_args.m_settings.ro_config["sec2"].count("iii"));                );
 
     BOOST_CHECK(test_args.IsArgSet("-a")
                 && test_args.IsArgSet("-b")

The last variant has the following benefits:

  • no error-prone parenthesis paring
  • no redundant local variables
  • better logging

Update: but https://www.boost.org/doc/libs/1_73_0/libs/test/doc/html/boost_test/utf_reference/testing_tool_ref/assertion_boost_level.html says that for BOOST_CHECK(predicate); "it's safe to pass complex expression for validation."

@Crypt-iQ

Crypt-iQ commented Aug 14, 2020

Copy link
Copy Markdown
Contributor

Tested, code review ACK 568d42b
On ubuntu, clang-10

Changes are straightforward and they assert the same thing as they did before so should be fine.

test_bitcoin coverage: https://crypt-iq.github.io/pr19709/test_bitcoin.coverage/
total coverage: https://crypt-iq.github.io/pr19709/total.coverage/

@maflcko maflcko left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach ACK. This will also print nicer error messages in case of failure

@vasild vasild left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 568d42b

It is always better to have

assert(a);
assert(b);

instead of

assert(a && b);

due to better diagnostics in case of failure.

The patch is good as is, but if you are in a mood for it - take the suggestion below.

Comment thread src/test/util_tests.cpp Outdated
BOOST_CHECK(!test_args.IsArgSet("-zzz"));
BOOST_CHECK(!test_args.IsArgSet("-iii"));

BOOST_CHECK(test_args.GetArg("-a", "xxx") == "");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
BOOST_CHECK(test_args.GetArg("-a", "xxx") == "");
BOOST_CHECK_EQUAL(test_args.GetArg("-a", "xxx"), "");

would produce a better error message, if it fails some day.

Same in all places below where BOOST_CHECK(a == b); can be replaced with BOOST_CHECK_EQUAL(a, b);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Updated.

@hebasto

hebasto commented Aug 14, 2020

Copy link
Copy Markdown
Member Author

Updated 568d42b -> 35cd2da (pr19709.01 -> pr19709.02, diff):

Same in all places below where BOOST_CHECK(a == b); can be replaced with BOOST_CHECK_EQUAL(a, b);

@vasild

vasild commented Aug 14, 2020

Copy link
Copy Markdown
Contributor

ACK 35cd2da

1 similar comment
@Crypt-iQ

Copy link
Copy Markdown
Contributor

ACK 35cd2da

@maflcko maflcko merged commit 1a43cd3 into bitcoin:master Aug 14, 2020
@hebasto hebasto deleted the 200813-lcov branch August 14, 2020 13:02
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants