/** @file

    $Id$

    $Date$
    $Author$

    @copy &copy; Marc W&auml;ckerlin
    @license LGPL, see file <a href="license.html">COPYING</a>

    $Log$
    Revision 1.3  2005/04/07 20:55:21  marc
    Oops, there's a make distcheck...? Now it works.

    Revision 1.2  2005/03/11 23:18:02  marc
    bugfix: linenumbers change at checkin...

    Revision 1.1  2005/03/11 21:07:55  marc
    initial version


         1         2         3         4         5         6         7         8
    5678901234567890123456789012345678901234567890123456789012345678901234567890
*/

#include <mrw/functiontrace.hpp>
#include <mrw/regexp.hpp>
#include <mrw/file.hpp>
#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>

class A {
  public:
    A() {
      METHOD("A::A()");
    }
    ~A() {
      METHOD("A::~A()");
    }
    void fn1() {
      METHOD("A::fn1()");
      fn2();
    }
    void fn2() {
      METHOD("A::fn2()");
      fn3();
      fn4();
    }
    void fn3() {
      METHOD("A::fn3()");
      fn4();
    }
    void fn4(bool flag=true) {
      METHOD("A::fn4()");
      if (flag) fn4(false);
    }
};

void fn(A a) {
  FUNCTION("fn(A)");
  a.fn1();
}

class FunctionTraceTest: public CppUnit::TestFixture { 
  public:
    void Init() {
      try {mrw::File::remove("functiontrace_test.log");} catch (...) {}
      log4cxx::helpers::Properties properties;
      properties.setProperty("log4j.rootLogger",
                             "DEBUG, A1");
      properties.setProperty("log4j.appender.A1",
                             "org.apache.log4j.FileAppender");
      properties.setProperty("log4j.appender.A1.layout",
                             "org.apache.log4j.PatternLayout");
      properties.setProperty("log4j.appender.A1.layout.ConversionPattern",
                             "%F:%L - %m%n");
      properties.setProperty("log4j.appender.A1.filename",
                             "functiontrace_test.log");
      log4cxx::PropertyConfigurator::configure(properties);
    }
    void Calls() {
      fn(A());
      mrw::RegExp match
        (".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+: \\\\ A::A\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+: / A::A\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ -                  \\\\ fn\\(A\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:  \\\\ A::fn1\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:   \\\\ A::fn2\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:    \\\\ A::fn3\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:     \\\\ A::fn4\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:      \\\\ A::fn4\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:      / A::fn4\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:     / A::fn4\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:    / A::fn3\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:    \\\\ A::fn4\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:     \\\\ A::fn4\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:     / A::fn4\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:    / A::fn4\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:   / A::fn2\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+:  / A::fn1\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ -                  / fn\\(A\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+: \\\\ A::~A\\(\\)\n"
         ".*functiontrace_test.cpp:[0-9]+ - *0x[0-9a-fA-F]+: / A::~A\\(\\)\n");
      CPPUNIT_ASSERT(match(mrw::File::read("functiontrace_test.log")));
      mrw::File::remove("functiontrace_test.log");
    }
    CPPUNIT_TEST_SUITE(FunctionTraceTest);
    CPPUNIT_TEST(Init);
    CPPUNIT_TEST(Calls);
    CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_REGISTRATION(FunctionTraceTest);

int main() {
  CppUnit::TextUi::TestRunner runner;
  runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
  return runner.run() ? 0 : 1;
}
