trabajo-afectivo/spec/models/scheduler_spec.rb
2022-01-01 14:38:12 +01:00

209 lines
5 KiB
Ruby

# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
require 'rails_helper'
require 'models/concerns/has_xss_sanitized_note_examples'
RSpec.describe Scheduler do
let(:test_backend_class) do
Class.new do
def self.start
# noop
end
# rubocop:disable Style/TrivialAccessors
def self.reschedule=(reschedule)
@reschedule = reschedule
end
# rubocop:enable Style/TrivialAccessors
def self.reschedule?(_delayed_job)
@reschedule || false
end
end
end
let(:test_backend_name) { 'SpecSpace::DelayedJobBackend' }
before do
stub_const test_backend_name, test_backend_class
end
it_behaves_like 'HasXssSanitizedNote', model_factory: :scheduler
describe '.failed_jobs' do
it 'does list failed jobs' do
job = create(:scheduler, status: 'error', active: false)
failed_list = described_class.failed_jobs
expect(failed_list).to be_present
expect(failed_list).to include(job)
end
end
describe '.restart_failed_jobs' do
it 'does restart failed jobs' do
job = create(:scheduler, status: 'error', active: false)
described_class.restart_failed_jobs
job.reload
expect(job.active).to be true
end
end
describe '._start_job' do
it 'sets error status/message for failed jobs' do
job = create(:scheduler)
described_class._start_job(job)
expect(job.status).to eq 'error'
expect(job.active).to be false
expect(job.error_message).to be_present
end
it 'executes job that is expected to succeed' do
expect(Setting).to receive(:reload)
job = create(:scheduler, method: 'Setting.reload')
described_class._start_job(job)
expect(job.status).to eq 'ok'
end
end
describe '.cleanup' do
it 'gets called by .threads' do
allow(described_class).to receive(:cleanup).and_throw(:called)
expect do
described_class.threads
end.to throw_symbol(:called)
end
context 'not called from .threads method' do
it 'throws an exception' do
expect do
described_class.cleanup
end.to raise_error(RuntimeError)
end
it 'throws no exception with force parameter' do
expect do
described_class.cleanup(force: true)
end.not_to raise_error
end
end
# helpers to avoid the throwing behaviour "describe"d above
def simulate_threads_call
threads
end
def threads
described_class.cleanup
end
context 'Delayed::Job' do
it 'keeps unlocked' do
# meta :)
described_class.delay.cleanup
expect do
simulate_threads_call
end.not_to change {
Delayed::Job.count
}
end
context 'locked' do
it 'gets destroyed' do
# meta :)
described_class.delay.cleanup
# lock job (simluates interrupted scheduler task)
locked_job = Delayed::Job.last
locked_job.update!(locked_at: Time.zone.now)
expect do
simulate_threads_call
end.to change {
Delayed::Job.count
}.by(-1)
end
context 'respond to reschedule?' do
it 'gets rescheduled for positive responses' do
SpecSpace::DelayedJobBackend.reschedule = true
SpecSpace::DelayedJobBackend.delay.start
# lock job (simluates interrupted scheduler task)
locked_job = Delayed::Job.last
locked_job.update!(locked_at: Time.zone.now)
expect do
simulate_threads_call
end.to not_change {
Delayed::Job.count
}.and change {
Delayed::Job.last.locked_at
}
end
it 'gets destroyed for negative responses' do
SpecSpace::DelayedJobBackend.reschedule = false
SpecSpace::DelayedJobBackend.delay.start
# lock job (simluates interrupted scheduler task)
locked_job = Delayed::Job.last
locked_job.update!(locked_at: Time.zone.now)
expect do
simulate_threads_call
end.to change {
Delayed::Job.count
}.by(-1)
end
end
end
end
context 'ImportJob' do
context 'affected job' do
let(:job) { create(:import_job, started_at: 5.minutes.ago) }
it 'finishes stuck jobs' do
expect do
simulate_threads_call
end.to change {
job.reload.finished_at
}
end
it 'adds an error message to the result' do
expect do
simulate_threads_call
end.to change {
job.reload.result[:error]
}
end
end
it "doesn't change jobs added after stop" do
job = create(:import_job)
expect do
simulate_threads_call
end.not_to change {
job.reload
}
end
end
end
end