diff options
Diffstat (limited to 'spec/models/ci/runner_spec.rb')
-rw-r--r-- | spec/models/ci/runner_spec.rb | 177 |
1 files changed, 155 insertions, 22 deletions
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index ffe0b0d0b19..61f80bd43b1 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -75,6 +75,22 @@ RSpec.describe Ci::Runner do expect { create(:group, runners: [project_runner]) } .to raise_error(ActiveRecord::RecordInvalid) end + + context 'when runner has config' do + it 'is valid' do + runner = build(:ci_runner, config: { gpus: "all" }) + + expect(runner).to be_valid + end + end + + context 'when runner has an invalid config' do + it 'is invalid' do + runner = build(:ci_runner, config: { test: 1 }) + + expect(runner).not_to be_valid + end + end end context 'cost factors validations' do @@ -257,6 +273,20 @@ RSpec.describe Ci::Runner do end end + describe '.recent' do + subject { described_class.recent } + + before do + @runner1 = create(:ci_runner, :instance, contacted_at: nil, created_at: 2.months.ago) + @runner2 = create(:ci_runner, :instance, contacted_at: nil, created_at: 3.months.ago) + @runner3 = create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 2.months.ago) + @runner4 = create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 3.months.ago) + @runner5 = create(:ci_runner, :instance, contacted_at: 3.months.ago, created_at: 5.months.ago) + end + + it { is_expected.to eq([@runner1, @runner3, @runner4])} + end + describe '.online' do subject { described_class.online } @@ -349,6 +379,22 @@ RSpec.describe Ci::Runner do it { is_expected.to eq([@runner1])} end + describe '#tick_runner_queue' do + it 'sticks the runner to the primary and calls the original method' do + runner = create(:ci_runner) + + allow(Gitlab::Database::LoadBalancing).to receive(:enable?) + .and_return(true) + + expect(Gitlab::Database::LoadBalancing::Sticking).to receive(:stick) + .with(:runner, runner.id) + + expect(Gitlab::Workhorse).to receive(:set_key_and_notify) + + runner.tick_runner_queue + end + end + describe '#can_pick?' do using RSpec::Parameterized::TableSyntax @@ -653,7 +699,7 @@ RSpec.describe Ci::Runner do describe '#heartbeat' do let(:runner) { create(:ci_runner, :project) } - subject { runner.heartbeat(architecture: '18-bit') } + subject { runner.heartbeat(architecture: '18-bit', config: { gpus: "all" }) } context 'when database was updated recently' do before do @@ -701,6 +747,7 @@ RSpec.describe Ci::Runner do def does_db_update expect { subject }.to change { runner.reload.read_attribute(:contacted_at) } .and change { runner.reload.read_attribute(:architecture) } + .and change { runner.reload.read_attribute(:config) } end end @@ -826,12 +873,12 @@ RSpec.describe Ci::Runner do expect(described_class.search(runner.token)).to eq([runner]) end - it 'returns runners with a partially matching token' do - expect(described_class.search(runner.token[0..2])).to eq([runner]) + it 'does not return runners with a partially matching token' do + expect(described_class.search(runner.token[0..2])).to be_empty end - it 'returns runners with a matching token regardless of the casing' do - expect(described_class.search(runner.token.upcase)).to eq([runner]) + it 'does not return runners with a matching token with different casing' do + expect(described_class.search(runner.token.upcase)).to be_empty end it 'returns runners with a matching description' do @@ -919,29 +966,13 @@ RSpec.describe Ci::Runner do end end - context 'build picking improvement enabled' do - before do - stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: true) - end - + context 'build picking improvement' do it 'does not check if the build is assignable to a runner' do expect(runner).not_to receive(:can_pick?) runner.pick_build!(build) end end - - context 'build picking improvement disabled' do - before do - stub_feature_flags(ci_reduce_queries_when_ticking_runner_queue: false) - end - - it 'checks if the build is assignable to a runner' do - expect(runner).to receive(:can_pick?).and_call_original - - runner.pick_build!(build) - end - end end describe 'project runner without projects is destroyable' do @@ -975,6 +1006,108 @@ RSpec.describe Ci::Runner do end end + describe '.runner_matchers' do + subject(:matchers) { described_class.all.runner_matchers } + + context 'deduplicates on runner_type' do + before do + create_list(:ci_runner, 2, :instance) + create_list(:ci_runner, 2, :project) + end + + it 'creates two matchers' do + expect(matchers.size).to eq(2) + + expect(matchers.map(&:runner_type)).to match_array(%w[instance_type project_type]) + end + end + + context 'deduplicates on public_projects_minutes_cost_factor' do + before do + create_list(:ci_runner, 2, public_projects_minutes_cost_factor: 5) + create_list(:ci_runner, 2, public_projects_minutes_cost_factor: 10) + end + + it 'creates two matchers' do + expect(matchers.size).to eq(2) + + expect(matchers.map(&:public_projects_minutes_cost_factor)).to match_array([5, 10]) + end + end + + context 'deduplicates on private_projects_minutes_cost_factor' do + before do + create_list(:ci_runner, 2, private_projects_minutes_cost_factor: 5) + create_list(:ci_runner, 2, private_projects_minutes_cost_factor: 10) + end + + it 'creates two matchers' do + expect(matchers.size).to eq(2) + + expect(matchers.map(&:private_projects_minutes_cost_factor)).to match_array([5, 10]) + end + end + + context 'deduplicates on run_untagged' do + before do + create_list(:ci_runner, 2, run_untagged: true, tag_list: ['a']) + create_list(:ci_runner, 2, run_untagged: false, tag_list: ['a']) + end + + it 'creates two matchers' do + expect(matchers.size).to eq(2) + + expect(matchers.map(&:run_untagged)).to match_array([true, false]) + end + end + + context 'deduplicates on access_level' do + before do + create_list(:ci_runner, 2, access_level: :ref_protected) + create_list(:ci_runner, 2, access_level: :not_protected) + end + + it 'creates two matchers' do + expect(matchers.size).to eq(2) + + expect(matchers.map(&:access_level)).to match_array(%w[ref_protected not_protected]) + end + end + + context 'deduplicates on tag_list' do + before do + create_list(:ci_runner, 2, tag_list: %w[tag1 tag2]) + create_list(:ci_runner, 2, tag_list: %w[tag3 tag4]) + end + + it 'creates two matchers' do + expect(matchers.size).to eq(2) + + expect(matchers.map(&:tag_list)).to match_array([%w[tag1 tag2], %w[tag3 tag4]]) + end + end + end + + describe '#runner_matcher' do + let(:runner) do + build_stubbed(:ci_runner, :instance_type, tag_list: %w[tag1 tag2]) + end + + subject(:matcher) { runner.runner_matcher } + + it { expect(matcher.runner_type).to eq(runner.runner_type) } + + it { expect(matcher.public_projects_minutes_cost_factor).to eq(runner.public_projects_minutes_cost_factor) } + + it { expect(matcher.private_projects_minutes_cost_factor).to eq(runner.private_projects_minutes_cost_factor) } + + it { expect(matcher.run_untagged).to eq(runner.run_untagged) } + + it { expect(matcher.access_level).to eq(runner.access_level) } + + it { expect(matcher.tag_list).to match_array(runner.tag_list) } + end + describe '#uncached_contacted_at' do let(:contacted_at_stored) { 1.hour.ago.change(usec: 0) } let(:runner) { create(:ci_runner, contacted_at: contacted_at_stored) } |