C++ Library containing a lot of needful things: Stack Trace, Command Line Parser, Resource Handling, Configuration Files, Unix Command Execution, Directories, Regular Expressions, Tokenizer, Function Trace, Standard Extensions.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
249 lines
11 KiB
249 lines
11 KiB
/** @file |
|
|
|
$Id$ |
|
|
|
$Date$ |
|
$Author$ |
|
|
|
@copy © Marc Wäckerlin |
|
@license LGPL, see file <a href="license.html">COPYING</a> |
|
|
|
$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 <log4cxx/propertyconfigurator.h> |
|
#include <log4cxx/helpers/properties.h> |
|
#include <cppunit/TestFixture.h> |
|
#include <cppunit/ui/text/TestRunner.h> |
|
#include <cppunit/extensions/HelperMacros.h> |
|
#include <cppunit/extensions/TestFactoryRegistry.h> |
|
#include <mrw/file.hxx> |
|
#include <mrw/regexp.hxx> |
|
#include <mrw/string.hxx> |
|
#include <mrw/stacktrace.hxx> |
|
#include <map> |
|
|
|
#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 <boost/thread/thread.hxx> |
|
//#include <unistd.h> // 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.log");} |
|
#else |
|
try {mrw::File::remove("mrwautofunctiontracelog4cxx_test.log");} |
|
#endif |
|
catch (...) {} |
|
log4cxx::helpers::Properties properties; |
|
std::string name, cont; |
|
properties.setProperty((name="log4j.rootLogger", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF, A1", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="DEBUG", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.global", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.allocator", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.std.*", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.log4cxx", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.boost", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.Thread", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.mrw", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.std", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.new", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.CppUnit", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.logger.mrw.fn.__gnu_cxx", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="OFF", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.appender.A1", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="org.apache.log4j.FileAppender", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.appender.A1.layout", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="org.apache.log4j.PatternLayout", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
#ifdef _MT |
|
properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="%t-%-27c%m%n", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.appender.A1.filename", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="mrwautofunctiontracelog4cxx_test-mt.log", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
#else |
|
properties.setProperty((name="log4j.appender.A1.layout.ConversionPattern", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="%-27c%m%n", |
|
log4cxx::String(cont.begin(), cont.end()))); |
|
properties.setProperty((name="log4j.appender.A1.filename", |
|
log4cxx::String(name.begin(), name.end())), |
|
(cont="mrwautofunctiontracelog4cxx_test.log", |
|
log4cxx::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::thread thread1(threadFunction); |
|
boost::thread::thread thread2(threadFunction); |
|
boost::thread::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.log")); |
|
typedef std::map<unsigned long, std::string> 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<unsigned long>(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.log"); |
|
#else |
|
CPPUNIT_ASSERT_MESSAGE |
|
("The following text does not match the " |
|
"Expectation:\n--------------------\n" |
|
+mrw::File::read("mrwautofunctiontracelog4cxx_test.log") |
|
+"--------------------", |
|
match(mrw::File::read("mrwautofunctiontracelog4cxx_test.log"))); |
|
mrw::File::remove("mrwautofunctiontracelog4cxx_test.log"); |
|
#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: "<<e.what()<<std::endl; |
|
return 1; |
|
}
|
|
|