/** @file $Id$ $Date$ $Author$ @copy © Marc Wäckerlin @license LGPL, see file COPYING $Log$ Revision 1.3 2005/11/29 12:39:42 marc make it compilable with gcc 4.0.2 and newer doxygen Revision 1.2 2005/04/07 20:42:38 marc renamed loggerhierarchy from mrw.gccfunctiontrace to mrw.fn Revision 1.1 2005/03/11 21:07:55 marc initial version 1 2 3 4 5 6 7 8 5678901234567890123456789012345678901234567890123456789012345678901234567890 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #if (__GNUC__==3 && __GNUC_MINOR__<4 || __GNUC__<3) \ && defined(_REENTRANT) && !defined(_MT) #define _MT #endif namespace HalloWelt { class A { public: void method() { } }; void fn(int) { A().method(); A().method(); } void fn1() { fn(1); fn(2); } } void anotherFunction() { HalloWelt::fn1(); } #ifdef _MT #include //#include // sleep, the one from boost::thread does not work! class Thread { public: void operator()() { anotherFunction(); } }; #endif namespace mrw { class AutoFunctionTraceLog4CxxTest: public CppUnit::TestFixture { public: void testcase() { mrw::StackTrace::createSymtable(); #ifdef _MT try {mrw::File::remove("mrwautofunctiontracelog4cxx_test-mt.trace");} #else try {mrw::File::remove("mrwautofunctiontracelog4cxx_test.trace");} #endif catch (...) {} log4cxx::helpers::Properties properties; std::string name, cont; properties.setProperty((name="log4j.rootLogger", std::string(name.begin(), name.end())), (cont="OFF, A1", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn", std::string(name.begin(), name.end())), (cont="DEBUG", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.global", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.allocator", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.std.*", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.log4cxx", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.boost", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.Thread", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.mrw", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.std", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.new", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.CppUnit", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.logger.mrw.fn.__gnu_cxx", std::string(name.begin(), name.end())), (cont="OFF", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.appender.A1", std::string(name.begin(), name.end())), (cont="org.apache.log4j.FileAppender", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.appender.A1.layout", std::string(name.begin(), name.end())), (cont="org.apache.log4j.PatternLayout", std::string(cont.begin(), cont.end()))); #ifdef _MT properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", std::string(name.begin(), name.end())), (cont="%t-%-27c%m%n", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.appender.A1.filename", std::string(name.begin(), name.end())), (cont="mrwautofunctiontracelog4cxx_test-mt.trace", std::string(cont.begin(), cont.end()))); #else properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", std::string(name.begin(), name.end())), (cont="%-27c%m%n", std::string(cont.begin(), cont.end()))); properties.setProperty((name="log4j.appender.A1.filename", std::string(name.begin(), name.end())), (cont="mrwautofunctiontracelog4cxx_test.trace", std::string(cont.begin(), cont.end()))); #endif log4cxx::PropertyConfigurator::configure(properties); #ifdef _MT // sleep(4); // to be reproducable, wait for "main" flag Thread threadFunction; boost::thread thread1(threadFunction); boost::thread thread2(threadFunction); boost::thread thread3(threadFunction); #endif anotherFunction(); #ifdef _MT thread1.join(); thread2.join(); thread3.join(); #endif } void checkfile() { mrw::RegExp match ("^mrw\\.fn\\.anotherFunction ( ? ? ?)\\\\ anotherFunction\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.fn1 \\1 \\\\ HalloWelt::fn1\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.fn \\1 \\\\ HalloWelt::fn\\(int\\)\n" "mrw\\.fn\\.HalloWelt\\.A\\.method \\1 \\\\ HalloWelt::A::method\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.A\\.method \\1 / HalloWelt::A::method\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.A\\.method \\1 \\\\ HalloWelt::A::method\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.A\\.method \\1 / HalloWelt::A::method\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.fn \\1 / HalloWelt::fn\\(int\\)\n" "mrw\\.fn\\.HalloWelt\\.fn \\1 \\\\ HalloWelt::fn\\(int\\)\n" "mrw\\.fn\\.HalloWelt\\.A\\.method \\1 \\\\ HalloWelt::A::method\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.A\\.method \\1 / HalloWelt::A::method\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.A\\.method \\1 \\\\ HalloWelt::A::method\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.A\\.method \\1 / HalloWelt::A::method\\(\\)\n" "mrw\\.fn\\.HalloWelt\\.fn \\1 / HalloWelt::fn\\(int\\)\n" "mrw\\.fn\\.HalloWelt\\.fn1 \\1 / HalloWelt::fn1\\(\\)\n" "mrw\\.fn\\.anotherFunction \\1/ anotherFunction\\(\\)\n$"); #ifdef _MT std::string log(mrw::File::read("mrwautofunctiontracelog4cxx_test-mt.trace")); typedef std::map Logs; Logs logs; for (std::string::size_type pos(0), last(0); (pos=log.find('\n', pos+1))!=std::string::npos; last=pos) { std::string::size_type dash(log.find('-', last)); CPPUNIT_ASSERT_MESSAGE("\"-\" not found", dash!=std::string::npos); logs[mrw::to(log.substr(last, dash-last))] += log.substr(dash+1, pos-dash); } CPPUNIT_ASSERT_EQUAL((Logs::size_type)4, logs.size()); // 4 threads for (Logs::iterator it(logs.begin()); it!=logs.end(); ++it) CPPUNIT_ASSERT_MESSAGE("The following text does not match the " "Expectation:\n--------------------\n" +it->second+"--------------------", match(it->second)); mrw::File::remove("mrwautofunctiontracelog4cxx_test-mt.trace"); #else CPPUNIT_ASSERT_MESSAGE ("The following text does not match the " "Expectation:\n--------------------\n" +mrw::File::read("mrwautofunctiontracelog4cxx_test.trace") +"--------------------", match(mrw::File::read("mrwautofunctiontracelog4cxx_test.trace"))); mrw::File::remove("mrwautofunctiontracelog4cxx_test.trace"); #endif } CPPUNIT_TEST_SUITE(AutoFunctionTraceLog4CxxTest); CPPUNIT_TEST(testcase); CPPUNIT_TEST(checkfile); CPPUNIT_TEST_SUITE_END(); }; CPPUNIT_TEST_SUITE_REGISTRATION(AutoFunctionTraceLog4CxxTest); } int main(int argc, char** argv) try { std::ofstream ofs((*argv+std::string(".xml")).c_str()); CppUnit::TextUi::TestRunner runner; runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), ofs)); runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest()); return runner.run() ? 0 : 1; } catch (std::exception& e) { std::cerr<<"***Exception: "<