<commit_before>// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "ObjectPoolTest.hpp"
#include "TestFixtures/SimpleThreaded.hpp"
#include <autowiring/ObjectPool.h>

class PooledObject {
};

TEST_F(ObjectPoolTest, VerifyOutstandingLimit) {
  ObjectPool<PooledObject> pool(2);

  std::shared_ptr<PooledObject> obj1, obj2, obj3;

  // Try to grab some objects out of the pool:
  pool(obj1);
  pool(obj2);

  // Verify that grabbing a third object fails:
  pool(obj3);
  EXPECT_TRUE(obj3 == nullptr) << "Object pool issued more objects than it was authorized to issue";
}

class LifeCycle {
  //Lock ensures that status checks are atomic.
  //This does not prevent asynchronous calls.
  std::mutex lock;
  enum LifeStage {
    construct,
    pooled,
    issued,
    destruct
  } stage;

public:
  LifeCycle() : stage(construct) {
    std::lock_guard<std::mutex> guard(lock);
    if (stage == construct)
      stage = pooled;
    else
      throw std::runtime_error("Initialization interrupted");
  }

  ~LifeCycle() {
    lock.lock();
    if (stage != pooled)
      throw std::runtime_error("Destructor called before Finalize");
    lock.unlock();
  }

  static ObjectPool<LifeCycle>* NewObjectPool(size_t limit = ~0, size_t maxPooled = ~0) {
    return new ObjectPool<LifeCycle>(limit, maxPooled,
      [] { return new LifeCycle(); },
      [] (LifeCycle& life) { life.Initialize(); },
      [] (LifeCycle& life) { life.Finalize(); }
    );
  }

protected:
  void Initialize() {
    std::lock_guard<std::mutex> guard(lock);
    if (stage != pooled)
      throw std::runtime_error("Initialize called on object not pooled");
    stage = issued;
  }

  void Finalize() {
    std::lock_guard<std::mutex> guard(lock);
    if (stage != issued)
      throw std::runtime_error("Finalize called on object not issued");
    stage = pooled;
  }
};

TEST_F(ObjectPoolTest, LifeCycleTestLimitOne) {
  std::shared_ptr<ObjectPool<LifeCycle>> pool(LifeCycle::NewObjectPool(~1, ~1));
  std::shared_ptr<LifeCycle> obj;

  // Create & Issue
  try {
    (*pool)(obj);
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }

  // Return to Pool
  try {
    obj.reset();
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }

  // Issue from Pool
  try {
    (*pool)(obj);
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }

  // Return & Destroy
  try {
    pool.reset();
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }
}

TEST_F(ObjectPoolTest, VerifyAsynchronousUsage) {
  AutoCreateContext ctxt;
  CurrentContextPusher pshr(ctxt);

  AutoRequired<SimpleThreadedT<PooledObject>> obj;<commit_msg>Modifying test to show allocation in pool and deallocation after destruction of pool.<commit_after>// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "ObjectPoolTest.hpp"
#include "TestFixtures/SimpleThreaded.hpp"
#include <autowiring/ObjectPool.h>

class PooledObject {
};

TEST_F(ObjectPoolTest, VerifyOutstandingLimit) {
  ObjectPool<PooledObject> pool(2);

  std::shared_ptr<PooledObject> obj1, obj2, obj3;

  // Try to grab some objects out of the pool:
  pool(obj1);
  pool(obj2);

  // Verify that grabbing a third object fails:
  pool(obj3);
  EXPECT_TRUE(obj3 == nullptr) << "Object pool issued more objects than it was authorized to issue";
}

class LifeCycle {
  //Lock ensures that status checks are atomic.
  //This does not prevent asynchronous calls.
  std::mutex lock;
  enum LifeStage {
    construct,
    pooled,
    issued,
    destruct
  } stage;

public:
  LifeCycle() : stage(construct) {
    std::lock_guard<std::mutex> guard(lock);
    if (stage == construct)
      stage = pooled;
    else
      throw std::runtime_error("Initialization interrupted");
  }

  ~LifeCycle() {
    lock.lock();
    if (stage != pooled)
      throw std::runtime_error("Destructor called before Finalize");
    lock.unlock();
  }

  static ObjectPool<LifeCycle>* NewObjectPool(size_t limit = ~0, size_t maxPooled = ~0) {
    return new ObjectPool<LifeCycle>(limit, maxPooled,
      [] { return new LifeCycle(); },
      [] (LifeCycle& life) { life.Initialize(); },
      [] (LifeCycle& life) { life.Finalize(); }
    );
  }

protected:
  void Initialize() {
    std::lock_guard<std::mutex> guard(lock);
    if (stage != pooled)
      throw std::runtime_error("Initialize called on object not pooled");
    stage = issued;
  }

  void Finalize() {
    std::lock_guard<std::mutex> guard(lock);
    if (stage != issued)
      throw std::runtime_error("Finalize called on object not issued");
    stage = pooled;
  }
};

TEST_F(ObjectPoolTest, LifeCycleTestLimitOne) {
  std::shared_ptr<ObjectPool<LifeCycle>> pool(LifeCycle::NewObjectPool(2, 2));
  std::shared_ptr<LifeCycle> objHold, objDrop;

  // Create in Pool
  try {
    pool->Preallocate(1);
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }

  // Issue from Pool
  try {
    (*pool)(objHold);
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }

  // Issue from Pool with implicit Creation of objDrop
  try {
    (*pool)(objDrop);
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }

  // Return to Pool
  try {
    objDrop.reset();
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }

  // Destroy Pool with implicit Destruction of objDrop
  try {
    pool.reset();
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }

  // Return to Pool redirected to Destruction of objHold
  try {
    objHold.reset();
  } catch (std::runtime_error e) {
    FAIL() << e.what();
  }
}

TEST_F(ObjectPoolTest, VerifyAsynchronousUsage) {
  AutoCreateContext ctxt;
  CurrentContextPusher pshr(ctxt);

  AutoRequired<SimpleThreadedT<PooledObject>> obj;
{'fraction_non_alphanumeric': 0.13987836663770634, 'fraction_numerical': 0.007124239791485664, 'mean_word_length': 3.53585500394011, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5310297', 'n_tokens_mistral': 1966, 'n_tokens_neox': 1905, 'n_words': 480}