Browse Source

Merge of rework for Junit and TAP

Brian Aker 11 years ago
parent
commit
c8026e6abe
8 changed files with 491 additions and 239 deletions
  1. 105 34
      libtest/collection.cc
  2. 24 12
      libtest/collection.h
  3. 150 70
      libtest/formatter.cc
  4. 48 22
      libtest/formatter.hpp
  5. 30 52
      libtest/framework.cc
  6. 26 20
      libtest/framework.h
  7. 28 29
      libtest/main.cc
  8. 80 0
      libtest/test.h

+ 105 - 34
libtest/collection.cc

@@ -38,9 +38,11 @@
 
 
 #include <libtest/common.h>
 #include <libtest/common.h>
 
 
+#include <algorithm>
+
 // @todo possibly have this code fork off so if it fails nothing goes bad
 // @todo possibly have this code fork off so if it fails nothing goes bad
 static test_return_t runner_code(libtest::Framework* frame,
 static test_return_t runner_code(libtest::Framework* frame,
-                                 test_st* run, 
+                                 const struct test_st* run, 
                                  libtest::Timer& _timer)
                                  libtest::Timer& _timer)
 { // Runner Code
 { // Runner Code
 
 
@@ -84,46 +86,119 @@ static test_return_t runner_code(libtest::Framework* frame,
 
 
 namespace libtest {
 namespace libtest {
 
 
-Collection::Collection(Framework* frame_arg,
-                       collection_st* arg) :
-  _name(arg->name),
-  _pre(arg->pre),
-  _post(arg->post),
-  _tests(arg->tests),
-  _frame(frame_arg),
+Collection::Collection(Framework* frame_,
+                       collection_st* tests_) :
+  _name(tests_->name),
+  _ret(TEST_SKIPPED),
+  _pre(tests_->pre),
+  _post(tests_->post),
+  _tests(tests_->tests),
+  _frame(frame_),
   _success(0),
   _success(0),
   _skipped(0),
   _skipped(0),
   _failed(0),
   _failed(0),
-  _total(0),
-  _formatter(frame_arg->name(), _name)
+  _formatter(frame_->formatter())
+{
+  fatal_assert(tests_);
+  for (const test_st *run= _tests; run->name; run++)
+  {
+    push_testcase(run);
+  }
+
+  case_iter= _testcases.begin();
+}
+
+Collection::~Collection()
 {
 {
-  fatal_assert(arg);
+  std::for_each(_testcases.begin(), _testcases.end(), DeleteFromVector());
+  _testcases.clear();
+
+  std::for_each(_formatter.begin(), _formatter.end(), DeleteFromVector());
+  _formatter.clear();
+}
+
+void Collection::push_testcase(const test_st* test_)
+{
+  TestCase* _current_testcase= new TestCase(test_);
+  _testcases.push_back(_current_testcase);
+}
+
+void Collection::format()
+{
+  for (Formatters::iterator format_iter= _formatter.begin();
+       format_iter != _formatter.end();
+       ++format_iter)
+  {
+    (*format_iter)->report((*case_iter), std::distance(_testcases.begin(), case_iter));
+  }
+}
+
+void Collection::plan()
+{
+  for (Formatters::iterator format_iter= _formatter.begin();
+       format_iter != _formatter.end();
+       ++format_iter)
+  {
+    (*format_iter)->plan(this);
+  }
+}
+
+void Collection::complete()
+{
+  for (Formatters::iterator format_iter= _formatter.begin();
+       format_iter != _formatter.end();
+       ++format_iter)
+  {
+    (*format_iter)->complete();
+  }
+}
+
+void Collection::succeess()
+{
+  _success++;
+  (*case_iter)->success(_timer);
+  format();
+}
+
+void Collection::skip()
+{
+  _skipped++;
+  (*case_iter)->skipped();
+  format();
+}
+
+void Collection::fail()
+{
+  _failed++;
+  (*case_iter)->failed();
+  format();
 }
 }
 
 
 test_return_t Collection::exec()
 test_return_t Collection::exec()
 {
 {
+  // Write out any headers required by formatting.
+  plan();
+
   if (test_success(_frame->runner()->setup(_pre, _frame->creators_ptr())))
   if (test_success(_frame->runner()->setup(_pre, _frame->creators_ptr())))
   {
   {
-    for (test_st *run= _tests; run->name; run++)
+    for (; case_iter != _testcases.end();
+         ++case_iter)
     {
     {
-      formatter()->push_testcase(run->name);
-      if (_frame->match(run->name))
+      if (_frame->match((*case_iter)->name()))
       {
       {
-        formatter()->skipped();
+        skip();
         continue;
         continue;
       }
       }
-      _total++;
 
 
       test_return_t return_code;
       test_return_t return_code;
       try 
       try 
       {
       {
-        if (run->requires_flush)
+        if ((*case_iter)->requires_flush())
         {
         {
           if (test_failed(_frame->runner()->flush(_frame->creators_ptr())))
           if (test_failed(_frame->runner()->flush(_frame->creators_ptr())))
           {
           {
             Error << "frame->runner()->flush(creators_ptr)";
             Error << "frame->runner()->flush(creators_ptr)";
-            _skipped++;
-            formatter()->skipped();
+            skip();
             continue;
             continue;
           }
           }
         }
         }
@@ -132,7 +207,7 @@ test_return_t Collection::exec()
 
 
         try 
         try 
         {
         {
-          return_code= runner_code(_frame, run, _timer);
+          return_code= runner_code(_frame, (*case_iter)->test(), _timer);
         }
         }
         catch (...)
         catch (...)
         {
         {
@@ -145,26 +220,22 @@ test_return_t Collection::exec()
       catch (const libtest::fatal& e)
       catch (const libtest::fatal& e)
       {
       {
         stream::cerr(e.file(), e.line(), e.func()) << e.what();
         stream::cerr(e.file(), e.line(), e.func()) << e.what();
-        _failed++;
-        formatter()->failed();
+        fail();
         throw;
         throw;
       }
       }
 
 
       switch (return_code)
       switch (return_code)
       {
       {
       case TEST_SUCCESS:
       case TEST_SUCCESS:
-        _success++;
-        formatter()->success(_timer);
+        succeess();
         break;
         break;
 
 
       case TEST_FAILURE:
       case TEST_FAILURE:
-        _failed++;
-        formatter()->failed();
+        fail();
         break;
         break;
 
 
       case TEST_SKIPPED:
       case TEST_SKIPPED:
-        _skipped++;
-        formatter()->skipped();
+        skip();
         break;
         break;
 
 
       default:
       default:
@@ -180,17 +251,17 @@ test_return_t Collection::exec()
 
 
   if (_failed == 0 and _skipped == 0 and _success)
   if (_failed == 0 and _skipped == 0 and _success)
   {
   {
-    return TEST_SUCCESS;
+    _ret= TEST_SUCCESS;
   }
   }
-
-  if (_failed)
+  else if (_failed)
   {
   {
-    return TEST_FAILURE;
+    _ret= TEST_FAILURE;
   }
   }
 
 
-  fatal_assert(_skipped or _success == 0);
+  // Complete any headers required by formatting.
+  complete();
 
 
-  return TEST_SKIPPED;
+  return _ret;
 }
 }
 
 
 } // namespace libtest
 } // namespace libtest

+ 24 - 12
libtest/collection.h

@@ -58,41 +58,52 @@ namespace libtest {
 class Collection {
 class Collection {
 public:
 public:
   Collection(libtest::Framework*, collection_st*);
   Collection(libtest::Framework*, collection_st*);
+  ~Collection();
 
 
   test_return_t exec();
   test_return_t exec();
 
 
-  const char* name()
+  const char* name() const
   {
   {
     return _name.c_str();
     return _name.c_str();
   }
   }
 
 
-  uint32_t success()
+  void succeess();
+
+  void skip();
+
+  void fail();
+
+  uint32_t succeeded() const
   {
   {
     return _success;
     return _success;
   }
   }
 
 
-  uint32_t skipped()
+  uint32_t skipped() const
   {
   {
     return _skipped;
     return _skipped;
   }
   }
 
 
-  uint32_t failed()
+  uint32_t failed() const
   {
   {
     return _failed;
     return _failed;
   }
   }
 
 
-  uint32_t total()
-  {
-    return _total;
-  }
+  void format();
 
 
-  libtest::Formatter* formatter()
+  size_t total() const
   {
   {
-    return &_formatter;
+    return _testcases.size();
   }
   }
 
 
+  void plan();
+  void complete();
+
+private:
+  void push_testcase(const test_st* test_);
+
 private:
 private:
   std::string _name;
   std::string _name;
+  test_return_t _ret;
   test_callback_fn *_pre;
   test_callback_fn *_pre;
   test_callback_fn *_post;
   test_callback_fn *_post;
   struct test_st *_tests;
   struct test_st *_tests;
@@ -100,9 +111,10 @@ private:
   uint32_t _success;
   uint32_t _success;
   uint32_t _skipped;
   uint32_t _skipped;
   uint32_t _failed;
   uint32_t _failed;
-  uint32_t _total;
   libtest::Timer _timer;
   libtest::Timer _timer;
-  libtest::Formatter _formatter;
+  libtest::Formatters& _formatter;
+  TestCases _testcases;
+  TestCases::iterator case_iter;
 
 
 private:
 private:
   Collection( const Collection& );
   Collection( const Collection& );

+ 150 - 70
libtest/formatter.cc

@@ -44,101 +44,190 @@
   
   
 namespace libtest {
 namespace libtest {
 
 
-class TestCase {
-public:
-  TestCase(const std::string& arg):
-    _name(arg),
-    _result(TEST_FAILURE)
-  {
-  }
+Formatter::Formatter(const Framework* frame_, std::ostream& output_):
+  _frame(frame_),
+  _output(output_)
+{
+}
 
 
-  const std::string& name() const
-  {
-    return _name;
-  }
+const std::string& Formatter::name() const
+{
+  return _frame->name();
+}
 
 
-  test_return_t result() const
-  {
-    return _result;
-  }
+Legacy::Legacy(const Framework* frame_, std::ostream& output_):
+  Formatter(frame_, output_),
+  _collection(NULL)
+{
+}
 
 
-  void result(test_return_t arg)
-  {
-    _result= arg;
-  }
 
 
-  void result(test_return_t arg, const libtest::Timer& timer_)
+Legacy::~Legacy()
+{
+  if (getenv("YATL_SUMMARY"))
   {
   {
-    _result= arg;
-    _timer= timer_;
+    Outn();
+    Out << "Tests\t\t\t\t\t" << _frame->total();
+    Out << "\tFailed\t\t\t\t\t" << _frame->failed();
+    Out << "\tSkipped\t\t\t\t\t" << _frame->skipped();
+    Out << "\tSucceeded\t\t\t\t" << _frame->success();
   }
   }
+}
 
 
-  const libtest::Timer& timer() const
-  {
-    return _timer;
-  }
+void Legacy::plan(const Collection* collection)
+{
+  _collection= collection;
+}
 
 
-  void timer(libtest::Timer& arg)
+void Legacy::report(const libtest::TestCase* test, size_t) const
+{
+  switch (test->result())
   {
   {
-    _timer= arg;
+    case TEST_SUCCESS:
+      Out << name() << "."
+        << _collection->name() << "."
+        << test->name()
+        <<  "\t\t\t\t\t" 
+        << test->timer() 
+        << " [ " << test_strerror(test->result()) << " ]";
+      break;
+
+    case TEST_FAILURE:
+      Out << name() << "."
+        << _collection->name() << "."
+        << test->name()
+        <<  "\t\t\t\t\t" << "[ " << test_strerror(test->result()) << " ]";
+      break;
+
+    case TEST_SKIPPED:
+      Out << name() << "."
+        << _collection->name() << "."
+        << test->name()
+        <<  "\t\t\t\t\t" << "[ " << test_strerror(test->result()) << " ]";
+      break;
   }
   }
+}
 
 
-private:
-  std::string _name;
-  test_return_t _result;
-  libtest::Timer _timer;
-};
+Junit::Junit(const Framework* frame_, std::ostream& output_):
+  Formatter(frame_, output_)
+{
+  _output << "<testsuites name=\"" << name() << "\">" << std::endl;
+}
 
 
-Formatter::Formatter(const std::string& frame_name, const std::string& arg)
+Junit::~Junit()
 {
 {
-  _suite_name= frame_name;
-  _suite_name+= ".";
-  _suite_name+= arg;
+  _output << "</testsuites>" << std::endl;
 }
 }
 
 
-Formatter::~Formatter()
+void Junit::report(const libtest::TestCase* test, size_t) const
 {
 {
-  std::for_each(_testcases.begin(), _testcases.end(), DeleteFromVector());
-  _testcases.clear();
+  _output << "\t\t<testcase name=\"" 
+    << test->name() 
+    << "\" time=\"" 
+    << test->timer().elapsed_milliseconds() 
+    << "\">" 
+    << std::endl;
+
+  switch (test->result())
+  {
+    case TEST_SKIPPED:
+      _output << "\t\t <skipped/>" << std::endl;
+      break;
+
+    case TEST_FAILURE:
+      _output << "\t\t <failure message=\"\" type=\"\"/>"<< std::endl;
+      break;
+
+    case TEST_SUCCESS:
+      break;
+  }
+  _output << "\t\t</testcase>" << std::endl;
 }
 }
 
 
-TestCase* Formatter::current()
+void Junit::plan(const Collection* collection)
 {
 {
-  return _testcases.back();
+  _output << "\t<testsuite name=\"" << collection->name() << "\"  classname=\"\" package=\"\">" << std::endl;
 }
 }
 
 
-void Formatter::skipped()
+void Junit::complete()
 {
 {
-  current()->result(TEST_SKIPPED);
-  Out << name() << "." << current()->name() <<  "\t\t\t\t\t" << "[ " << test_strerror(current()->result()) << " ]";
+  _output << "\t</testsuite>" << std::endl;
+}
+
+TAP::TAP(const Framework* frame_, std::ostream& output_):
+  Formatter(frame_, output_)
+{
+}
 
 
-  reset();
+TAP::~TAP()
+{
 }
 }
 
 
-void Formatter::failed()
+void TAP::report(const libtest::TestCase* test, size_t position) const
 {
 {
-  assert(current());
-  current()->result(TEST_FAILURE);
+  assert(test);
+  switch (test->result())
+  {
+    case TEST_SUCCESS:
+      _output << "ok " << position << " - " << test->name() << " # ";
+      _output << test->timer().elapsed_milliseconds();
+      break;
 
 
-  Out << name() << "." << current()->name() <<  "\t\t\t\t\t" << "[ " << test_strerror(current()->result()) << " ]";
+    case TEST_FAILURE:
+      _output << "not ok " << position << " - " << test->name() << " # ";
+      break;
 
 
-  reset();
+    case TEST_SKIPPED:
+      _output << "ok " << position << " - # SKIP ";
+      break;
+  }
+
+  _output << std::endl;
 }
 }
 
 
-void Formatter::success(const libtest::Timer& timer_)
+void TAP::plan(const Collection* collection)
 {
 {
-  assert(current());
-  current()->result(TEST_SUCCESS, timer_);
+  _output << "0.." << collection->total() << std::endl;
+}
 
 
-  Out << name() << "."
-    << current()->name()
-    <<  "\t\t\t\t\t" 
-    << current()->timer() 
-    << " [ " << test_strerror(current()->result()) << " ]";
+#if 0
+void Formatter::tap(libtest::Framework& framework_, std::ofstream& output)
+{
+  for (Suites::iterator framework_iter= framework_.suites().begin();
+       framework_iter != framework_.suites().end();
+       ++framework_iter)
+  {
+    output << "1.." << (*framework_iter)->formatter()->testcases().size() << " # " << (*framework_iter)->name() << std::endl;
 
 
-  reset();
+    size_t test_count= 1;
+    for (TestCases::iterator case_iter= (*framework_iter)->formatter()->testcases().begin();
+         case_iter != (*framework_iter)->formatter()->testcases().end();
+         ++case_iter)
+    {
+      switch ((*case_iter)->result())
+      {
+        case TEST_SKIPPED:
+        output << "ok " << test_count << " - # SKIP ";
+        break;
+
+        case TEST_FAILURE:
+        output << "not ok " << test_count << " - " << (*case_iter)->name() << " # ";
+        break;
+
+        case TEST_SUCCESS:
+        output << "ok " << test_count << " - " << (*case_iter)->name() << " # ";
+        break;
+      }
+
+      output 
+        << (*case_iter)->timer().elapsed_milliseconds() 
+        << std::endl;
+    }
+  }
 }
 }
+#endif
 
 
+#if 0
 void Formatter::xml(libtest::Framework& framework_, std::ofstream& output)
 void Formatter::xml(libtest::Framework& framework_, std::ofstream& output)
 {
 {
   output << "<testsuites name=\"" << framework_.name() << "\">" << std::endl;
   output << "<testsuites name=\"" << framework_.name() << "\">" << std::endl;
@@ -178,15 +267,6 @@ void Formatter::xml(libtest::Framework& framework_, std::ofstream& output)
   }
   }
   output << "</testsuites>" << std::endl;
   output << "</testsuites>" << std::endl;
 }
 }
+#endif
 
 
-void Formatter::push_testcase(const std::string& arg)
-{
-  assert(_suite_name.empty() == false);
-  TestCase* _current_testcase= new TestCase(arg);
-  _testcases.push_back(_current_testcase);
-}
-
-void Formatter::reset()
-{
-}
 } // namespace libtest
 } // namespace libtest

+ 48 - 22
libtest/formatter.hpp

@@ -43,43 +43,69 @@ namespace libtest { class Framework; }
 
 
 namespace libtest {
 namespace libtest {
 
 
-class TestCase;
-typedef std::vector<libtest::TestCase*> TestCases;
+class Collection;
+
+class Formatter;
+typedef std::vector<libtest::Formatter*> Formatters;
 
 
 class Formatter {
 class Formatter {
 public:
 public:
-  Formatter(const std::string& frame_name, const std::string& arg);
+  Formatter(const Framework* frame_, std::ostream&);
 
 
-  ~Formatter();
+  virtual ~Formatter() {}
 
 
-  void skipped();
+  virtual void plan(const libtest::Collection*) {}
+  virtual void report(const libtest::TestCase*, size_t) const {}
+  virtual void complete() {}
 
 
-  void failed();
+protected:
+  const std::string& name() const;
 
 
-  void success(const libtest::Timer&);
+#if 0
+  static void xml(libtest::Framework&, std::ofstream&);
+  static void tap(libtest::Framework&, std::ofstream&);
+#endif
 
 
-  void push_testcase(const std::string&);
+protected:
+  const Framework* _frame;
 
 
-  const std::string& name() const
-  {
-    return _suite_name;
-  }
+protected:
+  std::ostream& _output;
+};
 
 
-  TestCases& testcases()
-  {
-    return _testcases;
-  }
+class Junit : public Formatter
+{
+public:
+  Junit(const Framework*, std::ostream&);
+  ~Junit();
 
 
-  static void xml(libtest::Framework&, std::ofstream&);
+  void report(const libtest::TestCase*, size_t position) const;
 
 
-private:
-  void reset();
+  void plan(const libtest::Collection*);
+  void complete();
+};
+
+class TAP : public Formatter
+{
+public:
+  TAP(const Framework*, std::ostream&);
+  ~TAP();
+
+  void plan(const libtest::Collection*);
+  void report(const libtest::TestCase*, size_t position) const;
+};
+
+class Legacy : public Formatter
+{
+public:
+  Legacy(const Framework*, std::ostream&);
+  ~Legacy();
 
 
-  TestCase* current();
+  void plan(const libtest::Collection*);
+  void report(const libtest::TestCase*, size_t position) const;
 
 
 private:
 private:
-  std::string _suite_name;
-  TestCases _testcases;
+  const libtest::Collection* _collection;
 };
 };
 
 
 } // namespace libtest
 } // namespace libtest

+ 30 - 52
libtest/framework.cc

@@ -125,6 +125,33 @@ Framework::Framework(libtest::SignalThread& signal_,
   _name(name_)
   _name(name_)
 {
 {
   get_world(this);
   get_world(this);
+
+  {
+    std::string file_name;
+    if (getenv("WORKSPACE"))
+    {
+      file_name.append(getenv("WORKSPACE"));
+      file_name.append("/");
+    }
+    file_name.append(name());
+    file_name.append(".xml");
+    xml_file.open(file_name.c_str(), std::ios::trunc);
+    _formatter.push_back(new libtest::Junit(this, xml_file));
+  }
+
+  {
+    std::string file_name;
+    if (getenv("WORKSPACE"))
+    {
+      file_name.append(getenv("WORKSPACE"));
+      file_name.append("/");
+    }
+    file_name.append(name());
+    file_name.append(".tap");
+    tap_file.open(file_name.c_str(), std::ios::trunc);
+    _formatter.push_back(new libtest::TAP(this, tap_file));
+  }
+  _formatter.push_back(new libtest::Legacy(this, std::cout));
 }
 }
 
 
 void Framework::collections(collection_st collections_[])
 void Framework::collections(collection_st collections_[])
@@ -148,6 +175,9 @@ Framework::~Framework()
 
 
   std::for_each(_collection.begin(), _collection.end(), DeleteFromVector());
   std::for_each(_collection.begin(), _collection.end(), DeleteFromVector());
   _collection.clear();
   _collection.clear();
+
+  std::for_each(_formatter.begin(), _formatter.end(), DeleteFromVector());
+  _formatter.clear();
 }
 }
 
 
 bool Framework::match(const char* arg)
 bool Framework::match(const char* arg)
@@ -232,58 +262,6 @@ void Framework::exec()
   }
   }
 }
 }
 
 
-uint32_t Framework::sum_total()
-{
-  uint32_t count= 0;
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end();
-       ++iter)
-  {
-    count+= (*iter)->total();
-  }
-
-  return count;
-}
-
-uint32_t Framework::sum_success()
-{
-  uint32_t count= 0;
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end();
-       ++iter)
-  {
-    count+= (*iter)->success();
-  }
-
-  return count;
-}
-
-uint32_t Framework::sum_skipped()
-{
-  uint32_t count= 0;
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end();
-       ++iter)
-  {
-    count+= (*iter)->skipped();
-  }
-
-  return count;
-}
-
-uint32_t Framework::sum_failed()
-{
-  uint32_t count= 0;
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end();
-       ++iter)
-  {
-    count+= (*iter)->failed();
-  }
-
-  return count;
-}
-
 libtest::Runner *Framework::runner()
 libtest::Runner *Framework::runner()
 {
 {
   if (_runner == NULL)
   if (_runner == NULL)

+ 26 - 20
libtest/framework.h

@@ -2,7 +2,7 @@
  *
  *
  *  Data Differential YATL (i.e. libtest)  library
  *  Data Differential YATL (i.e. libtest)  library
  *
  *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
  *
  *
  *  Redistribution and use in source and binary forms, with or without
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that the following conditions are
  *  modification, are permitted provided that the following conditions are
@@ -45,6 +45,7 @@
 */
 */
 
 
 #include <vector>
 #include <vector>
+#include <fstream>
 
 
 namespace { class Collection; }
 namespace { class Collection; }
 typedef std::vector<libtest::Collection*> Suites;
 typedef std::vector<libtest::Collection*> Suites;
@@ -126,47 +127,48 @@ public:
     return _signal;
     return _signal;
   }
   }
 
 
-  uint32_t sum_total();
-  uint32_t sum_success();
-  uint32_t sum_skipped();
-  uint32_t sum_failed();
-
   size_t size() 
   size_t size() 
   {
   {
     return _collection.size();
     return _collection.size();
   }
   }
 
 
-  uint32_t total() const
+  Suites& suites()
+  {
+    return _collection;
+  }
+
+  libtest::Formatters& formatter()
+  {
+    return _formatter;
+  }
+
+  size_t total() const
   {
   {
     return _total;
     return _total;
   }
   }
 
 
-  uint32_t success() const
+  size_t success() const
   {
   {
     return _success;
     return _success;
   }
   }
 
 
-  uint32_t skipped() const
+  size_t skipped() const
   {
   {
     return _skipped;
     return _skipped;
   }
   }
 
 
-  uint32_t failed() const
+  size_t failed() const
   {
   {
     return _failed;
     return _failed;
   }
   }
 
 
-  Suites& suites()
-  {
-    return _collection;
-  }
-
 private:
 private:
-  uint32_t _total;
-  uint32_t _success;
-  uint32_t _skipped;
-  uint32_t _failed;
-  
+  // Sums
+  size_t _total;
+  size_t _success;
+  size_t _skipped;
+  size_t _failed;
+
   /* These methods are called outside of any collection call. */
   /* These methods are called outside of any collection call. */
   test_callback_create_fn *_create;
   test_callback_create_fn *_create;
   test_callback_destroy_fn *_destroy;
   test_callback_destroy_fn *_destroy;
@@ -195,6 +197,10 @@ private:
 private:
 private:
   Framework( const Framework& );
   Framework( const Framework& );
   const Framework& operator=( const Framework& );
   const Framework& operator=( const Framework& );
+  libtest::Formatters _formatter;
+  std::ofstream xml_file;
+  std::ofstream tap_file;
+
 };
 };
 
 
 } // namespace libtest
 } // namespace libtest

+ 28 - 29
libtest/main.cc

@@ -60,25 +60,6 @@
 
 
 using namespace libtest;
 using namespace libtest;
 
 
-static void stats_print(libtest::Framework *frame)
-{
-  if (frame->failed() == 0 and frame->success() == 0)
-  {
-    return;
-  }
-
-  Outn();
-  Out << "Collections\t\t\t\t\t" << frame->total();
-  Out << "\tFailed\t\t\t\t\t" << frame->failed();
-  Out << "\tSkipped\t\t\t\t\t" << frame->skipped();
-  Out << "\tSucceeded\t\t\t\t" << frame->success();
-  Outn();
-  Out << "Tests\t\t\t\t\t" << frame->sum_total();
-  Out << "\tFailed\t\t\t\t" << frame->sum_failed();
-  Out << "\tSkipped\t\t\t\t" << frame->sum_skipped();
-  Out << "\tSucceeded\t\t\t" << frame->sum_success();
-}
-
 #include <getopt.h>
 #include <getopt.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
@@ -380,19 +361,37 @@ int main(int argc, char *argv[], char* environ_[])
         Out << "All tests completed successfully.";
         Out << "All tests completed successfully.";
       }
       }
 
 
-      stats_print(frame.get());
+#if 0
+      {
+        std::ofstream xml_file;
+        std::string file_name;
+        if (getenv("WORKSPACE"))
+        {
+          file_name.append(getenv("WORKSPACE"));
+          file_name.append("/");
+        }
+        file_name.append(frame->name());
+        file_name.append(".xml");
+        xml_file.open(file_name.c_str(), std::ios::trunc);
+        libtest::Formatter::xml(*frame, xml_file);
+      }
+#endif
 
 
-      std::ofstream xml_file;
-      std::string file_name;
-      if (getenv("WORKSPACE"))
+#if 0
       {
       {
-        file_name.append(getenv("WORKSPACE"));
-        file_name.append("/");
+        std::ofstream tap_file;
+        std::string file_name;
+        if (getenv("WORKSPACE"))
+        {
+          file_name.append(getenv("WORKSPACE"));
+          file_name.append("/");
+        }
+        file_name.append(frame->name());
+        file_name.append(".tap");
+        tap_file.open(file_name.c_str(), std::ios::trunc);
+        libtest::Formatter::tap(*frame, tap_file);
       }
       }
-      file_name.append(frame->name());
-      file_name.append(".xml");
-      xml_file.open(file_name.c_str(), std::ios::trunc);
-      libtest::Formatter::xml(*frame, xml_file);
+#endif
 
 
       Outn(); // Generate a blank to break up the messages if make check/test has been run
       Outn(); // Generate a blank to break up the messages if make check/test has been run
     } while (exit_code == EXIT_SUCCESS and --opt_repeat);
     } while (exit_code == EXIT_SUCCESS and --opt_repeat);

+ 80 - 0
libtest/test.h

@@ -51,6 +51,86 @@ struct test_st {
   test_callback_fn *test_fn;
   test_callback_fn *test_fn;
 };
 };
 
 
+namespace libtest {
+
+class TestCase;
+typedef std::vector<libtest::TestCase*> TestCases;
+
+class TestCase {
+public:
+  TestCase(const struct test_st* test_):
+    _result(TEST_FAILURE)
+  {
+    _test.name= test_->name;
+    _test.requires_flush= test_->requires_flush;
+    _test.test_fn= test_->test_fn;
+  }
+
+  const char* name() const
+  {
+    return _test.name;
+  }
+
+  test_return_t result() const
+  {
+    return _result;
+  }
+
+  void result(test_return_t result_)
+  {
+    _result= result_;
+  }
+
+  void result(test_return_t result_, const libtest::Timer& timer_)
+  {
+    _result= result_;
+    _timer= timer_;
+  }
+
+  const libtest::Timer& timer() const
+  {
+    return _timer;
+  }
+
+  void timer(libtest::Timer& timer_)
+  {
+    _timer= timer_;
+  }
+
+  void skipped()
+  {
+    _result= TEST_SKIPPED;
+  }
+
+  void failed()
+  {
+    _result= TEST_FAILURE;
+  }
+
+  void success(const libtest::Timer& timer_)
+  {
+    _result= TEST_SUCCESS;
+    _timer= timer_;
+  }
+
+
+  const struct test_st* test() const
+  {
+    return &_test;
+  }
+
+  bool requires_flush() const
+  {
+    return _test.requires_flush;
+  }
+
+private:
+  struct test_st _test;
+  test_return_t _result;
+  libtest::Timer _timer;
+};
+} // namespace libtest
+
 #define test_assert_errno(A) \
 #define test_assert_errno(A) \
 do \
 do \
 { \
 { \