/*
 * 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 .
 */
/*
 * AtomsCalculationUnitTest.cpp
 *
 *  Created on: Feb 19, 2010
 *      Author: crueger
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "AtomsCalculationUnitTest.hpp"
#include 
#include 
#include 
#include 
#include 
#include "Descriptors/AtomDescriptor.hpp"
#include "Descriptors/AtomIdDescriptor.hpp"
#include "Actions/AtomsCalculation.hpp"
#include "Actions/AtomsCalculation_impl.hpp"
#include "Actions/ActionRegistry.hpp"
#include "Actions/ActionTrait.hpp"
#include "World.hpp"
#include "World_calculations.hpp"
#include "Atom/atom.hpp"
using namespace MoleCuilder;
#ifdef HAVE_TESTRUNNER
#include "UnitTestMain.hpp"
#endif /*HAVE_TESTRUNNER*/
// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION( AtomsCalculationTest );
// set up and tear down
void AtomsCalculationTest::setUp(){
  World::getInstance();
  for(int i=0;igetId();
  }
}
void AtomsCalculationTest::tearDown(){
  World::purgeInstance();
  ActionRegistry::purgeInstance();
}
// some helper functions
static bool hasAllIds(std::vector atoms,atomId_t ids[ATOM_COUNT], std::set excluded = std::set()){
  for(int i=0;i::iterator iter;
      bool res=false;
      for(iter=atoms.begin();iter!=atoms.end();++iter){
        res |= (*iter) == id;
      }
      if(!res) {
        cout << "Atom " << id << " missing in returned list" << endl;
        return false;
      }
    }
  }
  return true;
}
static bool hasNoDuplicates(std::vector ids){
  std::set found;
  std::vector::iterator iter;
  for(iter=ids.begin();iter!=ids.end();++iter){
    int id = (*iter);
    if(found.count(id))
      return false;
    found.insert(id);
  }
  return true;
}
void AtomsCalculationTest::testCalculateSimple(){
  ActionTrait FooTrait("FOO");
  AtomsCalculation *calc = World::getInstance().calcOnAtoms(boost::bind(&atom::getId,_1),FooTrait,AllAtoms());
  std::vector allIds = (*calc)();
  CPPUNIT_ASSERT(hasAllIds(allIds,atomIds));
  CPPUNIT_ASSERT(hasNoDuplicates(allIds));
}
void AtomsCalculationTest::testCalculateExcluded(){
  ActionTrait FooTrait("FOO");
  atomId_t excluded = atomIds[ATOM_COUNT/2];
  AtomsCalculation *calc = World::getInstance().calcOnAtoms(boost::bind(&atom::getId,_1),FooTrait,AllAtoms() && !AtomById(excluded));
  std::vector allIds = (*calc)();
  std::set excluded_set;
  excluded_set.insert(excluded);
  CPPUNIT_ASSERT(hasAllIds(allIds,atomIds,excluded_set));
  CPPUNIT_ASSERT(hasNoDuplicates(allIds));
  CPPUNIT_ASSERT_EQUAL((size_t)(ATOM_COUNT-1),allIds.size());
}