diff options
author | Shinya Maeda <shinya@gitlab.com> | 2018-06-25 17:59:46 +0900 |
---|---|---|
committer | Shinya Maeda <shinya@gitlab.com> | 2018-06-25 17:59:46 +0900 |
commit | 82d98426854eb375bbe8ce0c830562e7c65a790a (patch) | |
tree | c589c69158f038aaeeda873dfeb83489d2dd7303 /spec | |
parent | 6c3eea0db04be446a1daebf629b6ddf9e0f18d18 (diff) | |
download | gitlab-ce-82d98426854eb375bbe8ce0c830562e7c65a790a.tar.gz |
Enable specs for atomic operations
Diffstat (limited to 'spec')
-rw-r--r-- | spec/models/ci/build_trace_chunk_spec.rb | 152 |
1 files changed, 87 insertions, 65 deletions
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb index 44eaf7afad3..2b4dfba5c2a 100644 --- a/spec/models/ci/build_trace_chunk_spec.rb +++ b/spec/models/ci/build_trace_chunk_spec.rb @@ -60,9 +60,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do let(:data_store) { :fog } before do - ::Fog::Storage.new(JobArtifactUploader.object_store_credentials).tap do |connection| - connection.put_object('artifacts', "tmp/builds/#{build.id}/chunks/#{chunk_index}.log", 'Sample data in fog') - end + build_trace_chunk.send(:unsafe_set_data!, 'Sample data in fog') end it { is_expected.to eq('Sample data in fog') } @@ -104,9 +102,23 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do expect(build_trace_chunk.data).to eq(merged_data) end + context 'when the other process is appending' do + let(:lease_key) { "trace_write:#{build_trace_chunk.build.id}:chunks:#{build_trace_chunk.chunk_index}" } + + it 'raise an error' do + begin + uuid = Gitlab::ExclusiveLease.new(lease_key, timeout: 1.day).try_obtain + + expect { subject }.to raise_error('Failed to obtain a lock') + ensure + Gitlab::ExclusiveLease.cancel(lease_key, uuid) + end + end + end + context 'when new_data is nil' do let(:new_data) { nil } - + it 'raises an error' do expect { subject }.to raise_error('New data is nil') end @@ -114,10 +126,10 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do context 'when new_data is empty' do let(:new_data) { '' } - + it 'does not append' do subject - + expect(build_trace_chunk.data).to eq(data) end @@ -361,7 +373,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do end context 'when data does not exist' do - it { expect{ subject }.to raise_error(Excon::Error::NotFound) } + it { expect { subject }.to raise_error(Excon::Error::NotFound) } end end end @@ -369,6 +381,22 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do describe '#persist_data!' do subject { build_trace_chunk.persist_data! } + shared_examples_for 'Atomic operation' do + context 'when the other process is persisting' do + let(:lease_key) { "trace_write:#{build_trace_chunk.build.id}:chunks:#{build_trace_chunk.chunk_index}" } + + it 'raise an error' do + begin + uuid = Gitlab::ExclusiveLease.new(lease_key, timeout: 1.day).try_obtain + + expect { subject }.to raise_error('Failed to obtain a lock') + ensure + Gitlab::ExclusiveLease.cancel(lease_key, uuid) + end + end + end + end + context 'when data_store is redis' do let(:data_store) { :redis } @@ -392,6 +420,8 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data) end + + it_behaves_like 'Atomic operation' end context 'when data does not exist' do @@ -424,6 +454,8 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data) end + + it_behaves_like 'Atomic operation' end context 'when data does not exist' do @@ -456,66 +488,56 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data) end + + it_behaves_like 'Atomic operation' end end end - ## TODO: - # describe 'ExclusiveLock' do - # before do - # allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain) { nil } - # stub_const('Ci::BuildTraceChunk::WRITE_LOCK_RETRY', 1) - # end - - # it 'raise an error' do - # expect { build_trace_chunk.append('ABC', 0) }.to raise_error('Failed to obtain write lock') - # end - # end - - # describe 'deletes data in redis after a parent record destroyed' do - # let(:project) { create(:project) } - - # before do - # pipeline = create(:ci_pipeline, project: project) - # create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project) - # create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project) - # create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project) - # end - - # shared_examples_for 'deletes all build_trace_chunk and data in redis' do - # it do - # Gitlab::Redis::SharedState.with do |redis| - # expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(3) - # end - - # expect(described_class.count).to eq(3) - - # subject - - # expect(described_class.count).to eq(0) - - # Gitlab::Redis::SharedState.with do |redis| - # expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(0) - # end - # end - # end - - # context 'when traces are archived' do - # let(:subject) do - # project.builds.each do |build| - # build.success! - # end - # end - - # it_behaves_like 'deletes all build_trace_chunk and data in redis' - # end - - # context 'when project is destroyed' do - # let(:subject) do - # project.destroy! - # end - - # it_behaves_like 'deletes all build_trace_chunk and data in redis' - # end - # end + describe 'deletes data in redis after a parent record destroyed' do + let(:project) { create(:project) } + + before do + pipeline = create(:ci_pipeline, project: project) + create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project) + create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project) + create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project) + end + + shared_examples_for 'deletes all build_trace_chunk and data in redis' do + it do + Gitlab::Redis::SharedState.with do |redis| + expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(3) + end + + expect(described_class.count).to eq(3) + + subject + + expect(described_class.count).to eq(0) + + Gitlab::Redis::SharedState.with do |redis| + expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(0) + end + end + end + + context 'when traces are archived' do + let(:subject) do + project.builds.each do |build| + build.success! + end + end + + it_behaves_like 'deletes all build_trace_chunk and data in redis' + end + + context 'when project is destroyed' do + let(:subject) do + project.destroy! + end + + it_behaves_like 'deletes all build_trace_chunk and data in redis' + end + end end |