<commit_before>require File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', 'data_objects', 'support', 'pooling')
require 'timeout'

# This implements dispose
# and works perfectly with
# pooling.
class DisposableResource
  include Object::Pooling
  attr_reader :name

  def initialize(name = "")
    @name = name
  end

  def dispose
    @name = nil
  end
end

# This baby causes exceptions
# to be raised when you use
# it with pooling.
class UndisposableResource
end



describe Object::Pooling::ResourcePool do
  before :each do
    @pool = Object::Pooling::ResourcePool.new(7, DisposableResource)
  end

  it "responds to flush!" do
    @pool.should respond_to(:flush!)
  end

  it "responds to aquire" do
    @pool.should respond_to(:aquire)
  end

  it "responds to release" do
    @pool.should respond_to(:release)
  end

  it "responds to :available?" do
    @pool.should respond_to(:available?)
  end

  it "has a size limit" do
    @pool.size_limit.should == 7
  end

  it "has initial size of zero" do
    @pool.size.should == 0
  end

  it "has a set of reserved resources" do
    @pool.instance_variable_get("@reserved").should be_empty
  end

  it "has a set of available resources" do
    @pool.instance_variable_get("@available").should be_empty
  end

  it "knows class of resources (objects) it works with" do
    @pool.class_of_resources.should == DisposableResource
  end

  it "raises exception when given anything but class for resources class" do
    lambda {
      @pool = Object::Pooling::ResourcePool.new(7, "Hooray!")
    }.should raise_error(ArgumentError, /class/)
  end

  it "requires class of resources (objects) it works with to have a dispose instance method" do
    lambda {
      @pool = Object::Pooling::ResourcePool.new(3, UndisposableResource)
    }.should raise_error(ArgumentError, /dispose/)
  end

  it "may take initialization arguments" do
    @pool = Object::Pooling::ResourcePool.new(7, DisposableResource, "paper")
    @pool.instance_variable_get("@initialization_args").should == ["paper"]
  end
end




describe "Aquire from contant size pool" do
  before :each do
    DisposableResource.initialize_pool(2)
  end

  it "increased size of the pool" do
    @time = DisposableResource.pool.aquire
    DisposableResource.pool.size.should == 1
  end

  it "places initialized instance in the reserved set" do
    @time = DisposableResource.pool.aquire
    DisposableResource.pool.instance_variable_get("@reserved").size.should == 1
  end

  it "raises an exception when pool size limit is hit" do
    @t1 = DisposableResource.pool.aquire
    @t2 = DisposableResource.pool.aquire

    lambda { DisposableResource.pool.aquire }.should raise_error(RuntimeError)
  end

  it "returns last released resource" do
    @t1 = DisposableResource.pool.aquire
    @t2 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t1)

    DisposableResource.pool.aquire.should == @t1
  end

  it "really truly returns last released resource" do
    @t1 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t1)

    @t2 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t2)

    @t3 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t3)

    DisposableResource.pool.aquire.should == @t1
    @t1.should == @t3
  end

  it "sets allocation timestamp on resource instance" do
    @t1 = DisposableResource.new
    @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 2)
  end
end



describe "Releasing from contant size pool" do
  before :each do
    DisposableResource.initialize_pool(2)
  end

  it "decreases size of the pool" do
    @t1 = DisposableResource.pool.aquire
    @t2 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t1)

    DisposableResource.pool.size.should == 1
  end

  it "raises an exception on attempt to releases object not in pool" do
    @t1 = DisposableResource.new
    @t2 = Set.new

    DisposableResource.pool.release(@t1)
    lambda { DisposableResource.pool.release(@t2) }.should raise_error(RuntimeError)
  end

  it "disposes released object" do
    @t1 = DisposableResource.pool.aquire

    @t1.should_receive(:dispose)
    DisposableResource.pool.release(@t1)
  end

  it "removes released object from reserved set" do
    @t1 = DisposableResource.pool.aquire

    lambda {
      DisposableResource.pool.release(@t1)
    }.should change(DisposableResource.pool.instance_variable_get("@reserved"), :size).by(-1)
  end

  it "returns released object back to available set" do
    @t1 = DisposableResource.pool.aquire

    lambda {
      DisposableResource.pool.release(@t1)
    }.should change(DisposableResource.pool.instance_variable_get("@available"), :size).by(1)
  end

  it "updates aquire timestamp on already allocated resource instance" do
    # aquire it once
    @t1 = DisposableResource.new
    # wait a bit
    sleep 3

    # check old timestamp
    @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 4)

    # re-aquire
    DisposableResource.pool.release(@t1)
    @t1 = DisposableResource.new
    # see timestamp is updated
    @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 2)
  end
end



describe Object::Pooling::ResourcePool, "#available?" do
  before :each do
    DisposableResource.initialize_pool(2)
    DisposableResource.new
  end

  it "returns true when pool has available instances" do
    DisposableResource.pool.should be_available
  end

  it "returns false when pool is exhausted" do
    # aquires the last available resource
    DisposableResource.new
    DisposableResource.pool.should_not be_available
  end
end



describe "Flushing of contant size pool" do
  before :each do
    DisposableResource.initialize_pool(2)

    @t1 = DisposableResource.new
    @t2 = DisposableResource.new

    # sanity check
    DisposableResource.pool.instance_variable_get("@reserved").should_not be_empty
  end

  it "disposes all pooled objects" do
    [@t1, @t2].each { |instance| instance.should_receive(:dispose) }

    DisposableResource.pool.flush!
  end

  it "empties reserved set" do
    DisposableResource.pool.flush!

    DisposableResource.pool.instance_variable_get("@reserved").should be_empty
  end

  it "returns all instances to available set" do
    DisposableResource.pool.flush!

    DisposableResource.pool.instance_variable_get("@available").size.should == 2
  end
end



describe "Poolable resource class" do
  before :each do
    DisposableResource.initialize_pool(3, "paper")
  end

  it "aquires new instances from pool" do
    @instance_one = DisposableResource.new

    DisposableResource.pool.aquired?(@instance_one).should be(true)
  end

  it "flushed existing pool on re-initialization" do
    DisposableResource.pool.should_receive(:flush!)
    DisposableResource.initialize_pool(5)
  end

  it "replaces pool on re-initialization" do
    DisposableResource.initialize_pool(5)
    DisposableResource.pool.size_limit.should == 5
  end

  it "passes initialization parameters to newly created resource instances" do
    DisposableResource.new.name.should == "paper"
  end
end
<commit_msg>Pending spec for instances disposing thread.<commit_after>require File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', 'data_objects', 'support', 'pooling')
require 'timeout'

# This implements dispose
# and works perfectly with
# pooling.
class DisposableResource
  include Object::Pooling
  attr_reader :name

  def initialize(name = "")
    @name = name
  end

  def dispose
    @name = nil
  end
end

# This baby causes exceptions
# to be raised when you use
# it with pooling.
class UndisposableResource
end



describe Object::Pooling::ResourcePool do
  before :each do
    @pool = Object::Pooling::ResourcePool.new(7, DisposableResource)
  end

  it "responds to flush!" do
    @pool.should respond_to(:flush!)
  end

  it "responds to aquire" do
    @pool.should respond_to(:aquire)
  end

  it "responds to release" do
    @pool.should respond_to(:release)
  end

  it "responds to :available?" do
    @pool.should respond_to(:available?)
  end

  it "has a size limit" do
    @pool.size_limit.should == 7
  end

  it "has initial size of zero" do
    @pool.size.should == 0
  end

  it "has a set of reserved resources" do
    @pool.instance_variable_get("@reserved").should be_empty
  end

  it "has a set of available resources" do
    @pool.instance_variable_get("@available").should be_empty
  end

  it "knows class of resources (objects) it works with" do
    @pool.class_of_resources.should == DisposableResource
  end

  it "raises exception when given anything but class for resources class" do
    lambda {
      @pool = Object::Pooling::ResourcePool.new(7, "Hooray!")
    }.should raise_error(ArgumentError, /class/)
  end

  it "requires class of resources (objects) it works with to have a dispose instance method" do
    lambda {
      @pool = Object::Pooling::ResourcePool.new(3, UndisposableResource)
    }.should raise_error(ArgumentError, /dispose/)
  end

  it "may take initialization arguments" do
    @pool = Object::Pooling::ResourcePool.new(7, DisposableResource, "paper")
    @pool.instance_variable_get("@initialization_args").should == ["paper"]
  end
end




describe "Aquire from contant size pool" do
  before :each do
    DisposableResource.initialize_pool(2)
  end

  it "increased size of the pool" do
    @time = DisposableResource.pool.aquire
    DisposableResource.pool.size.should == 1
  end

  it "places initialized instance in the reserved set" do
    @time = DisposableResource.pool.aquire
    DisposableResource.pool.instance_variable_get("@reserved").size.should == 1
  end

  it "raises an exception when pool size limit is hit" do
    @t1 = DisposableResource.pool.aquire
    @t2 = DisposableResource.pool.aquire

    lambda { DisposableResource.pool.aquire }.should raise_error(RuntimeError)
  end

  it "returns last released resource" do
    @t1 = DisposableResource.pool.aquire
    @t2 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t1)

    DisposableResource.pool.aquire.should == @t1
  end

  it "really truly returns last released resource" do
    @t1 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t1)

    @t2 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t2)

    @t3 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t3)

    DisposableResource.pool.aquire.should == @t1
    @t1.should == @t3
  end

  it "sets allocation timestamp on resource instance" do
    @t1 = DisposableResource.new
    @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 2)
  end
end



describe "Releasing from contant size pool" do
  before :each do
    DisposableResource.initialize_pool(2)
  end

  it "decreases size of the pool" do
    @t1 = DisposableResource.pool.aquire
    @t2 = DisposableResource.pool.aquire
    DisposableResource.pool.release(@t1)

    DisposableResource.pool.size.should == 1
  end

  it "raises an exception on attempt to releases object not in pool" do
    @t1 = DisposableResource.new
    @t2 = Set.new

    DisposableResource.pool.release(@t1)
    lambda { DisposableResource.pool.release(@t2) }.should raise_error(RuntimeError)
  end

  it "disposes released object" do
    @t1 = DisposableResource.pool.aquire

    @t1.should_receive(:dispose)
    DisposableResource.pool.release(@t1)
  end

  it "removes released object from reserved set" do
    @t1 = DisposableResource.pool.aquire

    lambda {
      DisposableResource.pool.release(@t1)
    }.should change(DisposableResource.pool.instance_variable_get("@reserved"), :size).by(-1)
  end

  it "returns released object back to available set" do
    @t1 = DisposableResource.pool.aquire

    lambda {
      DisposableResource.pool.release(@t1)
    }.should change(DisposableResource.pool.instance_variable_get("@available"), :size).by(1)
  end

  it "updates aquire timestamp on already allocated resource instance" do
    # aquire it once
    @t1 = DisposableResource.new
    # wait a bit
    sleep 3

    # check old timestamp
    @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 4)

    # re-aquire
    DisposableResource.pool.release(@t1)
    @t1 = DisposableResource.new
    # see timestamp is updated
    @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 2)
  end
end



describe Object::Pooling::ResourcePool, "#available?" do
  before :each do
    DisposableResource.initialize_pool(2)
    DisposableResource.new
  end

  it "returns true when pool has available instances" do
    DisposableResource.pool.should be_available
  end

  it "returns false when pool is exhausted" do
    # aquires the last available resource
    DisposableResource.new
    DisposableResource.pool.should_not be_available
  end
end



describe "Flushing of contant size pool" do
  before :each do
    DisposableResource.initialize_pool(2)

    @t1 = DisposableResource.new
    @t2 = DisposableResource.new

    # sanity check
    DisposableResource.pool.instance_variable_get("@reserved").should_not be_empty
  end

  it "disposes all pooled objects" do
    [@t1, @t2].each { |instance| instance.should_receive(:dispose) }

    DisposableResource.pool.flush!
  end

  it "empties reserved set" do
    DisposableResource.pool.flush!

    DisposableResource.pool.instance_variable_get("@reserved").should be_empty
  end

  it "returns all instances to available set" do
    DisposableResource.pool.flush!

    DisposableResource.pool.instance_variable_get("@available").size.should == 2
  end
end



describe "Poolable resource class" do
  before :each do
    DisposableResource.initialize_pool(3, "paper")
  end

  it "aquires new instances from pool" do
    @instance_one = DisposableResource.new

    DisposableResource.pool.aquired?(@instance_one).should be(true)
  end

  it "flushed existing pool on re-initialization" do
    DisposableResource.pool.should_receive(:flush!)
    DisposableResource.initialize_pool(5)
  end

  it "replaces pool on re-initialization" do
    DisposableResource.initialize_pool(5)
    DisposableResource.pool.size_limit.should == 5
  end

  it "passes initialization parameters to newly created resource instances" do
    DisposableResource.new.name.should == "paper"
  end
end



describe "Pool resource instances expiration" do
  before :each do
    DisposableResource.initialize_pool(7)
  end

  it "disposes is outdated instances"
end

{'fraction_non_alphanumeric': 0.09197691990658058, 'fraction_numerical': 0.008861107294958098, 'mean_word_length': 3.844925124792013, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '6267563', 'n_tokens_mistral': 4745, 'n_tokens_neox': 4386, 'n_words': 1212}