/** @file

    $Id$

    $Date$
    $Author$

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

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

    Revision 1.4  2004/11/25 18:27:03  marc
    additional test for release and reset

    Revision 1.3  2004/08/28 16:21:25  marc
    mrw-c++-0.92 (mrw)
    - new file: version.cxx
    - new file header for all sources
    - work around warning in mrw::auto<T>
    - possibility to compile without log4cxx
    - work around bugs in demangle.h and libiberty.h
    - corrections in documentation
    - added simple tracing mechanism
    - more warnings
    - small corrections in Auto<>::Free and a new test for it
    - possibility to compile without stack trace

*/
#include <mrw/auto.hxx>
#include <mrw/stdext.hxx> // ifelse
#include <cppunit/TestFixture.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/XmlOutputter.h>
#include <fstream>
#include <fcntl.h> // open
#include <string.h> // strncpy
#include <stdlib.h> // getenv

class AutoTest: public CppUnit::TestFixture { 
public: 
  void AutoFile() {
    char c(0);
    int i(-1);
    {
      mrw::AutoFile a;
      CPPUNIT_ASSERT_EQUAL(-1, (mrw::AutoFile::Type)a); // init as -1
      i = a = open((std::string(mrw::ifelse(getenv("srcdir"), "."))
                    +"/test.dat").c_str(), O_RDONLY);
      CPPUNIT_ASSERT(i==(int)a && (int)a>0); // file is now open
      mrw::AutoFile b(a);
      CPPUNIT_ASSERT((int)a==-1 && i==(int)b); // b has taken ownership
      CPPUNIT_ASSERT(read(b, &c, 1)==1 && c=='H'); // file is good
      mrw::AutoFile cc(i);
      CPPUNIT_ASSERT(i==(int)b && (int)b==(int)cc); // ooops, two owner!
      cc.release();
      CPPUNIT_ASSERT(i==(int)b && (int)cc==-1); // it's ok now
      b = open("test.dat", O_RDONLY);
      //close(i);
      CPPUNIT_ASSERT_EQUAL((ssize_t)-1, read(i, &c, 1)); // old file is closed
      i = b.reset();
      CPPUNIT_ASSERT_EQUAL((ssize_t)-1, read(i, &c, 1)); // new file is closed
      i = a = open("test.dat", O_RDONLY);
    }
    CPPUNIT_ASSERT_EQUAL((ssize_t)-1, read(i, &c, 1)); // file is closed now
  }
  void AutoFree() {
    const char C[] = "Hello World";
    mrw::Auto<char*>::Free c(malloc(sizeof(C)));
    CPPUNIT_ASSERT(c);
    strncpy(c, C, sizeof(C));
    CPPUNIT_ASSERT_EQUAL(std::string(C), std::string(c));
    mrw::Auto<char*>::Free c2(c.release());
    CPPUNIT_ASSERT(c==0 && c2!=0);
    CPPUNIT_ASSERT_EQUAL(std::string(C), std::string(c2));
    c2.reset();
    CPPUNIT_ASSERT_EQUAL((char*)0, (char*)c2);
  }
  CPPUNIT_TEST_SUITE(AutoTest);
  CPPUNIT_TEST(AutoFile);
  CPPUNIT_TEST(AutoFree);
  CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_REGISTRATION(AutoTest);

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;
 }
