Skip to content

Conversation

hebasto
Copy link
Member

@hebasto hebasto commented Aug 13, 2020

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
Contributor

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

@hebasto
Copy link
Member Author

hebasto commented Aug 13, 2020

@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
Copy link
Member

laanwj commented Aug 13, 2020

@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
Copy link
Contributor

fjahr commented Aug 13, 2020

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
Copy link
Member Author

hebasto commented Aug 13, 2020

@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
Copy link
Contributor

Crypt-iQ commented Aug 14, 2020

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/

Copy link
Member

@maflcko maflcko left a comment

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

Copy link
Contributor

@vasild vasild left a comment

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.

BOOST_CHECK(!test_args.IsArgSet("-zzz"));
BOOST_CHECK(!test_args.IsArgSet("-iii"));

BOOST_CHECK(test_args.GetArg("-a", "xxx") == "");
Copy link
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
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
Copy link
Member Author

hebasto commented Aug 14, 2020

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
Copy link
Contributor

vasild commented Aug 14, 2020

ACK 35cd2da

1 similar comment
@Crypt-iQ
Copy link
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