Boost.Tests: Unit test defines own main() function, why?

Hi, I would like to know why Boost's unit test framework requires that the user defines init_unit_test_suite(int, char**) (or with char *[] argument???) instead of main(). I recently had again some trouble because of it: * It broke the general autoconf test in boost.m4 as the existance of a Boost library can normally easily be tested by using boost code in main() and not init_unit_test_suite(). (Will probably be fixed soon in boost.m4.) * According to http://lists.boost.org/Archives/boost/2007/05/121601.php linkers don't look into libraries (either static or dynamic) to find main so that unit tests cannot be cimpiled as shared library. * I noticed that Debian's Boost library doesn't work for me as main() is not found in the shared library (but in the static one). I found now beside my bug report http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=456863 also http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=432921 which mainly refers to the link above. I'm not sure whether my problem is an error in Debian's packages or not but I ask why is main handled differently in Boost.test? Wouldn't it be sufficient to ask the user simple to start init_unit_test_suite() from a user specified main() to make most problems go away? Maybe it would be even OK to just start init_unit_test_suite() in the constructor of a static variable (yes, I know that the initialisation order may cause trouble with other static data). http://www.boost.org/libs/test/doc/faq.html doesn't explain it! I will now use ifdef's to easily allow using boost/test/included/unit_test.hpp as alternative to the library. Jens

On Dec 18, 2007, at 10:50 AM, Jens Seidel wrote:
Hi,
I would like to know why Boost's unit test framework requires that the user defines init_unit_test_suite(int, char**) (or with char *[] argument???) instead of main().
I recently had again some trouble because of it: * It broke the general autoconf test in boost.m4 as the existance of a Boost library can normally easily be tested by using boost code in main() and not init_unit_test_suite(). (Will probably be fixed soon in boost.m4.)
Hmm I was going to fix this today but now that you're raising this issue here, I'll wait to have a better insight of the situation before taking action. -- Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory

On Dec 18, 2007, at 11:16 AM, Benoit Sigoure wrote:
On Dec 18, 2007, at 10:50 AM, Jens Seidel wrote:
Hi,
I would like to know why Boost's unit test framework requires that the user defines init_unit_test_suite(int, char**) (or with char *[] argument???) instead of main().
I recently had again some trouble because of it: * It broke the general autoconf test in boost.m4 as the existance of a Boost library can normally easily be tested by using boost code in main() and not init_unit_test_suite(). (Will probably be fixed soon in boost.m4.)
Hmm I was going to fix this today but now that you're raising this issue here, I'll wait to have a better insight of the situation before taking action.
Hi guys, so I'm about to fix my BOOST_TEST macro that tests whether Boost.Tests can be used and linked against. Hubert Figuiere contributed the following fix. He suggested that I add: using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int argc, char ** argv) { return NULL; } Before my `main' (which reads: int main() { BOOST_CHECK(2 == 2); return 0; }) He said that this fixed the macro for Boost 1.33.1. Can anyone confirm the fix? I tested it on a Debian with 1.33.1 and it worked. I didn't find any clear conclusion in this thread and I must admit that I find this fix utterly awkward, so I'd be grateful if someone could explain it to me. In case anyone wants to test the patch, I attached it. If you have Git: git clone git://repo.or.cz/boost.m4.git # You can use http:// if you're stuck behind a nazi firewall cd boost.m4 git am 0001-Fix-the-test-for-Boost.Test.patch If you don't have Git: wget 'http://repo.or.cz/w/boost.m4.git? a=snapshot;h=59d8d8fd;sf=tgz' -O boost.m4.tgz tar xfz boost.m4.tgz cd boost.m4 patch -p1 < 0001-Fix-the-test-for-Boost.Test.patch Then in both cases, run: ./bootstrap ./configure -C make check TESTSUITEFLAGS='20 21' If you have Boost < 1.34 installed (which would be great to test with an older version of Boost such as 1.33.1), you need to change line 29 of configure.ac to this: BOOST_REQUIRE() to drop the minimum version requirement. Otherwise configure will fail (because it will try to find Boost >= 1.34). Don't forget to re- run ./bootstrap if you change configure.ac. Cheers, -- Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory

Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
On Dec 18, 2007, at 11:16 AM, Benoit Sigoure wrote: Hi guys, so I'm about to fix my BOOST_TEST macro that tests whether Boost.Tests can be used and linked against. Hubert Figuiere contributed the following fix. He suggested that I add: using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int argc, char ** argv) { return NULL; } Before my `main' (which reads: int main() { BOOST_CHECK(2 == 2); return 0; })
I can't say I understand 100% what you are trying to do here, but using Testing tools outside of the UnitTest framework might not be a good idea. In 1.35 I've implemented a check against it and it may throw an exception. Gennadiy

Hi Gennadiy, On Mon, Jan 07, 2008 at 04:26:46PM +0000, Gennadiy Rozental wrote:
On Dec 18, 2007, at 11:16 AM, Benoit Sigoure wrote: so I'm about to fix my BOOST_TEST macro that tests whether Boost.Tests can be used and linked against. Hubert Figuiere contributed the following fix. He suggested that I add: using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int argc, char ** argv) { return NULL; } Before my `main' (which reads: int main() { BOOST_CHECK(2 == 2); return 0; })
I can't say I understand 100% what you are trying to do here, but using
let me reply instead of Benoit. The aim of the code above is to be used in boost.m4 (M4 is the GNU macro package) to be used itself in configure scripts which are started on each system before the compilation starts to test the system, look for the compiler and available libraries ... Using this information a system specific Makefile is written and the build system is portable. So Benoit tries to find an easy way to test a system whether Boost.Test is available. Considering the many different system configurations (think about the CRT mess on Windows!!!) such system tests for projects using autotools are a very important step. It is in general not possible to hardcode paths, compiler options, ... as it will break on some exotic systems. With autotools compiling code is as simple as: ./configure [optional options such as --prefix=/usr/local or --with-boost=path ...] make make install This works everywhere (yes, even on the proprietary system you're using). Gennadiy, I don't understand the following:
Testing tools outside of the UnitTest framework might not be a good idea. In 1.35 I've implemented a check against it and it may throw an exception.
What does "outside of UnitTest framework" mean? Do you refer to a special namespace, the requirement to link against the boost-unittest library or what? Benoit: As Gennadiy pointed out (thanks) it is possible to define the macro whether shared or static libraries are used directly in the Makefile. I'm sorry to note that I consider it now your job to determine whether you link against the shared or static library and to set BOOST_CXXFLAGS accordingly. You probably have to check whether test code compiled with or without a user specified main function to determine this. Maybe Gennadiy can help even more by providing a single (two or three lines only) check for both? Jens

Jens Seidel <jensseidel <at> users.sf.net> writes:
So Benoit tries to find an easy way to test a system whether Boost.Test is available.
This is quite open ended question. What specifically are you trying to detect? Presence of Boost.Test headers? Presence of prebuild Boost.Test libraries (static and/or dynamic)? Presence od single header variant of Boost.Test? Presence of Unit test framework or program execution monitor or just an execution monitor. Support for specific feature in Boost.Test I would guess each require separate and different test.
What does "outside of UnitTest framework" mean? Do you refer to a special namespace, the requirement to link against the boost-unittest library or what?
No. I mean outside of test case - directly in main()
Benoit: As Gennadiy pointed out (thanks) it is possible to define the macro whether shared or static libraries are used directly in the Makefile. I'm sorry to note that I consider it now your job to determine whether you link against the shared or static library and to set BOOST_CXXFLAGS accordingly.
Depending what are you are trying to find you will need different tests and potencially different make rules.
You probably have to check whether test code compiled with or without a user specified main function to determine this. Maybe Gennadiy can help even more by providing a single (two or three lines only) check for both?
I am not quite sure what main() has to do with it. From where I stand, you don't need main() in either case. Gennadiy

Hi guys, let me just make this clear before we start: Hubert's fix (adding a `init_unit_test_suite' that returns NULL) works. That is, it enable me to link against Boost.Test < 1.34. On Jan 11, 2008, at 8:00 AM, Gennadiy Rozental wrote:
Jens Seidel <jensseidel <at> users.sf.net> writes:
So Benoit tries to find an easy way to test a system whether Boost.Test is available.
This is quite open ended question. What specifically are you trying to detect?
Presence of Boost.Test headers? Presence of prebuild Boost.Test libraries (static and/or dynamic)? Presence od single header variant of Boost.Test? Presence of Unit test framework or program execution monitor or just an execution monitor. Support for specific feature in Boost.Test
I want the smallest code that compiles and links against the greatest number of versions of Boost.Test. This test case should use the most common headers of this library and must use symbols from the library so that the resulting object file cannot be linked without having the correct -lflag. I want this test to work with as many flavors/ combinations/versions of Boost.Test as possible. Would it be possible for you to give me the smallest dumb code that exercises the most basic feature of Boost.Test + compilation and linkage against Boost.Test? Cheers, -- Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory

Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
Would it be possible for you to give me the smallest dumb code that exercises the most basic feature of Boost.Test + compilation and linkage against Boost.Test?
Test for single header variant; no need to link with the library: #define BOOST_TEST_MODULE boost.m4 #include <boost/test/included/unit_test.hpp> BOOST_AUTO_TEST_CASE( case ) { BOOST_ERROR( "expected" ); } --------------------- Standalone library variants: #define BOOST_TEST_MODULE boost.m4 #include <boost/test/unit_test.hpp> BOOST_AUTO_TEST_CASE( case ) { BOOST_ERROR( "expected" ); } This should work both for static and shared library variants. In later case you need to add BOOST_TEST_DYN_LINK to the compiler options and corresponding link options to enforce linking with shared library. Some specific features of Boost.Test (like floating point comparisons) require additional headers. We can come up with corresponding tests as well. Gennadiy

On Jan 11, 2008, at 7:50 PM, Gennadiy Rozental wrote:
Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
Would it be possible for you to give me the smallest dumb code that exercises the most basic feature of Boost.Test + compilation and linkage against Boost.Test?
Test for single header variant; no need to link with the library:
#define BOOST_TEST_MODULE boost.m4 #include <boost/test/included/unit_test.hpp>
BOOST_AUTO_TEST_CASE( case ) { BOOST_ERROR( "expected" ); }
---------------------
Standalone library variants:
#define BOOST_TEST_MODULE boost.m4 #include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE( case ) { BOOST_ERROR( "expected" ); }
This should work both for static and shared library variants. In later case you need to add BOOST_TEST_DYN_LINK to the compiler options and corresponding link options to enforce linking with shared library.
Some specific features of Boost.Test (like floating point comparisons) require additional headers. We can come up with corresponding tests as well.
Thanks for your code. It grieves me that Boost.Test is the *only* library for which I have to write "special cases" only because it's not "well-behaved". -- Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory

On Jan 12, 2008, at 3:26 AM, Gennadiy Rozental wrote:
Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
Thanks for your code. It grieves me that Boost.Test is the *only* library for which I have to write "special cases" only because it's not "well-behaved".
In what sence? How do you define well behaved?
What is this whole thread about? Boost.Test is non standard because it messes up your `main' and must be used differently whether you're linking with it as a shared library or a static archive. -- Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory

"Benoit Sigoure" <tsuna@lrde.epita.fr> wrote in message news:805924BB-31B0-44E8-88CE-9538D89B082C@lrde.epita.fr...
On Jan 12, 2008, at 3:26 AM, Gennadiy Rozental wrote:
Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
Thanks for your code. It grieves me that Boost.Test is the *only* library for which I have to write "special cases" only because it's not "well-behaved".
In what sence? How do you define well behaved?
What is this whole thread about? Boost.Test is non standard because it messes up your `main'
Why do you care? how does it make Boost.Test behave badly?
and must be used differently whether you're linking with it as a shared library or a static archive.
As you have seen in my example, it is exactly the same for both usage variants. The only difference is additional macro in makefile. But, than, link command is going to be different anyway. Gennadiy

On Mon, Jan 14, 2008 at 01:16:51AM -0500, Gennadiy Rozental wrote:
"Benoit Sigoure" <tsuna@lrde.epita.fr> wrote in message news:805924BB-31B0-44E8-88CE-9538D89B082C@lrde.epita.fr...
On Jan 12, 2008, at 3:26 AM, Gennadiy Rozental wrote:
Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
Thanks for your code. It grieves me that Boost.Test is the *only* library for which I have to write "special cases" only because it's not "well-behaved".
In what sence? How do you define well behaved?
What is this whole thread about? Boost.Test is non standard because it messes up your `main'
Why do you care? how does it make Boost.Test behave badly?
Normally one is able to test for the existence of a library by just calling a function inside main() or by creating an instance of a special type: #include <required_lib_header.h> int main(int argc, char* argv[]) { double a = function_from_lib(); type_in_lib object; } If this links successfully (using current compiler flags maybe after extented with -l <libname>) one can be sure that the library is properly installed. This is a very common task. That's why Autoconf provides a macro AC_TRY_LINK which expects the arguments "#include <required_lib_header.h>" and the body of main. A example of one of my configure.ac files (the last two arguments specify the code used if the linkage works or not, resp., I nested it): AC_TRY_LINK([#include <math.h>], [double f=3.14; return isnan(f);],, [AC_TRY_LINK([#include <math.h> int __isnand(double x) { return x != x; }], [double f=3.14; return isnan(f);], AC_DEFINE(NEED___ISNAND, 1, [Use own implementation of __isnand (cygwin)]))]) Beeing forced to also write int main(int argc, char* argv[]) { } is just not required for nearly all library tests and error prone. This is probably the argument of Benoit. He also wrapped AC_TRY_LINK to simplify his tests (it is necessary to test all library variants (multithreaded or not, ...) so a own macro makes sense) and expects a single header file name only. See e.g. the following excerpt of boost.m4: # BOOST_WAVE([PREFERRED-RT-OPT]) # ------------------------------ # Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the # documentation of BOOST_FIND_LIB above. AC_DEFUN([BOOST_WAVE], [BOOST_FIND_LIB([wave], [$1], [boost/wave.hpp], [boost::wave::token_id id; get_token_name(id);])]) There is in general no guarantee that a single header file is sufficent for a test but it worked for all other Boost libraries as well. That's why he was looking for the most simple test.
and must be used differently whether you're linking with it as a shared library or a static archive.
As you have seen in my example, it is exactly the same for both usage variants. The only difference is additional macro in makefile. But, than, link command is going to be different anyway.
No, you're wrong. There is no need to specify different link commands for shared or static libraries in general. I tried to compile your proposed test: #define BOOST_TEST_MODULE boost.m4 #include <boost/test/unit_test.hpp> BOOST_AUTO_TEST_CASE( MyCase ) { BOOST_ERROR( "expected" ); } Normally (for at least 95% of all libraries) one just adds -l <libname> to get it compile: $ g++ test.cpp -lboost_unit_test_framework /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: ld returned 1 exit status It works indeed well with $ g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework Once I remove /usr/lib/libboost_unit_test_framework.so so that only the static library /usr/lib/libboost_unit_test_framework.a (which is a symbolic (filesystem) link to libboost_unit_test_framework-gcc41-1_34_1.a in Debian testing) exists one can also (normally) just specify -l <libname>. But I get: $ g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework /tmp/ccKcB2Ps.o: In function `main': test.cpp:(.text+0x3d4): undefined reference to `boost::unit_test::unit_test_main(bool (*)(), int, char**)' /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/libboost_unit_test_framework.a(framework.o): In function `boost::unit_test::framework::init(int, char**)': (.text+0x6fa): undefined reference to `init_unit_test_suite(int, char**)' collect2: ld returned 1 exit status Without -DBOOST_TEST_DYN_LINK $ g++ test.cpp -lboost_unit_test_framework it works. You're right that it is also possible to enforce using the static library (even if the shared one exists) by using different arguments: $ g++ test.cpp /usr/lib/libboost_unit_test_framework.a But in general everyone probably just uses -l <libname> and let's the compiler decide (which defaults to shared library variant if available). This normally works even if only one variant of a library is installed except with Boost.Test. Jens

On Jan 14, 2008, at 9:31 AM, Jens Seidel wrote:
$ g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework /tmp/ccKcB2Ps.o: In function `main': test.cpp:(.text+0x3d4): undefined reference to `boost::unit_test::unit_test_main(bool (*)(), int, char**)' /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/ libboost_unit_test_framework.a(framework.o): In function `boost::unit_test::framework::init(int, char**)': (.text+0x6fa): undefined reference to `init_unit_test_suite(int, char**)' collect2: ld returned 1 exit status
I /worked around/ this issue by always defining a dummy init_unit_test_suite symbol (which was an idea and a contribution of Hubert Figuiere). This seems totally wrong to me but "It Gets The Job Done". I'm just sad that I have to write such kludge to satisfy the weird need of a library. Most of the lib I know which need to interact directly with `main' require you to invoke a function directly from within main. Qt is a great example, you must instantiate a QApplication and give it argc and argv. It's a very common idiom. Yet Boost.Test decided that it was a good idea to embed a `main' in a library (!). What if I want to link with two libraries that decided that it was their own right to define `main'? Come on, this is almost ridiculous and it seems that Gennadiy is not willing to make any effort to understand the problem. Gennadiy, don't take this remark as an attack against you, I have nothing against you, it's just that you don't seem to be inclined to understand the issue. -- Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory

Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
On Jan 14, 2008, at 9:31 AM, Jens Seidel wrote:
$ g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework /tmp/ccKcB2Ps.o: In function `main': test.cpp:(.text+0x3d4): undefined reference to `boost::unit_test::unit_test_main(bool (*)(), int, char**)' /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/ libboost_unit_test_framework.a(framework.o): In function `boost::unit_test::framework::init(int, char**)': (.text+0x6fa): undefined reference to `init_unit_test_suite(int, char**)' collect2: ld returned 1 exit status
I /worked around/ this issue by always defining a dummy init_unit_test_suite symbol (which was an idea and a contribution of Hubert Figuiere). This seems totally wrong to me but "It Gets The
It *is* totally wrong.
Job Done". I'm just sad that I have to write such kludge to satisfy the weird need of a library. Most of the lib I know which need to
You don't. You just misuse the library. Did you try snippets I recommend?
interact directly with `main' require you to invoke a function directly from within main. Qt is a great example, you must instantiate a QApplication and give it argc and argv. It's a very common idiom. Yet Boost.Test decided that it was a good idea to embed a `main' in a library (!). What if I want to link with two libraries that decided that it was their own right to define `main'? Come on, this is almost ridiculous and it seems that Gennadiy is not willing to make any effort to understand the problem.
I understand perfectly your problem. It seems you are not willing to listen to the solution I present. You need to understand I am long time in this buseness. I heard and thought of most possible issues with desing of the library. This one is pretty old. I believe that though solution I came up with may not be ideal for all involved, is the best under circomstances. 1. Embedding main into libtary has it's perks. Would you need to implement the same main() routine 10 times a day for a year, I can imagine you would also look for some way to avoid it. Avoiding to explain test runner API helps as well. It shortens learning curve for new users. 2. My primary limitation is to be portable. 3. Starting 1.34 there is a valid simple solution to the situation above: use shared library and you are good. Gennadiy

On Jan 14, 2008, at 5:35 PM, Gennadiy Rozental wrote:
Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
interact directly with `main' require you to invoke a function directly from within main. Qt is a great example, you must instantiate a QApplication and give it argc and argv. It's a very common idiom. Yet Boost.Test decided that it was a good idea to embed a `main' in a library (!). What if I want to link with two libraries that decided that it was their own right to define `main'? Come on, this is almost ridiculous and it seems that Gennadiy is not willing to make any effort to understand the problem.
I understand perfectly your problem. It seems you are not willing to listen to the solution I present. You need to understand I am long time in this buseness. I heard and thought of most possible issues with desing of the library. This one is pretty old. I believe that though solution I came up with may not be ideal for all involved, is the best under circomstances.
1. Embedding main into libtary has it's perks. Would you need to implement the same main() routine 10 times a day for a year, I can imagine you would also look for some way to avoid it. Avoiding to explain test runner API helps as well. It shortens learning curve for new users.
2. My primary limitation is to be portable.
3. Starting 1.34 there is a valid simple solution to the situation above: use shared library and you are good.
Look, you seem to believe that static and dynamic linking ought to be totally different. That's a point on which we disagree. In modern build systems, the user must be able to switch from one to the other transparently. The build system takes care of adjusting the -lflags or whatever. Your library requires extra special steps to make this work, it's just annoying. I still think that embedding `main' in a library is wrong, and should I be in your situation of `same main() routine for 10 times a day' I'd make my `main' a one liner the way we delegate it to a QApplication for instance. Your method that works for 1.34 is not good for me, I provide a *generic* build system tool which ought to work no matter which version of Boost you use, no matter which compiler you use, no matter whether you want to link dynamically or statically against the library. I know you surely have good reasons for having done so, nevertheless I still think this design goes against "standard" expectations. And once again, if everyone was to reason like you and said "OK let's factor `main' in a library" we'd end up with a big mess when trying to link with 2+ libraries that define their own `main'... -- Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory

Jens Seidel <jensseidel <at> users.sf.net> writes:
On Mon, Jan 14, 2008 at 01:16:51AM -0500, Gennadiy Rozental wrote:
"Benoit Sigoure" <tsuna <at> lrde.epita.fr> wrote in message news:805924BB-31B0-44E8-88CE-9538D89B082C <at> lrde.epita.fr...
On Jan 12, 2008, at 3:26 AM, Gennadiy Rozental wrote:
Benoit Sigoure <tsuna <at> lrde.epita.fr> writes:
Thanks for your code. It grieves me that Boost.Test is the *only* library for which I have to write "special cases" only because it's not "well-behaved".
In what sence? How do you define well behaved?
What is this whole thread about? Boost.Test is non standard because it messes up your `main'
Why do you care? how does it make Boost.Test behave badly?
Normally one is able to test for the existence of a library by just calling a function inside main() or by creating an instance of a special type:
[...]
Beeing forced to also write
int main(int argc, char* argv[]) {
}
is just not required for nearly all library tests and error prone. This
You are not required to do above with Boost.Test. In fact it's plain wrong for your purposes.
and must be used differently whether you're linking with it as a shared library or a static archive.
As you have seen in my example, it is exactly the same for both usage variants. The only difference is additional macro in makefile. But, than, link command is going to be different anyway.
No, you're wrong. There is no need to specify different link commands for shared or static libraries in general.
I disagree. In general you do need to specify what you want to link with. The fact that your compiler allows some shortcuts and "smart" enough to have some defaults doesn't make it general.
I tried to compile your proposed test:
#define BOOST_TEST_MODULE boost.m4 #include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE( MyCase ) { BOOST_ERROR( "expected" ); }
Normally (for at least 95% of all libraries) one just adds -l <libname> to get it compile:
$ g++ test.cpp -lboost_unit_test_framework /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: ld returned 1 exit status
You need to enforce static library here *with link options*.
It works indeed well with $ g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework
as expected
Once I remove /usr/lib/libboost_unit_test_framework.so so that only the static library /usr/lib/libboost_unit_test_framework.a (which is a symbolic (filesystem) link to libboost_unit_test_framework-gcc41-1_34_1.a in Debian testing) exists one can also (normally) just specify -l <libname>. But I get:
$ g++ -DBOOST_TEST_DYN_LINK test.cpp -lboost_unit_test_framework /tmp/ccKcB2Ps.o: In function `main': test.cpp:(.text+0x3d4): undefined reference to `boost::unit_test::unit_test_main(bool (*)(), int, char**)' /usr/lib/gcc/i486-linux- gnu/4.2.3/../../../../lib/libboost_unit_test_framework.a(framework.o): In function `boost::unit_test::framework::init(int, char**)': (.text+0x6fa): undefined reference to `init_unit_test_suite(int, char**)' collect2: ld returned 1 exit status
Why would you expect it to work? You specified dynamic library, but linking with static.
Without -DBOOST_TEST_DYN_LINK $ g++ test.cpp -lboost_unit_test_framework it works.
As expected. It would have work from the begininng would you specify -static (if I am not mistaken) during linking.
You're right that it is also possible to enforce using the static library (even if the shared one exists) by using different arguments: $ g++ test.cpp /usr/lib/libboost_unit_test_framework.a
You should be able to do it without absilute path to the library.
But in general everyone probably just uses -l <libname> and let's the compiler decide (which defaults to shared library variant if available). This normally works even if only one variant of a library is installed except with Boost.Test.
The real cause of the problem is that both static and dynamic library have the same name in *nix. So you need to specify which one you need explicetly. I hope by now you should understand why static library behaves the way it is. All you need to work without problem is to stop relying on linker guessing what library to link with and explicetly specify it (and stop misusing the library - saying you want dynamic, but supplying static is not gonna work). Gennadiy

Jens Seidel <jensseidel <at> users.sf.net> writes:
Hi,
I would like to know why Boost's unit test framework requires that the user defines init_unit_test_suite(int, char**) (or with char *[] argument???) instead of main().
It doesn't. At least not always.
I recently had again some trouble because of it: * It broke the general autoconf test in boost.m4 as the existance of a Boost library can normally easily be tested by using boost code in main() and not init_unit_test_suite(). (Will probably be fixed soon in boost.m4.)
I can't comment on this, since I am not familiar with autoconf.
* According to http://lists.boost.org/Archives/boost/2007/05/121601.php linkers don't look into libraries (either static or dynamic) to find main so that unit tests cannot be cimpiled as shared library.
They do. On *nix platforms you can put main both in shared and static libs. On NT only static. This was a source of inconsistency till 1.34.1, so starting that release I've removed main from shared library builds on all platforms. And that was the problem in post above (plus the fact that gcc prefers shared library to static one if both exist with hte same name)
* I noticed that Debian's Boost library doesn't work for me as main() is not found in the shared library (but in the static one). I found now beside my bug report http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=456863 also http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=432921 which mainly refers to the link above.
It's not a bug. It's a feature. ;) Starting 1.34.1 main() doesn't reside in shared libs.
I'm not sure whether my problem is an error in Debian's packages or not but I ask why is main handled differently in Boost.test?
See above.
Wouldn't it be sufficient to ask the user simple to start init_unit_test_suite() from a user specified main() to make most problems go away?
Maybe it would be even OK to just start init_unit_test_suite() in the constructor of a static variable (yes, I know that the initialisation order may cause trouble with other static data).
Jens, to be frank with you, I am not quite sure what you are complaining about: absence of main or presence of one. In any case Boost.Test supports what you want. In many, many cases you don't need init_.. function anymore and boost test provides a way for users to get away without it and function main() as well both with static and shared library usage variant of the UTF. If you prefer to define main youself and invoke init function you can do it as well with shared library variant. Please look for more details here: http://www.patmedia.net/~rogeeff/html/index.html Please let me know if there is any issues still. Genandiy

On Tue, Dec 18, 2007 at 03:46:29PM +0000, Gennadiy Rozental wrote:
Jens Seidel <jensseidel <at> users.sf.net> writes:
I would like to know why Boost's unit test framework requires that the user defines init_unit_test_suite(int, char**) (or with char *[] argument???) instead of main().
It doesn't. At least not always.
OK.
I recently had again some trouble because of it: * It broke the general autoconf test in boost.m4 as the existance of a Boost library can normally easily be tested by using boost code in main() and not init_unit_test_suite(). (Will probably be fixed soon in boost.m4.)
I can't comment on this, since I am not familiar with autoconf.
This is not necessary. I just mentioned that I thought I observed that instead of an ordinary main() function init_unit_test_suite() needs to be defined which is just different from normal coding.
* According to http://lists.boost.org/Archives/boost/2007/05/121601.php linkers don't look into libraries (either static or dynamic) to find main so that unit tests cannot be cimpiled as shared library.
They do. On *nix platforms you can put main both in shared and static libs. On NT only static. This was a source of inconsistency till 1.34.1, so starting that release I've removed main from shared library builds on all platforms.
And why are static and shared libraries handled differently? Why not just removing main also from static libraries? Should code really behave differently depending how it is linked (which is just a build configuration)? Do there exist other (non-Boost) libraries which do such stuff?
It's not a bug. It's a feature. ;) Starting 1.34.1 main() doesn't reside in shared libs.
Is this change documented? Where can I find the Changelog? Did you also consider using a stable ABI (application binary interface, would allow a binary to be used with different library version without need to recompile) or API (application programming interface, no need to change the source code to be able to compile against a new version of a library) (at least some time in the future) which would make incompatibilities between shared and static libraries impossible and simplifies using different versions of Boost a lot? Whenever I try another Boost version existing code fails to compile or link ... The problem is that the example in the official documentation (which is (or should be) on www.boost.org not somewhere outside) just contains: "the Unit Test Framework is responsible for supplying function main()" Even if you consider that to be outdated (again: Why do you not update it??????) you should assume that most code arround does not provide main() and fails that's why starting with recent versions. According to the updated documentation (http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-runners.html) using the static library results in int main(int argc, char* argv[]) { return unit_test_main(argc, argv); } whereas the shared library uses int unit_test_main( bool (*init_unit_test_func)(), int argc, char* argv[] ); How could I define my own main function which is compatible with shared and dynamic libraries? unit_test_main has different signatures!? Probably I have to define BOOST_TEST_MAIN and let Boost create main. Let's hope this works for all linking options (shared/static).
In any case Boost.Test supports what you want. In many, many cases you don't need init_.. function anymore and boost test provides a way for users to get away without it and function main() as well both with static and shared library usage variant of the UTF. If you
OK. This is probably preferred.
prefer to define main youself and invoke init function you can do it as well with shared library variant.
The main problem is that I miss a porting guide. Is there a need to change the code, are some changes suggested, others required? How do I ensure that this changed code is compatible with as many versions of Boost as possible? I have really problems ignoring http://www.boost.org/libs/test/doc/components/utf/index.html as I consider this the offical documentation for Boost.Test. But it contradicts in some parts with your updated one!
Please look for more details here:
http://www.patmedia.net/~rogeeff/html/index.html
Please let me know if there is any issues still.
Problem with your updated documentation: http://www.patmedia.net/~rogeeff/html/utf/user-guide/usage-variants/static-l... <quote> For a test module to be able to link with prebuilt library, the flag BOOST_TEST_ALTERNATIVE_INIT_API has to be defined both during library and a test module compilation. </quote> Hm, strange. Above I read that I can optionally define BOOST_TEST_ALTERNATIVE_INIT_API or not. Maybe you want to inform that BOOST_TEST_ALTERNATIVE_INIT_API needs to be (un)defined for both - compiling the library and a test module compilation, e.g. it is invalid to compile the first with this macro defined and the test module without? http://www.patmedia.net/~rogeeff/html/utf/user-guide/usage-variants/dynamic-... <quote> This variant requires you to define the flag BOOST_TEST_DYN_LINK either in a makefile or before the header boost/test/unit_test.hpp inclusion. </quote> Is there really a need to define BOOST_TEST_DYN_LINK or does it just simplify linking on the proprietary win32 platform? Again: Why are static and shared libraries handled differently? It shouldn't matter! Let me summarize: There is old and new documention which contradict each other and there is shared ans static code. So I wonder whether it's possible to work with a single code base. Jens

Hi, I know it may no longer fit on this list but as I started here let's not move the list ... I read most of the new documentation but to make it short: I still fail to use unit tests. It worked in the past but after a lot of changes in Boost.Tests it is now unusable for me. On Wed, Dec 19, 2007 at 10:02:39AM +0100, Jens Seidel wrote:
On Tue, Dec 18, 2007 at 03:46:29PM +0000, Gennadiy Rozental wrote:
Jens Seidel <jensseidel <at> users.sf.net> writes:
I recently had again some trouble because of it: * It broke the general autoconf test in boost.m4 as the existance of a Boost library can normally easily be tested by using boost code in main() and not init_unit_test_suite(). (Will probably be fixed soon in boost.m4.)
Benoit: Have fun updating boost.m4. Additionally you have now to care about incompatible differences in recent versions, different handling depending on linkage and probably more. It will be interesting to see you solving this for all possibilities :-)
* According to http://lists.boost.org/Archives/boost/2007/05/121601.php linkers don't look into libraries (either static or dynamic) to find main so that unit tests cannot be cimpiled as shared library.
It's not a bug. It's a feature. ;) Starting 1.34.1 main() doesn't reside in shared libs.
In any case Boost.Test supports what you want. In many, many cases you don't need init_.. function anymore and boost test provides a way for users to get away without it and function main() as well both with static and shared library usage variant of the UTF. If you
OK. This is probably preferred.
But now I wonder why I should make a lot of incompatibles changes? I want my program and all tests beeing able to compile everywhere with (nearly) all versions of Boost. Using some small code parts condionally depending on autotools system and Boost tests (version of boost, shared library is available?, ...) would be acceptable but I'm no willing to make major changes to my code.
prefer to define main youself and invoke init function you can do it as well with shared library variant.
And how?
Please look for more details here:
http://www.patmedia.net/~rogeeff/html/index.html
Please let me know if there is any issues still.
I read again carefully the documentation (http://www.patmedia.net/~rogeeff/html) which exists in parallel to http://www.boost.org/libs/test/doc and can confirm that the problem that main() is not found still exists! Including the header boost/test/included/unit_test.hpp *once* per binary seems to work but normal using of boost/test/unit_test.hpp together with an additional #define BOOST_TEST_DYN_LINK still leads to a missing main() function. I get since 1.34.1: /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: ld returned 1 exit status I defined also a dummy main function (just to make the linker happy as I assumed the tests are maybe started in the contructor of a static variable) but my test is not called. Even calling init_unit_test_suite() from main() does not work. I also defined BOOST_TEST_DYN_LINK on the comandline to ensure that all code uses it. Same result! Defining addionally BOOST_TEST_MAIN results in a a proper empty test with the output "Test setup error: test tree is empty" I thought I have also seen a conflict with my own init_unit_test_suite() implementation if I define BOOST_TEST_MAIN but cannot reproduce it. A question: Would it be save to define BOOST_TEST_DYN_LINK also for static linkage? I hope so as I have never, really never used different code depending on linker options. Even after renaming my main test_suite* init_unit_test_suite(int, char *[]) function into bool init_unit_test() (but only for dynamic linkage?) as noticed on http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html I fail as usual. Short: In the past it was so simple: #include <boost/test/unit_test.hpp> using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int, char *[]) { test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(BOOST_TEST_CASE(&JacobiTest1)); return test; } Now I use * Additional autoconf code to define HAVE_UNIT_TEST_LIB if the (shared?) library is used. #ifdef HAVE_CONFIG_H #include <config.h> // HAVE_UNIT_TEST_LIB #endif #ifdef HAVE_UNIT_TEST_LIB # define BOOST_TEST_DYN_LINK # include <boost/test/unit_test.hpp> #else # include <boost/test/included/unit_test.hpp> #endif using boost::unit_test::test_suite; bool init_unit_test() { // my old init_unit_test_suite code } /* int main(int argc, char *argv[]) { init_unit_test_suite(argc, argv); return 0; } */ I'm now really tired and stoped. A more or less easy to use library (I had to follow only same advises on http://www.boost.org/libs/test/doc/components/utf/index.html) is now more or less unusable. The code depends on the linkage, the documentation can be found outside of the boost.org domain, the required information is wrong and incomplete and addionally scattered across multiple pages such as http://www.patmedia.net/~rogeeff/html/utf/compilation.html http://www.patmedia.net/~rogeeff/html/utf/compilation/direct-include.html http://www.patmedia.net/~rogeeff/html/utf/user-guide/usage-variants.html (and all referenced sub pages) http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-runners.html http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html To show you that I really read (at least up to UTF) the documenation I mention a few errors in it: http://www.patmedia.net/~rogeeff/html/faq.html: * "provide provide" * "link with libunit_test_framework.lib" that's platform specific!!! * "The reasons for this error is that in your implementation you should specify second argument of init_unit_test_suite exactly as in a specification, i.e.: char* []." s/as in a specification/as in the specification/ (I first read e.g. instead of i.e. which confused me even more, maybe you should avoid "i.e.".) http://www.patmedia.net/~rogeeff/html/open-issues.html * "Finish update for CLA support" What is CLA? * Remove two or three full stops in the enumeration * "Better Unicode support (reports and log in wostream)" Sorry, I don't see any relation of wostream and Unicode! You mean UTF16 encoding? UTF8 should work fine with both ostream and wostream, right? http://www.patmedia.net/~rogeeff/html/execution-monitor.html * "Also The Execution Monitor" s/The/the/ http://www.patmedia.net/~rogeeff/html/execution-monitor/reference.html * Page misses a "next" link to http://www.patmedia.net/~rogeeff/html/boost/execution_exception.html http://www.patmedia.net/~rogeeff/html/prg-exec-monitor/impl.html * Link to libs/test/execution_monitor.cpp does not work * "wraps a several system headers" s/a// http://www.patmedia.net/~rogeeff/html/minimal.html * "other then include boost/test/minimal.hpp" s/include/including/ * "This approach is are similar" (belongs to folded text for example 4) s/are// http://www.patmedia.net/~rogeeff/html/tutorials/intro-in-testing.html * "why testing worth the effort" s/testing/testing is/ http://www.patmedia.net/~rogeeff/html/tutorials/new-year-resolution.html * s/BOOST_AUTO_EST_CASE/BOOST_AUTO_TEST_CASE/ * "As a result my test suite became to look like this:" Wrong example!!! data_access_test() was expected http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html * "Alternatively in you can employ" s/in// * "with the static library or single-header variants of the UTF requires the specific function specification." Check this! s/specification/signature/, s/specific/original/? Per accident (used wrong browser window) I read also partely the old documentation: http://www.boost.org/libs/test/doc/components/utf/index.html * s/messy a error/messy error/ * "The framework" ... "provides function main() that initialize the framework" That's wrong! * Example file "unit_test_example1.cpp" does not exist on your server (error 404). Jens

"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071220161635.GA515@imkf-pc073.imkf.tu-freiberg.de...
Hi,
I know it may no longer fit on this list but as I started here let's not move the list ...
I read most of the new documentation but to make it short: I still fail to use unit tests. It worked in the past but after a lot of changes in Boost.Tests it is now unusable for me.
Let's see concrete examples.
* According to http://lists.boost.org/Archives/boost/2007/05/121601.php linkers don't look into libraries (either static or dynamic) to find main so that unit tests cannot be cimpiled as shared library.
It's not a bug. It's a feature. ;) Starting 1.34.1 main() doesn't reside in shared libs.
In any case Boost.Test supports what you want. In many, many cases you don't need init_.. function anymore and boost test provides a way for users to get away without it and function main() as well both with static and shared library usage variant of the UTF. If you
OK. This is probably preferred.
But now I wonder why I should make a lot of incompatibles changes? I want my program and all tests beeing able to compile everywhere with (nearly) all versions of Boost.
Using some small code parts condionally depending on autotools system and Boost tests (version of boost, shared library is available?, ...) would be acceptable but I'm no willing to make major changes to my code.
You shouldn't be required.
prefer to define main youself and invoke init function you can do it as well with shared library variant.
And how?
See example 9 on http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-organization/manua...
Including the header boost/test/included/unit_test.hpp *once* per binary seems to work but normal using of boost/test/unit_test.hpp together with an additional #define BOOST_TEST_DYN_LINK still leads to a missing main() function. I get since 1.34.1: /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: ld returned 1 exit status
You also need to define either BOOST_TEST_MODULE or BOOST_TEST_MAIN if you want Boost.Test to generate main function for you. Like in an example 18 here: http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-organization/maste...
I defined also a dummy main function (just to make the linker happy as I assumed the tests are maybe started in the contructor of a static variable) but my test is not called. Even calling init_unit_test_suite() from main() does not work.
You need to call a test runner not init function. See example 9 above.
I also defined BOOST_TEST_DYN_LINK on the comandline to ensure that all code uses it. Same result! Defining addionally BOOST_TEST_MAIN results in a a proper empty test with the output "Test setup error: test tree is empty"
Because BOOST_TEST_MAIN produces both function main and empty init function. It's assumed that test units are automatically registered.
I thought I have also seen a conflict with my own init_unit_test_suite() implementation if I define BOOST_TEST_MAIN but cannot reproduce it.
There would be a compile time error if you follow proper signature of init function for use with shared library.
A question: Would it be save to define BOOST_TEST_DYN_LINK also for static linkage?
No.
I hope so as I have never, really never used different code depending on linker options.
We have to be tollerant to guest from other continents. Our policies selected to work the same way for every one.
Even after renaming my main test_suite* init_unit_test_suite(int, char *[]) function into bool init_unit_test() (but only for dynamic linkage?) as noticed on http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html I fail as usual.
You should see compilation errors now.
Short: In the past it was so simple:
#include <boost/test/unit_test.hpp> using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int, char *[]) { test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(BOOST_TEST_CASE(&JacobiTest1)); return test; }
Now I use
* Additional autoconf code to define HAVE_UNIT_TEST_LIB if the (shared?) library is used.
#ifdef HAVE_CONFIG_H #include <config.h> // HAVE_UNIT_TEST_LIB #endif
#ifdef HAVE_UNIT_TEST_LIB # define BOOST_TEST_DYN_LINK # include <boost/test/unit_test.hpp> #else # include <boost/test/included/unit_test.hpp> #endif
1. You can use static library and no need to define BOOST_TEST_DYN_LINK for either library of included variant 2. You can use included variant always 3. You can switch to automated registration and you don't need to define nor function main(), nor init function
using boost::unit_test::test_suite;
bool init_unit_test() { // my old init_unit_test_suite code }
/* int main(int argc, char *argv[]) { init_unit_test_suite(argc, argv); return 0; } */
If you insist on combination of manual registration with shared library, it should look like this: int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main( &init_unit_test, argc, argv ); }
the required information is wrong and incomplete and addionally
What is wrong?
scattered across multiple pages such as http://www.patmedia.net/~rogeeff/html/utf/compilation.html http://www.patmedia.net/~rogeeff/html/utf/compilation/direct-include.html http://www.patmedia.net/~rogeeff/html/utf/user-guide/usage-variants.html (and all referenced sub pages) http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-runners.html http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html
If you can express it all better I am open to sugestions. It is indeed not very trivial (considering many different usage variant of Boost.Test) to describe all necessary information and be both complete and easily accessible to first timers.
To show you that I really read (at least up to UTF) the documenation I mention a few errors in it:
I'll look on these later. Thanks for the comments Gennadiy

Sorry for breaking into discussion but I have a bunch of related questions. Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message [snip] Because BOOST_TEST_MAIN produces both function main and empty init function. It's assumed that test units are automatically registered.
Why both? Also, why defining BOOST_TEST_DYN_LINK switches on BOOST_TEST_ALTERNATIVE_INIT_API? Suppose I need to perform some initialization call, e.g. boost::filesystem::initial_path(). Currently, with shared Boost.Test I am forced to not to define BOOST_TEST_MAIN and to copy/paste the main() function like this: int BOOST_TEST_CALL_DECL main(int argc, char* argv[]) { return boost::unit_test::unit_test_main(&init_unit_test, argc, argv); } Now if I want to support using static Boost.Test, I am forced to define BOOST_TEST_ALTERNATIVE_INIT_API.
I thought I have also seen a conflict with my own init_unit_test_suite() implementation if I define BOOST_TEST_MAIN but cannot reproduce it.
There would be a compile time error if you follow proper signature of init function for use with shared library.
A question: Would it be save to define BOOST_TEST_DYN_LINK also for static linkage?
No.
I hope so as I have never, really never used different code depending on linker options.
We have to be tollerant to guest from other continents. Our policies selected to work the same way for every one.
Even after renaming my main test_suite* init_unit_test_suite(int, char *[]) function into bool init_unit_test() (but only for dynamic linkage?) as noticed on http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html I fail as usual.
You should see compilation errors now.
Short: In the past it was so simple:
#include <boost/test/unit_test.hpp> using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int, char *[]) { test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(BOOST_TEST_CASE(&JacobiTest1)); return test; }
Now I use
* Additional autoconf code to define HAVE_UNIT_TEST_LIB if the (shared?) library is used.
#ifdef HAVE_CONFIG_H #include <config.h> // HAVE_UNIT_TEST_LIB #endif
#ifdef HAVE_UNIT_TEST_LIB # define BOOST_TEST_DYN_LINK # include <boost/test/unit_test.hpp> #else # include <boost/test/included/unit_test.hpp> #endif
1. You can use static library and no need to define BOOST_TEST_DYN_LINK for either library of included variant 2. You can use included variant always 3. You can switch to automated registration and you don't need to define nor function main(), nor init function
using boost::unit_test::test_suite;
bool init_unit_test() { // my old init_unit_test_suite code }
/* int main(int argc, char *argv[]) { init_unit_test_suite(argc, argv); return 0; } */
If you insist on combination of manual registration with shared library, it should look like this:
int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main( &init_unit_test, argc, argv ); }
the required information is wrong and incomplete and addionally
What is wrong?
scattered across multiple pages such as http://www.patmedia.net/~rogeeff/html/utf/compilation.html http://www.patmedia.net/~rogeeff/html/utf/compilation/direct-include.html http://www.patmedia.net/~rogeeff/html/utf/user-guide/usage-variants.html (and all referenced sub pages) http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-runners.html http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html
If you can express it all better I am open to sugestions. It is indeed not very trivial (considering many different usage variant of Boost.Test) to describe all necessary information and be both complete and easily accessible to first timers.
To show you that I really read (at least up to UTF) the documenation I mention a few errors in it:
I'll look on these later.
Thanks for the comments
Gennadiy
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Ilya Sokolov" <fal_delivery@mail.ru> wrote in message news:fkg1cd$gdv$1@ger.gmane.org...
Sorry for breaking into discussion but I have a bunch of related questions.
Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message [snip] Because BOOST_TEST_MAIN produces both function main and empty init function. It's assumed that test units are automatically registered.
Why both? Also, why defining BOOST_TEST_DYN_LINK switches on BOOST_TEST_ALTERNATIVE_INIT_API?
1. Because alternatively I would've required 90% of the users to define 2 pretty closely names macro: BOOST_TEST_MAIN to define init function (this is what this macro always did, so I can't change the meaning) plus another one BOOST_TEST_MAIN_FUNCTION that will actually produce the function main() 2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one.
Suppose I need to perform some initialization call, e.g. boost::filesystem::initial_path(). Currently, with shared Boost.Test I am forced to not to define BOOST_TEST_MAIN and to copy/paste the main() function like this:
int BOOST_TEST_CALL_DECL main(int argc, char* argv[]) { return boost::unit_test::unit_test_main(&init_unit_test, argc, argv); }
No. I don't think this is the best approach. Much better (and shorter) solution is struct init { init() { boost::filesystem::initial_path(); } } BOOST_GLOBAL_FIXTURE( init );
Now if I want to support using static Boost.Test, I am forced to define BOOST_TEST_ALTERNATIVE_INIT_API.
I always find it confusing: why would you want to support both static and shared libraries? Pick one more convinient for you and stick with it. It's not like you need to test your test module with all variants of Boost.Test framework. It's your own test, not the test for the UTF. All in all I find an effort for simultanious support for both static and shared variant of the UTF a bit misguided. Gennadiy

Gennadiy Rozental wrote:
"Ilya Sokolov" <fal_delivery@mail.ru> wrote in message news:fkg1cd$gdv$1@ger.gmane.org...
Sorry for breaking into discussion but I have a bunch of related questions.
Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message [snip] Because BOOST_TEST_MAIN produces both function main and empty init function. It's assumed that test units are automatically registered. Why both? Also, why defining BOOST_TEST_DYN_LINK switches on BOOST_TEST_ALTERNATIVE_INIT_API?
1. Because alternatively I would've required 90% of the users to define 2 pretty closely names macro: BOOST_TEST_MAIN to define init function (this is what this macro always did, so I can't change the meaning)
In my opinion, BOOST_TEST_MAIN is a misleading name because it produces not only the main() function.
plus another one BOOST_TEST_MAIN_FUNCTION that will actually produce the function main()
2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one.
I don't see it unacceptable, given the majority of init_unit_test_suite() functions using BOOST_TEST_SUITE macro. I think BOOST_ALTERNATIVE_INIT_API should be default, but not the requirement for dynamic builds. And maybe it should be default for static builds also, because now it is recommended to use "master test suite".
Suppose I need to perform some initialization call, e.g. boost::filesystem::initial_path(). Currently, with shared Boost.Test I am forced to not to define BOOST_TEST_MAIN and to copy/paste the main() function like this:
int BOOST_TEST_CALL_DECL main(int argc, char* argv[]) { return boost::unit_test::unit_test_main(&init_unit_test, argc, argv); } No. I don't think this is the best approach. Much better (and shorter) solution is
struct init { init() { boost::filesystem::initial_path(); } }
BOOST_GLOBAL_FIXTURE( init );
I see this much cleaner: #ifdef BOOST_TEST_DYN_LINK # define BOOST_TEST_MAIN_FUNCTION #endif #include <boost/test/unit_test.hpp> bool init_unit_test() { boost::filesystem::initial_path(); return true; }
Now if I want to support using static Boost.Test, I am forced to define BOOST_TEST_ALTERNATIVE_INIT_API.
I always find it confusing: why would you want to support both static and shared libraries?
Why not???
Pick one more convinient for you and stick with it. It's not like you need to test your test module with all variants of Boost.Test framework. It's your own test, not the test for the UTF. All in all I find an effort for simultanious support for both static and shared variant of the UTF a bit misguided.
I want to seamlessly migrate from static UTF to shared. I need to fallback to the static UTF where it is not supported (by toolchain).
Gennadiy

Ilya Sokolov wrote:
Gennadiy Rozental wrote: [snip]
I want to seamlessly migrate from static UTF to shared.
And that is important for Boost itself, for example: http://lists.boost.org/Archives/boost/2006/11/113037.php --- quote --- I think the problem here is for Boost tests itself. Now, large number of them does not work with shared linking. So, I'm about to commit Juergen's patch that explicitly makes all Boost test link to static version of Boost.Test Vladimir Prus --- end of quote ---

"Ilya Sokolov" <fal_delivery@mail.ru> wrote in message news:fkoag7$squ$1@ger.gmane.org...
Ilya Sokolov wrote:
Gennadiy Rozental wrote: [snip]
I want to seamlessly migrate from static UTF to shared.
And that is important for Boost itself, for example:
http://lists.boost.org/Archives/boost/2006/11/113037.php
--- quote --- I think the problem here is for Boost tests itself. Now, large number of them does not work with shared linking. So, I'm about to commit Juergen's patch that explicitly makes all Boost test link to static version of Boost.Test
As far as I know Boost is using shared libraries where possible and uses static otherwise. Gennadiy

Gennadiy Rozental wrote:
"Ilya Sokolov" <fal_delivery@mail.ru> wrote in message news:fkoag7$squ$1@ger.gmane.org...
Ilya Sokolov wrote:
Gennadiy Rozental wrote: [snip]
I want to seamlessly migrate from static UTF to shared.
And that is important for Boost itself, for example:
http://lists.boost.org/Archives/boost/2006/11/113037.php
--- quote --- I think the problem here is for Boost tests itself. Now, large number of them does not work with shared linking. So, I'm about to commit Juergen's patch that explicitly makes all Boost test link to static version of Boost.Test
As far as I know Boost is using shared libraries where possible and uses static otherwise.
I think the point is that right now, many test Jamfiles explicitly specify static linking to Boost.Thread. This increases disk space requirements for running full boost testsuite, and might increase running time, since linking static library can be slower. Ideally, shared version of Boost.Test should be used, but given that shared and static version has slightly different interface, this actually requires code changes. - Volodya

"Ilya Sokolov" <fal_delivery@mail.ru> wrote in message news:fko5dv$g8l$1@ger.gmane.org...
Gennadiy Rozental wrote:
"Ilya Sokolov" <fal_delivery@mail.ru> wrote in message news:fkg1cd$gdv$1@ger.gmane.org...
Sorry for breaking into discussion but I have a bunch of related questions.
Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message [snip] Because BOOST_TEST_MAIN produces both function main and empty init function. It's assumed that test units are automatically registered. Why both? Also, why defining BOOST_TEST_DYN_LINK switches on BOOST_TEST_ALTERNATIVE_INIT_API?
1. Because alternatively I would've required 90% of the users to define 2 pretty closely names macro: BOOST_TEST_MAIN to define init function (this is what this macro always did, so I can't change the meaning)
In my opinion, BOOST_TEST_MAIN is a misleading name because it produces not only the main() function.
It is a bit. Now. But you should understand the history. First of all this macro primary puspose is to produce init function (not function main(), so you got quite the opposite "because"). Initially test module init function was considerred a replacement for the function main(), since the fnction main itself was part of the library. And BOOST_TEST_MAIN was intended to generate empty one. Later on during dynamic library support update it functionality was increased t oactually produce the function main(). I don't see ths as a big problem. In most cases it's still clear what it means - it designate test file as containing test module entry point.
plus another one BOOST_TEST_MAIN_FUNCTION that will actually produce the function main()
2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one.
I don't see it unacceptable, given the majority of init_unit_test_suite() functions using BOOST_TEST_SUITE macro. I think
See my other post. It has nothing to do with BOOST_TEST_SUITE macro
BOOST_ALTERNATIVE_INIT_API should be default, but not the requirement for dynamic builds. And maybe it should be default for static builds also, because now it is recommended to use "master test suite".
Quite the opposite: I can't be default and it is a requirement for the dynamic builds. And again it has nothing to do with master test suite interface.
Suppose I need to perform some initialization call, e.g. boost::filesystem::initial_path(). Currently, with shared Boost.Test I am forced to not to define BOOST_TEST_MAIN and to copy/paste the main() function like this:
int BOOST_TEST_CALL_DECL main(int argc, char* argv[]) { return boost::unit_test::unit_test_main(&init_unit_test, argc, argv); } No. I don't think this is the best approach. Much better (and shorter) solution is
struct init { init() { boost::filesystem::initial_path(); } }
BOOST_GLOBAL_FIXTURE( init );
I see this much cleaner:
#ifdef BOOST_TEST_DYN_LINK # define BOOST_TEST_MAIN_FUNCTION #endif
Where this maro is used?
#include <boost/test/unit_test.hpp>
bool init_unit_test() { boost::filesystem::initial_path(); return true; }
What if you need to to some cleanup as well? What if you need to do multiple initialization bits that reside in different test files? What if all your test units are automatically registerred - init function definition will require function main as well if you intend to use shared library.
Now if I want to support using static Boost.Test, I am forced to define BOOST_TEST_ALTERNATIVE_INIT_API.
I always find it confusing: why would you want to support both static and shared libraries?
Why not???
Why yes?? From my prospective it's misgueded effort, sinse most of the time you select one usage fariant and stick with it.
Pick one more convinient for you and stick with it. It's not like you need to test your test module with all variants of Boost.Test framework. It's your own test, not the test for the UTF. All in all I find an effort for simultanious support for both static and shared variant of the UTF a bit misguided.
I want to seamlessly migrate from static UTF to shared. I need to fallback to the static UTF where it is not supported (by toolchain).
Where? The primary direction of my effort was to make sure shared library works consistently on all platforms. If you still insist on static/shared library compartibility it can be achieved: define BOOST_TEST_NO_MAIN and BOOST_TEST_ALTERMNATIVE_INIT_API during library compilation and you got what you need. Genadiy

Gennadiy Rozental wrote: [snip]
2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one. I don't see it unacceptable, given the majority of init_unit_test_suite() functions using BOOST_TEST_SUITE macro. I think
See my other post.
What post? [snip]
I want to seamlessly migrate from static UTF to shared. I need to fallback to the static UTF where it is not supported (by toolchain).
Where? The primary direction of my effort was to make sure shared library works consistently on all platforms.
Even on platforms that does not have shared libraries at all? ;-)
If you still insist on static/shared library compartibility it can be achieved: define BOOST_TEST_NO_MAIN and BOOST_TEST_ALTERMNATIVE_INIT_API during library compilation and you got what you need.
I'm trying to argue that such use case is needlessly complex.

"Ilya Sokolov" <fal_delivery@mail.ru> wrote in message news:fkqcr5$9g0$1@ger.gmane.org...
Gennadiy Rozental wrote:
[snip]
2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one. I don't see it unacceptable, given the majority of init_unit_test_suite() functions using BOOST_TEST_SUITE macro. I think
See my other post.
What post?
Look at the bottom of http://permalink.gmane.org/gmane.comp.lib.boost.devel/169545
[snip]
I want to seamlessly migrate from static UTF to shared. I need to fallback to the static UTF where it is not supported (by toolchain).
Where? The primary direction of my effort was to make sure shared library works consistently on all platforms.
Even on platforms that does not have shared libraries at all? ;-)
On these platform it works as well, since if there is no shared libraries no problem can be either.
If you still insist on static/shared library compartibility it can be achieved: define BOOST_TEST_NO_MAIN and BOOST_TEST_ALTERMNATIVE_INIT_API during library compilation and you got what you need.
I'm trying to argue that such use case is needlessly complex.
If you can suggest a different/easier one I'll be happy to hear it. Gennadiy

Gennadiy Rozental wrote:
2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one. I don't see it unacceptable, given the majority of init_unit_test_suite() functions using BOOST_TEST_SUITE macro. I think See my other post. What post?
Look at the bottom of http://permalink.gmane.org/gmane.comp.lib.boost.devel/169545
I still don't see why is it unacceptable. Can you state it explicitly?
I want to seamlessly migrate from static UTF to shared. I need to fallback to the static UTF where it is not supported (by toolchain). Where? The primary direction of my effort was to make sure shared library works consistently on all platforms. Even on platforms that does not have shared libraries at all? ;-)
On these platform it works as well, since if there is no shared libraries no problem can be either.
Problem arise with library that should work on both platforms, with and without dll support.

Ilya Sokolov <fal_delivery <at> mail.ru> writes:
Gennadiy Rozental wrote:
2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one. I don't see it unacceptable, given the majority of init_unit_test_suite() functions using BOOST_TEST_SUITE macro. I think See my other post. What post?
Look at the bottom of http://permalink.gmane.org/gmane.comp.lib.boost.devel/169545
I still don't see why is it unacceptable. Can you state it explicitly?
Hmm. How to state it more explicitly. How about this: It does not link.
Problem arise with library that should work on both platforms, with and without dll support.
What platforms are you talking about? Why the solutions I provided are not satisfactory? Gennadiy

Gennadiy Rozental wrote:
> 2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one. [snip] I still don't see why is it unacceptable. Can you state it explicitly?
Hmm. How to state it more explicitly. How about this:
It does not link.
i.e., boost::unit_test::test_suite* init_unit_test_suite( int, char* [] ) link, but bool init_unit_test() doesn't link?
Problem arise with library that should work on both platforms, with and without dll support.
What platforms are you talking about?
dos/djgpp
Why the solutions I provided are not satisfactory?
they are too complex for such simple problem

"Ilya Sokolov" <fal_delivery@mail.ru> wrote in message news:fkuive$ijf$1@ger.gmane.org...
Gennadiy Rozental wrote:
>> 2. Unfortunately original test modult function signature is unacceptable for DLL initialization. So i had to introduce new one. [snip] I still don't see why is it unacceptable. Can you state it explicitly?
Hmm. How to state it more explicitly. How about this:
It does not link.
i.e., boost::unit_test::test_suite* init_unit_test_suite( int, char* [] ) link, but bool init_unit_test() doesn't link?
Quite the opposite. Original testrunner/initialization function signatures cause Boost.Test fail to build as DLL.
Problem arise with library that should work on both platforms, with and without dll support.
What platforms are you talking about?
dos/djgpp
I am not sure Boost.Test and/or Boost support these. What compiler r u using? Do we run regression tests on these?
Why the solutions I provided are not satisfactory?
they are too complex for such simple problem
The problem is far from being simple and what is complicated in solution I recomended? Gennadiy

On Sun, Dec 23, 2007 at 07:41:48PM -0500, Gennadiy Rozental wrote:
I always find it confusing: why would you want to support both static and shared libraries? Pick one more convinient for you and stick with it. It's not like you need to test your test module with all variants of Boost.Test framework. It's your own test, not the test for the UTF. All in all I find an effort for simultanious support for both static and shared variant of the UTF a bit misguided.
OK. So reading this, I have the following question. Suppose I'm writing a nifty library and distributing the source code. I write unit tests using Boost.Test. Now I distribute my code -- together with the tests. Someone else builds my code on their system and runs the tests. I have no control over their install of Boost: they might have static libs, shared libs, or both. Can I write my unit tests so that they link and run in all three cases? Thanks, -Steve

Steve M. Robbins <steve <at> sumost.ca> writes:
OK. So reading this, I have the following question. Suppose I'm writing a nifty library and distributing the source code. I write unit tests using Boost.Test.
Now I distribute my code -- together with the tests. Someone else builds my code on their system and runs the tests. I have no control over their install of Boost: they might have static libs, shared libs, or both. Can I write my unit tests so that they link and run in all three cases?
choice 1: Write your unit tests using automated registration tools: #define BOOST_TEST_MODULE my tests #include <boost/test/unit_test.hpp> BOOST_AUTO_TEST_CASE( free_test_function ) { BOOST_CHECK( true /* test assertion */ ); } Userls of your library will be able to test it using static library or shared library. Later require BOOST_TEST_DYN_LINK to be added to the compilation line. choice 2: Use single-header variant of UTF #define BOOST_TEST_MODULE my tests #include <boost/test/included/unit_test.hpp> BOOST_AUTO_TEST_CASE( free_test_function ) { BOOST_CHECK( true /* test assertion */ ); } You don't care about library at all. Gennadiy

On Fri, Dec 21, 2007 at 02:51:40AM -0500, Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071220161635.GA515@imkf-pc073.imkf.tu-freiberg.de...
I read most of the new documentation but to make it short: I still fail to use unit tests. It worked in the past but after a lot of changes in Boost.Tests it is now unusable for me.
Let's see concrete examples.
Old code was as simple as: #include <boost/test/unit_test.hpp> using boost::unit_test::test_suite; test_suite* Jacobi_test_suite(); test_suite* init_unit_test_suite(int, char *[]) { Initialize_logging(); test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(Jacobi_test_suite()); return test; }
prefer to define main youself and invoke init function you can do it as well with shared library variant.
And how?
See example 9 on
http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-organization/manua...
Right. Thanks! Just changing test_suite* init_unit_test_suite(int, char *[]) { Initialize_logging(); test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(Jacobi_test_suite()); return test; } into bool init_unit_test() { Initialize_logging(); boost::unit_test::framework::master_test_suite().add(Jacobi_test_suite()); return true; } int main(int argc, char *argv[]) { return ::boost::unit_test::unit_test_main(&init_unit_test, argc, argv); } works. Please note that one has to read dozens of pages before as this is nearly at the end of the documentation. Is this kind of usage really so difficult that you think it is worth the effort to hide it for the user and suggest automatic registration instead?
Including the header boost/test/included/unit_test.hpp *once* per binary seems to work but normal using of boost/test/unit_test.hpp together with an additional #define BOOST_TEST_DYN_LINK still leads to a missing main() function. I get since 1.34.1: /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: ld returned 1 exit status
You also need to define either BOOST_TEST_MODULE or BOOST_TEST_MAIN if you want Boost.Test to generate main function for you. Like in an example 18 here:
http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-organization/maste...
That's completely different from my current code. I will definitevly not use it as it uses too many macros (BOOST_TEST_MODULE, BOOST_AUTO_TEST_CASE and the probably required BOOST_TEST_DYN_LINK). It seems also impossible for me to use template functions as tests (which I currently use: template<bool var> void JacobiTest2(); test->add(BOOST_TEST_CASE(&JacobiTest2<true>)); test->add(BOOST_TEST_CASE(&JacobiTest2<false>)); Macros are evil!
I also defined BOOST_TEST_DYN_LINK on the comandline to ensure that all code uses it. Same result! Defining addionally BOOST_TEST_MAIN results in a a proper empty test with the output "Test setup error: test tree is empty"
Because BOOST_TEST_MAIN produces both function main and empty init function.
According to http://www.patmedia.net/~rogeeff/html/utf/compilation.html#utf.flag.main: BOOST_TEST_MAIN Define this flag to generate an empty test module initialization function. I do not read anything about main().
It's assumed that test units are automatically registered.
I don't see many advantages as it only saved a single line of code and requires just another macro.
Short: In the past it was so simple:
#include <boost/test/unit_test.hpp> using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int, char *[]) { test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(BOOST_TEST_CASE(&JacobiTest1)); return test; }
Now I use
* Additional autoconf code to define HAVE_UNIT_TEST_LIB if the (shared?) library is used.
#ifdef HAVE_CONFIG_H #include <config.h> // HAVE_UNIT_TEST_LIB #endif
#ifdef HAVE_UNIT_TEST_LIB # define BOOST_TEST_DYN_LINK # include <boost/test/unit_test.hpp> #else # include <boost/test/included/unit_test.hpp> #endif
1. You can use static library and no need to define BOOST_TEST_DYN_LINK for either library of included variant 2. You can use included variant always 3. You can switch to automated registration and you don't need to define nor function main(), nor init function
If you insist on combination of manual registration with shared library, it should look like this:
int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main( &init_unit_test, argc, argv ); }
Without changing the registration to use framework::master_test_suite()->add(Jacobi_test_suite()) I would still get: Test setup error: test tree is empty
scattered across multiple pages such as http://www.patmedia.net/~rogeeff/html/utf/compilation.html http://www.patmedia.net/~rogeeff/html/utf/compilation/direct-include.html http://www.patmedia.net/~rogeeff/html/utf/user-guide/usage-variants.html (and all referenced sub pages) http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-runners.html http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html
If you can express it all better I am open to sugestions. It is indeed not very trivial (considering many different usage variant of Boost.Test) to describe all necessary information and be both complete and easily accessible to first timers.
I suggest to simple reduce many different usage variants of Boost.Test! Let the user always specify main(), remove the init_unit_test parameter together with most of the macros as BOOST_TEST_DYN_LINK, BOOST_TEST_MAIN, BOOST_TEST_ALTERNATIVE_INIT_API, ... This will result in only two or three lines more of code but will be much easier to understand and to document (compare the clear old documentation!). Jens

"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071221141109.GB9314@imkf-pc073.imkf.tu-freiberg.de...
On Fri, Dec 21, 2007 at 02:51:40AM -0500, Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071220161635.GA515@imkf-pc073.imkf.tu-freiberg.de...
I read most of the new documentation but to make it short: I still fail to use unit tests. It worked in the past but after a lot of changes in Boost.Tests it is now unusable for me.
Let's see concrete examples.
Old code was as simple as:
#include <boost/test/unit_test.hpp> using boost::unit_test::test_suite;
test_suite* Jacobi_test_suite();
where this function is defined? Why can't you automatically register your test units?
test_suite* init_unit_test_suite(int, char *[]) { Initialize_logging();
This should go into global fixture
test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(Jacobi_test_suite()); return test; }
prefer to define main youself and invoke init function you can do it as well with shared library variant.
And how?
See example 9 on
http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-organization/manua...
Right. Thanks! Just changing
test_suite* init_unit_test_suite(int, char *[]) { Initialize_logging(); test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(Jacobi_test_suite()); return test; }
into
bool init_unit_test() { Initialize_logging();
boost::unit_test::framework::master_test_suite().add(Jacobi_test_suite());
return true; }
int main(int argc, char *argv[]) { return ::boost::unit_test::unit_test_main(&init_unit_test, argc, argv); }
works. Please note that one has to read dozens of pages before as this is nearly at the end of the documentation.
Is this kind of usage really so difficult that you think it is worth the effort to hide it for the user and suggest automatic registration instead?
Yes. I believe you describing an extreme case. At this point there are no good/common reasons to implement your test module like this. The only one I can think of if you want to manage what test unis to execute yourself within init function for some reason. Everything else can be done more efficiently with aut-registration facilities. Another reason is that the test module might be written already in old style. In this case you might not want to invest time into converting it. Boost.Test still supprots it. But it requires small changes in case if you were using shared library.
Including the header boost/test/included/unit_test.hpp *once* per binary seems to work but normal using of boost/test/unit_test.hpp together with an additional #define BOOST_TEST_DYN_LINK still leads to a missing main() function. I get since 1.34.1: /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: ld returned 1 exit status
You also need to define either BOOST_TEST_MODULE or BOOST_TEST_MAIN if you want Boost.Test to generate main function for you. Like in an example 18 here:
http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-organization/maste...
That's completely different from my current code. I will definitevly not use it as it uses too many macros (BOOST_TEST_MODULE, BOOST_AUTO_TEST_CASE and the probably required BOOST_TEST_DYN_LINK). It
You are mixing in a lot of different concepts. Each macro serve it's purpose and only used when required.
seems also impossible for me to use template functions as tests (which I currently use: template<bool var> void JacobiTest2(); test->add(BOOST_TEST_CASE(&JacobiTest2<true>)); test->add(BOOST_TEST_CASE(&JacobiTest2<false>));
I don't see any problems doing above. But the UTF provides better way to implement this through test case template support. It has both automated and manual registration.
Macros are evil!
They might be, but they might be also a quite powerfull code generation tool. The Boost.Test is very carefull in how it's defines and names macros. I might find it difficult to avoid them, since more than 80% of library interfaces is based on macros.
I also defined BOOST_TEST_DYN_LINK on the comandline to ensure that all code uses it. Same result! Defining addionally BOOST_TEST_MAIN results in a a proper empty test with the output "Test setup error: test tree is empty"
Because BOOST_TEST_MAIN produces both function main and empty init function.
According to http://www.patmedia.net/~rogeeff/html/utf/compilation.html#utf.flag.main: BOOST_TEST_MAIN Define this flag to generate an empty test module initialization function.
I do not read anything about main().
Hmmmm. It's realy early in documentation to alk about complications like this. I've added statement in this regard. Let me know if it's clearer now (I'll post updated docs later today)
It's assumed that test units are automatically registered.
I don't see many advantages as it only saved a single line of code and requires just another macro.
It saves much more than 1 line. Compare: void my_test_case() { ... } bool init_unit_test() { boost::unit_test::framework::master_test_suite().add(Jacobi_test_suite()); return true; } with BOOST_AUTO_TEST_CASE( my_test_case ) { ... }
Short: In the past it was so simple:
#include <boost/test/unit_test.hpp> using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int, char *[]) { test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(BOOST_TEST_CASE(&JacobiTest1)); return test; }
Now I use
* Additional autoconf code to define HAVE_UNIT_TEST_LIB if the (shared?) library is used.
#ifdef HAVE_CONFIG_H #include <config.h> // HAVE_UNIT_TEST_LIB #endif
#ifdef HAVE_UNIT_TEST_LIB # define BOOST_TEST_DYN_LINK # include <boost/test/unit_test.hpp> #else # include <boost/test/included/unit_test.hpp> #endif
1. You can use static library and no need to define BOOST_TEST_DYN_LINK for either library of included variant 2. You can use included variant always 3. You can switch to automated registration and you don't need to define nor function main(), nor init function
If you insist on combination of manual registration with shared library, it should look like this:
int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main( &init_unit_test, argc, argv ); }
Without changing the registration to use framework::master_test_suite()->add(Jacobi_test_suite()) I would still get: Test setup error: test tree is empty
I am not sure I am following. You do need to register your test units.
If you can express it all better I am open to sugestions. It is indeed not very trivial (considering many different usage variant of Boost.Test) to describe all necessary information and be both complete and easily accessible to first timers.
I suggest to simple reduce many different usage variants of Boost.Test! Let the user always specify main(), remove the init_unit_test parameter together with most of the macros as BOOST_TEST_DYN_LINK, BOOST_TEST_MAIN, BOOST_TEST_ALTERNATIVE_INIT_API, ... This will result in only two or three lines more of code but will be
In most cases it's more than that. And many people are not willing to sacrify that. There is also the notion of init function and you will still need BOOST_TEST_MAIN. In addition the change wouldn't be backward compartible and many people will not be happy. Gennadiy

(sorry - this should have gone thru 5 days ago) On Dec 20, 2007 11:16 AM, Jens Seidel <jensseidel@users.sf.net> wrote:
Hi,
I know it may no longer fit on this list but as I started here let's not move the list ...
I read most of the new documentation but to make it short: I still fail to use unit tests. It worked in the past but after a lot of changes in Boost.Tests it is now unusable for me.
Well here's a success story, if it can encourage you to persevere. We have a library of many hundreds of manually-registered test cases grouped into many dozen manually-registered test suites, all running under Boost.Test 1.33.1. I'm happy to report that we had all those test cases running under Boost.Test 1.34.1 within one hour of upgrading. Even better: most of our tests written since 1.34.1 came out use the automatic registration facility and the two types of tests coexist happily (all statically linked BTW - I've never tried the dynamic linking feature). Even better: I've got things set up so they are backward compatible with 1.33.1 (well, at least the manually-registered test cases are for sure). Like you, we define our own init_unit_test_suite() function to perform some boilerplate initialisation. Here's how I solved the problem. #if (BOOST_VERSION / 100 < 1034) // Not necessary for Boost 1.34 and later. #define init_unit_test_suite init_auto_unit_test_suite #define BOOST_AUTO_TEST_MAIN "Automatic" #include <boost/test/auto_unit_test.hpp> #undef init_unit_test_suite #endif boost::unit_test::test_suite* init_unit_test_suite( int argc, char * argv[] ) { // Create the master test suite. #if (BOOST_VERSION / 100 < 1034) // Not necessary for Boost 1.34 and later. boost::unit_test::test_suite * main_suite = A2M_NEW boost::unit_test::test_suite; // Add automatically-registered tests main_suite->add(init_auto_unit_test_suite(argc,argv)); // Add user-defined test suites, if any boost::unit_test::test_suite * user_suite = unittest::init_unit_test_suite(argc,argv); if (user_suite) { main_suite->add(user_suite); } #else boost::unit_test::test_suite * main_suite = unittest::init_unit_test_suite(argc,argv); #endif // Initialise our own pre-test setup fixture. unittest::SetupFixture::Init(); // All done. Boost.Test framework takes over from here. return main_suite; } } Our test executables only need to define unittest::init_unit_test_suite() to register manual test cases/suites if necessary (where unittest is a namespace we chose arbitrarily). If the test executable has no manual tests to register, you can skip the above code and define BOOST_TEST_MODULE and just use the auto registration and that's it. BTW I disagree that Boost.Test should force users to define a main(). I believe Gennadiy has made the correct compromise, which is to make the frequent case fast (and easy), while allowing special cases to be worked in. One suggestion might be to add a new class of fixture. There is a feature for test case specific fixtures, another for test suite-specifc fixtures, and the perhaps ill-named global fixture, which is run independently for all test cases. Perhaps there should be another fixture, a really global one, which is constructed before all tests are run and destroyed after all tests are run. A static variable won't cut it because of the order-of-initialisation fiasco. pj On Dec 21, 2007 9:11 AM, Jens Seidel <jensseidel@users.sf.net> wrote:
On Fri, Dec 21, 2007 at 02:51:40AM -0500, Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071220161635.GA515@imkf-pc073.imkf.tu-freiberg.de...
I read most of the new documentation but to make it short: I still fail to use unit tests. It worked in the past but after a lot of changes in Boost.Tests it is now unusable for me.
Let's see concrete examples.
Old code was as simple as:
#include <boost/test/unit_test.hpp> using boost::unit_test::test_suite;
test_suite* Jacobi_test_suite();
test_suite* init_unit_test_suite(int, char *[]) { Initialize_logging(); test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(Jacobi_test_suite()); return test; }
prefer to define main youself and invoke init function you can do it as well with shared library variant.
And how?
See example 9 on
Right. Thanks! Just changing
test_suite* init_unit_test_suite(int, char *[]) { Initialize_logging(); test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(Jacobi_test_suite()); return test; }
into
bool init_unit_test() { Initialize_logging();
boost::unit_test::framework::master_test_suite().add(Jacobi_test_suite());
return true; }
int main(int argc, char *argv[]) { return ::boost::unit_test::unit_test_main(&init_unit_test, argc, argv); }
works. Please note that one has to read dozens of pages before as this is nearly at the end of the documentation.
Is this kind of usage really so difficult that you think it is worth the effort to hide it for the user and suggest automatic registration instead?
Including the header boost/test/included/unit_test.hpp *once* per binary seems to work but normal using of boost/test/unit_test.hpp together with an additional #define BOOST_TEST_DYN_LINK still leads to a missing main() function. I get since 1.34.1: /usr/lib/gcc/i486-linux-gnu/4.2.3/../../../../lib/crt1.o: In function `_start': (.text+0x18): undefined reference to `main' collect2: ld returned 1 exit status
You also need to define either BOOST_TEST_MODULE or BOOST_TEST_MAIN if you want Boost.Test to generate main function for you. Like in an example 18 here:
That's completely different from my current code. I will definitevly not use it as it uses too many macros (BOOST_TEST_MODULE, BOOST_AUTO_TEST_CASE and the probably required BOOST_TEST_DYN_LINK). It seems also impossible for me to use template functions as tests (which I currently use: template<bool var> void JacobiTest2(); test->add(BOOST_TEST_CASE(&JacobiTest2<true>)); test->add(BOOST_TEST_CASE(&JacobiTest2<false>));
Macros are evil!
I also defined BOOST_TEST_DYN_LINK on the comandline to ensure that all code uses it. Same result! Defining addionally BOOST_TEST_MAIN results in a a proper empty test with the output "Test setup error: test tree is empty"
Because BOOST_TEST_MAIN produces both function main and empty init function.
According to http://www.patmedia.net/~rogeeff/html/utf/compilation.html#utf.flag.main<http://www.patmedia.net/%7Erogeeff/html/utf/compilation.html#utf.flag.main> : BOOST_TEST_MAIN Define this flag to generate an empty test module initialization function.
I do not read anything about main().
It's assumed that test units are automatically registered.
I don't see many advantages as it only saved a single line of code and requires just another macro.
Short: In the past it was so simple:
#include <boost/test/unit_test.hpp> using boost::unit_test::test_suite; test_suite* init_unit_test_suite(int, char *[]) { test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(BOOST_TEST_CASE(&JacobiTest1)); return test; }
Now I use
* Additional autoconf code to define HAVE_UNIT_TEST_LIB if the (shared?) library is used.
#ifdef HAVE_CONFIG_H #include <config.h> // HAVE_UNIT_TEST_LIB #endif
#ifdef HAVE_UNIT_TEST_LIB # define BOOST_TEST_DYN_LINK # include <boost/test/unit_test.hpp> #else # include <boost/test/included/unit_test.hpp> #endif
1. You can use static library and no need to define BOOST_TEST_DYN_LINK for either library of included variant 2. You can use included variant always 3. You can switch to automated registration and you don't need to define nor function main(), nor init function
If you insist on combination of manual registration with shared library, it should look like this:
int main( int argc, char* argv[] ) { return ::boost::unit_test::unit_test_main( &init_unit_test, argc, argv ); }
Without changing the registration to use framework::master_test_suite()->add(Jacobi_test_suite()) I would still get: Test setup error: test tree is empty
scattered across multiple pages such as http://www.patmedia.net/~rogeeff/html/utf/compilation.html<http://www.patmedia.net/%7Erogeeff/html/utf/compilation.html>
(and all referenced sub pages) http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-runners.html<http://www.patmedia.net/%7Erogeeff/html/utf/user-guide/test-runners.html>
If you can express it all better I am open to sugestions. It is indeed not very trivial (considering many different usage variant of Boost.Test) to describe all necessary information and be both complete and easily accessible to first timers.
I suggest to simple reduce many different usage variants of Boost.Test! Let the user always specify main(), remove the init_unit_test parameter together with most of the macros as BOOST_TEST_DYN_LINK, BOOST_TEST_MAIN, BOOST_TEST_ALTERNATIVE_INIT_API, ... This will result in only two or three lines more of code but will be much easier to understand and to document (compare the clear old documentation!).
Jens _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Pierre-Jules Tremblay" <boost@piairjooles.ca> wrote in message
One suggestion might be to add a new class of fixture. There is a feature for test case specific fixtures, another for test suite-specifc fixtures, and the perhaps ill-named global fixture, which is run independently for all test cases. Perhaps there should be another fixture, a really global one, which is constructed before all tests are run and destroyed after all tests are run. A static variable won't cut it because of the order-of-initialisation fiasco.
I might be missing something, but from my understanding that is what BOOST_GLOBAL_FIXTURE is doing. It is setup leg executed before testing is started. Teardown once all tests are completed. Gennadiy

On Fri, Dec 21, 2007 at 03:11:09PM +0100, Jens Seidel wrote:
On Fri, Dec 21, 2007 at 02:51:40AM -0500, Gennadiy Rozental wrote:
Let's see concrete examples.
Old code was as simple as:
#include <boost/test/unit_test.hpp> using boost::unit_test::test_suite;
test_suite* Jacobi_test_suite();
test_suite* init_unit_test_suite(int, char *[]) { Initialize_logging(); test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(Jacobi_test_suite()); return test; }
prefer to define main youself and invoke init function you can do it as well with shared library variant.
And how?
See example 9 on
http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-organization/manua...
Right. Thanks! Just changing
test_suite* init_unit_test_suite(int, char *[]) { Initialize_logging(); test_suite *test = BOOST_TEST_SUITE("Master test suite"); test->add(Jacobi_test_suite()); return test; }
into
bool init_unit_test() { Initialize_logging(); boost::unit_test::framework::master_test_suite().add(Jacobi_test_suite());
return true; }
int main(int argc, char *argv[]) { return ::boost::unit_test::unit_test_main(&init_unit_test, argc, argv); }
works. Please note that one has to read dozens of pages before as this is nearly at the end of the documentation.
But it does not work with Boost 1.33.1 in contrast to 1.34.1 as master_test_suite() returns a const reference. I switched now to inclusion of boost/test/included/unit_test_framework.hpp instead of using libraries. Let's see whether it will break soon as well ... Jens

On Tue, Jan 15, 2008 at 04:58:07PM +0100, Jens Seidel wrote:
On Fri, Dec 21, 2007 at 03:11:09PM +0100, Jens Seidel wrote:
int main(int argc, char *argv[]) { return ::boost::unit_test::unit_test_main(&init_unit_test, argc, argv); }
works. Please note that one has to read dozens of pages before as this is nearly at the end of the documentation.
But it does not work with Boost 1.33.1 in contrast to 1.34.1 as master_test_suite() returns a const reference.
Oops, I forgot to mention that it even in 1.34.1 crashs if I provide 0 as init function pointer. This forced me during my tests to also define a dummy function just to make unit_test_main() happy. I suggest to overload a new function which doesn't take a init function at all but 0 should also be a valid pointer.
I switched now to inclusion of boost/test/included/unit_test_framework.hpp instead of using libraries. Let's see whether it will break soon as well ...
It still works :-)) Jens

Jens Seidel <jensseidel <at> users.sf.net> writes:
But it does not work with Boost 1.33.1 in contrast to 1.34.1 as master_test_suite() returns a const reference.
Using "auto" macros you can build version what works with both versions.
Oops, I forgot to mention that it even in 1.34.1 crashs if I provide 0 as init function pointer. This forced me during my tests to also define a dummy function just to make unit_test_main() happy.
I suggest to overload a new function which doesn't take a init function at all but 0 should also be a valid pointer.
Ok. I'll consider this. Gennadiy

"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071220161635.GA515@imkf-pc073.imkf.tu-freiberg.de...
To show you that I really read (at least up to UTF) the documenation I mention a few errors in it:
http://www.patmedia.net/~rogeeff/html/faq.html: * "provide provide"
fixed
* "link with libunit_test_framework.lib" that's platform specific!!!
Why?
* "The reasons for this error is that in your implementation you should specify second argument of init_unit_test_suite exactly as in a specification, i.e.: char* []." s/as in a specification/as in the specification/ (I first read e.g. instead of i.e. which confused me even more, maybe you should avoid "i.e.".)
fixed
http://www.patmedia.net/~rogeeff/html/open-issues.html * "Finish update for CLA support" What is CLA?
I removed abbriviation
* Remove two or three full stops in the enumeration
What do you mean?
* "Better Unicode support (reports and log in wostream)" Sorry, I don't see any relation of wostream and Unicode! You mean UTF16 encoding? UTF8 should work fine with both ostream and wostream, right?
I 'll be more equipped to to answer this once I start doing this.
http://www.patmedia.net/~rogeeff/html/execution-monitor.html * "Also The Execution Monitor" s/The/the/
fixed
http://www.patmedia.net/~rogeeff/html/execution-monitor/reference.html * Page misses a "next" link to http://www.patmedia.net/~rogeeff/html/boost/execution_exception.html
This is being reworked.
http://www.patmedia.net/~rogeeff/html/prg-exec-monitor/impl.html * Link to libs/test/execution_monitor.cpp does not work
should work now
* "wraps a several system headers" s/a//
fixed
http://www.patmedia.net/~rogeeff/html/minimal.html * "other then include boost/test/minimal.hpp" s/include/including/ * "This approach is are similar" (belongs to folded text for example 4) s/are//
fixed
http://www.patmedia.net/~rogeeff/html/tutorials/intro-in-testing.html * "why testing worth the effort" s/testing/testing is/
fixed
http://www.patmedia.net/~rogeeff/html/tutorials/new-year-resolution.html * s/BOOST_AUTO_EST_CASE/BOOST_AUTO_TEST_CASE/ * "As a result my test suite became to look like this:" Wrong example!!! data_access_test() was expected
fixed
http://www.patmedia.net/~rogeeff/html/utf/user-guide/initialization.html * "Alternatively in you can employ" s/in//
fixed
* "with the static library or single-header variants of the UTF requires the specific function specification." Check this! s/specification/signature/, s/specific/original/?
No, namely specification: both signature and function name. And it's quite specific. I agree it doesn't sound right though. Thanks for your comments. Gennadiy

"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071219090237.GA13691@imkf-pc073.imkf.tu-freiberg.de...
* According to http://lists.boost.org/Archives/boost/2007/05/121601.php linkers don't look into libraries (either static or dynamic) to find main so that unit tests cannot be cimpiled as shared library.
They do. On *nix platforms you can put main both in shared and static libs. On NT only static. This was a source of inconsistency till 1.34.1, so starting that release I've removed main from shared library builds on all platforms.
And why are static and shared libraries handled differently? Why not just removing main also from static libraries?
1. For backward compartibility 2. For enhanced usebility in many cases. For people producing a lot of unit tests adding extra function main() implementation is unnnecessary burdan (not mentioning that they will have to actually learn how implement it properly. 3. In many (if not the most) cases function main() handling is hidden completely from the users and usage and both usage variants behave pretty much the same. The only difference is presence of an extra macro BOOST_TEST_DYN_LINK.
Should code really behave differently depending how it is linked (which is just a build configuration)? Do there exist other (non-Boost) libraries which do such stuff?
You comming to this from *nix prospecive. On NT dll and lib are two quite different ball games. Boost.Test opted to be consystent in between platforms.
It's not a bug. It's a feature. ;) Starting 1.34.1 main() doesn't reside in shared libs.
Is this change documented? Where can I find the Changelog?
In svn I guess.
Did you also consider using a stable ABI (application binary interface, would allow a binary to be used with different library version without need to recompile)
I sugest I write Boost.Test using C? In Boost.Test a lot of staff happends in headers. We might find it difficult.
or API (application programming interface, no need to change the source code to be able to compile against a new version of a library) (at least some time in the future)
I do not plan any changes that should break backward compartibility. 1.34.1 did break it for very small number of use cases, which where never officially supported in a first place (plus I believe 1 tool was found unsafe and the interface was changes).
which would make incompatibilities between shared and static libraries impossible and simplifies using different versions of Boost a lot? Whenever I try another Boost version existing code fails to compile or link ...
I am sure we will be able to figure it out. As far as i know there is no problem compiling/linking Boost.Test.
The problem is that the example in the official documentation (which is (or should be) on www.boost.org not somewhere outside) just contains: "the Unit Test Framework is responsible for supplying function main()"
Even if you consider that to be outdated (again: Why do you not update it??????) you should assume that most code arround does not provide main() and fails that's why starting with recent versions.
I did. And it deosn't fail for: 1. Users linking with static library 2. Users using included version 3. Users linking shared library and relying on automatic registration. Only those who employ shared library and manual registration had an issue. Which is very easily resolve on all the cases.
According to the updated documentation (http://www.patmedia.net/~rogeeff/html/utf/user-guide/test-runners.html) using the static library results in
int main(int argc, char* argv[]) { return unit_test_main(argc, argv); }
No, that page doesn't say it. You *may* use it like this if you opt, but by default function main() reside in library and you don't need to implement one.
whereas the shared library uses int unit_test_main( bool (*init_unit_test_func)(), int argc, char* argv[] );
How could I define my own main function which is compatible with shared and dynamic libraries? unit_test_main has different signatures!?
1. shared and dynamic libs are comparitble ;) 2. Don't define init function at all. Employ automated registration facilities. And you don;t need ot care about test runner function signature. 3. The test runner function signature is now the same for both static and dyanmic library (see svn). I am yet to update the updated docs ;)
Probably I have to define BOOST_TEST_MAIN and let Boost create main. Let's hope this works for all linking options (shared/static).
It will if you are using autmatic registration facility.
In any case Boost.Test supports what you want. In many, many cases you don't need init_.. function anymore and boost test provides a way for users to get away without it and function main() as well both with static and shared library usage variant of the UTF. If you
OK. This is probably preferred.
prefer to define main youself and invoke init function you can do it as well with shared library variant.
The main problem is that I miss a porting guide. Is there a need to change the code, are some changes suggested, others required? How do I ensure
In many case no changes are required. It should work as is.
that this changed code is compatible with as many versions of Boost as possible?
I have really problems ignoring http://www.boost.org/libs/test/doc/components/utf/index.html as I consider this the offical documentation for Boost.Test. But it contradicts in some parts with your updated one!
Yes, the version on boost.org is very old. Docs writting take as much time (if not more) as actual development.
Please look for more details here:
http://www.patmedia.net/~rogeeff/html/index.html
Please let me know if there is any issues still.
Problem with your updated documentation: http://www.patmedia.net/~rogeeff/html/utf/user-guide/usage-variants/static-l...
<quote> For a test module to be able to link with prebuilt library, the flag BOOST_TEST_ALTERNATIVE_INIT_API has to be defined both during library and a test module compilation. </quote>
Hm, strange. Above I read that I can optionally define BOOST_TEST_ALTERNATIVE_INIT_API or not. Maybe you want to inform that BOOST_TEST_ALTERNATIVE_INIT_API needs to be (un)defined for both - compiling the library and a test module compilation, e.g. it is invalid to compile the first with this macro defined and the test module without?
I might need to rephrase it. The idea is that if you opted to use alternative API you neeed to define this flag both during library and test module compilation.
http://www.patmedia.net/~rogeeff/html/utf/user-guide/usage-variants/dynamic-... <quote> This variant requires you to define the flag BOOST_TEST_DYN_LINK either in a makefile or before the header boost/test/unit_test.hpp inclusion. </quote>
Is there really a need to define BOOST_TEST_DYN_LINK or does it just simplify linking on the proprietary win32 platform?
Really, really ;)
Again: Why are static and shared libraries handled differently? It shouldn't matter!
It does on windows. Gennadiy

Hi Gennadiy, first of all thanks for your comments. Some stuff is now a little bit more understandable other stuff not. I hope you didn't considered my mails as complaints, I just tried to express that some parts of Boost.Test need some improvement. To be honest I think that your library is a very important one and well done. I will definitively look into it more carefully (reading the code/the docs multiple days) as it is impossible to understand the current implemention compared to the old outdated documenation with current resources in let's say less than one day. Please note that I'm also willing to resolve these issues and will try some improvements to the documenation. I have to confess that I did not write much documenation myself but I'm (mostly as translator) involved in many Open Source documents such as Debian Reference, Debian Website and other documents (HOWTOs, manpages, ...). I know XML and SGML based tools really well (and maintain these partely myself) so I do not expect problems with Boost documentation system. I don't have much time to explain all my issues with Boost.Test now in detail (I still have to buy some presents :-) but I will at least answer your questions: On Fri, Dec 21, 2007 at 02:27:31AM -0500, Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071219090237.GA13691@imkf-pc073.imkf.tu-freiberg.de...
And why are static and shared libraries handled differently? Why not just removing main also from static libraries?
Let me again note that I think that the words "static" and "shared" do not match here as both libraries are indeed different ones (which share a lot of code). This *needs* to be fixed! The current situation is clearly NOT acceptable (no joke!).
1. For backward compartibility
Here you assume that most users do not use the shared library. OK, let's assume this for now.
2. For enhanced usebility in many cases. For people producing a lot of unit tests adding extra function main() implementation is unnnecessary burdan (not mentioning that they will have to actually learn how implement it properly.
Confusing users with all kind of combinations of BOOST_TEST_DYN_LINK, BOOST_TEST_MAIN, BOOST_TEST_ALTERNATIVE_INIT_API, usage or not usage of main and the init method is OK? I'm sure many combination of these flags are just incompatible to each other. Defining a one line main() method (containing also test module initialization API code) instead of using macros would simplify a lot in code and documentaion (but would require a new API :-().
3. In many (if not the most) cases function main() handling is hidden completely from the users and usage and both usage variants behave pretty much the same. The only difference is presence of an extra macro BOOST_TEST_DYN_LINK.
Maybe. But I was never largely involved into Boost.Test and followed the first time mainly the normal starting instructions from the old docs (which are very easy!) and extented some parts later as needed (test_tools::predicate_result stuff, ...). So I consider my code the normal use case and you think it is very exotic as nearly no part of the documentation and your mails adress my usage?
You comming to this from *nix prospecive.
Right.
On NT dll and lib are two quite different ball games. Boost.Test opted to be consystent in between platforms.
But why not select the best of both systems? (To be honest I do not know anything with could be used from your propritary world.) You did it the opposite way.
Did you also consider using a stable ABI (application binary interface, would allow a binary to be used with different library version without need to recompile)
I sugest I write Boost.Test using C? In Boost.Test a lot of staff happends
The first "I" should probably be "You".
in headers. We might find it difficult.
No, one can also use ABIs in C++. Included code is part of the binary if it comes from headers and fixed even if you move the binary to another system where different shared libraries may be installed. ABI affects exported symbols in shared libraries only. As most Boost libs are indeed header based ABI does not affect these.
or API (application programming interface, no need to change the source code to be able to compile against a new version of a library) (at least some time in the future)
I do not plan any changes that should break backward compartibility. 1.34.1 did break it for very small number of use cases, which where never officially supported in a first place (plus I believe 1 tool was found unsafe and the interface was changes).
A stable API is a very good think. But if the current interface is unusable (and also impossible to document) it may be useful. All Boost libraries need to pass an initial review. Is it possible to rewrite libs after it completely (as you did????) or would it make sense to ask the community if changes are worth to be done?
which would make incompatibilities between shared and static libraries impossible and simplifies using different versions of Boost a lot? Whenever I try another Boost version existing code fails to compile or link ...
I am sure we will be able to figure it out.
Would be great!
As far as i know there is no problem compiling/linking Boost.Test.
I did not wrote about problems compiling Boost.Test but about using it! I prefer of course to use Boost from the packages provided on my system. Even if Boost isn't installed by default it is possible to select it for installation during seconds on each modern system.
The problem is that the example in the official documentation (which is (or should be) on www.boost.org not somewhere outside) just contains: "the Unit Test Framework is responsible for supplying function main()"
Even if you consider that to be outdated (again: Why do you not update it??????)
This seems to be one of the most important questions: Why do you not replace http://www.boost.org/libs/test/doc/index.html with http://www.patmedia.net/~rogeeff/html/index.html? Does the content need to be transfered from HTML first or what steps are missing?
you should assume that most code arround does not provide main() and fails that's why starting with recent versions.
Only those who employ shared library and manual registration had an issue.
Which is the default case in the old documentation. I also see some advantages: * No usage of just another macro * It's easier to uncomment a test (only a single line needs a comment, the compiler can still check the syntax of the not used test * I know the order of the execution of the tests for sure and can test basic stuff at the beginning
How could I define my own main function which is compatible with shared and dynamic libraries? unit_test_main has different signatures!?
1. shared and dynamic libs are comparitble ;)
I assume you forgot "not" here. Otherwise you refer to code rewriting (automatic registration, ...)?
2. Don't define init function at all.
I need an init function. I use a logger and set some parts to verbose file output and compare as another test the generated output with expected one. I would nevertheless like to do this directly in main() without need for another init function.
3. The test runner function signature is now the same for both static and dyanmic library (see svn). I am yet to update the updated docs ;)
Good.
Yes, the version on boost.org is very old. Docs writting take as much time (if not more) as actual development.
I fully agree. But why not using the best of both? Remove outdated pages on www.boost.org with your new docu *now*. Why do you wait?
Again: Why are static and shared libraries handled differently? It shouldn't matter!
It does on windows.
But it does not have to differ! Most Open Source code from Linux can be compiled on Windows as well. Do you think part of the porting is to change interfaces just for fun? It is not necessary! Jens

Hi Jens, This is in response to one of your points in this conversation: On Dec 21, 2007 9:23 PM, Jens Seidel <jensseidel@users.sf.net> wrote:
On Fri, Dec 21, 2007 at 02:27:31AM -0500, Gennadiy Rozental wrote:
Yes, the version on boost.org is very old. Docs writting take as much time (if not more) as actual development.
I fully agree. But why not using the best of both? Remove outdated pages on www.boost.org with your new docu *now*. Why do you wait?
The reason is because the version in www.boost.org pertains to documentation for the latest release of the code -- which is 1.34.1. If you're looking at and/or using the Boost.Test version in Trunk, then you should be able to generate the documentation from the distribution you've downloaded. Now, if you're saying that 1.34.1's documentation is not consistent with the released version, then perhaps it would be more productive if you look at how the Boost C++ Library does its development and release process -- then submit patches slated for 1.35. It's not like we just update a Wiki page and it pertains to the current stable version as far as documentation goes.
Again: Why are static and shared libraries handled differently? It shouldn't matter!
It does on windows.
But it does not have to differ! Most Open Source code from Linux can be compiled on Windows as well. Do you think part of the porting is to change interfaces just for fun? It is not necessary!
It differs because Windows treats DLL's differently from how Linux deals with shared object files (.so's). Boost.Test uses macro's to hide the details you otherwise have to worry about on a per platform basis -- like how do you load DLL's, and how do you leverage autolinking in Windows. Much of this stuff you don't have to worry about in Linux especially if you've got Linux specific constructs in your main(), but that makes your code non-platform specific. I hope this helps. -- Dean Michael C. Berris Software Engineer, Friendster, Inc. [http://cplusplus-soup.blogspot.com/] [mikhailberis@gmail.com] [+63 928 7291459] [+1 408 4049523]

"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071221132309.GA9314@imkf-pc073.imkf.tu-freiberg.de...
Hi Gennadiy,
first of all thanks for your comments. Some stuff is now a little bit more understandable other stuff not.
I hope you didn't considered my mails as complaints, I just tried to express that some parts of Boost.Test need some improvement. To be honest I think that your library is a very important one and well done. I will definitively look into it more carefully (reading the code/the docs multiple days) as it is impossible to understand the current implementation compared to the old outdated documentation with current resources in let's say less than one day.
Please note that I'm also willing to resolve these issues and will try some improvements to the documentation. I have to confess that I did not write much documentation myself but I'm (mostly as translator) involved in many Open Source documents such as Debian Reference, Debian Website and other documents (HOWTOs, manpages, ...). I know XML and SGML based tools really well (and maintain these partely myself) so I do not expect problems with Boost documentation system.
I don't have much time to explain all my issues with Boost.Test now in detail (I still have to buy some presents :-) but I will at least answer your questions:
On Fri, Dec 21, 2007 at 02:27:31AM -0500, Gennadiy Rozental wrote:
"Jens Seidel" <jensseidel@users.sf.net> wrote in message news:20071219090237.GA13691@imkf-pc073.imkf.tu-freiberg.de...
And why are static and shared libraries handled differently? Why not just removing main also from static libraries?
Let me again note that I think that the words "static" and "shared" do not match here as both libraries are indeed different ones (which share a lot of code). This *needs* to be fixed! The current situation is clearly NOT acceptable (no joke!).
They are not different in most part. The only part that is different is test runner signature and required init function signature.
1. For backward compatibility
Here you assume that most users do not use the shared library. OK, let's assume this for now.
Till 1.34.1 shared library was not officially supported at all.
2. For enhanced usability in many cases. For people producing a lot of unit tests adding extra function main() implementation is unnecessary burden (not mentioning that they will have to actually learn how implement it properly.
Confusing users with all kind of combinations of BOOST_TEST_DYN_LINK, BOOST_TEST_MAIN, BOOST_TEST_ALTERNATIVE_INIT_API, usage or not usage of main and the init method is OK?
1. IMO majority of the users will never need to know anything about BOOST_TEST_ALTERNATIVE_INIT_API 2. What do you find confusing? BOOST_TEST_DYN_LINK and BOOST_TEST_MAIN macros serve separate and orthogonal purposes. 3. IMO majority of the users will never need to know anything about both init and main() functions.
I'm sure many combination of these flags are just incompatible to each other.
BOOST_TEST_MAIN and BOOST_TEST_DYN_LINK are for the most part orthogonal.
Defining a one line main() method (containing also test module initialization API code) instead of using macros would simplify a lot in code and documentation (but would require a new API :-().
And is not necessary in majority of use case IMO. It might simplify docs though.
3. In many (if not the most) cases function main() handling is hidden completely from the users and usage and both usage variants behave pretty much the same. The only difference is presence of an extra macro BOOST_TEST_DYN_LINK.
Maybe. But I was never largely involved into Boost.Test and followed the first time mainly the normal starting instructions from the old docs (which are very easy!) and extended some parts later as needed (test_tools::predicate_result stuff, ...). So I consider my code the normal use case and you think it is very exotic as nearly no part of the documentation and your mails address my usage?
Your use case is still supported, unless I am missing something. It's just is not considered the most user friendly and accordingly might require extra leg work.
You coming to this from *nix prospective.
Right.
On NT dll and lib are two quite different ball games. Boost.Test opted to be consistent in between platforms.
But why not select the best of both systems? (To be honest I do not know anything with could be used from your proprietary world.) You did it the opposite way.
I did it in a way to make library portable in between different platforms. Being consistent in between different usage variants was not my primary priority (though would be nice to have). Usually usage variant is selected once based on some external restriction and users don't need to jump from one to another every few seconds.
Did you also consider using a stable ABI (application binary interface, would allow a binary to be used with different library version without need to recompile)
I suggest I write Boost.Test using C? In Boost.Test a lot of staff happened
The first "I" should probably be "You".
in headers. We might find it difficult.
No, one can also use ABIs in C++. Included code is part of the binary if it comes from headers and fixed even if you move the binary to another system where different shared libraries may be installed. ABI affects exported symbols in shared libraries only. As most Boost libs are indeed header based ABI does not affect these.
Boost.Test is still evolving. My priority is not stable ABI, but backward compartibility in a sense that test modules that used to work should still work when built with new version of boost. Once dust is settled we might see stable ABI.
or API (application programming interface, no need to change the source code to be able to compile against a new version of a library) (at least some time in the future)
I do not plan any changes that should break backward compatibility. 1.34.1 did break it for very small number of use cases, which where never officially supported in a first place (plus I believe 1 tool was found unsafe and the interface was changes).
A stable API is a very good think. But if the current interface is unusable (and also impossible to document) it may be useful.
I am not sure what interface you mean, but if you refer to test runner interface and shared library, than yes it was unusable. But shared library never was part of "contract". It was never tested against and only existed on some platforms as a fluke of make system. There were no problems with pre 1.34 interfaces for static library and they stay the same. There were new interfaces introduced for automated test units registration, but old one still supported.
All Boost libraries need to pass an initial review. Is it possible to rewrite libs after it completely (as you did????) or would it make sense to ask the community if changes are worth to be done?
The public interfaces were not changed in most part, though the library did undergo major implementation rework somewhere in between 1.33 and 1.34. In a retrospect It might've been useful to do a mini review.
As far as I know there is no problem compiling/linking Boost.Test.
I did not wrote about problems compiling Boost.Test but about using it!
I means problems compiling/linking of test modules with Boost.Test.
I prefer of course to use Boost from the packages provided on my system. Even if Boost isn't installed by default it is possible to select it for installation during seconds on each modern system.
So select one usage variant (static or shared) and stick with it. Why do you concerned with inter-variant compatibility.
The problem is that the example in the official documentation (which is (or should be) on www.boost.org not somewhere outside) just contains: "the Unit Test Framework is responsible for supplying function main()"
Even if you consider that to be outdated (again: Why do you not update it??????)
This seems to be one of the most important questions: Why do you not replace http://www.boost.org/libs/test/doc/index.html with http://www.patmedia.net/~rogeeff/html/index.html? Does the content need to be transferred from HTML first or what steps are missing?
1. I do not how to do it 2. I do not know if it possible at all. 3. The later version is beta I am still working on.
you should assume that most code around does not provide main() and fails that's why starting with recent versions.
Only those who employ shared library and manual registration had an issue.
Which is the default case in the old documentation. I also see some
No. shared library was *never* supported. for a long time the default and only case was static library. Next was "included" variant. Next I finally managed to support dynamic library in 1.34. Latest addition is an ability to build test module as shared library and run using external test runner. Users of static library and manual registration did not see any differences when upgraded to 1.34.
advantages:
* No usage of just another macro
Not a big advantage. In fact it rather disadvantage in this case: 1. Point of test case definition and registration are remote. You may just forget to register one and no one will notice. 2. It's repetitive: for each test case you need to repeat it second time for registration. And in case if it's defined in another test file you will need extern declaration as well.
* It's easier to uncomment a test (only a single line needs a comment, the compiler can still check the syntax of the not used test
It still pretty simple to comment out single test case. And in 1.35 there will be an ability to filter out test units by name.
* I know the order of the execution of the tests for sure and can test basic stuff at the beginning
In fact you don't. And you shouldn't. Proper test case should be self contained.
How could I define my own main function which is compatible with shared and dynamic libraries? unit_test_main has different signatures!?
1. shared and dynamic libs are compatible ;)
I assume you forgot "not" here. Otherwise you refer to code rewriting (automatic registration, ...)?
No. I did not. IMO shared == dynamic.
2. Don't define init function at all.
I need an init function. I use a logger and set some parts to verbose file output and compare as another test the generated output with expected one. I would nevertheless like to do this directly in main() without need for another init function.
You are better of with global fixture. How can you compare anything with expected output from init function?
3. The test runner function signature is now the same for both static and dynamic library (see svn). I am yet to update the updated docs ;)
Good.
Well almost. Init function signature is different. And it;s required as an argument in both cases.
Again: Why are static and shared libraries handled differently? It shouldn't matter!
It does on windows.
But it does not have to differ! Most Open Source code from Linux can be compiled on Windows as well. Do you think part of the porting is to change interfaces just for fun? It is not necessary!
I did not change interfaces in between Linux and Windows. Static and Dynamic libraries interface does differ. I am afraid that might sound like repetition, but let me retell the story again: Original Boost.Test library was working only as static library. The problem with dynamic libraries was: * it can't included main() * it can't have unresolved symbols. Accordingly original initialization interface, that is based on externally defined init function was not going to work for shared libraries. I had several alternatives: 1. Forget about it. This is what we were doing before 1.34 2. Change all the interfaces plus require users to define function main(). This is what you suggest. This was problematic, since there were many users of Boost.Test already and many of them are content with macro usage and much prefer to avoid unnecessary work of function main() definition. 3. Make an alternative interface for use with shared libraries. and require users to implement function main oh their test modules. This solution makes static and shared library usages incompatible. But this is the least evil I found in this case. In addition I've changed the meaning of some of the macro in case of dynamic library so that function main can be generated in some cases automatically. Hope this will clear it out, Gennadiy

on Sun Dec 23 2007, "Gennadiy Rozental" <rogeeff-AT-gmail.com> wrote:
This seems to be one of the most important questions: Why do you not replace http://www.boost.org/libs/test/doc/index.html with http://www.patmedia.net/~rogeeff/html/index.html? Does the content need to be transferred from HTML first or what steps are missing?
1. I do not how to do it 2. I do not know if it possible at all.
Oh, come on, man. That's just too hard to swallow. http://lists.boost.org/Archives/boost/2005/08/91786.php
3. The later version is beta I am still working on.
-- Dave Abrahams Boost Consulting http://www.boost-consulting.com

David Abrahams <dave <at> boost-consulting.com> writes:
on Sun Dec 23 2007, "Gennadiy Rozental" <rogeeff-AT-gmail.com> wrote:
This seems to be one of the most important questions: Why do you not replace http://www.boost.org/libs/test/doc/index.html with http://www.patmedia.net/~rogeeff/html/index.html? Does the content need to be transferred from HTML first or what steps are missing?
1. I do not how to do it 2. I do not know if it possible at all.
Oh, come on, man. That's just too hard to swallow. http://lists.boost.org/Archives/boost/2005/08/91786.php
Yeah. Since I never got to do it, I forgot about it. At this point I will wait for 1.35 Gennadiy

Gennadiy Rozental wrote: >> >>>> This seems to be one of the most important questions: Why do you not >>>> replace http://www.boost.org/libs/test/doc/index.html with >>>> http://www.patmedia.net/~rogeeff/html/index.html? >>>> Does the content need to be transferred from HTML first or what steps are >>>> missing? >>> 1. I do not how to do it >>> 2. I do not know if it possible at all. >> Oh, come on, man. That's just too hard to swallow. >> http://lists.boost.org/Archives/boost/2005/08/91786.php > > Yeah. Since I never got to do it, I forgot about it. At this point I will wait > for 1.35 > It appears to me that the new docs are not yet in the 1.35 release branch. Should they be? http://svn.boost.org/svn/boost/branches/release/libs/test/doc/ ... or am I looking in the wrong spot?

eg <egoots <at> gmail.com> writes: > > Gennadiy Rozental wrote: > >> > >>>> This seems to be one of the most important questions: Why do you not > >>>> replace http://www.boost.org/libs/test/doc/index.html with > >>>> http://www.patmedia.net/~rogeeff/html/index.html? > >>>> Does the content need to be transferred from HTML first or what steps are > >>>> missing? > >>> 1. I do not how to do it > >>> 2. I do not know if it possible at all. > >> Oh, come on, man. That's just too hard to swallow. > >> http://lists.boost.org/Archives/boost/2005/08/91786.php > > > > Yeah. Since I never got to do it, I forgot about it. At this point I will wait > > for 1.35 > > > > It appears to me that the new docs are not yet in the 1.35 release > branch. Should they be? Yes, they should. And yes they are not there yet. I've spent last couple weeks updating them with recent changes in Boost.Test. New beta now in regular location in patmedia.net/~rogeeff. The only one major problem that's left is incorporating my docs with official boostbook. The primary obstacle from me is lack of any support for this component. I am not even sure there is any particular person responsible for it. I need to introduce quite big changes into boostbook and in a past I was not able to get any responce for even simple support requests. I am planing to follow up un Boost.docs list with conreate list of changes I need. Also I'll need changes in boost.Build since I need additional options for xsltproc. Gennadiy

on Fri Dec 21 2007, Jens Seidel <jensseidel-AT-users.sf.net> wrote:
All Boost libraries need to pass an initial review. Is it possible to rewrite libs after it completely (as you did????)
Yes.
or would it make sense to ask the community if changes are worth to be done?
We give library maintainers total freedom to modify a library once it is accepted; that's a very strong incentive to participate. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com
participants (10)
-
Benoit Sigoure
-
David Abrahams
-
Dean Michael Berris
-
eg
-
Gennadiy Rozental
-
Ilya Sokolov
-
Jens Seidel
-
Pierre-Jules Tremblay
-
Steve M. Robbins
-
Vladimir Prus