Is there interest in unit testing both passing and failing BOOST_MPL_ASSERTs?

This submission would make it possible to write a complete set of unit tests for meta-programs, to test both the positive, compiling statements, and the negative, non-compiling statements. These tests will all compile, and the negative tests can throw an exception instead of failing to compile. After reading the recent interest submission from Abel Sinkovics, it occurred to me that it should be possible to modify the four existing BOOST_MPL_ASSERT_* macros to achieve this capability. This behavior would only be enabled if a specific compile flag was defined. Here is a sample code fragment which I have compiled and tested to work as described: // This definition shuts off the BOOST_MPL_ASSERT compile errors, and enables the run-time errors. #define BOOST_MPL_UNITTEST_ASSERTS defined BOOST_AUTO_TEST_CASE(ordinary_passing_test_cases) { BOOST_CHECK_NO_THROW( integers_only<char> passing0; ); BOOST_CHECK_NO_THROW( integers_only<short> passing1; ); BOOST_CHECK_NO_THROW( integers_only<int> passing2; ); BOOST_CHECK_NO_THROW( integers_only<unsigned int> passing3; ); } // These test cases now actually compile, but then throw at runtime, which is unit-testable. BOOST_AUTO_TEST_CASE(fantastic_failing_test_cases) { BOOST_CHECK_THROW( integers_only<float> failing0;, boost::mpl_assert_false); BOOST_CHECK_THROW( integers_only<double> failing1;, boost::mpl_assert_false ); } As you can see, existing code which uses the four BOOST_MPL_ASSERT_* macros, can now be unit tested, without modification, for both positive, and negative use cases. Is anybody interested in this capability, and/or my modifications to the single file boost/mpl/assert.hpp which have enabled this capability? Regards, Ben Robinson, Ph.D.

on Tue Sep 13 2011, Ben Robinson <icaretaker-AT-gmail.com> wrote:
This submission would make it possible to write a complete set of unit tests for meta-programs, to test both the positive, compiling statements, and the negative, non-compiling statements. These tests will all compile, and the negative tests can throw an exception instead of failing to compile.
Is anybody interested in this capability, and/or my modifications to the single file boost/mpl/assert.hpp which have enabled this capability?
If you're just checking MPL assertions, then presumably there's a predicate that can be evaluated without throwing. Why not just feed those predicates' results to regular runtime assertions? Doesn't seem like we need a new tool. The very point of BOOST_MPL_ASSERT_* is to catch errors at compile time. If you want something else, there are plenty of appropriate choices. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Le 13/09/11 18:10, Dave Abrahams a écrit :
on Tue Sep 13 2011, Ben Robinson<icaretaker-AT-gmail.com> wrote:
Is anybody interested in this capability, and/or my modifications to the single file boost/mpl/assert.hpp which have enabled this capability? If you're just checking MPL assertions, then presumably there's a predicate that can be evaluated without throwing. Why not just feed those predicates' results to regular runtime assertions?
Doesn't seem like we need a new tool. The very point of BOOST_MPL_ASSERT_* is to catch errors at compile time. If you want something else, there are plenty of appropriate choices.
+1 Vicente

Hi Dave,
If you're just checking MPL assertions, then presumably there's a predicate that can be evaluated without throwing. Why not just feed those predicates' results to regular runtime assertions?
In addition to feeding those predicates to runtime assertions a type pretty-printing utility can be used to provide more detail on why the predicate failed. Relying on a pretty-printer rather than the compiler error messages makes the output standard across platforms/compilers and more readable in many cases. For example for the following predicate: typedef equal_to<int_<13>, function_to_test<int_<7> >::type> p; it can provide a reason like "equal_to<int_<13>, int_<11> >" compared to a verbose compiler error message containing the point somewhere. The difference becomes more significant when there are more failed predicates and a unit testing report can list and clearly separate the failed test cases (and their reasons) from each other. I found this very useful while I was developing metaprogramming libraries. This thing can be wrapped by something (template function, macro, etc) taking the predicate as a nullary metafunction. That wrapper can either give the result of the predicate and the pretty-printed reason to a runtime assertion or collect them somewhere. In the latter case, an integration tool can feed them to runtime assertions which makes template metaprogramming tests independent of the tool being used to test runtime code. Regards, Abel

On Sep 13, 2011, at 2:33 PM, Ábel Sinkovics wrote:
On Sep 13, 2011, at 12:10 PM, Dave Abrahams wrote:
If you're just checking MPL assertions, then presumably there's a predicate that can be evaluated without throwing. Why not just feed those predicates' results to regular runtime assertions?
In addition to feeding those predicates to runtime assertions a type pretty-printing utility can be used to provide more detail on why the predicate failed. Relying on a pretty-printer rather than the compiler error messages makes the output standard across platforms/compilers and more readable in many cases.
Yes. I am sold. I currently rely on compilation failure in order to determine that an assertion has **failed in the right way** - e.g. if I need to verify that a compile-time expression fails to parse, I need to see the details of why it didn't parse. Currently I can only get that by generating an error and looking over it by eye. Or more prosaically, if I do a depth-first search on a compile-time graph, and verify that I get the expected sequence, it's not good enough to have only success cases. For how do I know I'm not just doing the comparison wrong? Currently I only have examples and not proper tests for MPL.Graph, because I couldn't figure out how to automate these necessary failures. I have a few 'bad' examples which are commented out which I occasionally uncomment in order to verify those failures. Not robust! In addition to compilation failure not being unit test material, you also only get one per file which is pretty inefficient if your metaprogram spent 30 seconds just getting everything set up. One thing I'd like to clarify: I don't think anyone is talking about capturing general compilation failures and turning them into exceptions. That would be freakin' amazing if possible * but I'm pretty sure we're just talking about an exception with some type metadata (pretty-printed). It is equivalent to or can be #def'd into a static_assert. Thanks Abel & Ben, this will be a big help! Cheers, Gordon * Sounds like the kind of thing Godel proved impossible.

Yes. I am sold.
I am pleased.
One thing I'd like to clarify: I don't think anyone is talking about capturing general compilation failures and turning them into exceptions. That would be freakin' amazing if possible * but I'm pretty sure we're just talking about an exception with some type metadata (pretty-printed). It is equivalent to or can be #def'd into a static_assert.
Correct, once a compiler error is thrown, it is too late to magically
Thanks Abel & Ben, this will be a big help!
Thank you for your insight into some additional benefits of this capability. I had not considered the convenience of debugging an actual run-time call stack vs. the compiler trace. I will design this library so
convert that into a run-time exception. I am indeed talking about a conditionally compiled macro(s), which would statically assert, or generate a run-time exception, depending on a pre-processor defined flag. that by setting a single breakpoint in the library, it will always give access to the call-stack leading up to the failed assertion.
Cheers, Gordon
Ben Robinson, Ph.D.

On Sep 15, 2011, at 3:54 AM, Ben Robinson wrote:
Thank you for your insight into some additional benefits of this capability.
Thank you for making my library properly testable!
I had not considered the convenience of debugging an actual run-time call stack vs. the compiler trace. I will design this library so that by setting a single breakpoint in the library, it will always give access to the call-stack leading up to the failed assertion.
Oo. Neat. Actually I was just imagining an integrated pretty-print facility like Abel was suggesting, that puts the failed type calculation into the exception string. For example, one of my typical tests BOOST_MPL_ASSERT(( mpl::equal<preorder_adj::type, mpl::vector<A,B,C,D,E,F,G,A> > )); currently fails with depth_first_search.cpp:85:1: error: No match for 'assertion_failed( mpl_::failed ************ boost::mpl::equal< boost::mpl::v_item<G, boost::mpl::v_item<F, boost::mpl::v_item<E, boost::mpl::v_item<D, boost::mpl::v_item<C, boost::mpl::v_item<B, boost::mpl::v_item<A, boost::mpl::vector<mpl_::na>, 0>, 0>, 0>, 0>, 0>, 0>, 0> , boost::mpl::vector<A, B, C, D, E, F, G, A> >::************ )' and instead it could throw an exception that includes the gold inside the ***s. Then when running the unit test in verbose mode, I could verify that the failures are failing for the right reasons. I don't know much Boost.Test (nor have I looked closely at metatest) but it may even be possible to verify this automatically. Cheers, Gordon

Hi, The suggestions I've made are all based on a library I have already implemented: this is the metatest (sub)-library of mpllibs I mentioned on another thread (Template metaprogramming libraries). You can download and try it out. The repository is here: https://github.com/sabel83/mpllibs The source tree follows the structure of the Boost libraries but uses the mpllibs namespace (and macro prefix) instead of boost. Documentation is here: http://abel.web.elte.hu/mpllibs/metatest/index.html Examples on how to use it: in the libs/metatest/example directory of the source tree. You can find a number of the unit tests of Boost.MPL ported to use metatest in the boost_mpl_unit_test example.
BOOST_MPL_ASSERT(( mpl::equal<preorder_adj::type, mpl::vector<A,B,C,D,E,F,G,A> > ));
Gordon, you can rewrite this example using metatest: ---- #include <mpllibs/metatest/test.hpp> const mpllibs::metatest::suite_path suite("example_test_suite"); typedef mpl::equal<preorder_adj::type, mpl::vector<A,B,C,D,E,F,G,A> > my_test; MPLLIBS_ADD_TEST(suite, my_test) ---- You need a main function as well. You can use one of the already created ones (eg. "#include <mpllibs/metatest/main.hpp>"). It will show you a pretty-printed error message in case of a failure. The way the library works at the moment: instead of asserting or throwing exceptions it collects the results and pretty-printed reasons in a runtime tree structure. A main() function can browse this tree and display a report or call the assertion solution of any testing tool (such integration code for Boost.Test is included - see documentation). The reason I implemented it this way was that I could easily (by implementing/changing the integration function only) use it in any testing framework. I have tested the rest of the mpllibs libraries using this tool, you can take a look at the tests of those libraries as examples as well. Ben, your idea of throwing an exception for a failed compile-time predicate can be easily implemented in this library by using a template function taking the predicate as template argument. Note that Boost.MPL data-type support for the pretty-printer (to_stream) is proof-of-concept only in its current form. That should be implemented inside Boost.MPL instead (the rest of the libraries in mpllibs implement pretty-printing support themselves as well). If you have a chance to play with it, I'm happy to receive feedback and suggestions. Regards, Abel

on Thu Sep 15 2011, Ábel Sinkovics <abel-AT-elte.hu> wrote:
BOOST_MPL_ASSERT(( mpl::equal<preorder_adj::type, mpl::vector<A,B,C,D,E,F,G,A> > ));
Gordon, you can rewrite this example using metatest:
---- #include <mpllibs/metatest/test.hpp>
const mpllibs::metatest::suite_path suite("example_test_suite");
typedef mpl::equal<preorder_adj::type, mpl::vector<A,B,C,D,E,F,G,A> > my_test;
MPLLIBS_ADD_TEST(suite, my_test) ----
Why not use the function-type-trick with double parentheses employed by BOOST_MPL_ASSERT and avoid the need to write a separate typedef? -- Dave Abrahams BoostPro Computing http://www.boostpro.com

Why not use the function-type-trick with double parentheses employed by BOOST_MPL_ASSERT and avoid the need to write a separate typedef?
Because when there is a syntax error, the compiler can point me to the location of the error in the typedef. When I define the body of the predicate in a macro call, the compiler points me to the macro call, thus the error is more difficult to locate. Regards, Abel

Hi,
The suggestions I've made are all based on a library I have already implemented: this is the metatest (sub)-library of mpllibs I mentioned on another thread (Template metaprogramming libraries). You can download and try it out.
If you have a chance to play with it, I'm happy to receive feedback and suggestions.
Regards, Abel
Abel, it was only after looking through your library that I conceived of
On Thu, Sep 15, 2011 at 12:27 PM, Ábel Sinkovics <abel@elte.hu> wrote: this idea I am proposing, and I cited this in my original post, since I think you have done a great work there. I need to spend more time and look at it closer when I get the chance. I did want to keep the interface to this capability a single macro invocation, without any setup except a #define, since that is as close to what developers are already used to with BOOST_MPL_ASSERT_*. Also, it was my assumption that developers are also accustomed to writing test cases for when exceptions are thrown/not thrown (at least I am). I need to put something together sooner rather than later, so there is something concrete to discuss, and compare/contrast with your solution. Perhaps the best solution lied somewhere in between. I look forward to your additional feedback, and will provide my own on your implementation as soon as I can. Regards, Ben Robinson, Ph.D.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Hi Ben,
I did want to keep the interface to this capability a single macro invocation, without any setup except a #define, since that is as close to what developers are already used to with BOOST_MPL_ASSERT_*. Also, it was my assumption that developers are also accustomed to writing test cases for when exceptions are thrown/not thrown (at least I am).
When a complex predicate defined inside a macro call has a syntax error, the compiler doesn't locate it (the error message points to the macro call). In those cases defining the predicate outside macro calls makes life easier. The metatest examples contain a TEST_IF_EQUAL macro implementation (https://github.com/sabel83/mpllibs/blob/master/libs/metatest/example/misc/in...) which you can use to play with the interface and see the difference between the error messages. Pretty-printing replaces BOOST_MPL_ASSERT_NOT and BOOST_MPL_ASSERT_RELATION, since a lazy version of the not_ metafunction and comparison metafunctions can be used. In case of a failure, the pretty-printed error message is something like "equal_to<expected_value, actual_value>". metatest initially contained an extra macro for testing a predicate returning false, but I've removed it when I realised the duplicated functionality. Regards, Abel

on Tue Sep 13 2011, Ábel Sinkovics <abel-AT-elte.hu> wrote:
Hi Dave,
If you're just checking MPL assertions, then presumably there's a predicate that can be evaluated without throwing. Why not just feed those predicates' results to regular runtime assertions?
In addition to feeding those predicates to runtime assertions a type pretty-printing utility can be used to provide more detail on why the predicate failed. Relying on a pretty-printer rather than the compiler error messages makes the output standard across platforms/compilers and more readable in many cases.
Okay, point taken. But that's *not* BOOST_MPL_ASSERT. IMO you need a different macro for that purpose. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Thu, Sep 15, 2011 at 9:12 AM, Dave Abrahams <dave@boostpro.com> wrote:
Okay, point taken. But that's *not* BOOST_MPL_ASSERT. IMO you need a different macro for that purpose.
I agree. I will be creating new macros for my purposes. They will likely
conditionally forward to the BOOST_MPL_ASSERT_* macros, since they produce the most informative output when a compile error is desired. Thank you, Ben Robinson, Ph.D.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

If you're just checking MPL assertions, then presumably there's a predicate that can be evaluated without throwing. Why not just feed those predicates' results to regular runtime assertions?
Thank you for considering my proposal. You are correct in that my code has
predicates, and I do want to ship my library with these predicates evaluated by a static assert, so that uses who incorrectly use the library, receive a compile error. This library has a thorough set of unit tests, demonstrating the proper usage of the library with expected results. However, I cannot write any unit tests for regression purposes, which would validate that a false predicate result will block compilation, because of course, that unit test would not compile. When I develop code with static asserts, I generally write a number of unit tests, prove that they do not compile, and then comment them out. There is no automated regression testing. There must be other solutions to this problem I am not aware of. I considered two solutions which both basically apply the FTSE. First, the proposal I submitted allows the library author to place BOOST_MPL_ASSERT_* macros directly in the library, but then conditionally alters these macros to generate the desired run-time error in a unit test environment. The second solution would involve the library author calling a new macro/function/etc which would conditionally call the corresponding BOOST_MPL_ASSERT_* macro, or instead generate a run-time error. The second solution increases the surface area static asserts, so I favored the first solution. Doesn't seem like we need a new tool. The very point of
BOOST_MPL_ASSERT_* is to catch errors at compile time. If you want something else, there are plenty of appropriate choices.
If something already exists which meets my stated requirements above, I would greatly appreciate a pointer in the right direction. I hope I have more clearly communicated which my proposal is trying to achieve.
Thank you (really), :) Ben Robinson, Ph.D.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Tue, Sep 13, 2011 at 11:55 PM, Ben Robinson <icaretaker@gmail.com> wrote:
If you're just checking MPL assertions, then presumably there's a predicate that can be evaluated without throwing. Why not just feed those predicates' results to regular runtime assertions?
Thank you for considering my proposal. You are correct in that my code
has predicates, and I do want to ship my library with these predicates evaluated by a static assert, so that uses who incorrectly use the library, receive a compile error. This library has a thorough set of unit tests, demonstrating the proper usage of the library with expected results. However, I cannot write any unit tests for regression purposes, which would validate that a false predicate result will block compilation, because of course, that unit test would not compile.
I'm not following :( If I wanted to validate that a false predicate results, then I would do BOOST_STATIC_ASSERT(!predicate). When I develop code with static asserts, I generally write a number of unit
tests, prove that they do not compile, and then comment them out. There is no automated regression testing. There must be other solutions to this problem I am not aware of.
Okay, let me see if I understand now: You want a way for the compiler to ignore the static assertions and actually *try* to compile to errant code to ensure that you do, in fact, get a compiler error (which would normally be caught early on by the static assertion). Is that right? - Jeff

Okay, let me see if I understand now: You want a way for the compiler to ignore the static assertions and actually *try* to compile to errant code to ensure that you do, in fact, get a compiler error (which would normally be caught early on by the static assertion). Is that right?
- Jeff
Yes. That is exactly it. :)
One simple practical example I can give, is that in a library of mine, I have overloaded the free function operator+ for certain types of arguments. I then include the following in the function body:following: BOOST_MPL_ASSERT(sizof(T) == 0); This blocks the user from attempting to add these pairs of types together and it works nicely. But I need a way to write a run-time unit test which will demonstrate that this code will fail to compile, when instantiated by the user of the library. When instantiated by the unit-test framework, the code instead throws an exception. Regards, Ben Robinson, Ph.D.

On 09/14/2011 03:21 AM, Ben Robinson wrote:
But I need a way to write a run-time unit test which will demonstrate that this code will fail to compile, when instantiated by the user of the library.
Then your run-time unit test needs to invoke the compiler, right?
When instantiated by the unit-test framework, the code instead throws an exception.
How does "the code" throw an exception if it doesn't even compile? At best you're showing that some other, similar-looking, code will throw an exception. What does that really mean though? Especially for the types of things MPL is used for. - Marsh

on Wed Sep 14 2011, Ben Robinson <icaretaker-AT-gmail.com> wrote:
Okay, let me see if I understand now: You want a way for the compiler to ignore the static assertions and actually *try* to compile to errant code to ensure that you do, in fact, get a compiler error (which would normally be caught early on by the static assertion). Is that right?
- Jeff
Yes. That is exactly it. :)
One simple practical example I can give, is that in a library of mine, I have overloaded the free function operator+ for certain types of arguments. I then include the following in the function body:following:
BOOST_MPL_ASSERT(sizof(T) == 0);
No you don't :-) That shouldn't compile under any circumstances. BOOST_MPL_ASSERT takes a parenthesized type, not an integral constant expression, as an argument. BOOST_MPL_ASSERT((mpl::equal_to<int_<sizeof(T)>, int_<0> >)) might work. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Thu, Sep 15, 2011 at 9:17 AM, Dave Abrahams <dave@boostpro.com> wrote:
BOOST_MPL_ASSERT(sizof(T) == 0);
No you don't :-)
That shouldn't compile under any circumstances. BOOST_MPL_ASSERT takes a parenthesized type, not an integral constant expression, as an argument.
BOOST_MPL_ASSERT((mpl::equal_to<int_<sizeof(T)>, int_<0> >))
might work.
Sorry for the typo. I meant:
BOOST_MPL_ASSERT_MSG(sizeof(T) == 0, INFORMATIVE_NAME, (T));
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Ben Robinson <icaretaker <at> gmail.com> writes:
This submission would make it possible to write a complete set of unit tests for meta-programs, to test both the positive, compiling statements, and the negative, non-compiling statements. These tests will all compile, and the negative tests can throw an exception instead of failing to compile.
Runtime checks for compilability is rather interesting subject. Whether or not generic component compiles with different inputs is one of the expectations and it would be nice to be able to test it. Not sure how you are planning to achieve it though. Can you outline the idea? What are the limitations? Why does it have to be implemented as BOOST_MPL_ASSERT? Can it be done as a separate testing tool? We can consider it for Boost.Test. Gennadiy

On Sep 14, 2011, at 6:05 PM, Gennadiy Rozental wrote:
Why does it have to be implemented as BOOST_MPL_ASSERT? Can it be done as a separate testing tool? We can consider it for Boost.Test.
I agree that stuffing it into BOOST_MPL_ASSERT probably doesn't make sense, because that should retain its current behavior inside of tests. Test codes that don't compile now, shouldn't throw tomorrow. It also sounds like it's for more than just testing. So maybe it could go into some other headers in MPL? I do hope it integrates into Boost.Test, that's what I'd use it for.

On Wed, Sep 14, 2011 at 11:39 PM, Gordon Woodhull <gordon@woodhull.com>wrote:
On Sep 14, 2011, at 6:05 PM, Gennadiy Rozental wrote:
Why does it have to be implemented as BOOST_MPL_ASSERT? Can it be done as a separate testing tool? We can consider it for Boost.Test.
I agree that stuffing it into BOOST_MPL_ASSERT probably doesn't make sense, because that should retain its current behavior inside of tests. Test codes that don't compile now, shouldn't throw tomorrow.
I am coming around and agree as well. I will leave BOOST_MPL_ASSERT alone,
It also sounds like it's for more than just testing. So maybe it could go into some other headers in MPL? I do hope it integrates into Boost.Test, that's what I'd use it for.
It will integrate nicely not just with Boost.Test, but by any unit testing
and provide a new interface for this new functionality. framework which can catch exceptions. I suspect it belongs in Boost.Mpl, but that decision can be deferred for now. Thank you, Ben Robinson, Ph.D.

On Sep 15, 2011, at 6:19 PM, Gennadiy Rozental <rogeeff@gmail.com> wrote:
Gordon Woodhull <gordon <at> woodhull.com> writes:
It also sounds like it's for more than just testing.
What else can you use this for?
That's what I'd use it for, but Ben is talking about assertions that double as tests, so they'd go into the code proper and have different behavior in test mode. Cheers, Gordon

Gordon Woodhull <gordon <at> woodhull.com> writes:
On Sep 15, 2011, at 6:19 PM, Gennadiy Rozental <rogeeff <at> gmail.com> wrote:
Gordon Woodhull <gordon <at> woodhull.com> writes:
It also sounds like it's for more than just testing.
What else can you use this for?
That's what I'd use it for, but Ben is talking about assertions that double as
tests, so they'd go into the
code proper and have different behavior in test mode.
This is bad idea in general compile you unit test with different options than your regular build and bad idea generate different code in this case as well. Also what these statements do in regular build? Server as static asserts? Gennadiy

Gordon Woodhull <gordon <at> woodhull.com> writes:
This is bad idea in general compile you unit test with different options than your regular build and bad idea generate different code in this case as well. Also what these statements do in regular build? Server as static asserts?
In general, I agree that is is bad idea to compile code under test with different compiler flags than in production, but in this case, with the
On Thu, Sep 15, 2011 at 3:46 PM, Gennadiy Rozental <rogeeff@gmail.com>wrote: production flags, the code would fail to compile anyway, so nothing would be produced that can be run in a unit test framework. The key ingredient of my idea, is to allow the code to compile by conditionally replacing the failing static asserts with throwing a run-time exception. Now the code can compile, and unit tests can be written to confirm that each assertion either passes or fails as desired. And yes, in a production build, they are static asserts that will fail to compile if the library user instantiates something incorrectly. Regards, Ben Robinson, Ph.D.
Gennadiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Ben Robinson <icaretaker <at> gmail.com> writes:
produced that can be run in a unit test framework. The key ingredient of my idea, is to allow the code to compile by conditionally replacing the failing static asserts with throwing a run-time exception. Now the code can compile, and unit tests can be written to confirm that each assertion either passes or fails as desired.
As they say: I'll believe it, when I see it ;) Until that time this is all too much vapor for me. As I mention in other post, you never explained how this condition is checked and who is going to check it: compiler, preprocessor, person. Gennadiy

On Fri, Sep 16, 2011 at 3:19 PM, Gennadiy Rozental <rogeeff@gmail.com>wrote:
Ben Robinson <icaretaker <at> gmail.com> writes:
As they say: I'll believe it, when I see it ;) Until that time this is all too much vapor for me. As I mention in other post, you never explained how this condition is checked and who is going to check it: compiler, preprocessor, person.
Gennadiy
My written communication skills could certainly be improved, I'll try again. When compiled for production, the compiler will generate a compiler error for failing predicates/conditions which are statically asserted (exactly the same functionality as the BOOST_MPL_ASSERT_* macros). When compiled for testing, the code will compile around the predicates, and during run-time, if the predicates/conditions fail, an exception is thrown. This allows shipping the code with the usual static assert functionality, but now enables writing run-time unit tests for both regression testing, and confirming that the predicates do in fact fail when they should. Is that a better explanation? Regards, Ben Robinson, Ph.D.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Sat, Sep 17, 2011 at 1:08 AM, Ben Robinson <icaretaker@gmail.com> wrote:
On Fri, Sep 16, 2011 at 3:19 PM, Gennadiy Rozental <rogeeff@gmail.com
wrote:
Ben Robinson <icaretaker <at> gmail.com> writes:
As they say: I'll believe it, when I see it ;) Until that time this is all too much vapor for me. As I mention in other post, you never explained how this condition is checked and who is going to check it: compiler, preprocessor, person.
Gennadiy
My written communication skills could certainly be improved, I'll try again.
When compiled for production, the compiler will generate a compiler error for failing predicates/conditions which are statically asserted (exactly the same functionality as the BOOST_MPL_ASSERT_* macros).
When compiled for testing, the code will compile around the predicates, and during run-time, if the predicates/conditions fail, an exception is thrown.
This allows shipping the code with the usual static assert functionality, but now enables writing run-time unit tests for both regression testing, and confirming that the predicates do in fact fail when they should.
Is that a better explanation?
It would seem to me that, typically, removing a static_assert that would fail for a particular instantiation will just push the compiler errors further on down the code after the (removed) static_assert; i.e., the static_assert is only meant to catch compiler errors early and in a readable way. Do you have a particular use case in mind? - Jeff

On Sat, Sep 17, 2011 at 2:24 AM, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
It would seem to me that, typically, removing a static_assert that would fail for a particular instantiation will just push the compiler errors further on down the code after the (removed) static_assert; i.e., the static_assert is only meant to catch compiler errors early and in a readable way.
Do you have a particular use case in mind?
It may be necessary to add primary templates to an implementation, with a
failing static assert inside, to allow everything to compile with incorrect types, and produce the error at runtime. At this point, I have successfully determined there is indeed interest, and I will be submitting an implementation with unit tests shortly. Regards, Ben Robinson, Ph.D.
- Jeff
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Runtime checks for compilability is rather interesting subject. Whether or not generic component compiles with different inputs is one of the expectations and it would be nice to be able to test it. Not sure how you are planning to achieve it though. Can you outline the idea? What are the limitations?
Why does it have to be implemented as BOOST_MPL_ASSERT? Can it be done as a separate testing tool? We can consider it for Boost.Test.
Gennadiy
I agree with the feedback that this interface should be separate from the
BOOST_MPL_ASSERT_* family of macros. I will move the logic I have implemented out of those macros, and create a similar family of macros, for unit testing purposes. These macros will stand on their own, and should be usable as part of any C++ unit testing framework, including Boost.Test. For this discussion, let's assume these new macros have the name BOOST_MPL_UNITTEST_*. The idea is to for a meta-program author to write their programs, using BOOST_MPL_UNITTEST_* to statically assert various predicates and conditions required by the meta-program. However, when the unit-tests instantiate the code, since they will define a symbol to #ifdef on, the implementation of BOOST_MPL_UNITTEST_* will not generate a compile error, but will instead instantiate an object which will throw a run-time exception upon instantiation. This run-time error can be caught by any capable unit testing framework, allowing meta-program authors the ability to prove both the success, and failure conditions of the library under test. It also allows shipping the library with classic static assertions in place. Regards, Ben Robinson, Ph.D.

Ben Robinson <icaretaker <at> gmail.com> writes:
I agree with the feedback that this interface should be separate from the BOOST_MPL_ASSERT_* family of macros. I will move the logic I have implemented out of those macros, and create a similar family of macros, for unit testing purposes. These macros will stand on their own, and should be usable as part of any C++ unit testing framework, including Boost.Test. For this discussion, let's assume these new macros have the name BOOST_MPL_UNITTEST_*.
You obviosly free to implement this whatever way you prefer, but implementing this as Boost.Test tool involve much more that simple exception being thrown.
The idea is to for a meta-program author to write their programs,
Write their programs or unit tests? Do you intend this to be part of the library code or part of the unit test module?
using BOOST_MPL_UNITTEST_* to statically assert various predicates and conditions required by the meta-program. However, when the unit-tests instantiate the code, since they will define a symbol to #ifdef on, the
What symbol? Why do I need to do this if this statement reside in my unit test?
implementation of BOOST_MPL_UNITTEST_* will not generate a compile error, but will instead instantiate an object which will throw a run-time exception upon instantiation.
How this macro will know that code would fail to compile? I still do not see how you intend to check for compilability. Let's say I develop single parameter template class Foo. How would I check that instantiation Foo<int> fails to compile and report it at runtime? Gennadiy
participants (8)
-
Ben Robinson
-
Dave Abrahams
-
Gennadiy Rozental
-
Gordon Woodhull
-
Jeffrey Lee Hellrung, Jr.
-
Marsh Ray
-
Vicente J. Botet Escriba
-
Ábel Sinkovics