Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/test/impl/test_tools.ipp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 19.7 KB
Line 
1//  (C) Copyright Gennadiy Rozental 2005.
2//  Distributed under the Boost Software License, Version 1.0.
3//  (See accompanying file LICENSE_1_0.txt or copy at
4//  http://www.boost.org/LICENSE_1_0.txt)
5
6//  See http://www.boost.org/libs/test for the library home page.
7//
8//  File        : $RCSfile: test_tools.ipp,v $
9//
10//  Version     : $Revision: 1.12 $
11//
12//  Description : supplies offline implementation for the Test Tools
13// ***************************************************************************
14
15#ifndef BOOST_TEST_TEST_TOOLS_IPP_012205GER
16#define BOOST_TEST_TEST_TOOLS_IPP_012205GER
17
18// Boost.Test
19#include <boost/test/test_tools.hpp>
20#include <boost/test/unit_test_log.hpp>
21#include <boost/test/output_test_stream.hpp>
22#include <boost/test/framework.hpp>
23#include <boost/test/execution_monitor.hpp> // execution_aborted
24#include <boost/test/unit_test_suite_impl.hpp>
25
26// Boost
27#include <boost/config.hpp>
28
29// STL
30#include <fstream>
31#include <string>
32#include <cstring>
33#include <cctype>
34#include <cwchar>
35#ifdef BOOST_STANDARD_IOSTREAMS
36#include <ios>
37#endif
38
39// !! should we use #include <cstdarg>
40#include <stdarg.h>
41
42#include <boost/test/detail/suppress_warnings.hpp>
43
44//____________________________________________________________________________//
45
46# ifdef BOOST_NO_STDC_NAMESPACE
47namespace std { using ::strcmp; using ::strlen; using ::isprint; }
48#if !defined( BOOST_NO_CWCHAR )
49namespace std { using ::wcscmp; }
50#endif
51# endif
52
53namespace boost {
54
55namespace test_tools {
56
57namespace tt_detail {
58
59// ************************************************************************** //
60// **************            TOOL BOX Implementation           ************** //
61// ************************************************************************** //
62
63void
64check_impl( predicate_result const& pr, wrap_stringstream& check_descr,
65            const_string file_name, std::size_t line_num,
66            tool_level tl, check_type ct,
67            std::size_t num_of_args, ... )
68{
69    using namespace unit_test;
70
71    if( !!pr )
72        tl = PASS;
73
74    log_level    ll;
75    char const*  prefix;
76    char const*  suffix;
77       
78    switch( tl ) {
79    case PASS:
80        ll      = log_successful_tests;
81        prefix  = "check ";
82        suffix  = " passed";
83        break;
84    case WARN:
85        ll      = log_warnings;
86        prefix  = "condition ";
87        suffix  = " is not satisfied";
88        break;
89    case CHECK:
90        ll      = log_all_errors;
91        prefix  = "check ";
92        suffix  = " failed";
93        break;
94    case REQUIRE:
95        ll      = log_fatal_errors;
96        prefix  = "critical check ";
97        suffix  = " failed";
98        break;
99    default:
100        return;
101    }
102
103    switch( ct ) {
104    case CHECK_PRED:
105        unit_test_log << unit_test::log::begin( file_name, line_num )
106                      << ll << prefix << check_descr.str() << suffix;
107       
108        if( !pr.has_empty_message() )
109            unit_test_log << ". " << pr.message();
110       
111        unit_test_log << unit_test::log::end();
112        break;
113
114    case CHECK_MSG:
115        unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
116       
117        if( tl == PASS )
118            unit_test_log << prefix << "'" << check_descr.str() << "'" << suffix;
119        else
120            unit_test_log << check_descr.str();
121       
122        if( !pr.has_empty_message() )
123            unit_test_log << ". " << pr.message();
124
125        unit_test_log << unit_test::log::end();
126        break;
127
128    case CHECK_EQUAL: {
129        va_list args;
130
131        va_start( args, num_of_args );
132        char const* arg1_descr  = va_arg( args, char const* );
133        char const* arg1_val    = va_arg( args, char const* );
134        char const* arg2_descr  = va_arg( args, char const* );
135        char const* arg2_val    = va_arg( args, char const* );
136
137        unit_test_log << unit_test::log::begin( file_name, line_num )
138                      << ll << prefix << arg1_descr << " == " << arg2_descr << suffix;
139
140        if( tl != PASS )
141            unit_test_log << " [" << arg1_val << " != " << arg2_val << "]" ;
142
143        va_end( args );
144       
145        if( !pr.has_empty_message() )
146            unit_test_log << ". " << pr.message();
147
148        unit_test_log << unit_test::log::end();
149        break;
150    }
151
152    case CHECK_CLOSE:
153    case CHECK_CLOSE_FRACTION: {
154        va_list args;
155
156        va_start( args, num_of_args );
157        char const* arg1_descr  = va_arg( args, char const* );
158        char const* arg1_val    = va_arg( args, char const* );
159        char const* arg2_descr  = va_arg( args, char const* );
160        char const* arg2_val    = va_arg( args, char const* );
161        /* toler_descr = */       va_arg( args, char const* );
162        char const* toler_val   = va_arg( args, char const* );
163
164        unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
165
166        unit_test_log << "difference between " << arg1_descr << "{" << arg1_val << "}"
167                      << " and "               << arg2_descr << "{" << arg2_val << "}"
168                      << ( tl == PASS ? " doesn't exceed " : " exceeds " )
169                      << toler_val;
170        if( ct == CHECK_CLOSE )
171            unit_test_log << "%";
172
173        va_end( args );
174       
175        if( !pr.has_empty_message() )
176            unit_test_log << ". " << pr.message();
177
178        unit_test_log << unit_test::log::end();
179        break;
180    }
181    case CHECK_SMALL: {
182        va_list args;
183
184        va_start( args, num_of_args );
185        char const* arg1_descr  = va_arg( args, char const* );
186        char const* arg1_val    = va_arg( args, char const* );
187        /* toler_descr = */       va_arg( args, char const* );
188        char const* toler_val   = va_arg( args, char const* );
189
190        unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
191
192        unit_test_log << "absolute value of " << arg1_descr << "{" << arg1_val << "}"
193                      << ( tl == PASS ? " doesn't exceed " : " exceeds " )
194                      << toler_val;
195
196        va_end( args );
197       
198        if( !pr.has_empty_message() )
199            unit_test_log << ". " << pr.message();
200
201        unit_test_log << unit_test::log::end();
202        break;
203    }
204
205    case CHECK_PRED_WITH_ARGS: {
206        unit_test_log << unit_test::log::begin( file_name, line_num )
207                      << ll << prefix << check_descr.str();
208
209        // print predicate call description
210        {
211            va_list args;
212            va_start( args, num_of_args );
213
214            unit_test_log << "( ";
215            for( std::size_t i = 0; i < num_of_args; ++i ) {
216                unit_test_log << va_arg( args, char const* );
217                va_arg( args, char const* ); // skip argument value;
218               
219                if( i != num_of_args-1 )
220                    unit_test_log << ", ";
221            }
222            unit_test_log << " )" << suffix;
223            va_end( args );
224        }
225                       
226        if( tl != PASS ) {
227            va_list args;
228            va_start( args, num_of_args );
229
230            unit_test_log << " for ( ";
231            for( std::size_t i = 0; i < num_of_args; ++i ) {
232                va_arg( args, char const* ); // skip argument description;           
233                unit_test_log << va_arg( args, char const* );
234               
235                if( i != num_of_args-1 )
236                    unit_test_log << ", ";
237            }
238            unit_test_log << " )";
239            va_end( args );
240        }
241       
242        if( !pr.has_empty_message() )
243            unit_test_log << ". " << pr.message();
244
245        unit_test_log << unit_test::log::end();
246        break;
247    }
248
249    case CHECK_EQUAL_COLL: {
250        va_list args;
251
252        va_start( args, num_of_args );
253        char const* left_begin_descr    = va_arg( args, char const* );
254        char const* left_end_descr      = va_arg( args, char const* );
255        char const* right_begin_descr   = va_arg( args, char const* );
256        char const* right_end_descr     = va_arg( args, char const* );
257
258        unit_test_log << unit_test::log::begin( file_name, line_num )
259                      << ll << prefix
260                      << "{ " << left_begin_descr  << ", " << left_end_descr  << " } == { "
261                              << right_begin_descr << ", " << right_end_descr << " }"
262                      << suffix;
263
264        va_end( args );
265       
266        if( !pr.has_empty_message() )
267            unit_test_log << ". " << pr.message();
268
269        unit_test_log << unit_test::log::end();
270        break;
271    }
272
273    case CHECK_BITWISE_EQUAL: {
274        va_list args;
275
276        va_start( args, num_of_args );
277        char const* left_descr    = va_arg( args, char const* );
278        char const* right_descr   = va_arg( args, char const* );
279
280        unit_test_log << unit_test::log::begin( file_name, line_num )
281                      << ll << prefix << left_descr  << " =.= " << right_descr << suffix;
282
283        va_end( args );
284       
285        if( !pr.has_empty_message() )
286            unit_test_log << ". " << pr.message();
287
288        unit_test_log << unit_test::log::end();
289        break;
290    }
291    }
292
293    switch( tl ) {
294    case PASS:
295        framework::assertion_result( true );
296        break;
297
298    case WARN:
299        break;
300
301    case CHECK:
302        framework::assertion_result( false );
303        break;
304       
305    case REQUIRE:
306        framework::assertion_result( false );
307
308        framework::test_unit_aborted( framework::current_test_case() );
309
310        throw execution_aborted();
311    }
312}
313
314//____________________________________________________________________________//
315
316predicate_result
317equal_impl( char const* left, char const* right )
318{
319    return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
320}
321
322//____________________________________________________________________________//
323
324#if !defined( BOOST_NO_CWCHAR )
325
326predicate_result
327equal_impl( wchar_t const* left, wchar_t const* right )
328{
329    return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
330}
331
332#endif // !defined( BOOST_NO_CWCHAR )
333
334//____________________________________________________________________________//
335
336bool
337is_defined_impl( const_string symbol_name, const_string symbol_value )
338{
339    symbol_value.trim_left( 2 );
340    return symbol_name != symbol_value;
341}
342
343//____________________________________________________________________________//
344
345// ************************************************************************** //
346// **************               log print helper               ************** //
347// ************************************************************************** //
348
349void
350print_log_value<char>::operator()( std::ostream& ostr, char t )
351{
352    if( (std::isprint)( t ) )
353        ostr << '\'' << t << '\'';
354    else
355        ostr << std::hex
356        // showbase is only available for new style streams:
357#ifndef BOOST_NO_STD_LOCALE
358        << std::showbase
359#else
360        << "0x"
361#endif
362        << (int)t;
363}
364
365//____________________________________________________________________________//
366
367void
368print_log_value<unsigned char>::operator()( std::ostream& ostr, unsigned char t )
369{
370    ostr << std::hex
371        // showbase is only available for new style streams:
372#ifndef BOOST_NO_STD_LOCALE
373        << std::showbase
374#else
375        << "0x"
376#endif
377       << (int)t;
378}
379
380//____________________________________________________________________________//
381
382void
383print_log_value<char const*>::operator()( std::ostream& ostr, char const* t )
384{
385    ostr << ( t ? t : "null string" );
386}
387
388//____________________________________________________________________________//
389
390void
391print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const* t )
392{
393    ostr << ( t ? t : L"null string" );
394}
395
396//____________________________________________________________________________//
397
398} // namespace tt_detail
399
400// ************************************************************************** //
401// **************               output_test_stream             ************** //
402// ************************************************************************** //
403
404struct output_test_stream::Impl
405{
406    std::fstream    m_pattern;
407    bool            m_match_or_save;
408    bool            m_text_or_binary;
409    std::string     m_synced_string;
410
411    char            get_char()
412    {
413        char res;
414        do {
415            m_pattern.get( res );
416        } while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
417
418        return res;
419    }
420
421    void            check_and_fill( predicate_result& res )
422    {
423        if( !res.p_predicate_value )
424            res.message() << "Output content: \"" << m_synced_string << '\"';
425    }
426};
427
428//____________________________________________________________________________//
429
430output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save, bool text_or_binary )
431: m_pimpl( new Impl )
432{
433    if( !pattern_file_name.is_empty() ) {
434        std::ios::openmode m = match_or_save ? std::ios::in : std::ios::out;
435        if( !text_or_binary )
436            m |= std::ios::binary;
437
438        m_pimpl->m_pattern.open( pattern_file_name.begin(), m );
439
440        BOOST_WARN_MESSAGE( m_pimpl->m_pattern.is_open(),
441                             "Couldn't open pattern file " << pattern_file_name
442                                << " for " << (m_pimpl->m_match_or_save ? "reading" : "writing") );
443    }
444
445    m_pimpl->m_match_or_save    = match_or_save;
446    m_pimpl->m_text_or_binary   = text_or_binary;
447}
448
449//____________________________________________________________________________//
450
451output_test_stream::~output_test_stream()
452{
453    delete m_pimpl;
454}
455
456//____________________________________________________________________________//
457
458predicate_result
459output_test_stream::is_empty( bool flush_stream )
460{
461    sync();
462
463    result_type res( m_pimpl->m_synced_string.empty() );
464
465    m_pimpl->check_and_fill( res );
466
467    if( flush_stream )
468        flush();
469
470    return res;
471}
472
473//____________________________________________________________________________//
474
475predicate_result
476output_test_stream::check_length( std::size_t length_, bool flush_stream )
477{
478    sync();
479
480    result_type res( m_pimpl->m_synced_string.length() == length_ );
481
482    m_pimpl->check_and_fill( res );
483
484    if( flush_stream )
485        flush();
486
487    return res;
488}
489
490//____________________________________________________________________________//
491
492predicate_result
493output_test_stream::is_equal( const_string arg, bool flush_stream )
494{
495    sync();
496
497    result_type res( const_string( m_pimpl->m_synced_string ) == arg );
498
499    m_pimpl->check_and_fill( res );
500
501    if( flush_stream )
502        flush();
503
504    return res;
505}
506
507//____________________________________________________________________________//
508
509predicate_result
510output_test_stream::match_pattern( bool flush_stream )
511{
512    sync();
513
514    result_type result( true );
515
516    if( !m_pimpl->m_pattern.is_open() ) {
517        result = false;
518        result.message() << "Pattern file could not be open!";
519    }
520    else {
521        if( m_pimpl->m_match_or_save ) {
522            for ( std::string::size_type i = 0; i < m_pimpl->m_synced_string.length(); ++i ) {
523                char c = m_pimpl->get_char();
524
525                result = !m_pimpl->m_pattern.fail() &&
526                         !m_pimpl->m_pattern.eof()  &&
527                         (m_pimpl->m_synced_string[i] == c);
528
529                if( !result ) {
530                    std::string::size_type suffix_size  = (std::min)( m_pimpl->m_synced_string.length() - i,
531                                                                    static_cast<std::string::size_type>(5) );
532
533                    // try to log area around the mismatch
534                    result.message() << "Mismatch at position " << i << '\n'
535                        << "..." << m_pimpl->m_synced_string.substr( i, suffix_size ) << "..." << '\n'
536                        << "..." << c;
537
538                    std::string::size_type counter = suffix_size;
539                    while( --counter ) {
540                        char c = m_pimpl->get_char();
541
542                        if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
543                            break;
544
545                        result.message() << c;
546                    }
547
548                    result.message() << "...";
549
550                    // skip rest of the bytes. May help for further matching
551                    m_pimpl->m_pattern.ignore(
552                        static_cast<std::streamsize>( m_pimpl->m_synced_string.length() - i - suffix_size) );
553                    break;
554                }
555            }
556        }
557        else {
558            m_pimpl->m_pattern.write( m_pimpl->m_synced_string.c_str(),
559                                      static_cast<std::streamsize>( m_pimpl->m_synced_string.length() ) );
560            m_pimpl->m_pattern.flush();
561        }
562    }
563
564    if( flush_stream )
565        flush();
566
567    return result;
568}
569
570//____________________________________________________________________________//
571
572void
573output_test_stream::flush()
574{
575    m_pimpl->m_synced_string.erase();
576
577#ifndef BOOST_NO_STRINGSTREAM
578    str( std::string() );
579#else
580    seekp( 0, std::ios::beg );
581#endif
582}
583
584//____________________________________________________________________________//
585
586std::size_t
587output_test_stream::length()
588{
589    sync();
590
591    return m_pimpl->m_synced_string.length();
592}
593
594//____________________________________________________________________________//
595
596void
597output_test_stream::sync()
598{
599#ifdef BOOST_NO_STRINGSTREAM
600    m_pimpl->m_synced_string.assign( str(), pcount() );
601    freeze( false );
602#elif BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x530) )
603    m_pimpl->m_synced_string.assign( str().c_str(), tellp() );
604#else
605    m_pimpl->m_synced_string = str();
606#endif
607}
608
609//____________________________________________________________________________//
610
611} // namespace test_tools
612
613} // namespace boost
614
615//____________________________________________________________________________//
616
617#include <boost/test/detail/enable_warnings.hpp>
618
619// ***************************************************************************
620//  Revision History :
621//
622//  $Log: test_tools.ipp,v $
623//  Revision 1.12  2006/02/01 07:58:25  rogeeff
624//  critical message made more consistent with rest
625//
626//  Revision 1.11  2006/01/28 07:01:25  rogeeff
627//  message error fixed
628//
629//  Revision 1.10  2005/12/14 05:33:47  rogeeff
630//  use simplified log API
631//  assertion_result call moved pass log statement
632//  Binary output test stream support implemented
633//
634//  Revision 1.9  2005/06/22 22:03:05  dgregor
635//  More explicit scoping needed for GCC 2.95.3
636//
637//  Revision 1.8  2005/04/30 17:56:31  rogeeff
638//  switch to stdarg.h to workarround como issues
639//
640//  Revision 1.7  2005/03/23 21:02:23  rogeeff
641//  Sunpro CC 5.3 fixes
642//
643//  Revision 1.6  2005/02/21 10:14:04  rogeeff
644//  CHECK_SMALL tool implemented
645//
646//  Revision 1.5  2005/02/20 08:27:07  rogeeff
647//  This a major update for Boost.Test framework. See release docs for complete list of fixes/updates
648//
649//  Revision 1.4  2005/02/02 12:08:14  rogeeff
650//  namespace log added for log manipulators
651//
652//  Revision 1.3  2005/02/01 06:40:07  rogeeff
653//  copyright update
654//  old log entries removed
655//  minor stilistic changes
656//  depricated tools removed
657//
658//  Revision 1.2  2005/01/30 03:18:27  rogeeff
659//  test tools implementation completely reworked. All tools inplemented through single vararg function
660//
661//  Revision 1.1  2005/01/22 19:22:12  rogeeff
662//  implementation moved into headers section to eliminate dependency of included/minimal component on src directory
663//
664//  Revision 1.43  2005/01/19 06:40:05  vawjr
665//  deleted redundant \r in many \r\r\n sequences of the source.  VC8.0 doesn't like them
666//
667//  Revision 1.42  2005/01/18 08:30:08  rogeeff
668//  unit_test_log rework:
669//     eliminated need for ::instance()
670//     eliminated need for << end and ...END macro
671//     straitend interface between log and formatters
672//     change compiler like formatter name
673//     minimized unit_test_log interface and reworked to use explicit calls
674//
675// ***************************************************************************
676
677#endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER
Note: See TracBrowser for help on using the repository browser.