#! /bin/sh /usr/share/dpatch/dpatch-run
## 90-docs.dpatch by martin f. krafft <madduck@debian.org>
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: Add documentation from webpage.
@DPATCH@
diff -urNad libtut-0.0.20060329~/docs/Makefile libtut-0.0.20060329/docs/Makefile
--- libtut-0.0.20060329~/docs/Makefile 1970-01-01 01:00:00.000000000 +0100
+++ libtut-0.0.20060329/docs/Makefile 2006-06-09 16:53:46.231411997 +0200
@@ -0,0 +1,6 @@
+.PHONY: get
+get:
+ for i in howto example design faq; do \
+ wget -O $$i.html http://tut-framework.sourceforge.net/$$i/; \
+ done
+ sed -i -e "\$$s,> .*,> $$(date)," README.docs
diff -urNad libtut-0.0.20060329~/docs/README.docs libtut-0.0.20060329/docs/README.docs
--- libtut-0.0.20060329~/docs/README.docs 1970-01-01 01:00:00.000000000 +0100
+++ libtut-0.0.20060329/docs/README.docs 2006-06-09 16:53:50.343609186 +0200
@@ -0,0 +1,9 @@
+libtut documentation README
+---------------------------
+
+The HTML files you can find in this directory have been pulled from the TUT
+homepage[0] at the point in time listed below.
+
+0. http://tut-framework.sourceforge.net
+
+ -- martin f. krafft <madduck@debian.org> Fri Jun 9 16:53:50 CEST 2006
diff -urNad libtut-0.0.20060329~/docs/design.html libtut-0.0.20060329/docs/design.html
--- libtut-0.0.20060329~/docs/design.html 1970-01-01 01:00:00.000000000 +0100
+++ libtut-0.0.20060329/docs/design.html 2006-06-09 16:53:49.667576768 +0200
@@ -0,0 +1,479 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title>TUT Design - TUT: C++ Unit Test Framework</title>
+<meta name="keywords" content="C++ test-driven unit tests TUT framework STL">
+<meta name="description" content="TUT Design - what's hidden under the hood of tut.h, and why things are such as they
+ are">
+<style type="text/css">
+<!--
+
+body, p, td
+{
+ scrollbar-base-color: #eeeeee;
+ scrollbar-track-color: #ffffff;
+ scrollbar-arrow-color: #cccccc;
+ scrollbar-shadow-color: #cccccc;
+ scrollbar-highlight-color: #cccccc;
+ scrollbar-darkshadow-color: #ffffff;
+ scrollbar-3dlight-color: #ffffff;
+
+ /*
+ scrollbar-base-color: #cccccc;
+ scrollbar-track-color: #ffffff;
+ scrollbar-arrow-color: #eeeeee;
+ */
+
+ font-family : Verdana, Arial, Helvetica, sans-serif;
+ font-size : 14px;
+ color: #000000;
+}
+
+pre
+{
+ font-family : Courier, sans-serif;
+ font-size : 12px;
+}
+
+strong, b
+{
+ font-weight : bold;
+}
+
+ul
+{
+ list-style-type : square;
+}
+
+.header
+{
+ font-size : 24px;
+ font-weight : bold;
+}
+
+.subheader
+{
+ font-size : 16px;
+ font-weight : bold;
+}
+
+.logo
+{
+ font-size : 24px;
+ font-weight : bold;
+}
+
+.question
+{
+ font-size : 16px;
+ font-weight : bold;
+ color : #000000;
+}
+
+a
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : none;
+}
+
+a:hover
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : underline;
+}
+
+a:visited
+{
+ font-weight : bold;
+ color : #ff9900;
+}
+
+a.menu
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : none;
+}
+
+a.menu:hover
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : underline;
+}
+
+a.menu:visited
+{
+ font-weight : bold;
+ color : #ff9900;
+}
+
+//-->
+</style>
+</head>
+
+<body text="#000000" link="#ff9900" alink="#ffcc00" vlink="#ff9900" bgcolor="#ffffff" leftmargin=0 topmargin=0 marginheight=0 marginwidth=0>
+
+<img src="/_img/pixel.gif" alt="" width=1 height=20><br>
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width=20 align=left valign=top>
+<img src="/_img/pixel.gif" alt="" width=20 height=1><br>
+</td>
+<td width="100%" align=left valign=top>
+<!-- home table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="logo"><a href="/">TUT: C++ Unit Test Framework</a></p>
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- home table << -->
+</td>
+<td width=20 align=left valign=top>
+<img src="/_img/pixel.gif" alt="" width=20 height=1><br>
+</td>
+</tr>
+</table>
+
+<table border=0 width="100%" cellspacing=20 cellpadding=0>
+<tr>
+<td width="30%" align=left valign=top>
+<!-- menu table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="subheader">Documentation</p>
+<ul>
+<li><p><a href="/howto/" class="menu">TUT How-To</a><br>minimum steps to make TUT work for you</p></li>
+<li><p><strong>TUT Design</strong><br>what's hidden under the hood of tut.h, and why things are such as they
+ are</p></li>
+<li><p><a href="/example/" class="menu">TUT Usage Example</a><br>it's better to see once...</p></li>
+<li><p><a href="/whole/" class="menu">TUT As Is</a><br>complete source of TUT</p></li>
+</ul>
+<p class="subheader">Distribution</p>
+<ul>
+<li><p><a href="/copyright/" class="menu">The TUT License</a><br>almost no restrictions to use</p></li>
+<li><p><a href="/download/" class="menu">TUT Downloads</a><br>latest version of TUT as well as other related stuff</p></li>
+</ul>
+<p class="subheader">Support</p>
+<ul>
+<li><p><a href="/faq/" class="menu">TUT Frequently Asked Questions</a><br>often asked questions and answers for them</p></li>
+<li><p><a href="/links/" class="menu">Links</a><br>related projects and concepts</p></li>
+<li><p><a href="/author/" class="menu">TUT Author</a><br>who is the author</p></li>
+</ul>
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- menu table << -->
+</td>
+<td width="70%" valign=top>
+<!-- content table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="header">TUT Design</p>
+<p>In this document I attempt to explain the decisions made while developing
+ TUT.</p>
+
+ <p class="subheader">Requirements</p>
+
+ <p> One day I ran into need of unit test framework for C++. So, I've made a small research
+ and discovered C++Unit, boost::test and a bunch of similar libraries.. Though
+ they were usable, I was not satisfied with the approach they offered; so I
+ designed my own variant of unit test framework based on the following
+ restrictions: </p>
+
+ <ul>
+ <li>No C-style macros</li>
+ <li>No manual registration for test groups and methods</li>
+ <li>No libraries of any kind</li>
+ <li>Neutrality to user interface</li>
+ <li>No Javisms</li>
+ </ul>
+
+ <p class="subheader">C-style macros and what's wrong with them</p>
+
+ <p> Usually C++ Unit test frameworks define a lot of macroses to achieve the goals
+ other languages have as built-in features: for example, Java is able to show you
+ the whole exception stack; and C++ cannot. So, to achieve the same (or similar)
+ results, C++ frameworks often declare a macro to catch any exception and trace
+ __FILE__ and __LINE__ variables. </p>
+
+ <p> The problem is that it turns the C++ code into something that is hard to read, where
+ "hard to read" actually means "hard to maintain". </p>
+
+ <p> Macros don't recognize namespace borders, so a simple macro can expand in the user
+ code into something unexpected. To avoid this, we have to give macros unique
+ prefixes, and this, in turn, reduces code readability even more. </p>
+
+ <p> From bad to worse, C-style macros can't handle modern C++ templates, so comma
+ separated template arguments will break the macro, since preprocessor will
+ handle the template as two arguments (separated by the comma used in the
+ template) to this macro. </p>
+
+ <p> And the final contra for macros is that even if used they cannot achieve the same
+ usability level as the native language tools; for example, macros cannot
+ generate a full stack trace (at least, in a platform-independent manner). So it
+ looks like we loose readability and get almost nothing for this. </p>
+
+ <p> See also Bjarne Stroustrup notices about macros harmness:
+ <a href="http://www.research.att.com/~bs/bs_faq2.html#macro"> So,
+ what's wrong with using macros?</a> </p>
+
+ <p class="subheader">Manual registration and why it annoys me</p>
+
+ <p> In JUnit (Java-based Unit Tests framework) reflection is used to recognize
+ user-written test methods. C++ has no reflection or similar mechanism, so user
+ must somehow tell the framework that "this, this and that" methods should be
+ considered as test methods, and others are just helpers for them. </p>
+
+ <p> The same can be said about test groups, which have to be registered in test runner
+ object. </p>
+
+ <p> Again, most C++ frameworks introduce macros or at least methods to register a
+ freestanding function or method as a test instance. I find writing redundant
+ code rather annoying: I have to write test itself and then I have to write more code
+ to mark that my test is a test. Even more, if I forget to register the method,
+ nothing will warn me or somehow indicate that I have not done what I should. </p>
+
+ <p class="subheader">Library and integration problems</p>
+
+ <p> Most of C++ frameworks require building a library that user must link to test
+ application to be able to run tests. The problem is that various platforms imply
+ different ways for building libraries. One popular C++ framework has more than
+ 60% bugs in their bug database that sound like "cannot build library on platform
+ XXX" or "built library doesn't work on platform YYY". </p>
+
+ <p> Besides, some platforms has complexities in library memory management (e.g.
+ Win32). </p>
+
+ <p class="subheader">User interface</p>
+
+ <p> Some frameworks provide predefined formatters for output results, for example
+ CSV or XML. This restricts users in test results presentation options. What if a
+ user wants some completely different format? Of course, he can implement his own
+ formatter, but why frameworks provide useless formatters then? </p>
+
+ <p> The ideal test framework must do only one thing: run tests. Anything beyond that is
+ the responsibility of the user code. Framework provides the test results, and
+ the user code then represents them in any desired form. </p>
+
+ <p class="subheader">Javisms</p>
+
+ <p>Most implementors of C++ test frameworks know about JUnit and inspired by
+ this exciting tool. But, carelessly copying a Java implementation to C++, we can
+ get strange and ugly design.</p>
+
+ <p>Rather obvious example: JUnit has methods for setting up a test (setUp) and for
+ cleaning after it (tearDown). I know at least two C++ frameworks that have these
+ methods with the same semantics and names. But in C++ the job these methods do is
+ the responsibility of constructor and destructor! In Java we don't have
+ guaranteed destruction, so JUnit authors had to invent their own replacement
+ for it - tearDown(); and it was natural then to introduce constructing
+ counterpart - setUp(). Doing the same in C++ is absolutely redundant
+ </p>
+
+ <p>C++ has its own way of working, and whenever possible, I am going to stay at the C++
+ roads, and will not repeat Java implementation just because it is really good for
+ Java. </p>
+
+ <p class="subheader">Decisions</p>
+
+ <p class="subheader">No C-style macros</p>
+
+ <p>The solution is that simple: just
+ <b>do not</b> use any macros. I personally never needed a macro during
+ development. </p>
+
+ <p class="subheader">No manual registration</p>
+
+ <p>Since C++ has no reflection, the only way to mark a method as a test is to give it a kind
+ of predefined name.</p>
+
+ <p>There would be a simple solution: create a set of virtual methods in test object base
+ class, and allow user to overwrite them. The code might look like:</p>
+
+ <pre> struct a_test_group : public test_group { virtual void test1() { ... } virtual
+ void test2() { ... } }; </pre>
+
+ <p>Unfortunately, this approach has major drawbacks:</p>
+
+ <ul>
+ <li>It scales badly. Consider, we have created 100 virtual test methods in a test
+ group, but user needs 200. How can he achieve that? There is no proper way.
+ Frankly speaking, such a demand will arise rarely (mostly in
+ script-generated tests), but even the possibility of it makes this kind of
+ design seemingly poor. </li>
+
+ <li>There is no way to iterate virtual methods automatically. We
+ would end up writing code that calls test1(), then test2(), and so on, each
+ with its own exception handling and reporting.</li>
+ </ul>
+
+ <p>Another possible solution is to substitute reflection with a dynamic loading.
+ User then would write static functions with predefined names, and TUT would use
+ dlsym()/GetProcAddress() to find out the implemented tests. </p>
+
+ <p>But I rejected the solution due to its platform and library operations
+ dependencies. As I described above, the library operations are quite different
+ on various platform. </p>
+
+ <p>There was also an idea to have a small parser, that can scan the user code and
+ generate registration procedure. This solution only looks simple; parsing
+ free-standing user code can be a tricky procedure, and might easily overgrow twelve TUTs
+ in complexity.</p>
+
+ <p>Fortunately, modern C++ compilers already have a tool that can parse the user code
+ and iterate methods. It is compiler template processing engine. To be more
+ precise, it is template specialization technique.</p>
+
+ <p>The following code iterates all methods named test<N> ranging from n to 0,
+ and takes the address of each:</p>
+
+ <pre>
+template <class Test,class Group,int n>
+struct tests_registerer
+{
+ static void reg(Group& group)
+ {
+ group.reg(n,&Test::template test<n>);
+ tests_registerer<Test,Group,n-1>::reg(group);
+ }
+};
+
+template<class Test,class Group>
+struct tests_registerer<Test,Group,0>
+{
+ static void reg(Group&){};
+};
+...
+test_registerer<test,group,100>.reg(grp);
+ </pre>
+
+ <p>This code generates recursive template instantiations until it reaches
+ tests_registerer<Test,Group,0> which has empty specialization.
+ There the recursion stops.</p>
+
+ <p>The code is suitable for our needs because in the specialization preference is
+ given to the user-written code, not to the generic one. Suppose we have a default
+ method test<N> in our test group, and the user-written specialization
+ for test<1>. So while iterating, compiler will get the address of the
+ default method for all N, except 1, since user has supplied a special version of
+ that method. </p>
+
+ <pre>
+template<int N>
+void test() { };
+...
+template<>
+void test_group::test<1>() { // user code here }
+ </pre>
+
+ <p>This approach can be regarded as kind of compile-time virtual functions, since
+ the user-written methods replace the default implementation. At the same time,
+ it scales well - one just has to specify another test number upper bound at compile
+ time. The method also allows iteration of methods, keeping code compact.</p>
+
+ <p class="subheader">Library</p>
+
+ <p>Since we dig into the template processing, it is natural to not build any
+ libraries, therefor this problem mostly disappeares. Unfortunately, not
+ completely: our code still needs some central point where it could register
+ itself. But that point (singleton) is so small that it would be an overkill to
+ create library just to put there one single object. Instead, we assume that the
+ user code will contain our singleton somewhere in the main module of test
+ application.</p>
+
+ <p class="subheader">User interface. Callbacks.</p>
+
+ <p>Our code will perform only minimamum set of tasks: TUT shall run tests. But we still
+ need a way to adapt the end-user presentation requirements. For some of users it
+ would be enough to see only failed tests in listing; others would like to see the
+ complete plain-text report; some would prefer to get XML reports, and some would
+ not want to get any reports at all since they draw their test execution log in GUI
+ plugin for an IDE. </p>
+
+ <p>"Many users" means "many demands", and satisfying all of them is quite a hard task.
+ Attempt to use a kind of silver bullet (like XML) is not the right solution, since
+ user would lack XML parser in his environment, or just would not want to put it into
+ his project due to integration complexities.</p>
+
+ <p>The decision was made to allow users to form their reports by themselfs. TUT will
+ report an event, and the user code will form some kind of an artefact based on this
+ event.</p>
+
+ <p>The implementation of this decision is interface tut::callback. The user code
+ creates a callback object, and passes it to the runner. When an appropriate event
+ occures, the test runner invokes callback methods. User code can do anything,
+ from dumping test results to std::cout to drawing 3D images, if desired. </p>
+
+ <p class="subheader">STL</p>
+
+ <p>Initially, there were plans to make TUT traits-based in order not to restrict
+ it with STL only, but have a possibility to use other kinds of strings
+ (TString, CString), containers and intercepted exceptions. </p>
+
+ <p>In the current version, these plans are not implemented due to relative
+ complexity of the task. For example, the actual set of operations can be quite
+ different for various map implementations and this makes writing generic code
+ much harder. </p>
+
+ <p>Thus so far TUT is completely STL-based, since STL is the only library existing
+ virtually on every platform. </p>
+<img src="/_img/pixel.gif" alt="" width=1 height=300><br>
+
+<center>
+<!--RAX counter-->
+<script language="JavaScript">
+<!--
+document.write('<a href="http://www.rax.ru/click" '+
+'target=_blank><img src="http://counter.yadro.ru/hit?t13.4;r'+
+escape(document.referrer)+((typeof(screen)=='undefined')?'':
+';s'+screen.width+'*'+screen.height+'*'+(screen.colorDepth?
+screen.colorDepth:screen.pixelDepth))+';'+Math.random()+
+'" alt="rax.ru: ïîêàçàíî ÷èñëî õèòîâ çà 24 ÷àñà, ïîñåòèòåëåé çà 24 ÷àñà è çà ñåãîäí\ÿ" '+
+'border=0 width=88 height=31></a><br>')
+//-->
+</script>
+<!--/RAX-->
+</center>
+
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- content table << -->
+</td>
+</tr>
+</table>
+
+</body>
+</html>
diff -urNad libtut-0.0.20060329~/docs/example.html libtut-0.0.20060329/docs/example.html
--- libtut-0.0.20060329~/docs/example.html 1970-01-01 01:00:00.000000000 +0100
+++ libtut-0.0.20060329/docs/example.html 2006-06-09 16:53:48.871538596 +0200
@@ -0,0 +1,379 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title>TUT Usage Example - TUT: C++ Unit Test Framework</title>
+<meta name="keywords" content="C++ test-driven unit tests TUT framework STL">
+<meta name="description" content="TUT Usage Example - it's better to see once...">
+<style type="text/css">
+<!--
+
+body, p, td
+{
+ scrollbar-base-color: #eeeeee;
+ scrollbar-track-color: #ffffff;
+ scrollbar-arrow-color: #cccccc;
+ scrollbar-shadow-color: #cccccc;
+ scrollbar-highlight-color: #cccccc;
+ scrollbar-darkshadow-color: #ffffff;
+ scrollbar-3dlight-color: #ffffff;
+
+ /*
+ scrollbar-base-color: #cccccc;
+ scrollbar-track-color: #ffffff;
+ scrollbar-arrow-color: #eeeeee;
+ */
+
+ font-family : Verdana, Arial, Helvetica, sans-serif;
+ font-size : 14px;
+ color: #000000;
+}
+
+pre
+{
+ font-family : Courier, sans-serif;
+ font-size : 12px;
+}
+
+strong, b
+{
+ font-weight : bold;
+}
+
+ul
+{
+ list-style-type : square;
+}
+
+.header
+{
+ font-size : 24px;
+ font-weight : bold;
+}
+
+.subheader
+{
+ font-size : 16px;
+ font-weight : bold;
+}
+
+.logo
+{
+ font-size : 24px;
+ font-weight : bold;
+}
+
+.question
+{
+ font-size : 16px;
+ font-weight : bold;
+ color : #000000;
+}
+
+a
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : none;
+}
+
+a:hover
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : underline;
+}
+
+a:visited
+{
+ font-weight : bold;
+ color : #ff9900;
+}
+
+a.menu
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : none;
+}
+
+a.menu:hover
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : underline;
+}
+
+a.menu:visited
+{
+ font-weight : bold;
+ color : #ff9900;
+}
+
+//-->
+</style>
+</head>
+
+<body text="#000000" link="#ff9900" alink="#ffcc00" vlink="#ff9900" bgcolor="#ffffff" leftmargin=0 topmargin=0 marginheight=0 marginwidth=0>
+
+<img src="/_img/pixel.gif" alt="" width=1 height=20><br>
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width=20 align=left valign=top>
+<img src="/_img/pixel.gif" alt="" width=20 height=1><br>
+</td>
+<td width="100%" align=left valign=top>
+<!-- home table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="logo"><a href="/">TUT: C++ Unit Test Framework</a></p>
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- home table << -->
+</td>
+<td width=20 align=left valign=top>
+<img src="/_img/pixel.gif" alt="" width=20 height=1><br>
+</td>
+</tr>
+</table>
+
+<table border=0 width="100%" cellspacing=20 cellpadding=0>
+<tr>
+<td width="30%" align=left valign=top>
+<!-- menu table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="subheader">Documentation</p>
+<ul>
+<li><p><a href="/howto/" class="menu">TUT How-To</a><br>minimum steps to make TUT work for you</p></li>
+<li><p><a href="/design/" class="menu">TUT Design</a><br>what's hidden under the hood of tut.h, and why things are such as they
+ are</p></li>
+<li><p><strong>TUT Usage Example</strong><br>it's better to see once...</p></li>
+<li><p><a href="/whole/" class="menu">TUT As Is</a><br>complete source of TUT</p></li>
+</ul>
+<p class="subheader">Distribution</p>
+<ul>
+<li><p><a href="/copyright/" class="menu">The TUT License</a><br>almost no restrictions to use</p></li>
+<li><p><a href="/download/" class="menu">TUT Downloads</a><br>latest version of TUT as well as other related stuff</p></li>
+</ul>
+<p class="subheader">Support</p>
+<ul>
+<li><p><a href="/faq/" class="menu">TUT Frequently Asked Questions</a><br>often asked questions and answers for them</p></li>
+<li><p><a href="/links/" class="menu">Links</a><br>related projects and concepts</p></li>
+<li><p><a href="/author/" class="menu">TUT Author</a><br>who is the author</p></li>
+</ul>
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- menu table << -->
+</td>
+<td width="70%" valign=top>
+<!-- content table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="header">TUT Usage Example</p>
+<pre>
+#include <tut.h>
+#include <set>
+#include <memory>
+
+/**
+ * This example test group tests std::auto_ptr implementation.
+ * Tests are far from full, of course.
+ */
+namespace tut
+{
+ /**
+ * Struct which may contain test data members.
+ * Test object (class that contains test methods)
+ * will inherite from it, so each test method can
+ * access members directly.
+ *
+ * Additionally, for each test, test object is re-created
+ * using defaut constructor. Thus, any prepare work can be put
+ * into default constructor.
+ *
+ * Finally, after each test, test object is destroyed independently
+ * of test result, so any cleanup work should be located in destructor.
+ */
+ struct auto_ptr_data
+ {
+ /**
+ * Type used to check scope lifetime of auto_ptr object.
+ * Sets extern boolean value into true at constructor, and
+ * to false at destructor.
+ */
+ bool exists;
+ struct existing
+ {
+ bool& s_;
+ existing(bool& s) : s_(s){ s_ = true; };
+ ~existing(){ s_ = false; };
+ };
+ };
+
+ /**
+ * This group of declarations is just to register
+ * test group in test-application-wide singleton.
+ * Name of test group object (auto_ptr_group) shall
+ * be unique in tut:: namespace. Alternatively, you
+ * you may put it into anonymous namespace.
+ */
+ typedef test_group<auto_ptr_data> tf;
+ typedef tf::object object;
+ tf auto_ptr_group("std::auto_ptr");
+
+ /**
+ * Checks default constructor.
+ */
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ std::auto_ptr<existing> ap;
+ ensure(ap.get()==0);
+ ensure(ap.operator->()==0);
+ }
+
+ /**
+ * Checks constructor with object
+ */
+ template<>
+ template<>
+ void object::test<2>()
+ {
+ {
+ std::auto_ptr<existing> ap(new existing(exists));
+ ensure("get",ap.get()!=0);
+ ensure_equals("constructed",exists,true);
+ }
+ // ptr left scope
+ ensure_equals("destructed",exists,false);
+ }
+
+ /**
+ * Checks operator -> and get()
+ */
+ template<>
+ template<>
+ void object::test<3>()
+ {
+ std::auto_ptr<existing> ap(new existing(exists));
+ existing* p1 = ap.get();
+ existing* p2 = ap.operator->();
+ ensure("get equiv ->",p1==p2);
+ // ensure no losing ownership
+ p1 = ap.get();
+ ensure("still owner",p1==p2);
+ }
+
+ /**
+ * Checks release()
+ */
+ template<>
+ template<>
+ void object::test<4>()
+ {
+ {
+ std::auto_ptr<existing> ap(new existing(exists));
+ existing* p1 = ap.get();
+ std::auto_ptr<existing> ap2(ap.release());
+ ensure("same pointer",p1==ap2.get());
+ ensure("lost ownership",ap.get()==0);
+ }
+ ensure("destructed",exists==false);
+ }
+
+ /**
+ * Checks assignment.
+ */
+ template<>
+ template<>
+ void object::test<5>()
+ {
+ {
+ std::auto_ptr<existing> ap(new existing(exists));
+ existing* p1 = ap.get();
+ std::auto_ptr<existing> ap2;
+ ap2 = ap;
+ ensure("same pointer",p1==ap2.get());
+ ensure("lost ownership",ap.get()==0);
+ }
+ ensure("destructed",exists==false);
+ }
+
+ /**
+ * Checks copy constructor.
+ */
+ template<>
+ template<>
+ void object::test<6>()
+ {
+ {
+ std::auto_ptr<existing> ap(new existing(exists));
+ existing* p1 = ap.get();
+ std::auto_ptr<existing> ap2(ap);
+ ensure("same pointer",p1==ap2.get());
+ ensure("lost ownership",ap.get()==0);
+ }
+ ensure("destructed",exists==false);
+ }
+}
+
+</pre>
+<img src="/_img/pixel.gif" alt="" width=1 height=300><br>
+
+<center>
+<!--RAX counter-->
+<script language="JavaScript">
+<!--
+document.write('<a href="http://www.rax.ru/click" '+
+'target=_blank><img src="http://counter.yadro.ru/hit?t13.4;r'+
+escape(document.referrer)+((typeof(screen)=='undefined')?'':
+';s'+screen.width+'*'+screen.height+'*'+(screen.colorDepth?
+screen.colorDepth:screen.pixelDepth))+';'+Math.random()+
+'" alt="rax.ru: ïîêàçàíî ÷èñëî õèòîâ çà 24 ÷àñà, ïîñåòèòåëåé çà 24 ÷àñà è çà ñåãîäí\ÿ" '+
+'border=0 width=88 height=31></a><br>')
+//-->
+</script>
+<!--/RAX-->
+</center>
+
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- content table << -->
+</td>
+</tr>
+</table>
+
+</body>
+</html>
diff -urNad libtut-0.0.20060329~/docs/faq.html libtut-0.0.20060329/docs/faq.html
--- libtut-0.0.20060329~/docs/faq.html 1970-01-01 01:00:00.000000000 +0100
+++ libtut-0.0.20060329/docs/faq.html 2006-06-09 16:53:50.335608802 +0200
@@ -0,0 +1,401 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title>TUT Frequently Asked Questions - TUT: C++ Unit Test Framework</title>
+<meta name="keywords" content="C++ test-driven unit tests TUT framework STL">
+<meta name="description" content="TUT Frequently Asked Questions - often asked questions and answers for them">
+<style type="text/css">
+<!--
+
+body, p, td
+{
+ scrollbar-base-color: #eeeeee;
+ scrollbar-track-color: #ffffff;
+ scrollbar-arrow-color: #cccccc;
+ scrollbar-shadow-color: #cccccc;
+ scrollbar-highlight-color: #cccccc;
+ scrollbar-darkshadow-color: #ffffff;
+ scrollbar-3dlight-color: #ffffff;
+
+ /*
+ scrollbar-base-color: #cccccc;
+ scrollbar-track-color: #ffffff;
+ scrollbar-arrow-color: #eeeeee;
+ */
+
+ font-family : Verdana, Arial, Helvetica, sans-serif;
+ font-size : 14px;
+ color: #000000;
+}
+
+pre
+{
+ font-family : Courier, sans-serif;
+ font-size : 12px;
+}
+
+strong, b
+{
+ font-weight : bold;
+}
+
+ul
+{
+ list-style-type : square;
+}
+
+.header
+{
+ font-size : 24px;
+ font-weight : bold;
+}
+
+.subheader
+{
+ font-size : 16px;
+ font-weight : bold;
+}
+
+.logo
+{
+ font-size : 24px;
+ font-weight : bold;
+}
+
+.question
+{
+ font-size : 16px;
+ font-weight : bold;
+ color : #000000;
+}
+
+a
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : none;
+}
+
+a:hover
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : underline;
+}
+
+a:visited
+{
+ font-weight : bold;
+ color : #ff9900;
+}
+
+a.menu
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : none;
+}
+
+a.menu:hover
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : underline;
+}
+
+a.menu:visited
+{
+ font-weight : bold;
+ color : #ff9900;
+}
+
+//-->
+</style>
+</head>
+
+<body text="#000000" link="#ff9900" alink="#ffcc00" vlink="#ff9900" bgcolor="#ffffff" leftmargin=0 topmargin=0 marginheight=0 marginwidth=0>
+
+<img src="/_img/pixel.gif" alt="" width=1 height=20><br>
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width=20 align=left valign=top>
+<img src="/_img/pixel.gif" alt="" width=20 height=1><br>
+</td>
+<td width="100%" align=left valign=top>
+<!-- home table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="logo"><a href="/">TUT: C++ Unit Test Framework</a></p>
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- home table << -->
+</td>
+<td width=20 align=left valign=top>
+<img src="/_img/pixel.gif" alt="" width=20 height=1><br>
+</td>
+</tr>
+</table>
+
+<table border=0 width="100%" cellspacing=20 cellpadding=0>
+<tr>
+<td width="30%" align=left valign=top>
+<!-- menu table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="subheader">Documentation</p>
+<ul>
+<li><p><a href="/howto/" class="menu">TUT How-To</a><br>minimum steps to make TUT work for you</p></li>
+<li><p><a href="/design/" class="menu">TUT Design</a><br>what's hidden under the hood of tut.h, and why things are such as they
+ are</p></li>
+<li><p><a href="/example/" class="menu">TUT Usage Example</a><br>it's better to see once...</p></li>
+<li><p><a href="/whole/" class="menu">TUT As Is</a><br>complete source of TUT</p></li>
+</ul>
+<p class="subheader">Distribution</p>
+<ul>
+<li><p><a href="/copyright/" class="menu">The TUT License</a><br>almost no restrictions to use</p></li>
+<li><p><a href="/download/" class="menu">TUT Downloads</a><br>latest version of TUT as well as other related stuff</p></li>
+</ul>
+<p class="subheader">Support</p>
+<ul>
+<li><p><strong>TUT Frequently Asked Questions</strong><br>often asked questions and answers for them</p></li>
+<li><p><a href="/links/" class="menu">Links</a><br>related projects and concepts</p></li>
+<li><p><a href="/author/" class="menu">TUT Author</a><br>who is the author</p></li>
+</ul>
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- menu table << -->
+</td>
+<td width="70%" valign=top>
+<!-- content table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="header">TUT Frequently Asked Questions</p>
+<p class="question">What is TUT?</p>
+<p>
+TUT is a small and portable unit test framework for C++. It's so small that it fits into
+one header file. It's so portable that it could be used on almost any C++ platform, including
+Windows, MacOS and unices.
+</p>
+
+
+<p class="question">
+How it's different from C++Unit (boost::test, ...)?
+</p>
+<p>
+C++Unit, boost::test and other frameworks perform similar tasks.
+</p>
+
+<p>
+But there are some issues with most of them:
+<ul>
+<li>they require to build them as a library</li>
+<li>tests depend on preprocessor macros</li>
+<li>they often overloaded with features</li>
+</ul>
+</p>
+
+<p>
+TUT, in contrast, is located in a single header file (20K).
+All you should do is to include it into the test module. No linking at all.
+</p>
+
+<p>
+TUT uses C++ template engine to dispatch calls to test methods. Therefore
+you shouldn't even register methods as tests: template will do it for you automatically.
+As a result, the test code will be more readable.
+</p>
+
+<p>
+And finally, TUT is a minimal software. It only does what it's designed for.
+It doesn't attempt to integrate with MSDN or to control production processes. It just runs tests.
+</p>
+
+
+<p class="question">
+What compilers are supported?
+</p>
+
+<p>
+Most modern compilers are supported.
+Some outdated compilers are unable to handle templates in TUT, though
+</p>
+
+<p>Supported:
+<ul>
+ <li>GNU GCC 2.95</li>
+ <li>GNU GCC 3.x (both under unix and <a href="http://www.mingw.org">MinGW</a>)</li>
+ <li>Borland 5.6 (Borland C++ Builder 6)</li>
+ <li>Intel C++ Compiler 6.x</li>
+ <li>Intel C++ Compiler 8.1</li>
+ <li>Sun Studio 9: C++ 5.6 Compiler</li>
+ <li>Microsoft VC7 (Microsoft VS.NET 2003 and later)</li>
+ <li>Sun WorkShop 6 update 2 C++ 5.3 (probably, previous versions as well)</li>
+</ul>
+</p>
+<p>Unsupported:
+<ul>
+ <li>Borland 5.5.x (Borland C++ Builder 5)</li>
+ <li>Microsoft VC6 (including SP5)</li>
+ <li>Microsoft VC7 (Microsoft VS.NET 2002)</li>
+ <li>C for AIX Compiler, Version 6</li>
+ <li>KAI C++ Compiler</li>
+ <li>Portland Group Compiler, Version 5.2-4</li>
+</ul>
+</p>
+
+<p>
+ If you use TUT with any other compiler or environment please let me know.
+</p>
+
+<p>
+Some broken compiler/linker/platform combinations require to make methods ensure(),
+ensure_equals and fail() to be inline, and not in anonymous namespace. Try to
+change tut.h accordingly if you see "duplicate symbol ensure" or "ensure is not found"
+during linking stage.
+</p>
+
+
+<p class="question">
+I've taken a look at the selftest code and it looks awful
+</p>
+
+<p>
+Self tests are very special beasties, and actually you've seen
+two(!) TUT frameworks running one under control of another. The case is
+quite extreme. Regular TUT tests are very simple to read; you'd better look
+at the online <a href="/example">example</a>.
+</p>
+
+
+<p class="question">
+Why don't you provide methods to catch user-code exceptions?
+</p>
+
+<p>
+First of all, the user-code exceptions are intercepted inside the test runner,
+and afterwards user receives them along with the test_result status. For std
+exceptions, a textual message is included into results. For the others there
+will be a message that an unknown exception was generated.
+</p>
+
+
+<p class="question">
+I've used ensure_equals() method and compiler refused to build my code complaining that there is ambiguous overload for operator <<.
+</p>
+<p>
+One or both types you've provided to ensure_equals() have no operator << at all.
+Since the diagnostic message is built using std::stringstream, compiler needs the
+operator to format your objects. Either add the operator or use ensure() method
+(which doesn't tell you the exact values the objects had, just the fact they were not equal).
+</p>
+
+
+<p class="question">
+What about segmentation faults in code being tested? What about deadlocks?
+</p>
+
+<p>
+C++ Standard doesn't specify what happens if the code references
+wrong address. Thus, segmentation fault processing is system and compiler dependent,
+and shall be handled differently in each system/compiler pair.
+</p>
+
+<p>
+If you want TUT to react correctly to tests failures caused by segfaults,
+you must somehow convert hardware faults into C++ exceptions.
+</p>
+
+<p>
+For Win32 TUT uses SEH. You need to specify -DTUT_USE_SEH at build time.
+</p>
+
+<p>
+For unixes there is no standard way to convert SIGSEGV into an exception.
+Consult your platform/compiler documentation for possible ways to do that.
+</p>
+
+<p>
+You may also use restartable wrapper defined in optional header
+tut_restartable.h. It runs the tests the same way
+as regular runner does, but also logs the progress. If a test crashes the test
+application, and then test application runs again, the wrapper will load last
+log record, and continue test execution from position after the crashed test.
+</p>
+
+<p>
+Of course, this requires helper script that runs test application
+until all tests will be runned. The script might be is as simple as
+</p>
+
+ <pre>
+while true
+do
+ ./restartable && exit 0
+done
+ </pre>
+
+<p>Directory examples/restartable contains simple restartable test application.</p>
+
+<p>
+This approach can be extended to support deadlocks in code. The script
+must be modified to automatically kill test application after specified
+period of time.
+</p>
+<img src="/_img/pixel.gif" alt="" width=1 height=300><br>
+
+<center>
+<!--RAX counter-->
+<script language="JavaScript">
+<!--
+document.write('<a href="http://www.rax.ru/click" '+
+'target=_blank><img src="http://counter.yadro.ru/hit?t13.4;r'+
+escape(document.referrer)+((typeof(screen)=='undefined')?'':
+';s'+screen.width+'*'+screen.height+'*'+(screen.colorDepth?
+screen.colorDepth:screen.pixelDepth))+';'+Math.random()+
+'" alt="rax.ru: ïîêàçàíî ÷èñëî õèòîâ çà 24 ÷àñà, ïîñåòèòåëåé çà 24 ÷àñà è çà ñåãîäí\ÿ" '+
+'border=0 width=88 height=31></a><br>')
+//-->
+</script>
+<!--/RAX-->
+</center>
+
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- content table << -->
+</td>
+</tr>
+</table>
+
+</body>
+</html>
diff -urNad libtut-0.0.20060329~/docs/howto.html libtut-0.0.20060329/docs/howto.html
--- libtut-0.0.20060329~/docs/howto.html 1970-01-01 01:00:00.000000000 +0100
+++ libtut-0.0.20060329/docs/howto.html 2006-06-09 16:53:48.015497547 +0200
@@ -0,0 +1,799 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title>TUT How-To - TUT: C++ Unit Test Framework</title>
+<meta name="keywords" content="C++ test-driven unit tests TUT framework STL">
+<meta name="description" content="TUT How-To - minimum steps to make TUT work for you">
+<style type="text/css">
+<!--
+
+body, p, td
+{
+ scrollbar-base-color: #eeeeee;
+ scrollbar-track-color: #ffffff;
+ scrollbar-arrow-color: #cccccc;
+ scrollbar-shadow-color: #cccccc;
+ scrollbar-highlight-color: #cccccc;
+ scrollbar-darkshadow-color: #ffffff;
+ scrollbar-3dlight-color: #ffffff;
+
+ /*
+ scrollbar-base-color: #cccccc;
+ scrollbar-track-color: #ffffff;
+ scrollbar-arrow-color: #eeeeee;
+ */
+
+ font-family : Verdana, Arial, Helvetica, sans-serif;
+ font-size : 14px;
+ color: #000000;
+}
+
+pre
+{
+ font-family : Courier, sans-serif;
+ font-size : 12px;
+}
+
+strong, b
+{
+ font-weight : bold;
+}
+
+ul
+{
+ list-style-type : square;
+}
+
+.header
+{
+ font-size : 24px;
+ font-weight : bold;
+}
+
+.subheader
+{
+ font-size : 16px;
+ font-weight : bold;
+}
+
+.logo
+{
+ font-size : 24px;
+ font-weight : bold;
+}
+
+.question
+{
+ font-size : 16px;
+ font-weight : bold;
+ color : #000000;
+}
+
+a
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : none;
+}
+
+a:hover
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : underline;
+}
+
+a:visited
+{
+ font-weight : bold;
+ color : #ff9900;
+}
+
+a.menu
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : none;
+}
+
+a.menu:hover
+{
+ font-weight : bold;
+ color : #ff9900;
+ text-decoration : underline;
+}
+
+a.menu:visited
+{
+ font-weight : bold;
+ color : #ff9900;
+}
+
+//-->
+</style>
+</head>
+
+<body text="#000000" link="#ff9900" alink="#ffcc00" vlink="#ff9900" bgcolor="#ffffff" leftmargin=0 topmargin=0 marginheight=0 marginwidth=0>
+
+<img src="/_img/pixel.gif" alt="" width=1 height=20><br>
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width=20 align=left valign=top>
+<img src="/_img/pixel.gif" alt="" width=20 height=1><br>
+</td>
+<td width="100%" align=left valign=top>
+<!-- home table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="logo"><a href="/">TUT: C++ Unit Test Framework</a></p>
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- home table << -->
+</td>
+<td width=20 align=left valign=top>
+<img src="/_img/pixel.gif" alt="" width=20 height=1><br>
+</td>
+</tr>
+</table>
+
+<table border=0 width="100%" cellspacing=20 cellpadding=0>
+<tr>
+<td width="30%" align=left valign=top>
+<!-- menu table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="subheader">Documentation</p>
+<ul>
+<li><p><strong>TUT How-To</strong><br>minimum steps to make TUT work for you</p></li>
+<li><p><a href="/design/" class="menu">TUT Design</a><br>what's hidden under the hood of tut.h, and why things are such as they
+ are</p></li>
+<li><p><a href="/example/" class="menu">TUT Usage Example</a><br>it's better to see once...</p></li>
+<li><p><a href="/whole/" class="menu">TUT As Is</a><br>complete source of TUT</p></li>
+</ul>
+<p class="subheader">Distribution</p>
+<ul>
+<li><p><a href="/copyright/" class="menu">The TUT License</a><br>almost no restrictions to use</p></li>
+<li><p><a href="/download/" class="menu">TUT Downloads</a><br>latest version of TUT as well as other related stuff</p></li>
+</ul>
+<p class="subheader">Support</p>
+<ul>
+<li><p><a href="/faq/" class="menu">TUT Frequently Asked Questions</a><br>often asked questions and answers for them</p></li>
+<li><p><a href="/links/" class="menu">Links</a><br>related projects and concepts</p></li>
+<li><p><a href="/author/" class="menu">TUT Author</a><br>who is the author</p></li>
+</ul>
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- menu table << -->
+</td>
+<td width="70%" valign=top>
+<!-- content table >> -->
+<table width="100%" cellspacing=0 cellpadding=0>
+<tr>
+<td width="100%" align=center valign=center bgcolor="#cccccc">
+<!-- >> -->
+<table width="100%" cellspacing=1 cellpadding=10>
+<tr>
+<td width="100%" align=left valign=top bgcolor="#eeeeee">
+<p class="header">TUT How-To</p>
+<p class="subheader">About this document</p>
+
+ <p>
+ This text contains an explanation how you can start to use TUT in shortest possible time.
+ It also contains some introductory information on unit testing itself for those who are
+ new in the field.
+ </p>
+
+ <p class="subheader">What is TUT</p>
+
+ <p>
+ TUT is a pure C++ unit test framework.
+ It's name - TUT - stands for Template Unit Tests.
+ </p>
+
+ <p>
+ Unit test frameworks help to organize and run
+ <a href="http://en.wikipedia.org/wiki/Unit_tests">unit tests</a>.
+ Unit tests are used to check application correctness according to requirements.
+ Those tests are usually run often (nightly or hourly) to achieve
+ <a href="http://www.martinfowler.com/articles/continuousIntegration.html">continuous integration</a>.
+ </p>
+
+ <p class="subheader">TUT tests organization</p>
+
+ <p>
+ C++ produces executable code, so tests have to be compiled into a single binary
+ called test application. The application can be built in automated mode to
+ perform nightly tests. It can also be built manually when a developer hunts for
+ bugs.
+ </p>
+
+ <p>
+ The test application contains tests, organized into test groups.
+ The functionality of a tested application can be divided into a few separate
+ functional blocks (e.g. Access Rights, Export, Processing, ...). It is natural to
+ group tests for each block together. Each test group has a unique human-readable
+ name and normally is located in a separate file.
+ </p>
+
+ <p class="subheader">Tests</p>
+
+ <p>
+ Test is a function (method) that implements some specific scenario and checks
+ if the code (unit) behaves as required. Each test usually checks only one
+ specific element of functionality. In almost any test we have a preparation
+ phase, execution phase and verification phase. For example, if we need to
+ test our container's clear() method is correct, we need:
+ <ul>
+ <li>create a container instance and fill it with some data (preparation phase)</li>
+ <li>call clear() method (execution phase)</li>
+ <li>ensure that size() now returns zero (verification phase)</li>
+ </ul>
+ </p>
+
+ <p class="subheader">What we are going to test?</p>
+
+ <p>
+ Suppose we need to create a shared_ptr class for our application.
+ We need to write tests for the class to be sure it works as it should.
+ The same tests would also guide someone who will maintain the code.
+ </p>
+
+ <p>
+ Prior to test writing we should decide what to test.
+ Maximalist approach requires to write so many tests that altering any single
+ line of your code will break at least one test. Minimalist approach allows
+ us to write tests only for the most general or the most complex use cases. The
+ truth lies somewhere in between. We should consider common correct and
+ incorrect usage scenarios, and use them as a basis for our tests.
+ </p>
+
+ <p>
+ For our shared_ptr we obviosly should test constructors, assignment operators,
+ referencing and passing ownership. Later we may come to some other test scenarios.
+ </p>
+
+ <p class="subheader">Skeleton</p>
+
+ <p>
+ If you don't have any implemented class to test yet, it would be good to implement it
+ as a set of stub methods first. Thus you'll get an interface, and be able to write
+ your tests. Yes, this is correct:
+ <a href="http://en.wikipedia.org/wiki/Test_driven_development">you should write your tests before writing the code</a>!
+ Writing tests often helps to understand oddities in the current interface, and fix it.
+ Besides, with the stubs all your tests will fail, so you'll be sure tests do their job.
+ </p>
+
+ <p class="subheader">Creating Test Group</p>
+
+ <p>
+ Since we're writing unit tests, it would be a good idea to group the tests for our
+ class in one place to be able to run them separately. It's also natural in C++ to
+ place all the tests of a group into one compilation unit (i.e. source file). So, to
+ begin, we should create a new file. Let's call it test_shared_ptr.cpp.
+ (<i>Final variant of the test group can be found in TUT distribution in directory examples/shared_ptr </i>)
+ </p>
+
+ <pre>
+// test_shared_ptr.cpp
+#include <tut.h>
+namespace tut { };
+ </pre>
+
+ <p>
+ As you see, you need to include TUT header file (as expected) and use namespace tut
+ for tests. You may also use anonymous namespace if your compiler allows it (you
+ will need to instantiate methods from tut namespace and some compilers refuse to
+ place such instantiations into the anonymous namespace).</p>
+
+ <p>
+ A test group in TUT framework is described by the special template
+ test_group<T>. The template parameter T is a type that will hold all
+ test-specific data during the test execution. Actually, the data stored in T are
+ member data of the test class. Test class is inherited from T, so any test can refer to
+ the data in T as it's member data. Complex? Not really, as you'll see.
+ </p>
+
+ <p>
+ For simple test groups (where all data are stored in test local variables) type T
+ could be an empty struct.
+ </p>
+
+ <pre>
+#include <tut.h>
+namespace tut
+{
+ struct shared_ptr_data { };
+}
+ </pre>
+
+ <p>
+ But when tests have complex or repeating creation phase, you may put data members
+ into T and provide constructor (and, if required, destructor) for it. For
+ each test, a new instance of T will be created. To prepare your test for execution
+ TUT will use default constructor. Similarly, after the test has been finished,
+ the destructor is called to clean up T. I.e.:
+ </p>
+
+ <pre>
+#include <tut.h>
+namespace tut
+{
+ struct complex_data
+ {
+ connection* con;
+ complex_data()
+ {
+ con = db_pool.get_connection();
+ }
+ ~complex_data()
+ {
+ db_pool.release_connection(con);
+ }
+ };
+
+ // each test from now on will have con data
+ // member initialized by constructor
+ ...
+ con->commit();
+ ...
+ </pre>
+
+ <p>
+ What will happen if the constructor throws an exception? TUT will treat it as if
+ test itself failed with exception, so this test will not be executed. You'll see
+ an exception mark near the test, and if the constructor throwed something
+ printable, the message will appear.
+ </p>
+
+ <p>
+ Exception in destructor is threated a bit different. Reaching destruction phase
+ means that the test is passed, so TUT marks test with warning status meaning that
+ test itself was OK, but something bad has happend <i>after</i> the test.
+ </p>
+
+ <p>
+ Well, all we have written so far is just a type declaration. To work with a group we
+ have to have an object, so we must create the test group object. Since we need only
+ one test group object for each unit, we can (and should, actually) make this
+ object static. To prevent name clash with other test group objects in the
+ namespace tut, we should provide an unique descriptive name (or, alternatively, we may
+ put it into the anonymous namespace). The former is more correct, but the
+ descriptive name usually works well too, unless you're too terse in giving names
+ to objects.
+ </p>
+
+ <pre>
+#include <tut.h>
+namespace tut
+{
+ struct shared_ptr_data {};
+ typedef test_group<shared_ptr_data> tg;
+ tg shared_ptr_group("shared_ptr");
+};
+ </pre>
+
+ <p>
+ As you see, any test group accepts a single parameter - it's human-readable name.
+ This name is used to identify the group when a programmer wants to execute all
+ tests or a single test within the group. So this name shall also be descriptive
+ enough to avoid clashes. Since we're writing tests for a specific unit, it's
+ enough to name it after the unit name.
+ </p>
+
+ <p>
+ Test group constructor will be called at unspecified moment at the test
+ application startup. The constructor performs self-registration; it calls
+ tut::runner and asks it to store the test group object name and location. Any
+ other test group in the system undergoes the same processing, i.e. each test
+ group object registers itself. Thus, test runner can iterate all test groups or
+ execute any test group by its name.
+ </p>
+
+ <p>
+ Newly created group has no tests associated with it. To be more precise, it has
+ predefined set of dummy tests. By default, there are 50 tests in a group,
+ including dummy ones. To create a test group with higher volume (e.g. when tests
+ are generated by a script and their number is higher) we must provide a higher
+ border of test group size when it is instantiated:
+ </p>
+
+ <pre>
+#include <tut.h>
+namespace tut
+{
+ struct huge_test_data { };
+ // test group with maximum 500 tests
+ typedef test_group<huge_test_data,500> testgroup;
+ testgroup huge_test_testgroup("huge group");
+};
+ </pre>
+
+ <p>
+ Note also that your compiler would possibly need a command-line switch or pragma
+ to enlarge recursive instantiation depth. For g++, for example, you should
+ specify at least --ftemplate-depth-501 to increase the depth to 500. For more
+ information see your compiler documentation.
+ </p>
+
+ <p class="subheader">Creating Tests</p>
+
+ <p>Now it's time to fill our test group with content.</p>
+
+ <p>
+ In TUT, all tests have unique <b>numbers</b> inside the test group.
+ Some people believe that textual names better describe failed tests in reports.
+ I agree. But C++ templates work with numbers because they are compile-time
+ constants and refuse to do the same with strings, since strings are in fact
+ addresses of character buffers, i.e. run-time data. So I had no other choice.
+ </p>
+
+ <p>
+ As I mentioned above, our test group already has a few dummy tests; and we can
+ replace any of them with something real just by writing our own version:
+ </p>
+
+ <pre>
+#include <tut.h>
+namespace tut
+{
+ struct shared_ptr_data{};
+ typedef test_group<shared_ptr_data> testgroup;
+ typedef testgroup::object testobject;
+ testgroup shared_ptr_testgroup("shared_ptr");
+
+ template<> template<>
+ void testobject::test<1>()
+ {
+ // do nothing test
+ }
+};
+ </pre>
+
+ <p>
+ So far this test does nothing, but it's enough to illustrate the way we may
+ create our own test methods. Note that your shouldn't call anything like
+ REGISTER_TEST() macro or do anything similarely annoying. Just write a test,
+ and it will be executed.
+ </p>
+
+ <p>
+ All tests in the group are methods of the type test_group<T>::object. This
+ class is directly inherited from our test data structure. In our case, it is
+ </p>
+
+ <pre>
+class object : public shared_ptr_data { };
+ </pre>
+
+ <p>
+ This allows to access members of the shared_ptr_data structure directly,
+ since at the same time they are members of the object type itself. We also
+ typedef the type with testobject for brevity.
+ </p>
+
+ <p>
+ We mark our test with number 1. Previously, test group had a dummy test with the same
+ number, but now, since we've defined our own version, it replaced the dummy test
+ as more specialized one. It's how C++ template ordering works.
+ </p>
+
+ <p>
+ The test we've written always succeeds. Successful test returns with no
+ exceptions. Unsuccessful one either throws an exception, or fails at fail() or
+ ensure() methods (which anyway just throw the exception when failed).
+ </p>
+
+ <p class="subheader">First real test</p>
+
+ <p>
+ Now we know enough to write the first real working test. This test will create
+ shared_ptr instances and check their state. We will define a small structure
+ (keepee) to use it as shared_ptr stored object type.
+ </p>
+
+ <pre>
+#include <tut.h>
+#include <shared_ptr.h>
+namespace tut
+{
+ struct shared_ptr_data
+ {
+ struct keepee{ int data; };
+ };
+
+ typedef test_group<shared_ptr_data> testgroup;
+ typedef testgroup::object testobject;
+ testgroup shared_ptr_testgroup("shared_ptr");
+
+ // checks default constructor.
+ template<> template<>
+ void testobject::test<1>()
+ {
+ shared_ptr<keepee> def;
+ ensure("null",def.get()== 0);
+ }
+};
+ </pre>
+
+ <p>
+ That's all! The first line creates shared_ptr. If constructor throws an
+ exception, test will fail (exceptions, including '...', are catched by the TUT
+ framework). If the first line succeeds, we must check whether the kept object is
+ null one. To do this, we use test object member function ensure(), which throws
+ std::logic_error with a given message if its second argument is not true.
+ Finally, if destructor of shared_ptr fails with exception, TUT also will report
+ this test as failed.
+ </p>
+
+ <p>
+ It's equally easy to write a test for the scenario where we expect to get an
+ exception: let's consider our class should throw an exception if it has no stored
+ object, and the operator -> is called.
+ </p>
+
+ <pre>
+ // checks operator -> throws instead of returning null.
+ template<> template<>
+ void testobject::test<2>()
+ {
+ try
+ {
+ shared_ptr<keepee> sp;
+ sp->data = 0;
+ fail("exception expected");
+ }
+ catch( const std::runtime_error& ex )
+ {
+ // ok
+ }
+ }
+ </pre>
+
+ <p>
+ Here we expect the std::runtime_error. If operator doesn't throw it, we'll force
+ the test to fail using another member function: fail(). It just throws
+ std::logic_error with a given message. If operator throws anything else, our
+ test will fail too, since we intercept only std::runtime_error, and any other
+ exception means the test has failed.
+ </p>
+
+ <p>
+ NB: our second test has number 2 in its name; it can, actually, be any in range
+ 1..Max; the only requirement is not to write tests with the same numbers. But if you
+ did, compiler will force you to fix it anyway.
+ </p>
+
+ <p>
+ And finally, one more test to demonstrate how to use the ensure_equals template
+ member function:
+ </p>
+
+ <pre>
+ /** checks keepee counting.
+ template<> template<>
+ void testobject::test<3>()
+ {
+ shared_ptr<keepee> sp1(new keepee());
+ shared_ptr<keepee> sp2(sp1);
+ ensure_equals("second copy at sp1",sp1.count(),2);
+ ensure_equals("second copy at sp2",sp2.count(),2);
+ }
+ </pre>
+
+ <p>
+ The test checks if the shared_ptr correctly counts references during copy
+ construction. What's interesting here is the template member ensure_equals.
+ It has an additional functionality comparing with similar call
+ ensure("second_copy",sp1.count()==2); it uses operator == to check the
+ equality of the two passed parameters and, what's more important, it uses
+ std::stringstream to format the passed parameters into a human-readable message
+ (smth like: "second copy: expected 2, got 1"). It means that ensure_equals
+ cannot be used with the types that don't have operator
+ <<; but for those having the operator it provides much more informational
+ message.
+ </p>
+
+ <p>
+ In contrast to JUnit assertEquals, where the expected value goes before the
+ actual one, ensure_equals() accepts the expected after the actual value. I
+ believe it's more natural to read ensure_equals("msg", count, 5) as "ensure
+ that count equals to 5" rather than JUnit's "assert that 5 is the value of the
+ count".
+ </p>
+
+ <p class="subheader">Running tests</p>
+
+ <p>
+ Tests are written, but an attempt to run them will be unsuccessful. We need
+ a few other bits to complete the test application.
+ </p>
+
+ <p>
+ First of all, we need a main() method, simply because it must be in every
+ application. Second, we need a test runner singleton. Remember I said each
+ test group should register itself in singleton? So, we need that singleton. And,
+ finally, we need a kind of a callback handler to visualize our test results.
+ </p>
+
+ <p>
+ The design of TUT doesn't strictly set a way the tests are visualized; instead, it
+ provides an opportunity to get the test results by means of callbacks. Moreover
+ it allows user to output the results in any format he prefers. Of course, there is a
+ "reference implementation" in the example/ subdirectory of the project.
+ </p>
+
+ <p>
+ Test runner singleton is defined in tut.h, so all we need to activate it is to
+ declare an object of the type tut::test_runner_singleton in the main module
+ with a special name tut::runner.
+ </p>
+
+ <p>
+ Now, with the test_runner we can run tests. Singleton has method get() returning a
+ reference to an instance of the test_runner class, which in turn has methods
+ <ul>>
+ <li>run_tests() to run all tests in all groups</li>
+ <li>run_tests(const std::string& groupname) to run all tests in a given group</li>
+ <li>run_test(const std::string& grp,int n) to run one test in the specified group.</li>
+ </ul>
+ </p>
+
+ <p>
+ So here goes our main module:
+ </p>
+
+ <pre>
+// main.cpp
+#include <tut.h>
+namespace tut
+{
+ test_runner_singleton runner;
+}
+
+int main()
+{
+ // run all tests in all groups
+ runner.get().run_tests();
+
+ // run all tests in group "shared_ptr"
+ runner.get().run_tests("shared_ptr");
+
+ // run test number 5 in group "shared_ptr"
+ runner.get().run_test("shared_ptr",5);
+
+ return 0;
+}
+ </pre>
+
+ <p>
+ It's up to user to handle command-line arguments or GUI messages and map those
+ arguments/messages to actual calls to test runner. Again, as you see, TUT
+ doesn't restrict user here.
+ </p>
+
+ <p>
+ But, the last question is still unanswered: how do we get our test results? The
+ answer lies inside tut::callback interface. We could create it's subclass,
+ and write a few simple methods. We also can omit any method since they have
+ default no-op implementation. Each corresponding method is called in the
+ following cases:
+ <ul>
+ <li>a new test run has started;</li>
+ <li>test is finished; </li>
+ <li>test run is finished.</li>
+ </ul>
+ </p>
+
+ <p>
+ Here is a minimal implementation:
+ </p>
+
+ <pre>
+class visualizator : public tut::callback
+{
+public:
+ void run_started(){ }
+ void test_completed(const tut::test_result& tr)
+ { // ... show test result here ... }
+ void run_completed(){ }
+};
+ </pre>
+
+ <p>
+ The most important is the test_completed() method; its parameter has type
+ test_result, and contains everything about the finished test, from its group
+ name and number to the exception message, if any. Member variable result is an
+ enum which contains status of the test: ok, fail or ex. Take a look at the
+ examples/basic/main.cpp for more complete visualizator.
+ </p>
+
+ <p>
+ Visualizator should be passed to the test_runner before the run. Knowing that, we are
+ ready to write the final version of our main module:
+ </p>
+
+ <pre>
+#include <tut.h>
+namespace tut
+{
+ test_runner_singleton runner;
+}
+
+class callback : public tut::callback
+{
+public:
+ void run_started(){ std::cout << "\nbegin"; }
+ void test_completed(const tut::test_result& tr)
+ { std::cout << tr.test_pos << "=" << tr.result << std::flush; }
+ void run_completed(){ std::cout << "\nend"; }
+};
+
+int main()
+{
+ callback clbk;
+ runner.get().set_callback(&clbk);
+ runner.get().run_tests();
+ return 0;
+}
+ </pre>
+
+ <p>
+ That's it. We are now ready to link and run our test application. Do it as often as
+ possible; once a day is a definite must. I hope TUT will help you to make your
+ application more robust and relieve your testing pain. Feel free to send your
+ questions, suggestions and critical opinions to me; I'll do my best to address
+ them asap.
+ </p>
+<img src="/_img/pixel.gif" alt="" width=1 height=300><br>
+
+<center>
+<!--RAX counter-->
+<script language="JavaScript">
+<!--
+document.write('<a href="http://www.rax.ru/click" '+
+'target=_blank><img src="http://counter.yadro.ru/hit?t13.4;r'+
+escape(document.referrer)+((typeof(screen)=='undefined')?'':
+';s'+screen.width+'*'+screen.height+'*'+(screen.colorDepth?
+screen.colorDepth:screen.pixelDepth))+';'+Math.random()+
+'" alt="rax.ru: ïîêàçàíî ÷èñëî õèòîâ çà 24 ÷àñà, ïîñåòèòåëåé çà 24 ÷àñà è çà ñåãîäí\ÿ" '+
+'border=0 width=88 height=31></a><br>')
+//-->
+</script>
+<!--/RAX-->
+</center>
+
+</td>
+</tr>
+</table>
+<!-- << -->
+</td>
+</tr>
+</table>
+<!-- content table << -->
+</td>
+</tr>
+</table>
+
+</body>
+</html>