#include "cppunit/extensions/HelperMacros.h"
#include "DataFormats/Common/interface/AtomicPtrCache.h"

#include <vector>

class testAtomicPtrCache : public CppUnit::TestFixture {
  CPPUNIT_TEST_SUITE(testAtomicPtrCache);
  CPPUNIT_TEST(check);
  CPPUNIT_TEST_SUITE_END();
public:
  void setUp() {}
  void tearDown() {}
  void check();
};

CPPUNIT_TEST_SUITE_REGISTRATION(testAtomicPtrCache);

typedef std::vector<int> Vec;
void
testAtomicPtrCache::check()
{
  using namespace edm;

  const Vec values = {1,2,3};
  
  {
    AtomicPtrCache<Vec> cache;
    CPPUNIT_ASSERT(false == cache.isSet());
    CPPUNIT_ASSERT(nullptr == cache.operator->());
    CPPUNIT_ASSERT(nullptr == cache.load());

    cache.set(std::make_unique<Vec>(values));
    CPPUNIT_ASSERT(true == cache.isSet());
    CPPUNIT_ASSERT(cache->size() == values.size());
    CPPUNIT_ASSERT((*cache).size() == values.size());
    CPPUNIT_ASSERT(cache.load()->size() == values.size());

    {
      //test const functions
      const AtomicPtrCache<Vec> & constCache = cache;

      CPPUNIT_ASSERT(true == constCache.isSet());
      CPPUNIT_ASSERT(constCache->size() == values.size());
      CPPUNIT_ASSERT((*constCache).size() == values.size());
      CPPUNIT_ASSERT(constCache.load()->size() == values.size());
    }
    
    cache.reset();
    CPPUNIT_ASSERT(false == cache.isSet());
  }
  
  {
    AtomicPtrCache<Vec> cache{new Vec{values}};
    CPPUNIT_ASSERT(true == cache.isSet());
    CPPUNIT_ASSERT(cache->size() == values.size());
  }
  
  {
    AtomicPtrCache<Vec> cache;
    CPPUNIT_ASSERT(false == cache.isSet());

    AtomicPtrCache<Vec> cache2{new Vec{values}};
    
    cache = cache2;
    
    CPPUNIT_ASSERT(true == cache.isSet());
    CPPUNIT_ASSERT(cache->size() == values.size());
    CPPUNIT_ASSERT(true == cache2.isSet());
    CPPUNIT_ASSERT(cache2->size() == values.size());
    CPPUNIT_ASSERT(cache.load() != cache2.load());
  }

  {
    AtomicPtrCache<Vec> cache2{new Vec{values}};
    AtomicPtrCache<Vec> cache{ cache2 };
    CPPUNIT_ASSERT(true == cache.isSet());
    CPPUNIT_ASSERT(cache->size() == values.size());
    CPPUNIT_ASSERT(true == cache2.isSet());
    CPPUNIT_ASSERT(cache2->size() == values.size());
    CPPUNIT_ASSERT(cache.load() != cache2.load());
  }

}
