10 #ifndef __PION_TEST_UNIT_TEST_HEADER__
11 #define __PION_TEST_UNIT_TEST_HEADER__
15 #include <boost/version.hpp>
16 #include <boost/algorithm/string.hpp>
17 #include <boost/thread/mutex.hpp>
18 #include <boost/thread/condition.hpp>
19 #include <boost/test/unit_test.hpp>
20 #include <boost/test/unit_test_log.hpp>
21 #include <boost/test/unit_test_log_formatter.hpp>
22 #include <boost/test/test_case_template.hpp>
23 #include <boost/test/utils/xml_printer.hpp>
24 #include <pion/logger.hpp>
28 #define CHANGE_DIRECTORY _chdir
29 #define GET_DIRECTORY(a,b) _getcwd(a,b)
32 #define CHANGE_DIRECTORY chdir
33 #define GET_DIRECTORY(a,b) getcwd(a,b)
36 #define DIRECTORY_MAX_SIZE 1000
44 :
public boost::unit_test::unit_test_log_formatter
50 : m_entry_in_progress(false)
58 boost::unit_test::counter_t test_cases_amount )
60 ostr <<
"<TestLog>" << std::endl;
66 ostr <<
"</TestLog>" << std::endl;
73 <<
" platform" << attr_value() << BOOST_PLATFORM
74 <<
" compiler" << attr_value() << BOOST_COMPILER
75 <<
" stl" << attr_value() << BOOST_STDLIB
76 <<
" boost=\"" << BOOST_VERSION/100000 <<
"."
77 << BOOST_VERSION/100 % 1000 <<
"."
78 << BOOST_VERSION % 100 <<
'\"'
84 boost::unit_test::test_unit
const& tu )
86 ostr <<
"<" << tu_type_name( tu ) <<
" name" << attr_value() << tu.p_name.get() <<
">" << std::endl;
91 boost::unit_test::test_unit
const& tu,
92 unsigned long elapsed )
94 if ( tu.p_type == boost::unit_test::tut_case )
95 ostr <<
"<TestingTime>" << elapsed <<
"</TestingTime>";
96 ostr <<
"</" << tu_type_name( tu ) <<
">" << std::endl;
101 boost::unit_test::test_unit
const& tu )
103 ostr <<
"<" << tu_type_name( tu )
104 <<
" name" << attr_value() << tu.p_name.get()
105 <<
" skipped" << attr_value() <<
"yes"
106 <<
"/>" << std::endl;
111 boost::unit_test::log_checkpoint_data
const& checkpoint_data,
112 boost::execution_exception
const& ex )
114 boost::execution_exception::location
const& loc = ex.where();
116 ostr <<
"<Exception file" << attr_value() << loc.m_file_name
117 <<
" line" << attr_value() << loc.m_line_num;
119 if( !loc.m_function.is_empty() )
120 ostr <<
" function" << attr_value() << loc.m_function;
122 ostr <<
">" << boost::unit_test::cdata() << ex.what();
124 if( !checkpoint_data.m_file_name.is_empty() ) {
125 ostr <<
"<LastCheckpoint file" << attr_value() << checkpoint_data.m_file_name
126 <<
" line" << attr_value() << checkpoint_data.m_line_num
128 << boost::unit_test::cdata() << checkpoint_data.m_message
129 <<
"</LastCheckpoint>";
132 ostr <<
"</Exception>" << std::endl;
137 boost::unit_test::log_entry_data
const& entry_data,
138 log_entry_types let )
140 boost::mutex::scoped_lock entry_lock(m_mutex);
141 while (m_entry_in_progress) {
142 m_entry_complete.wait(entry_lock);
144 m_entry_in_progress =
true;
146 static boost::unit_test::literal_string xml_tags[] = {
"Info",
"Message",
"Warning",
"Error",
"FatalError" };
147 m_curr_tag = xml_tags[let];
148 ostr <<
'<' << m_curr_tag
149 << BOOST_TEST_L(
" file" ) << attr_value() << entry_data.m_file_name
150 << BOOST_TEST_L(
" line" ) << attr_value() << entry_data.m_line_num
151 << BOOST_TEST_L(
"><![CDATA[" );
158 virtual void log_entry_value( std::ostream& ostr, boost::unit_test::const_string value )
160 boost::mutex::scoped_lock entry_lock(m_mutex);
161 if (m_entry_in_progress) {
171 boost::mutex::scoped_lock entry_lock(m_mutex);
172 if (m_entry_in_progress) {
173 ostr << BOOST_TEST_L(
"]]></" ) << m_curr_tag << BOOST_TEST_L(
">" ) << std::endl;
175 m_entry_in_progress =
false;
176 m_entry_complete.notify_all();
183 static boost::unit_test::const_string tu_type_name( boost::unit_test::test_unit
const& tu )
185 return tu.p_type == boost::unit_test::tut_case ?
"TestCase" :
"TestSuite";
189 typedef boost::unit_test::attr_value attr_value;
192 volatile bool m_entry_in_progress;
195 boost::condition m_entry_complete;
198 boost::mutex m_mutex;
201 boost::unit_test::const_string m_curr_tag;
212 std::cout <<
"global setup for all pion unit tests\n";
215 int argc = boost::unit_test::framework::master_test_suite().argc;
216 char** argv = boost::unit_test::framework::master_test_suite().argv;
217 bool verbose =
false;
220 if (argv[1][0] ==
'-' && argv[1][1] ==
'v') {
222 }
else if (strlen(argv[1]) > 13 && strncmp(argv[1],
"--log_output=", 13) == 0) {
223 const char *
const test_log_filename = argv[1] + 13;
229 std::cerr <<
"unable to open " << test_log_filename << std::endl;
235 PION_LOG_CONFIG_BASIC;
237 std::cout <<
"Use '-v' to enable logging of errors and warnings from pion.\n";
241 PION_LOG_SETLEVEL_WARN(log_ptr);
244 std::cout <<
"global teardown for all pion unit tests\n";
253 static inline char* trim(
char* str) {
254 for (
long len = strlen(str) - 1; len >= 0; len--) {
255 if (str[len] ==
'\n' || str[len] ==
'\r')
265 static inline bool read_lines_from_file(
const std::string& filename, std::list<std::string>& lines) {
267 std::ifstream a_file(filename.c_str(), std::ios::in | std::ios::binary);
268 if (! a_file.is_open())
273 std::string one_line;
274 while (std::getline(a_file, one_line)) {
275 boost::trim(one_line);
276 if (!one_line.empty() && one_line[0] !=
'#')
277 lines.push_back(one_line);
288 static inline bool check_files_match(
const std::string& fileA,
const std::string& fileB) {
290 std::list<std::string> a_lines, b_lines;
291 BOOST_REQUIRE(read_lines_from_file(fileA, a_lines));
292 BOOST_REQUIRE(read_lines_from_file(fileB, b_lines));
299 return (a_lines == b_lines);
302 static inline bool check_files_exact_match(
const std::string& fileA,
const std::string& fileB,
bool ignore_line_endings =
false) {
304 std::ifstream a_file(fileA.c_str(), std::ios::in | std::ios::binary);
305 BOOST_REQUIRE(a_file.is_open());
307 std::ifstream b_file(fileB.c_str(), std::ios::in | std::ios::binary);
308 BOOST_REQUIRE(b_file.is_open());
311 static const unsigned int BUF_SIZE = 4096;
312 char a_buf[BUF_SIZE];
313 char b_buf[BUF_SIZE];
315 if (ignore_line_endings) {
316 while (a_file.getline(a_buf, BUF_SIZE)) {
317 if (! b_file.getline(b_buf, BUF_SIZE))
321 if (strlen(a_buf) != strlen(b_buf))
323 if (memcmp(a_buf, b_buf, strlen(a_buf)) != 0)
326 if (b_file.getline(b_buf, BUF_SIZE))
329 while (a_file.read(a_buf, BUF_SIZE)) {
330 if (! b_file.read(b_buf, BUF_SIZE))
332 if (memcmp(a_buf, b_buf, BUF_SIZE) != 0)
335 if (b_file.read(b_buf, BUF_SIZE))
338 if (a_file.gcount() != b_file.gcount())
340 if (memcmp(a_buf, b_buf, a_file.gcount()) != 0)
418 #define BOOST_AUTO_TEST_SUITE_FIXTURE_TEMPLATE(suite_name, fixture_types) \
419 BOOST_AUTO_TEST_SUITE(suite_name) \
420 typedef fixture_types BOOST_AUTO_TEST_CASE_FIXTURE_TYPES; \
423 #define BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(test_name) \
424 template<typename F> \
425 struct test_name : public F \
426 { void test_method(); }; \
428 struct BOOST_AUTO_TC_INVOKER( test_name ) { \
429 template<typename TestType> \
430 static void run( boost::type<TestType>* = 0 ) \
432 test_name<TestType> t; \
437 BOOST_AUTO_TU_REGISTRAR( test_name )( \
438 boost::unit_test::ut_detail::template_test_case_gen< \
439 BOOST_AUTO_TC_INVOKER( test_name ), \
440 BOOST_AUTO_TEST_CASE_FIXTURE_TYPES >( \
441 BOOST_STRINGIZE( test_name ) ) ); \
443 template<typename F> \
444 void test_name<F>::test_method() \
static std::ofstream m_test_log_file
xml log results output stream (needs to be global)