require 'spec_helper'

describe CephStorage::Pool do
  let(:config) { cluster_config }
  let(:spconfig) { spec_config }
  let(:cluster) { CephStorage::ClusterFactory.build config }
  let(:pool_name) { spconfig[:pool][:name] }
  let(:pool) { cluster.pool(pool_name) }
  let(:object_name) { spconfig[:pool][:object] }
  subject { pool }

  it 'should be a PoolFactory' do
    expect(subject).to be_a CephStorage::PoolFactory
  end

  it 'should respond to rados_pool' do
    expect(subject).to respond_to :rados_pool
  end

  it 'should respond to rados_pool=' do
    expect(subject).to respond_to :rados_pool=
  end

  it 'should respond to storage_object' do
    expect(subject).to respond_to :storage_object
  end

  it 'should respond to storage_object_enumerator' do
    expect(subject).to respond_to :storage_object_enumerator
  end

  it 'should respond to size' do
    expect(subject).to respond_to :size
  end

  it 'should respond to num_locked' do
    expect(subject).to respond_to :num_locked
  end

  it 'should respond to num_free' do
    expect(subject).to respond_to :num_free
  end

  it 'should respond to close' do
    expect(subject).to respond_to :close
  end

  let(:rados_pool) { pool.rados_pool }

  describe 'rados_pool method' do
    subject { rados_pool }
    it 'should be a CephRuby::Pool object' do
      expect(subject).to be_a CephRuby::Pool
    end

    it 'should not equal another object popped off the stack' do
      expect(subject).not_to equal(pool.rados_pool)
    end

    let(:rados_pool1) { pool.rados_pool { |p| return p } }
    let(:rados_pool2) { pool.rados_pool { |p| return p } }

    it 'should push the pool back on the queue when called with a block' do
      expect(rados_pool1).to equal(rados_pool2)
    end

    describe 'when calling close on factory' do
      it 'should close be closeable' do
        expect { pool.close }.not_to raise_exception
      end

      it 'should have size 0' do
        expect(pool.size).to eq(0)
      end
    end

    describe 'behaviour when popping then pushing' do
      before(:each) { pool.rados_pool = pool.rados_pool }

      it 'size should be 1 after popping and pushing' do
        expect(pool.size).to eq(1)
        expect(pool.num_free).to eq(1)
        expect(pool.num_locked).to eq(0)
      end

      it 'size should still be 1 after doing that again' do
        expect(pool.num_free).to eq(1)
        expect(pool.num_locked).to eq(0)
      end
    end
  end

  describe 'inherited methods' do
    describe 'create' do
      it 'should not throw exception' do
        expect { subject.create }.not_to raise_exception
      end
    end

    describe 'stat' do
      subject { pool.stat }
      it 'should not throw exception' do
        expect { subject }.not_to raise_exception
      end

      it 'should be a Hash' do
        expect(subject).to be_a Hash
      end
    end

    describe 'id' do
      subject { pool.id }

      it 'should not throw an exception' do
        expect { subject }.not_to raise_exception
      end

      it 'should return an integer' do
        expect(subject).to be_a Fixnum
      end
    end

    describe 'exists?' do
      subject { pool.exists? }

      it 'should not throw an exception' do
        expect { subject }.not_to raise_exception
      end

      it 'should return true' do
        expect(subject).to be true
      end
    end

    describe 'auid' do
      subject { pool.auid }

      it 'should not throw an exception' do
        expect { subject }.not_to raise_exception
      end

      it 'should return an integer' do
        expect(subject).to be_a Fixnum
      end
    end

    describe 'destroy' do
      it 'should not throw an exception' do
        expect { subject.destroy }.not_to raise_exception
      end
      describe 'after destroy' do
        it 'should not exist' do
          expect(subject.exists?).to be false
        end
      end
    end
  end

  describe 'storage_object' do
    let(:storage_object) { pool.storage_object(object_name) }
    subject { storage_object }

    it 'should be a CephStorage::StorageObject::RadosStorageObject' do
      expect(subject).to be_a CephStorage::StorageObject::RadosStorageObject
    end
  end
end