/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2010-2012 University of Bonn. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    MoleCuilder is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoleCuilder.  If not, see .
 */
/*
 * DiscreteValueTest.cpp
 *
 *  Created on: Sep 28, 2011
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "DiscreteValueTest.hpp"
#include 
#include 
#include 
#include "Parameters/ParameterExceptions.hpp"
#include "Parameters/Value.hpp"
#ifdef HAVE_TESTRUNNER
#include "UnitTestMain.hpp"
#endif /*HAVE_TESTRUNNER*/
using namespace std;
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION( DiscreteValueTest );
void DiscreteValueTest::setUp()
{
  // failing asserts should be thrown
  ASSERT_DO(Assert::Throw);
  for (int i=1; i<=3;++i) {
    ValidValues.push_back(i);
  }
}
void DiscreteValueTest::tearDown()
{
  ValidValues.clear();
}
/************************************ tests ***********************************/
/** Unit test for findIndexOfValue.
 *
 */
void DiscreteValueTest::findIndexOfValueTest()
{
  // create instance
  Value test(ValidValues);
  // check valid values indices
  CPPUNIT_ASSERT_EQUAL((size_t)0, dynamic_cast &>(test.getValidator()).findIndexOfValue(1));
  CPPUNIT_ASSERT_EQUAL((size_t)1, dynamic_cast &>(test.getValidator()).findIndexOfValue(2));
  CPPUNIT_ASSERT_EQUAL((size_t)2, dynamic_cast &>(test.getValidator()).findIndexOfValue(3));
  // check invalid ones
  for (int i=-10; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL((size_t)-1, dynamic_cast &>(test.getValidator()).findIndexOfValue(i));
  for (int i=4; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL((size_t)-1, dynamic_cast &>(test.getValidator()).findIndexOfValue(i));
}
/** Unit test for isValidValue.
 *
 */
void DiscreteValueTest::isValidAsStringTest()
{
  // create instance
  Value test(ValidValues);
  // checking valid values
  for (int i=1; i<=3;++i)
    CPPUNIT_ASSERT_EQUAL(true, test.isValidAsString(toString(i)));
  // checking invalid values
  for (int i=-10; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL(false, test.isValidAsString(toString(i)));
  for (int i=4; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL(false, test.isValidAsString(toString(i)));
}
/** Unit test for isValid.
 *
 */
void DiscreteValueTest::isValidTest()
{
  // create instance
  Value test(ValidValues);
  // checking valid values
  for (int i=1; i<=3;++i)
    CPPUNIT_ASSERT_EQUAL(true, test.isValid(i));
  // checking invalid values
  for (int i=-10; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL(false, test.isValid(i));
  for (int i=4; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL(false, test.isValid(i));
}
/** Unit test for appendValidValue.
 *
 */
void DiscreteValueTest::appendValidValueTest()
{
  // create instance
  Value test(ValidValues);
  // adding values 4,5,6
  for (int i=4; i<=6;++i) {
    CPPUNIT_ASSERT_EQUAL(false, test.isValid(i));
    dynamic_cast &>(test.getValidator()).appendValidValue(i);
    CPPUNIT_ASSERT_EQUAL(true, test.isValid(i));
  }
  // adding same value, throws assertion
  const size_t size_before = dynamic_cast &>(test.getValidator()).getValidValues().size();
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  for (int i=1; i<=6;++i)
    CPPUNIT_ASSERT_THROW(dynamic_cast &>(test.getValidator()).appendValidValue(i), ParameterValidatorException);
  CPPUNIT_ASSERT_EQUAL( size_before, dynamic_cast &>(test.getValidator()).getValidValues().size() );
  // checking valid values
  for (int i=1; i<=6;++i)
    CPPUNIT_ASSERT_EQUAL(true, test.isValid(i));
  // checking invalid values
  for (int i=-10; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL(false, test.isValid(i));
  // checking invalid values
  for (int i=7; i<=10;++i)
    CPPUNIT_ASSERT_EQUAL(false, test.isValid(i));
}
/** Unit test for setters and getters.
 *
 */
void DiscreteValueTest::settergetterTest()
{
  // create instance
  Value test(ValidValues);
  // unset calling of get, throws
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.get(), ParameterValueException);
  // setting invalid and getting it, throws
  test.set(4);
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.get(), ParameterValueException);
  test.set(0);
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.get(), ParameterValueException);
  // checking all valid ones
  for (int i=1; i<=3;++i) {
    test.set(i);
    CPPUNIT_ASSERT_EQUAL(i, test.get());
  }
}
/** Unit test for setValue and getValue.
 *
 */
void DiscreteValueTest::settergetterAsStringTest()
{
  // create instance
  Value test(ValidValues);
  // unset calling of get, throws
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.getAsString(), ParameterValueException);
  // setting invalid and getting it, throws
  test.setAsString(toString(4));
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.getAsString(), ParameterValueException);
  test.setAsString(toString(0));
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.getAsString(), ParameterValueException);
  // checking all valid ones
  for (int i=1; i<=3;++i) {
    test.setAsString(toString(i));
    CPPUNIT_ASSERT_EQUAL(toString(i), test.getAsString());
  }
}
/** Unit test for comparator.
 *
 */
void DiscreteValueTest::comparatorTest()
{
  {
    // create instance
    Value test(ValidValues);
    Value instance(ValidValues);
    test.set(1);
    instance.set(1);
    // same value, same range
    {
      CPPUNIT_ASSERT(test == instance);
    }
    // different value, same range
    {
      const int oldvalue = instance.get();
      instance.set(2);
      CPPUNIT_ASSERT(test != instance);
      instance.set(oldvalue);
    }
  }
  {
    Value test(ValidValues);
    Value instance(ValidValues);
    dynamic_cast &>(instance.getValidator()).appendValidValue(4);
    test.set(1);
    instance.set(1);
    // same value, same range
    {
      CPPUNIT_ASSERT(test != instance);
    }
    // different value, same range
    {
      const int oldvalue = instance.get();
      instance.set(2);
      CPPUNIT_ASSERT(test != instance);
      instance.set(oldvalue);
    }
  }
}