canvas-lms/spec/lib/progress_runner_spec.rb

133 lines
4.2 KiB
Ruby

#
# Copyright (C) 2013 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe ProgressRunner do
before do
@progress = double("progress").as_null_object
end
module ProgressMessages
def message=(m)
@message = m
end
def message
@message
end
end
it "should perform normal processing and update progress" do
expect(@progress).to receive(:start!).once
expect(@progress).to receive(:calculate_completion!).exactly(3).times
expect(@progress).to receive(:complete!).once
expect(@progress).to receive(:completion=).with(100.0).once
expect(@progress).to receive(:message=).with("foo").once
expect(@progress).to receive(:save).once
progress_runner = ProgressRunner.new(@progress)
completed_message_value = nil
progress_runner.completed_message {|completed| completed_message_value = completed; "foo"}
error_callback_called = false
progress_runner.error_message {|message, error_ids| error_callback_called = true; "bar"}
process_callback_count = 0
ids = (0..9).to_a
progress_runner.do_batch_update(ids) do |id|
expect(id).to eql process_callback_count
process_callback_count += 1
end
expect(process_callback_count).to eql ids.size
expect(completed_message_value).to eql ids.size
expect(error_callback_called).to be_falsey
end
it "should rescue exceptions and record messages as errors" do
@progress.extend(ProgressMessages)
expect(@progress).to receive(:complete!).once
expect(@progress).to receive(:completion=).with(100.0)
expect(@progress).to receive(:save).once
progress_runner = ProgressRunner.new(@progress)
progress_runner.completed_message do |count|
expect(count).to eql 1
"abra"
end
error_callback_count = 0
progress_runner.error_message do |error, ids|
error_callback_count += 1
"#{error}: #{ids.join(', ')}"
end
ids = (1..3).to_a
progress_runner.do_batch_update(ids) do |id|
raise "error processing #{id}" if id >= 2
end
expect(error_callback_count).to eql 2
message_lines = @progress.message.lines.map(&:strip).sort
expect(message_lines.size).to eql 3
expect(message_lines).to eql ["abra", "error processing 2: 2", "error processing 3: 3"]
end
it "should have default completion and error messages" do
@progress.extend(ProgressMessages)
progress_runner = ProgressRunner.new(@progress)
ids = (1..4).to_a
progress_runner.do_batch_update(ids) do |id|
raise "processing error" if id >= 3
end
expect(@progress.message).to eql "2 items processed\nprocessing error: 3, 4"
end
# These are also tested above
#it "should accumulate like errors into a single mesage line"
#it "should complete progress if only some records fail"
it "should fail progress if all records fail" do
@progress.extend(ProgressMessages)
expect(@progress).to receive(:completion=).with(100.0)
expect(@progress).to receive(:fail!).once
expect(@progress).to receive(:save).once
progress_runner = ProgressRunner.new(@progress)
ids = (1..4).to_a
progress_runner.do_batch_update(ids) do |id|
raise "processing error"
end
expect(@progress.message).to eql "0 items processed\nprocessing error: 1, 2, 3, 4"
end
it "updates progress frequency relative to size of input" do
ids = (1..255).to_a
times_update = (ids.size / (ids.size / 20).to_f).ceil
expect(@progress).to receive(:calculate_completion!).exactly(times_update).times
progress_runner = ProgressRunner.new(@progress)
progress_runner.do_batch_update(ids) {}
end
end