/** @file

    $Id$

    $Date$
    $Author$

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

    $Log$
    Revision 1.9  2005/04/19 18:48:00  marc
    new feature PartialExec

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

    Revision 1.7  2004/12/20 13:21:21  marc
    exception tests: each exception must be in an own test case

    Revision 1.6  2004/12/14 20:30:10  marc
    added possibility to pass string to stdin of child process

    Revision 1.5  2004/10/13 10:43:11  marc
    test for bad exception specification

    Revision 1.4  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/exec.hxx>
#include <mrw/stdext.hxx>
#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 <string>
#include <stdlib.h>

class ExecTest: public CppUnit::TestFixture {
public:
  void lsTest() {
    std::string res = (mrw::Cmd("/bin/ls"), "-l",
                       std::string(getenv("srcdir"))+"/..").execute();
    CPPUNIT_ASSERT(res.find("COPYING")<res.size());
  }
  void catTest() {
    std::string res = mrw::Cmd("/bin/cat").execute("This is a test");
    CPPUNIT_ASSERT_EQUAL(std::string("This is a test"), res);
  }
  void excTest1() {
    CPPUNIT_ASSERT_THROW((mrw::Cmd("/bin/false")).execute(),
                         mrw::ExecutionFailedExc);
  }
  void excTest2() {
    CPPUNIT_ASSERT_THROW((mrw::Cmd("/bin/false")).execute(""),
                         mrw::ExecutionFailedExc);
  }
  void lsTest2() {
    std::string res;
    mrw::PartialExec exec = (mrw::Cmd("/bin/ls"), "-l",
                             std::string(getenv("srcdir"))+"/..").start();
    while (!exec.finished()) res+=exec.read().first;
    CPPUNIT_ASSERT(res.find("COPYING")<res.size());
  }
  void catTest2() {
    mrw::PartialExec exec = mrw::Cmd("/bin/cat").start(true);
    std::string res = exec.read("This is a test\n").first;
    res += exec.read("More to come...\n").first;
    exec.finish();
    while (!exec.finished()) res+=exec.read().first;
    CPPUNIT_ASSERT_EQUAL(std::string("This is a test\nMore to come...\n"), res);
  }
  void excTest12() {
    try {
      mrw::PartialExec exec = (mrw::Cmd("/bin/false")).start();
      while (!exec.finished()) exec.read();
      CPPUNIT_FAIL("Exception expected, shouldm't reach here");
    } catch (...) {
      CPPUNIT_ASSERT_THROW(throw, mrw::ExecutionFailedExc);
    }
  }
  void excTest22() {
    try {
      mrw::PartialExec exec = (mrw::Cmd("/bin/false")).start(true);
      while (!exec.finished()) exec.read("xxx");
      CPPUNIT_FAIL("Exception expected, shouldm't reach here");
    } catch (...) {
      CPPUNIT_ASSERT_THROW(throw, mrw::ExecutionFailedExc);
    }
  }
  void unexpectedExc2() throw(std::bad_exception) {
    try {
      mrw::PartialExec exec = (mrw::Cmd("/bin/false")).start();
      while (!exec.finished()) exec.read();
      CPPUNIT_FAIL("Exception expected, shouldm't reach here");
    } catch (...) {
      CPPUNIT_ASSERT_THROW(throw, mrw::ExecutionFailedExc);
    }
  }
  CPPUNIT_TEST_SUITE(ExecTest);
  CPPUNIT_TEST(lsTest);
  CPPUNIT_TEST(catTest);
  CPPUNIT_TEST(excTest1);
  CPPUNIT_TEST(excTest2);
  CPPUNIT_TEST(lsTest2);
  CPPUNIT_TEST(catTest2);
  CPPUNIT_TEST(excTest12);
  //CPPUNIT_TEST(excTest22); /// @bug strange failure from time to time
  CPPUNIT_TEST(unexpectedExc2);
  CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_REGISTRATION(ExecTest);

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