Commit 82d98426 authored by Shinya Maeda's avatar Shinya Maeda

Enable specs for atomic operations

parent 6c3eea0d
...@@ -60,9 +60,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do ...@@ -60,9 +60,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
let(:data_store) { :fog } let(:data_store) { :fog }
before do before do
::Fog::Storage.new(JobArtifactUploader.object_store_credentials).tap do |connection| build_trace_chunk.send(:unsafe_set_data!, 'Sample data in fog')
connection.put_object('artifacts', "tmp/builds/#{build.id}/chunks/#{chunk_index}.log", 'Sample data in fog')
end
end end
it { is_expected.to eq('Sample data in fog') } it { is_expected.to eq('Sample data in fog') }
...@@ -104,9 +102,23 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do ...@@ -104,9 +102,23 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
expect(build_trace_chunk.data).to eq(merged_data) expect(build_trace_chunk.data).to eq(merged_data)
end 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 context 'when new_data is nil' do
let(:new_data) { nil } let(:new_data) { nil }
it 'raises an error' do it 'raises an error' do
expect { subject }.to raise_error('New data is nil') expect { subject }.to raise_error('New data is nil')
end end
...@@ -114,10 +126,10 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do ...@@ -114,10 +126,10 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
context 'when new_data is empty' do context 'when new_data is empty' do
let(:new_data) { '' } let(:new_data) { '' }
it 'does not append' do it 'does not append' do
subject subject
expect(build_trace_chunk.data).to eq(data) expect(build_trace_chunk.data).to eq(data)
end end
...@@ -361,7 +373,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do ...@@ -361,7 +373,7 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
end end
context 'when data does not exist' do 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 end
end end
...@@ -369,6 +381,22 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do ...@@ -369,6 +381,22 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
describe '#persist_data!' do describe '#persist_data!' do
subject { build_trace_chunk.persist_data! } 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 context 'when data_store is redis' do
let(:data_store) { :redis } let(:data_store) { :redis }
...@@ -392,6 +420,8 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do ...@@ -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::Database.new.data(build_trace_chunk)).to be_nil
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data) expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
end end
it_behaves_like 'Atomic operation'
end end
context 'when data does not exist' do context 'when data does not exist' do
...@@ -424,6 +454,8 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state 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::Database.new.data(build_trace_chunk)).to be_nil
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data) expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
end end
it_behaves_like 'Atomic operation'
end end
context 'when data does not exist' do context 'when data does not exist' do
...@@ -456,66 +488,56 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state 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::Database.new.data(build_trace_chunk)).to be_nil
expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data) expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
end end
it_behaves_like 'Atomic operation'
end end
end end
end end
## TODO: describe 'deletes data in redis after a parent record destroyed' do
# describe 'ExclusiveLock' do let(:project) { create(:project) }
# before do
# allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain) { nil } before do
# stub_const('Ci::BuildTraceChunk::WRITE_LOCK_RETRY', 1) pipeline = create(:ci_pipeline, project: project)
# end create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project)
create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project)
# it 'raise an error' do create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project)
# expect { build_trace_chunk.append('ABC', 0) }.to raise_error('Failed to obtain write lock') end
# end
# end shared_examples_for 'deletes all build_trace_chunk and data in redis' do
it do
# describe 'deletes data in redis after a parent record destroyed' do Gitlab::Redis::SharedState.with do |redis|
# let(:project) { create(:project) } expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(3)
end
# before do
# pipeline = create(:ci_pipeline, project: project) expect(described_class.count).to eq(3)
# create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project)
# create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project) subject
# create(:ci_build, :running, :trace_live, pipeline: pipeline, project: project)
# end expect(described_class.count).to eq(0)
# shared_examples_for 'deletes all build_trace_chunk and data in redis' do Gitlab::Redis::SharedState.with do |redis|
# it do expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(0)
# Gitlab::Redis::SharedState.with do |redis| end
# expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(3) end
# end end
# expect(described_class.count).to eq(3) context 'when traces are archived' do
let(:subject) do
# subject project.builds.each do |build|
build.success!
# expect(described_class.count).to eq(0) end
end
# Gitlab::Redis::SharedState.with do |redis|
# expect(redis.scan_each(match: "gitlab:ci:trace:*:chunks:*").to_a.size).to eq(0) it_behaves_like 'deletes all build_trace_chunk and data in redis'
# end end
# end
# end context 'when project is destroyed' do
let(:subject) do
# context 'when traces are archived' do project.destroy!
# let(:subject) do end
# project.builds.each do |build|
# build.success! it_behaves_like 'deletes all build_trace_chunk and data in redis'
# end end
# 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 end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment