/*
* Copyright (c) 2003-2014 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/
// suite.cpp

#include "suite.h"
#include <iostream>
#include <stdexcept>
#include <cassert>
using namespace std;

class TestSuiteError : public logic_error
{
public:
  TestSuiteError(const string& s = "")
    : logic_error(s)
  {}
};

void Suite::addTest(Test* t) throw(TestSuiteError)
{
  // Make sure test has a stream:
  if (t == 0)
    throw TestSuiteError("Null test in Suite::addTest");
  else if (m_osptr != 0 && t->getStream() == 0)
    t->setStream(m_osptr);

  m_tests.push_back(t);
  t->reset();
}

void Suite::addSuite(const Suite& s) throw(TestSuiteError)
{
  for (size_t i = 0; i < s.m_tests.size(); ++i)
    addTest(s.m_tests[i]);
}

void Suite::free()
{
  // This is not a destructor because tests
  // don't have to be on the heap.
  for (size_t i = 0; i < m_tests.size(); ++i)
  {
    delete m_tests[i];
    m_tests[i] = 0;
  }
}

void Suite::run()
{
  reset();
  for (size_t i = 0; i < m_tests.size(); ++i)
  {
    assert(m_tests[i]);
    m_tests[i]->run();
  }
}

long Suite::report() const
{
  if (m_osptr)
  {
    long totFail = 0;
    *m_osptr << "Suite \"" << m_name << "\"\n=======";
    size_t i;
    for (i = 0; i < m_name.size(); ++i)
      *m_osptr << '=';
    *m_osptr << "=\n";

    for (i = 0; i < m_tests.size(); ++i)
    {
      assert(m_tests[i]);
      totFail += m_tests[i]->report();
    }

    *m_osptr << "=======";
    for (i = 0; i < m_name.size(); ++i)
      *m_osptr << '=';
    *m_osptr << "=\n";
    return totFail;
  }
  else
    return getNumFailed();
}

long Suite::getNumPassed() const
{
  long totPass = 0;
  for (size_t i = 0; i < m_tests.size(); ++i)
  {
    assert(m_tests[i]);
    totPass += m_tests[i]->getNumPassed();
  }
  return totPass;
}

long Suite::getNumFailed() const
{
  long totFail = 0;
  for (size_t i = 0; i < m_tests.size(); ++i)
  {
    assert(m_tests[i]);
    totFail += m_tests[i]->getNumFailed();
  }
  return totFail;
}

void Suite::reset()
{
  for (size_t i = 0; i < m_tests.size(); ++i)
  {
    assert(m_tests[i]);
    m_tests[i]->reset();
  }
}
