10 #ifndef __PION_TEST_UNIT_TEST_HEADER__ 11 #define __PION_TEST_UNIT_TEST_HEADER__ 15 #include <boost/version.hpp> 16 #include <boost/thread/mutex.hpp> 17 #include <boost/thread/condition.hpp> 18 #include <boost/test/unit_test.hpp> 19 #include <boost/test/unit_test_log.hpp> 20 #include <boost/test/unit_test_log_formatter.hpp> 21 #include <boost/test/test_case_template.hpp> 22 #include <boost/test/utils/xml_printer.hpp> 23 #include <pion/logger.hpp> 27 #define CHANGE_DIRECTORY _chdir 28 #define GET_DIRECTORY(a,b) _getcwd(a,b) 31 #define CHANGE_DIRECTORY chdir 32 #define GET_DIRECTORY(a,b) getcwd(a,b) 35 #define DIRECTORY_MAX_SIZE 1000 43 :
public boost::unit_test::unit_test_log_formatter
49 : m_entry_in_progress(false)
57 boost::unit_test::counter_t test_cases_amount )
59 ostr <<
"<TestLog>" << std::endl;
65 ostr <<
"</TestLog>" << std::endl;
72 <<
" platform" << attr_value() << BOOST_PLATFORM
73 <<
" compiler" << attr_value() << BOOST_COMPILER
74 <<
" stl" << attr_value() << BOOST_STDLIB
75 <<
" boost=\"" << BOOST_VERSION/100000 <<
"." 76 << BOOST_VERSION/100 % 1000 <<
"." 77 << BOOST_VERSION % 100 <<
'\"' 83 boost::unit_test::test_unit
const& tu )
85 ostr <<
"<" << tu_type_name( tu ) <<
" name" << attr_value() << tu.p_name.get() <<
">" << std::endl;
90 boost::unit_test::test_unit
const& tu,
91 unsigned long elapsed )
93 if ( tu.p_type == boost::unit_test::tut_case )
94 ostr <<
"<TestingTime>" << elapsed <<
"</TestingTime>";
95 ostr <<
"</" << tu_type_name( tu ) <<
">" << std::endl;
100 boost::unit_test::test_unit
const& tu )
102 ostr <<
"<" << tu_type_name( tu )
103 <<
" name" << attr_value() << tu.p_name.get()
104 <<
" skipped" << attr_value() <<
"yes" 105 <<
"/>" << std::endl;
110 boost::unit_test::log_checkpoint_data
const& checkpoint_data,
111 boost::execution_exception
const& ex )
113 boost::execution_exception::location
const& loc = ex.where();
115 ostr <<
"<Exception file" << attr_value() << loc.m_file_name
116 <<
" line" << attr_value() << loc.m_line_num;
118 if( !loc.m_function.is_empty() )
119 ostr <<
" function" << attr_value() << loc.m_function;
121 ostr <<
">" << boost::unit_test::cdata() << ex.what();
123 if( !checkpoint_data.m_file_name.is_empty() ) {
124 ostr <<
"<LastCheckpoint file" << attr_value() << checkpoint_data.m_file_name
125 <<
" line" << attr_value() << checkpoint_data.m_line_num
127 << boost::unit_test::cdata() << checkpoint_data.m_message
128 <<
"</LastCheckpoint>";
131 ostr <<
"</Exception>" << std::endl;
136 boost::unit_test::log_entry_data
const& entry_data,
137 log_entry_types let )
139 boost::mutex::scoped_lock entry_lock(m_mutex);
140 while (m_entry_in_progress) {
141 m_entry_complete.wait(entry_lock);
143 m_entry_in_progress =
true;
145 static boost::unit_test::literal_string xml_tags[] = {
"Info",
"Message",
"Warning",
"Error",
"FatalError" };
146 m_curr_tag = xml_tags[let];
147 ostr <<
'<' << m_curr_tag
148 << BOOST_TEST_L(
" file" ) << attr_value() << entry_data.m_file_name
149 << BOOST_TEST_L(
" line" ) << attr_value() << entry_data.m_line_num
150 << BOOST_TEST_L(
"><![CDATA[" );
157 virtual void log_entry_value( std::ostream& ostr, boost::unit_test::const_string value )
159 boost::mutex::scoped_lock entry_lock(m_mutex);
160 if (m_entry_in_progress) {
170 boost::mutex::scoped_lock entry_lock(m_mutex);
171 if (m_entry_in_progress) {
172 ostr << BOOST_TEST_L(
"]]></" ) << m_curr_tag << BOOST_TEST_L(
">" ) << std::endl;
174 m_entry_in_progress =
false;
175 m_entry_complete.notify_one();
182 static boost::unit_test::const_string tu_type_name( boost::unit_test::test_unit
const& tu )
184 return tu.p_type == boost::unit_test::tut_case ?
"TestCase" :
"TestSuite";
188 typedef boost::unit_test::attr_value attr_value;
191 volatile bool m_entry_in_progress;
194 boost::condition m_entry_complete;
197 boost::mutex m_mutex;
200 boost::unit_test::const_string m_curr_tag;
211 std::cout <<
"global setup for all pion unit tests\n";
214 int argc = boost::unit_test::framework::master_test_suite().argc;
215 char** argv = boost::unit_test::framework::master_test_suite().argv;
216 bool verbose =
false;
219 if (argv[1][0] ==
'-' && argv[1][1] ==
'v') {
221 }
else if (strlen(argv[1]) > 13 && strncmp(argv[1],
"--log_output=", 13) == 0) {
222 const char *
const test_log_filename = argv[1] + 13;
223 m_test_log_file.open(test_log_filename);
224 if (m_test_log_file.is_open()) {
225 boost::unit_test::unit_test_log.set_stream(m_test_log_file);
228 std::cerr <<
"unable to open " << test_log_filename << std::endl;
234 PION_LOG_CONFIG_BASIC;
236 std::cout <<
"Use '-v' to enable logging of errors and warnings from pion.\n";
240 PION_LOG_SETLEVEL_WARN(log_ptr);
243 std::cout <<
"global teardown for all pion unit tests\n";
252 static inline char* trim(
char* str) {
253 for (
long len = strlen(str) - 1; len >= 0; len--) {
254 if (str[len] ==
'\n' || str[len] ==
'\r')
264 static inline bool read_lines_from_file(
const std::string& filename, std::list<std::string>& lines) {
266 std::ifstream a_file(filename.c_str(), std::ios::in | std::ios::binary);
267 if (! a_file.is_open())
271 static const unsigned int BUF_SIZE = 4096;
272 char *ptr, buf[BUF_SIZE+1];
273 buf[BUF_SIZE] =
'\0';
276 while (a_file.getline(buf, BUF_SIZE)) {
278 if (*ptr !=
'\0' && *ptr !=
'#')
279 lines.push_back(ptr);
290 static inline bool check_files_match(
const std::string& fileA,
const std::string& fileB) {
292 std::list<std::string> a_lines, b_lines;
293 BOOST_REQUIRE(read_lines_from_file(fileA, a_lines));
294 BOOST_REQUIRE(read_lines_from_file(fileB, b_lines));
301 return (a_lines == b_lines);
304 static inline bool check_files_exact_match(
const std::string& fileA,
const std::string& fileB,
bool ignore_line_endings =
false) {
306 std::ifstream a_file(fileA.c_str(), std::ios::in | std::ios::binary);
307 BOOST_REQUIRE(a_file.is_open());
309 std::ifstream b_file(fileB.c_str(), std::ios::in | std::ios::binary);
310 BOOST_REQUIRE(b_file.is_open());
313 static const unsigned int BUF_SIZE = 4096;
314 char a_buf[BUF_SIZE];
315 char b_buf[BUF_SIZE];
317 if (ignore_line_endings) {
318 while (a_file.getline(a_buf, BUF_SIZE)) {
319 if (! b_file.getline(b_buf, BUF_SIZE))
323 if (strlen(a_buf) != strlen(b_buf))
325 if (memcmp(a_buf, b_buf, strlen(a_buf)) != 0)
328 if (b_file.getline(b_buf, BUF_SIZE))
331 while (a_file.read(a_buf, BUF_SIZE)) {
332 if (! b_file.read(b_buf, BUF_SIZE))
334 if (memcmp(a_buf, b_buf, BUF_SIZE) != 0)
337 if (b_file.read(b_buf, BUF_SIZE))
340 if (a_file.gcount() != b_file.gcount())
342 if (memcmp(a_buf, b_buf, a_file.gcount()) != 0)
420 #define BOOST_AUTO_TEST_SUITE_FIXTURE_TEMPLATE(suite_name, fixture_types) \ 421 BOOST_AUTO_TEST_SUITE(suite_name) \ 422 typedef fixture_types BOOST_AUTO_TEST_CASE_FIXTURE_TYPES; \ 425 #define BOOST_AUTO_TEST_CASE_FIXTURE_TEMPLATE(test_name) \ 426 template<typename F> \ 427 struct test_name : public F \ 428 { void test_method(); }; \ 430 struct BOOST_AUTO_TC_INVOKER( test_name ) { \ 431 template<typename TestType> \ 432 static void run( boost::type<TestType>* = 0 ) \ 434 test_name<TestType> t; \ 439 BOOST_AUTO_TU_REGISTRAR( test_name )( \ 440 boost::unit_test::ut_detail::template_test_case_gen< \ 441 BOOST_AUTO_TC_INVOKER( test_name ), \ 442 BOOST_AUTO_TEST_CASE_FIXTURE_TYPES >( \ 443 BOOST_STRINGIZE( test_name ) ) ); \ 445 template<typename F> \ 446 void test_name<F>::test_method() \
static std::ofstream m_test_log_file
xml log results output stream (needs to be global)