[test] console_test_runner ported on *nix

Hi, I've ported console_test_runner on *nix platforms. It now should work identically both on NT and *nix. I've added Jamfile as well. Please report any issues with it on this list. Gennadiy

Hi Gennadiy ! An'n Donnerstag 18 September 2008 hett Gennadiy Rozental schreven:
I've ported console_test_runner on *nix platforms. It now should work identically both on NT and *nix. I've added Jamfile as well.
Please report any issues with it on this list.
Some minor technical issues (find patch attached) : - There's no need to declare "lib dl; " on non-NT plattforms only. That case is handled fine by current Boost.Build. - The usage of "os.name" makes cross-compiling harder, please use <target-os> - The usage of "<os>LINUX" or "<target-os>linux" implies Linux _only_, not *nix ;-(( I've changed this to <toolset>gcc as this is used on most unices and might even include darwin ;-). And no, there is no generic "unix" flavour in Boost.Build right now (that I know of.) The console-runner exe is missing a commandline help option. Otherwise I have no need for it now, but it is great that it compiles on Linux ;-)) Yours, Jürgen -- * Dipl.-Math. Jürgen Hunold ! Ingenieurgesellschaft für * voice: ++49 511 262926 57 ! Verkehrs- und Eisenbahnwesen mbH * fax : ++49 511 262926 99 ! Lister Straße 15 * juergen.hunold@ivembh.de ! www.ivembh.de * * Geschäftsführer: ! Sitz des Unternehmens: Hannover * Prof. Dr.-Ing. Thomas Siefer ! Amtsgericht Hannover, HRB 56965 * PD Dr.-Ing. Alfons Radtke !

Jürgen Hunold <juergen.hunold <at> ivembh.de> writes:
Some minor technical issues (find patch attached) :
- There's no need to declare "lib dl; " on non-NT plattforms only. That case is handled fine by current Boost.Build. - The usage of "os.name" makes cross-compiling harder, please use <target-os> - The usage of "<os>LINUX" or "<target-os>linux" implies Linux _only_, not *nix ;-(( I've changed this to <toolset>gcc as this is used on most unices and might even include darwin . And no, there is no generic "unix" flavour in Boost.Build right now (that I know of.)
Yeah. I wanted to ask about this. Your solution is still un-acceptable IMO. I want some thing that will work for any non-NT toolset. Anyone? Genandiy

Hi Gennadiy ! An'n Donnerstag 18 September 2008 hett Gennaidy Rozental schreven:
Yeah. I wanted to ask about this.
Yes, some logical operators on properties would be great. Something along !<toolset> or so...
Your solution is still un-acceptable IMO. I want some thing that will work for any non-NT toolset.
Right. Please find a (hopefully) better solution attached.It uses target alternatives to distinguish windows and non-windows platfrom. I've added an extra "test_runner_src" aliases for better maintainability in case other platforms require an extra alternative. Please note that bjam can handle libraries as sources, so no need for an extra <library>dl requirement. Testet with current trunk on SuSE-11.0 (gcc-4.3.x) and Windows XP 64 (msvc-9.0) Hope this helps ! Yours ! Jürgen -- * Dipl.-Math. Jürgen Hunold ! Ingenieurgesellschaft für * voice: ++49 511 262926 57 ! Verkehrs- und Eisenbahnwesen mbH * fax : ++49 511 262926 99 ! Lister Straße 15 * juergen.hunold@ivembh.de ! www.ivembh.de * * Geschäftsführer: ! Sitz des Unternehmens: Hannover * Prof. Dr.-Ing. Thomas Siefer ! Amtsgericht Hannover, HRB 56965 * PD Dr.-Ing. Alfons Radtke !

Hi Gennadiy, yesterday I noticed that valgrind reports an error for the boost test framework. This is for a file with a single and empty BOOST_AUTO_TEST_CASE: ==3513== Invalid read of size 4 ==3513== at 0x40936E0: boost::unit_test::framework_impl::clear() (framework.ipp:133) ==3513== by 0x409383C: boost::unit_test::framework_impl::~framework_impl() (framework.ipp:122) ==3513== by 0x42466C8: exit (in /lib/libc-2.8.so) ==3513== by 0x422F5CC: (below main) (in /lib/libc-2.8.so) ==3513== Address 0x4375ba4 is 20 bytes inside a block of size 24 free'd ==3513== at 0x402272A: operator delete(void*) (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so) ==3513== by 0x409161C: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<unsigned long const, boost::unit_test::test_unit*> >
::deallocate(std::_Rb_tree_node<std::pair<unsigned long const, boost::unit_test::test_unit*> >*, unsigned) (new_allocator.h:98) ==3513== by 0x4091651: std::_Rb_tree<unsigned long, std::pair<unsigned long const, boost::unit_test::test_unit*>, std::_Select1st<std::pair<unsigned long const, boost::unit_test::test_unit*> >, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, boost::unit_test::test_unit*> > ::_M_put_node(std::_Rb_tree_node<std::pair<unsigned long const, boost::unit_test::test_unit*> >*) (stl_tree.h:361) ==3513== by 0x40916B1: std::_Rb_tree<unsigned long, std::pair<unsigned long const, boost::unit_test::test_unit*>, std::_Select1st<std::pair<unsigned long const, boost::unit_test::test_unit*> >, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, boost::unit_test::test_unit*> > ::_M_destroy_node(std::_Rb_tree_node<std::pair<unsigned long const, boost::unit_test::test_unit*> >*) (stl_tree.h:391) ==3513== by 0x4091707: std::_Rb_tree<unsigned long, std::pair<unsigned long const, boost::unit_test::test_unit*>, std::_Select1st<std::pair<unsigned long const, boost::unit_test::test_unit*> >, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, boost::unit_test::test_unit*> > ::_M_erase(std::_Rb_tree_node<std::pair<unsigned long const, boost::unit_test::test_unit*> >*) (stl_tree.h:943) ==3513== by 0x4091746: std::_Rb_tree<unsigned long, std::pair<unsigned long const, boost::unit_test::test_unit*>, std::_Select1st<std::pair<unsigned long const, boost::unit_test::test_unit*> >, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, boost::unit_test::test_unit*> > >::clear() (stl_tree.h:697) ==3513== by 0x4093C2A: std::_Rb_tree<unsigned long, std::pair<unsigned long const, boost::unit_test::test_unit*>, std::_Select1st<std::pair<unsigned long const, boost::unit_test::test_unit*> >, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, boost::unit_test::test_unit*> > ::erase(std::_Rb_tree_iterator<std::pair<unsigned long const, boost::unit_test::test_unit*> >, std::_Rb_tree_iterator<std::pair<unsigned long const, boost::unit_test::test_unit*> >) (stl_tree.h:1356) ==3513== by 0x4093CCC: std::_Rb_tree<unsigned long, std::pair<unsigned long const, boost::unit_test::test_unit*>, std::_Select1st<std::pair<unsigned long const, boost::unit_test::test_unit*> >, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, boost::unit_test::test_unit*> > >::erase(unsigned long const&) (stl_tree.h:1345) ==3513== by 0x4093D07: std::map<unsigned long, boost::unit_test::test_unit*, std::less<unsigned long>, std::allocator<std::pair<unsigned long const, boost::unit_test::test_unit*> > >::erase(unsigned long const&) (stl_map.h:538) ==3513== by 0x408F1C3: boost::unit_test::framework::deregister_test_unit(boost::unit_test::test_unit*) (framework.ipp:326) ==3513== by 0x40B2354: boost::unit_test::test_unit::~test_unit() (unit_test_suite.ipp:65) ==3513== by 0x40935DE: boost::unit_test::test_case::~test_case() (unit_test_suite_impl.hpp:110)

Kevin Sopp <baraclese <at> googlemail.com> writes:
Hi Gennadiy,
yesterday I noticed that valgrind reports an error for the boost test framework. This is for a file with a single and empty BOOST_AUTO_TEST_CASE:
==3513== Invalid read of size 4 ==3513== at 0x40936E0: boost::unit_test::framework_impl::clear() (framework.ipp:133)
Not sure what it complains about. This line delete (test_case const*)tu.second; deletes instance to unit_test. Gennadiy

==3513== Invalid read of size 4 ==3513== at 0x40936E0: boost::unit_test::framework_impl::clear() (framework.ipp:133)
Not sure what it complains about. This line delete (test_case const*)tu.second;
deletes instance to unit_test.
Yes, I believe you delete it twice. One time via framework_impl::clear() and then ~test_unit() calls framework::deregister_test_unit( this ); which will try to erase itself from the map again. Kevin

Kevin Sopp <baraclese <at> googlemail.com> writes:
==3513== Invalid read of size 4 ==3513== at 0x40936E0: boost::unit_test::framework_impl::clear() (framework.ipp:133)
Not sure what it complains about. This line delete (test_case const*)tu.second;
deletes instance to unit_test.
Yes, I believe you delete it twice. One time via framework_impl::clear() and then ~test_unit() calls framework::deregister_test_unit( this ); which will try to erase itself from the map again.
These are two distinct operations. clear() will free test unit memory. ~test_unit() will erase itself from framework registry. clear() does not call erase(). Genandiy

What happens is that delete (test_case const*) tu.second; first invokes the test_case destructor which will erase the value referenced by tu from the map, then the delete statement continues but tu references deallocated memory now at which point valgrind complains that you do an invalid read of 4 bytes.
These are two distinct operations. clear() will free test unit memory. ~test_unit() will erase itself from framework registry. clear() does not call erase().
Genandiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Kevin Sopp <baraclese <at> googlemail.com> writes:
What happens is that delete (test_case const*) tu.second; first invokes the test_case destructor which will erase the value referenced by tu from the map, then the delete statement continues but tu references deallocated memory now at which point valgrind complains that you do an invalid read of 4 bytes.
From what I understand order of events is as follows:
1. tu.second resolved (memory accessed) 2. ~test_case() invoked 3. ~test_unit() invoked 4. framework::deregister_test_unit( this ) is invoked 5. map.erase( tu ) 6. free( ptr ) If what you saying is true we perform first step twice. Second time before 6th step. Why would compiler do this? Can you test it? just create temp pointer test_unit* tu_ptr = tu.second; before delete. Gennadiy

From what I understand order of events is as follows:
1. tu.second resolved (memory accessed) 2. ~test_case() invoked 3. ~test_unit() invoked 4. framework::deregister_test_unit( this ) is invoked 5. map.erase( tu ) 6. free( ptr )
If what you saying is true we perform first step twice. Second time before 6th step. Why would compiler do this?
Because in debug mode the compiler doesn't optimize this access. Maybe it does in release, maybe not. Maybe valgrind would still complain ;-)
Can you test it? just create temp pointer test_unit* tu_ptr = tu.second; before delete.
I had to change the code like this to make it work: // the delete will erase this element from map test_unit* tu_ptr = tu.second; m_test_units.erase( tu.second->p_id ); if( test_id_2_unit_type( tu_ptr->p_id ) == tut_suite ) delete (test_suite const*)tu_ptr; else delete (test_case const*)tu_ptr; and I commented out the deregister_test_unit() code. Or first delete the test_unit then erase tu from the map. I like to destroy objects in the opposite order in which they were created.

Kevin Sopp <baraclese <at> googlemail.com> writes:
If what you saying is true we perform first step twice. Second time before 6th step. Why would compiler do this?
Because in debug mode the compiler doesn't optimize this access. Maybe it does in release, maybe not. Maybe valgrind would still complain
I guess it's possible.
Can you test it? just create temp pointer test_unit* tu_ptr = tu.second; before delete.
I had to change the code like this to make it work:
// the delete will erase this element from map test_unit* tu_ptr = tu.second; m_test_units.erase( tu.second->p_id ); if( test_id_2_unit_type( tu_ptr->p_id ) == tut_suite ) delete (test_suite const*)tu_ptr; else delete (test_case const*)tu_ptr;
and I commented out the deregister_test_unit() code.
Or first delete the test_unit then erase tu from the map. I like to destroy objects in the opposite order in which they were created.
Why not just add test_unit* tu_ptr = tu.second; and keep everything else the same. deregister_test_unit have to be invoked from test_unit destructor for completely different reason (to handle exceptions during custom test_unit construction). Gennadiy
participants (4)
-
Gennadiy Rozental
-
Gennaidy Rozental
-
Jürgen Hunold
-
Kevin Sopp