/*
 * 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 .
 */
/*
 * ContinuousValueTest.cpp
 *
 *  Created on: Sep 29, 2011
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "ContinuousValueTest.hpp"
#include 
#include 
#include 
#include "Parameters/Value.hpp"
#ifdef HAVE_TESTRUNNER
#include "UnitTestMain.hpp"
#endif /*HAVE_TESTRUNNER*/
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION( ContinuousValueTest );
void ContinuousValueTest::setUp()
{
  // failing asserts should be thrown
  ASSERT_DO(Assert::Throw);
  ValidIntRange = new range(1,4);
  ValidVectorRange = new range(Vector(0,1,2), Vector(10,11,12));
}
void ContinuousValueTest::tearDown()
{
  delete ValidIntRange;
  delete ValidVectorRange;
}
/************************************ tests ***********************************/
/** Unit test for isValid.
 *
 */
void ContinuousValueTest::isValidIntAsStringTest()
{
  // create instance
  Value test(*ValidIntRange);
  // checking valid values
  for (int i=1; i<=4;++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=5; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL(false, test.isValidAsString(toString(i)));
}
/** Unit test for isValid.
 *
 */
void ContinuousValueTest::isValidIntTest()
{
  // create instance
  Value test(*ValidIntRange);
  // checking valid values
  for (int i=1; i<=4;++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=5; i<=0;++i)
    CPPUNIT_ASSERT_EQUAL(false, test.isValid(i));
}
/** Unit test for setting/getting valid range.
 *
 */
void ContinuousValueTest::setgetValidIntRangeTest()
{
  {
    // create instance
    Value test(*ValidIntRange);
    // extending range and checking
    for (int i=5; i<=6;++i)
      CPPUNIT_ASSERT_EQUAL(false, test.isValid(i));
    test.setValidRange(range(1,6));
    for (int i=5; i<=6;++i)
      CPPUNIT_ASSERT_EQUAL(true, test.isValid(i));
  }
  {
    // create instance
    Value test(*ValidIntRange);
    // lowering range with set value
    test.set(4);
    CPPUNIT_ASSERT_EQUAL(true, test.ValueSet);
    std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
    CPPUNIT_ASSERT_THROW(test.setValidRange(range(1,3)), ParameterValueException);
    // no value is not set
    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);
    // value gets invalidated in either case
    CPPUNIT_ASSERT_EQUAL(false, test.ValueSet);
  }
}
/** Unit test for setValue and getValue.
 *
 */
void ContinuousValueTest::settergetterIntAsStringTest()
{
  // unset calling of get, throws ParameterValueException
  {
    Value test(*ValidIntRange);
    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 ParameterValueException
  {
    Value test(*ValidIntRange);
    test.setAsString(toString(5));
    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
  {
    Value test(*ValidIntRange);
    CPPUNIT_ASSERT_EQUAL(false, test.ValueSet);
    for (int i=1; i<=4;++i) {
      test.setAsString(toString(i));
      CPPUNIT_ASSERT_EQUAL(true, test.ValueSet);
      CPPUNIT_ASSERT_EQUAL(toString(i), test.getAsString());
    }
  }
}
/** Unit test for setters and getters.
 *
 */
void ContinuousValueTest::settergetterIntTest()
{
  // create instance
  Value test(*ValidIntRange);
  // unset calling of get, throws ParameterValueException
  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 ParameterValueException
  test.set(5);
  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<=4;++i) {
    test.set(i);
    CPPUNIT_ASSERT_EQUAL(i, test.get());
  }
}
/** Unit test for comparator.
 *
 */
void ContinuousValueTest::comparatorIntTest()
{
  {
    // create instance
    Value test(*ValidIntRange);
    Value instance(*ValidIntRange);
    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(*ValidIntRange);
    range OtherValidIntRange(1,5);
    Value instance(OtherValidIntRange);
    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);
    }
  }
}
/***************************** vector tests ***********************************/
/** Unit test for isValid.
 *
 */
void ContinuousValueTest::isValidVectorAsStringTest()
{
  // create instance
  /*ContinuousValue test(*ValidVectorRange);
  // checking valid values
  CPPUNIT_ASSERT_EQUAL(true, test.isValidValue(Vector(0,1,2)));
  CPPUNIT_ASSERT_EQUAL(true, test.isValidValue(Vector(9.9,10.9,11.9)));
  CPPUNIT_ASSERT_EQUAL(true, test.isValidValue(Vector(5,5,5)));
  // checking invalid values
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(-0.1,0.9,1.9)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(10.1,11.1,12.1)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(5,5,-1)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(5,-1,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(-1,5,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(5,5,20)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(5,20,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(20,5,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(0,0,0)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(5,-1,-1)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(-1,5,-1)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(-1,-1,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(5,20,20)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(20,5,20)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValidValue(Vector(20,20,5)));*/
}
/** Unit test for isValid.
 *
 */
void ContinuousValueTest::isValidVectorTest()
{
  // create instance
  Value test(*ValidVectorRange);
  // checking valid values
  CPPUNIT_ASSERT_EQUAL(true, test.isValid(Vector(0,1,2)));
  CPPUNIT_ASSERT_EQUAL(true, test.isValid(Vector(9.9,10.9,11.9)));
  CPPUNIT_ASSERT_EQUAL(true, test.isValid(Vector(5,5,5)));
  // checking invalid values
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(-0.1,0.9,1.9)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(10.1,11.1,12.1)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(5,5,-1)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(5,-1,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(-1,5,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(5,5,20)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(5,20,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(20,5,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(0,0,0)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(5,-1,-1)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(-1,5,-1)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(-1,-1,5)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(5,20,20)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(20,5,20)));
  CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(20,20,5)));
}
/** Unit test for setting/getting valid range.
 *
 */
void ContinuousValueTest::setgetValidVectorRangeTest()
{
  {
    // create instance
    Value test(*ValidVectorRange);
    // extending range and checking
    for (int i=15; i<=16;++i)
      CPPUNIT_ASSERT_EQUAL(false, test.isValid(Vector(i,5,5)));
    test.setValidRange(range(Vector(0,1,2),Vector(20,11,12)));
    for (int i=15; i<=16;++i)
      CPPUNIT_ASSERT_EQUAL(true, test.isValid(Vector(i,5,5)));
  }
  {
    // create instance
    Value test(*ValidVectorRange);
    // lowering range with set value
    test.set(Vector(4,4,4));
    CPPUNIT_ASSERT_EQUAL(true, test.ValueSet);
    std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
    CPPUNIT_ASSERT_THROW(test.setValidRange(range(Vector(1,1,1),Vector(3,3,3))), ParameterValueException);
    // no value is not set
    std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
    CPPUNIT_ASSERT_THROW(test.get(), ParameterException);
    // value gets invalidated in either case
    CPPUNIT_ASSERT_EQUAL(false, test.ValueSet);
  }
}
/** Unit test for setValue and getValue.
 *
 */
void ContinuousValueTest::settergetterVectorAsStringTest()
{
  // create instance
  /*Value test(*ValidVectorRange);
  // unset calling of get, throws
#ifndef NDEBUG
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.getValue(), Assert::AssertionFailure);
#endif
  // setting invalid, throws
#ifndef NDEBUG
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.setValue(Vector(5,0,0)), Assert::AssertionFailure);
#endif
#ifndef NDEBUG
  std::cout << "The following Assert failures are intended and do not indicate a failure of the test." << std::endl;
  CPPUNIT_ASSERT_THROW(test.setValue(Vector(5,20,5)), Assert::AssertionFailure);
#endif
  CPPUNIT_ASSERT_EQUAL(false, test.ValueSet);
  // checking some valid ones
  for (int i=1; i<=4;++i) {
    Vector v(i,5,5);
    test.setValue(v);
    CPPUNIT_ASSERT_EQUAL(true, test.ValueSet);
    CPPUNIT_ASSERT_EQUAL(v, test.getValue());
  }*/
}
/** Unit test for setters and getters.
 *
 */
void ContinuousValueTest::settergetterVectorTest()
{
  // unset calling of get, throws
  {
    Value test(*ValidVectorRange);
    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
  {
    Value test(*ValidVectorRange);
    test.set(Vector(5,0,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);
    test.set(Vector(5,20,5));
    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 some valid ones
  {
    Value test(*ValidVectorRange);
    CPPUNIT_ASSERT_EQUAL(false, test.ValueSet);
    for (int i=1; i<=4;++i) {
      Vector v(i,5,5);
      test.set(v);
      CPPUNIT_ASSERT_EQUAL(true, test.ValueSet);
      CPPUNIT_ASSERT_EQUAL(v, test.get());
    }
  }
}
/** Unit test for comparator.
 *
 */
void ContinuousValueTest::comparatorVectorTest()
{
  {
    // create instance
    Value test(*ValidVectorRange);
    Value instance(*ValidVectorRange);
    test.set(Vector(5,6,7));
    instance.set(Vector(5,6,7));
    // same value, same range
    {
      CPPUNIT_ASSERT(test == instance);
    }
    // different value, same range
    {
      const Vector oldvalue = instance.get();
      instance.set(Vector(2,3,4));
      CPPUNIT_ASSERT(test != instance);
      instance.set(oldvalue);
    }
  }
  {
    Value test(*ValidVectorRange);
    range OtherValidVectorRange(Vector(0,1,2), Vector(20,21,22));
    Value instance(OtherValidVectorRange);
    test.set(Vector(1,2,3));
    instance.set(Vector(1,2,3));
    // same value, same range
    {
      CPPUNIT_ASSERT(test != instance);
    }
    // different value, same range
    {
      const Vector oldvalue = instance.get();
      instance.set(Vector(2,3,4));
      CPPUNIT_ASSERT(test != instance);
      instance.set(oldvalue);
    }
  }
}