diff --git a/test/controllers/api/tasks_controller_test.rb b/test/controllers/api/tasks_controller_test.rb index b6ac278c1..9b9f0860d 100644 --- a/test/controllers/api/tasks_controller_test.rb +++ b/test/controllers/api/tasks_controller_test.rb @@ -55,7 +55,7 @@ class Api::TasksControllerTest < ActionController::TestCase results = JSON.parse(response.body)['results'] assert_equal 6, results.count assert_includes results.map { |r| r['id'] }, org1_task.id - refute_includes results.map { |r| r['id'] }, org2_task.id + assert_not_includes results.map { |r| r['id'] }, org2_task.id end end end @@ -176,30 +176,30 @@ def self.while_suspended describe 'POST /tasks/callback' do it 'passes the data to the corresponding action' do - Support::DummyProxyAction.reset - ForemanTasks::RemoteTask.any_instance - .expects(:proxy) - .returns(Support::DummyProxyAction.proxy) - - triggered = ForemanTasks.trigger(Support::DummyProxyAction, - Support::DummyProxyAction.proxy, - 'Proxy::DummyAction', - 'foo' => 'bar') - Support::DummyProxyAction.proxy.task_triggered.wait(5) - wait_for { ForemanTasks::Task.find_by(external_id: triggered.id).state == 'running' } - - task = ForemanTasks::Task.where(:external_id => triggered.id).first - assert_equal 'running', task.state - assert_equal 'pending', task.result - - callback = Support::DummyProxyAction.proxy.log[:trigger_task].first[1].first[1][:action_input][:callback] - post :callback, params: { 'callback' => callback, 'data' => { 'result' => 'success' } } - triggered.finished.wait(5) - - task.reload - assert_equal 'stopped', task.state - assert_equal 'success', task.result - assert_equal({ 'result' => 'success' }, task.main_action.output['proxy_output']) + Support::DummyProxyAction.reset + ForemanTasks::RemoteTask.any_instance + .expects(:proxy) + .returns(Support::DummyProxyAction.proxy) + + triggered = ForemanTasks.trigger(Support::DummyProxyAction, + Support::DummyProxyAction.proxy, + 'Proxy::DummyAction', + 'foo' => 'bar') + Support::DummyProxyAction.proxy.task_triggered.wait(5) + wait_for { ForemanTasks::Task.find_by(external_id: triggered.id).state == 'running' } + + task = ForemanTasks::Task.where(:external_id => triggered.id).first + assert_equal 'running', task.state + assert_equal 'pending', task.result + + callback = Support::DummyProxyAction.proxy.log[:trigger_task].first[1].first[1][:action_input][:callback] + post :callback, params: { 'callback' => callback, 'data' => { 'result' => 'success' } } + triggered.finished.wait(5) + + task.reload + assert_equal 'stopped', task.state + assert_equal 'success', task.result + assert_equal({ 'result' => 'success' }, task.main_action.output['proxy_output']) end end end diff --git a/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb b/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb index 949a73d25..23be1934e 100644 --- a/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +++ b/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb @@ -20,7 +20,7 @@ class ForemanTasksHelperTest < ActionView::TestCase @task.action = 'A task' stubs(:action_name).returns('show') items = breadcrumb_items - assert_equal ['Tasks', 'A task'], items.map { |i| i[:caption] } + assert_equal(['Tasks', 'A task'], items.map { |i| i[:caption] }) assert_nil items.last[:url] end @@ -31,7 +31,7 @@ class ForemanTasksHelperTest < ActionView::TestCase @task.action = 'A task' stubs(:action_name).returns('sub_tasks') items = breadcrumb_items - assert_equal ['Tasks', 'A task', 'Sub tasks'], items.map { |i| i[:caption] } + assert_equal(['Tasks', 'A task', 'Sub tasks'], items.map { |i| i[:caption] }) assert_nil items.last[:url] end end diff --git a/test/unit/actions/action_with_sub_plans_test.rb b/test/unit/actions/action_with_sub_plans_test.rb index 66a873902..5b6589a5e 100644 --- a/test/unit/actions/action_with_sub_plans_test.rb +++ b/test/unit/actions/action_with_sub_plans_test.rb @@ -54,7 +54,7 @@ def run; end specify "the locks of the sub-plan don't colide with the locks of its parent" do child_task = task.sub_tasks.first - refute child_task.locks.any?, "the lock is ensured by the parent" + assert_not child_task.locks.any?, "the lock is ensured by the parent" found = ForemanTasks::Link.for_resource(user).where(:task_id => child_task.id).any? assert found, "the action is linked properly" end diff --git a/test/unit/actions/proxy_action_test.rb b/test/unit/actions/proxy_action_test.rb index 7b42cb692..3b2b0df99 100644 --- a/test/unit/actions/proxy_action_test.rb +++ b/test/unit/actions/proxy_action_test.rb @@ -98,7 +98,7 @@ class ProxyActionTest < ActiveSupport::TestCase it 'saves the data comming from the proxy to the output and finishes' do action = run_action(@action, ::Actions::ProxyAction::CallbackData.new('result' => 'success')) - assert_equal({'result' => 'success'}, action.output[:proxy_output]) + assert_equal({ 'result' => 'success' }, action.output[:proxy_output]) end it 'handles connection errors' do @@ -141,7 +141,7 @@ class ProxyActionTest < ActiveSupport::TestCase action.world.stubs(:persistence).returns(persistence) action.wipe_secrets!(nil) - refute action.input.key?(:secrets) + assert_not action.input.key?(:secrets) end end end diff --git a/test/unit/cleaner_test.rb b/test/unit/cleaner_test.rb index 3cdf049df..8a2e4c2c3 100644 --- a/test/unit/cleaner_test.rb +++ b/test/unit/cleaner_test.rb @@ -26,10 +26,10 @@ class TasksTest < ActiveSupport::TestCase assert_equal tasks_to_keep.map(&:id).sort, ForemanTasks::Task.where(id: tasks_to_keep).order(:id).map(&:id) assert_equal 0, ForemanTasks.dynflow.world.persistence - .find_execution_plans(filters: { 'uuid' => tasks_to_delete.map(&:external_id) }).size + .find_execution_plans(filters: { 'uuid' => tasks_to_delete.map(&:external_id) }).size assert_equal tasks_to_keep.size, ForemanTasks.dynflow.world.persistence - .find_execution_plans(filters: { 'uuid' => tasks_to_keep.map(&:external_id) }).size + .find_execution_plans(filters: { 'uuid' => tasks_to_keep.map(&:external_id) }).size end describe "#orphaned_dynflow_tasks" do @@ -71,7 +71,7 @@ class TasksTest < ActiveSupport::TestCase assert_equal tasks_to_keep, ForemanTasks::Task.where(id: tasks_to_keep) assert_nil ForemanTasks::Link.find_by(id: link_to_delete.id) - refute_nil ForemanTasks::Link.find_by(id: link_to_keep.id) + assert_not_nil ForemanTasks::Link.find_by(id: link_to_keep.id) end it 'supports passing empty filter (just delete all)' do diff --git a/test/unit/recurring_logic_test.rb b/test/unit/recurring_logic_test.rb index ecdf958a0..6cc499d74 100644 --- a/test/unit/recurring_logic_test.rb +++ b/test/unit/recurring_logic_test.rb @@ -48,17 +48,17 @@ class RecurringLogicsTest < ActiveSupport::TestCase expected_result_daily = { :minutes => minutes, :hours => hours } expected_result_weekly = { :minutes => minutes, :hours => hours, :days_of_week => '1,4,6' } expected_result_monthly = { :minutes => minutes, :hours => hours, :days => days } - assert_equal expected_result_hourly, ForemanTasks::RecurringLogic.cronline_hash(:hourly, time_hash, days, days_of_week) - assert_equal expected_result_daily, ForemanTasks::RecurringLogic.cronline_hash(:daily, time_hash, days, days_of_week) - assert_equal expected_result_weekly, ForemanTasks::RecurringLogic.cronline_hash(:weekly, time_hash, days, days_of_week) + assert_equal expected_result_hourly, ForemanTasks::RecurringLogic.cronline_hash(:hourly, time_hash, days, days_of_week) + assert_equal expected_result_daily, ForemanTasks::RecurringLogic.cronline_hash(:daily, time_hash, days, days_of_week) + assert_equal expected_result_weekly, ForemanTasks::RecurringLogic.cronline_hash(:weekly, time_hash, days, days_of_week) assert_equal expected_result_monthly, ForemanTasks::RecurringLogic.cronline_hash(:monthly, time_hash, days, days_of_week) end it 'validates cronline correctly' do recurring_logic = ::ForemanTasks::RecurringLogic.new_from_cronline('* * * * abc') - refute recurring_logic.valid_cronline? + assert_not recurring_logic.valid_cronline? recurring_logic = ::ForemanTasks::RecurringLogic.new_from_cronline(nil) - refute recurring_logic.valid_cronline? + assert_not recurring_logic.valid_cronline? recurring_logic = ::ForemanTasks::RecurringLogic.new_from_cronline('* * * * *') assert recurring_logic.valid_cronline? recurring_logic = ::ForemanTasks::RecurringLogic.new_from_cronline('0 22 * * mon-fri') @@ -71,15 +71,15 @@ class RecurringLogicsTest < ActiveSupport::TestCase assert parser.can_continue? parser.max_iteration = 5 parser.expects(:iteration).twice.returns(5) - refute parser.can_continue? + assert_not parser.can_continue? parser.max_iteration = nil time = Time.utc(2015, 9, 29, 15, 0) parser.end_time = time - refute parser.can_continue?(time) + assert_not parser.can_continue?(time) parser.end_time = time + 120 assert parser.can_continue?(time) parser.max_iteration = 5 - refute parser.can_continue?(time) + assert_not parser.can_continue?(time) end it 'generates delay options' do @@ -185,17 +185,17 @@ class RecurringLogicsTest < ActiveSupport::TestCase it 'is invalid when end time in past' do logic.end_time = (Time.zone.now - 120) - refute logic.valid? + assert_not logic.valid? end it 'is invalid when iteration limit < 1' do logic.max_iteration = 0 - refute logic.valid? + assert_not logic.valid? end it 'is valid when in active state' do logic.end_time = (Time.zone.now - 120) - refute logic.valid? + assert_not logic.valid? logic.state = 'active' assert logic.valid? end diff --git a/test/unit/task_test.rb b/test/unit/task_test.rb index 2663d0589..0ed4d55f9 100644 --- a/test/unit/task_test.rb +++ b/test/unit/task_test.rb @@ -45,287 +45,287 @@ class TasksTest < ActiveSupport::TestCase end test 'can search the tasks by user\'s id' do - assert_equal [@task_one], ForemanTasks::Task.search_for("user.id = #{@user_one.id}") - assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id = #{@user_one.id}") - assert_equal [@task_one], ForemanTasks::Task.search_for("user.id != #{@user_two.id}") - assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id != #{@user_two.id}") - end - - test 'can search by array of user ids' do - assert_equal [@task_one], ForemanTasks::Task.search_for("user.id ^ (#{@user_one.id})") - assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id ^ (#{@user_one.id})") - assert_equal [@task_one], ForemanTasks::Task.search_for("user.id !^ (#{@user_two.id})") - assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id !^ (#{@user_two.id})") - end - - test 'cannot glob on user\'s id' do - assert_raises(ScopedSearch::QueryNotSupported) { ForemanTasks::Task.search_for("user.id ~ something") } - assert_raises(ScopedSearch::QueryNotSupported) { ForemanTasks::Task.search_for("user.id ~ 5") } - end - - test 'can search the tasks by user with wildcards' do - part = @user_one.login[1..-1] # search for '*ser1' if login is 'user1' - # The following two should be equivalent - assert_equal [@task_one], ForemanTasks::Task.search_for("user ~ #{part}") - assert_equal [@task_one], ForemanTasks::Task.search_for("user ~ *#{part}*") - SecureRandom.stubs(:hex).returns('abc') - assert_equal ForemanTasks::Task.search_for("user ~ #{part}").to_sql, - ForemanTasks::Task.search_for("user ~ *#{part}*").to_sql - end - - test 'can search the tasks by user with negated wildcards' do - part = @user_two.login[1..-1] # search for '*ser1' if login is 'user1' - # The following two should be equivalent - assert_equal [@task_one], ForemanTasks::Task.search_for("user !~ #{part}") - assert_equal [@task_one], ForemanTasks::Task.search_for("user !~ *#{part}*") - SecureRandom.stubs(:hex).returns('abc') - assert_equal ForemanTasks::Task.search_for("user !~ #{part}").to_sql, - ForemanTasks::Task.search_for("user !~ *#{part}*").to_sql - end - - test 'can search the tasks by array' do - assert_equal [@task_one], ForemanTasks::Task.search_for("user ^ (this_user, #{@user_one.login}, that_user)") - end - - test 'can search the tasks by negated array' do - assert_equal [@task_one], ForemanTasks::Task.search_for("user !^ (this_user, #{@user_two.login}, that_user)") - end - - test 'properly returns username' do - assert_equal @task_one.username, @user_one.login - end - end - - describe 'by duration' do - before do - @task_one, @task_two = FactoryBot.create_list(:dynflow_task, 2).sort_by(&:id) - end - - let(:scope) { ForemanTasks::Task.order(:id) } - - it 'can search by seconds ' do - skip unless on_postgresql? - assert_empty scope.search_for('duration < 2') - assert_equal [@task_one, @task_two], scope.search_for('duration = 2') - assert_empty scope.search_for('duration < "2 seconds"') - assert_empty scope.search_for('duration > "2 seconds"') - assert_equal [@task_one, @task_two], scope.search_for('duration = "2 seconds"') - assert_equal [@task_one, @task_two], scope.search_for('duration <= "2 seconds"') - assert_equal [@task_one, @task_two], scope.search_for('duration >= "2 seconds"') - end - - it 'can search by other time intervals' do - skip unless on_postgresql? - %w[minutes hours days months years].each do |interval| - assert_equal [@task_one, @task_two], scope.search_for("duration < \"2 #{interval}\"") - assert_empty scope.search_for("duration > \"2 #{interval}\"") - assert_empty scope.search_for("duration = \"2 #{interval}\"") - assert_equal [@task_one, @task_two], scope.search_for("duration <= \"2 #{interval}\"") - assert_empty scope.search_for("duration >= \"2 #{interval}\"") - end - end - - it 'raises an exception if duration is unknown' do - assert_raises(ScopedSearch::QueryNotSupported) { ForemanTasks::Task.search_for('duration = "25 potatoes"') } - end - end - - context 'by taxonomies' do - test 'can search by taxonomies using IN' do - assert_nothing_raised { ForemanTasks::Task.search_for('location_id ^ (1)').first } - assert_nothing_raised { ForemanTasks::Task.search_for('organization_id ^ (1)').first } - assert_nothing_raised { ForemanTasks::Task.search_for('location_id ^ (1,2)').first } - assert_nothing_raised { ForemanTasks::Task.search_for('organization_id ^ (1,2)').first } - assert_nothing_raised { ForemanTasks::Task.search_for('organization_id = 1').first } - end - end - end + assert_equal [@task_one], ForemanTasks::Task.search_for("user.id = #{@user_one.id}") + assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id = #{@user_one.id}") + assert_equal [@task_one], ForemanTasks::Task.search_for("user.id != #{@user_two.id}") + assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id != #{@user_two.id}") + end - describe 'users' do - test 'users can be deleted even if they have tasks assigned' do - user = FactoryBot.create(:user) - FactoryBot.create(:some_task, user: user) - user.destroy! - end - end + test 'can search by array of user ids' do + assert_equal [@task_one], ForemanTasks::Task.search_for("user.id ^ (#{@user_one.id})") + assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id ^ (#{@user_one.id})") + assert_equal [@task_one], ForemanTasks::Task.search_for("user.id !^ (#{@user_two.id})") + assert_equal [@task_one], ForemanTasks::Task.search_for("owner.id !^ (#{@user_two.id})") + end - describe 'state_updated_at' do - it 'updates the state_updated_at when the state changes' do - task = FactoryBot.create(:some_task) - assert_operator task.state_updated_at, :>, Time.now.utc - 1.minute, "Newly created task has to have state_updated_at set" - task.update(state_updated_at: nil) - task.result = 'error' - task.save - assert_nil task.state_updated_at, "Other than state change should not affect 'state_updated_at'" - task.state = 'running' - task.save - assert_not_nil task.state_updated_at, "State change should set 'state_updated_at'" - end - end + test 'cannot glob on user\'s id' do + assert_raises(ScopedSearch::QueryNotSupported) { ForemanTasks::Task.search_for("user.id ~ something") } + assert_raises(ScopedSearch::QueryNotSupported) { ForemanTasks::Task.search_for("user.id ~ 5") } + end - describe 'authorization filtering' do - it 'can filter by the task subject' do - user_role = FactoryBot.create(:user_user_role) - user = user_role.owner - role = user_role.role - permission = FactoryBot.build(:permission) - permission.resource_type = 'ForemanTasks::Task' - permission.save! - FactoryBot.create(:filter, role: role, permissions: [permission]) - - User.current = user - task = FactoryBot.create(:dynflow_task) - - auth = Authorizer.new(user) - assert auth.can?(permission.name.to_sym, task) - end - end + test 'can search the tasks by user with wildcards' do + part = @user_one.login[1..-1] # search for '*ser1' if login is 'user1' + # The following two should be equivalent + assert_equal [@task_one], ForemanTasks::Task.search_for("user ~ #{part}") + assert_equal [@task_one], ForemanTasks::Task.search_for("user ~ *#{part}*") + SecureRandom.stubs(:hex).returns('abc') + assert_equal ForemanTasks::Task.search_for("user ~ #{part}").to_sql, + ForemanTasks::Task.search_for("user ~ *#{part}*").to_sql + end - describe 'consistency check' do - it 'ensures the tasks marked as running are really running in Dynflow' do - task = ForemanTasks.sync_task(Support::DummyDynflowAction) - task.update(state: 'running') # Updating state updates the timestamp - task.update(state_updated_at: Time.zone.now - 5.minutes) + test 'can search the tasks by user with negated wildcards' do + part = @user_two.login[1..-1] # search for '*ser1' if login is 'user1' + # The following two should be equivalent + assert_equal [@task_one], ForemanTasks::Task.search_for("user !~ #{part}") + assert_equal [@task_one], ForemanTasks::Task.search_for("user !~ *#{part}*") + SecureRandom.stubs(:hex).returns('abc') + assert_equal ForemanTasks::Task.search_for("user !~ #{part}").to_sql, + ForemanTasks::Task.search_for("user !~ *#{part}*").to_sql + end - ForemanTasks::Task::DynflowTask.consistency_check - task.reload - assert_equal 'stopped', task.state - end - end + test 'can search the tasks by array' do + assert_equal [@task_one], ForemanTasks::Task.search_for("user ^ (this_user, #{@user_one.login}, that_user)") + end - describe 'active job task' do - it 'when scheduled to the future, the label and action is set properly' do - job = Support::DummyActiveJob.set(wait: 12.hours).perform_later - task = ForemanTasks::Task.find_by!(external_id: job.provider_job_id) - assert_equal "Dummy action", task.action - assert_equal "Support::DummyActiveJob", task.label - end - end + test 'can search the tasks by negated array' do + assert_equal [@task_one], ForemanTasks::Task.search_for("user !^ (this_user, #{@user_two.login}, that_user)") + end - describe 'task without valid execution plan' do - let(:missing_task_uuid) { '11111111-2222-3333-4444-555555555555' } - - let(:task) do - task = FactoryBot.create(:dynflow_task).tap do |task| - task.external_id = missing_task_uuid - task.save - end - ForemanTasks::Task.find(task.id) - end - - it 'handles the error while loading the task and does not propagate errors unless necessary' do - assert_nothing_raised { task.cancellable? } - assert_nothing_raised { task.resumable? } - assert_nothing_raised { task.main_action } - assert_equal 'Support::DummyDynflowAction', task.get_humanized(:humanized_name) - assert_equal 0, task.progress - assert_raises(KeyError) { task.cancel } - end - end + test 'properly returns username' do + assert_equal @task_one.username, @user_one.login + end + end - describe 'subtask count querying' do - let(:result_base) do - { - error: 0, - warning: 0, - total: 0, - success: 0, - cancelled: 0, - pending: 0, - } - end - let(:task) { FactoryBot.create(:dynflow_task) } - - describe 'without sub tasks' do - it 'calculates the progress report correctly' do - assert_equal result_base, task.sub_tasks_counts - end - end - - describe 'with sub tasks' do - let(:failed) { FactoryBot.create(:dynflow_task).tap { |t| t.result = :error } } - let(:success) { FactoryBot.create(:dynflow_task).tap { |t| t.result = :success } } - before { task.sub_tasks = [success, failed] } - - it 'calculate the progress report correctly' do - expected_result = result_base.merge(success: 1, error: 1, total: 2) - assert_equal expected_result, task.sub_tasks_counts - end - - it 'calculates the progress report correctly when using batch planning' do - result_base = self.result_base.merge(success: 1, error: 1, total: 25) - fake_action = OpenStruct.new(total_count: 25) - task.stubs(:main_action).returns(fake_action) - - task.state = 'stopped' - expected_result = result_base.merge(cancelled: 23) - assert_equal expected_result, task.sub_tasks_counts - - task.state = 'pending' - expected_result = result_base.merge(pending: 23) - assert_equal expected_result, task.sub_tasks_counts - end - end - end + describe 'by duration' do + before do + @task_one, @task_two = FactoryBot.create_list(:dynflow_task, 2).sort_by(&:id) + end - describe 'recurring task' do - let(:logic) { FactoryBot.build(:recurring_logic) } - let(:task) { FactoryBot.create(:dynflow_task) } + let(:scope) { ForemanTasks::Task.order(:id) } + + it 'can search by seconds ' do + skip unless on_postgresql? + assert_empty scope.search_for('duration < 2') + assert_equal [@task_one, @task_two], scope.search_for('duration = 2') + assert_empty scope.search_for('duration < "2 seconds"') + assert_empty scope.search_for('duration > "2 seconds"') + assert_equal [@task_one, @task_two], scope.search_for('duration = "2 seconds"') + assert_equal [@task_one, @task_two], scope.search_for('duration <= "2 seconds"') + assert_equal [@task_one, @task_two], scope.search_for('duration >= "2 seconds"') + end - it 'can indicate it is recurring' do - refute task.recurring? - task.add_missing_task_groups(logic.task_group) - task.reload - assert task.recurring? - end + it 'can search by other time intervals' do + skip unless on_postgresql? + %w[minutes hours days months years].each do |interval| + assert_equal [@task_one, @task_two], scope.search_for("duration < \"2 #{interval}\"") + assert_empty scope.search_for("duration > \"2 #{interval}\"") + assert_empty scope.search_for("duration = \"2 #{interval}\"") + assert_equal [@task_one, @task_two], scope.search_for("duration <= \"2 #{interval}\"") + assert_empty scope.search_for("duration >= \"2 #{interval}\"") end + end - describe 'delayed task' do - let(:task) { FactoryBot.create(:some_task) } + it 'raises an exception if duration is unknown' do + assert_raises(ScopedSearch::QueryNotSupported) { ForemanTasks::Task.search_for('duration = "25 potatoes"') } + end + end - it 'can indicate it is delayed' do - refute task.delayed? - assert_equal 'Immediate', task.execution_type - task.start_at = Time.now.utc + 100 - assert task.delayed? - assert_equal 'Delayed', task.execution_type - end - end + context 'by taxonomies' do + test 'can search by taxonomies using IN' do + assert_nothing_raised { ForemanTasks::Task.search_for('location_id ^ (1)').first } + assert_nothing_raised { ForemanTasks::Task.search_for('organization_id ^ (1)').first } + assert_nothing_raised { ForemanTasks::Task.search_for('location_id ^ (1,2)').first } + assert_nothing_raised { ForemanTasks::Task.search_for('organization_id ^ (1,2)').first } + assert_nothing_raised { ForemanTasks::Task.search_for('organization_id = 1').first } + end + end + end + + describe 'users' do + test 'users can be deleted even if they have tasks assigned' do + user = FactoryBot.create(:user) + FactoryBot.create(:some_task, user: user) + user.destroy! + end + end + + describe 'state_updated_at' do + it 'updates the state_updated_at when the state changes' do + task = FactoryBot.create(:some_task) + assert_operator task.state_updated_at, :>, Time.now.utc - 1.minute, "Newly created task has to have state_updated_at set" + task.update(state_updated_at: nil) + task.result = 'error' + task.save + assert_nil task.state_updated_at, "Other than state change should not affect 'state_updated_at'" + task.state = 'running' + task.save + assert_not_nil task.state_updated_at, "State change should set 'state_updated_at'" + end + end + + describe 'authorization filtering' do + it 'can filter by the task subject' do + user_role = FactoryBot.create(:user_user_role) + user = user_role.owner + role = user_role.role + permission = FactoryBot.build(:permission) + permission.resource_type = 'ForemanTasks::Task' + permission.save! + FactoryBot.create(:filter, role: role, permissions: [permission]) + + User.current = user + task = FactoryBot.create(:dynflow_task) + + auth = Authorizer.new(user) + assert auth.can?(permission.name.to_sym, task) + end + end + + describe 'consistency check' do + it 'ensures the tasks marked as running are really running in Dynflow' do + task = ForemanTasks.sync_task(Support::DummyDynflowAction) + task.update(state: 'running') # Updating state updates the timestamp + task.update(state_updated_at: Time.zone.now - 5.minutes) + + ForemanTasks::Task::DynflowTask.consistency_check + task.reload + assert_equal 'stopped', task.state + end + end + + describe 'active job task' do + it 'when scheduled to the future, the label and action is set properly' do + job = Support::DummyActiveJob.set(wait: 12.hours).perform_later + task = ForemanTasks::Task.find_by!(external_id: job.provider_job_id) + assert_equal "Dummy action", task.action + assert_equal "Support::DummyActiveJob", task.label + end + end + + describe 'task without valid execution plan' do + let(:missing_task_uuid) { '11111111-2222-3333-4444-555555555555' } - describe 'search for resource_ids' do - label = 'label1' - resource_ids = [1, 2] - resource_type = 'restype1' - - let(:task1_old) do - FactoryBot.create( - :task_with_links, - started_at: '2019-10-01 11:15:55', - ended_at: '2019-10-01 11:15:57', - resource_id: 1, - label: label, - resource_type: resource_type - ) - end - let(:task1_new) do - FactoryBot.create( - :task_with_links, - started_at: '2019-10-02 11:15:55', - ended_at: '2019-10-02 11:15:57', - resource_id: 1, - label: label, - resource_type: resource_type - ) - end - let(:task2) do - FactoryBot.create( - :task_with_links, - started_at: '2019-10-03 11:15:55', - ended_at: '2019-10-03 11:15:57', - resource_id: 2, - label: label, - resource_type: resource_type - ) + let(:task) do + task = FactoryBot.create(:dynflow_task).tap do |task| + task.external_id = missing_task_uuid + task.save + end + ForemanTasks::Task.find(task.id) + end + + it 'handles the error while loading the task and does not propagate errors unless necessary' do + assert_nothing_raised { task.cancellable? } + assert_nothing_raised { task.resumable? } + assert_nothing_raised { task.main_action } + assert_equal 'Support::DummyDynflowAction', task.get_humanized(:humanized_name) + assert_equal 0, task.progress + assert_raises(KeyError) { task.cancel } + end + end + + describe 'subtask count querying' do + let(:result_base) do + { + error: 0, + warning: 0, + total: 0, + success: 0, + cancelled: 0, + pending: 0, + } + end + let(:task) { FactoryBot.create(:dynflow_task) } + + describe 'without sub tasks' do + it 'calculates the progress report correctly' do + assert_equal result_base, task.sub_tasks_counts + end + end + + describe 'with sub tasks' do + let(:failed) { FactoryBot.create(:dynflow_task).tap { |t| t.result = :error } } + let(:success) { FactoryBot.create(:dynflow_task).tap { |t| t.result = :success } } + before { task.sub_tasks = [success, failed] } + + it 'calculate the progress report correctly' do + expected_result = result_base.merge(success: 1, error: 1, total: 2) + assert_equal expected_result, task.sub_tasks_counts + end + + it 'calculates the progress report correctly when using batch planning' do + result_base = self.result_base.merge(success: 1, error: 1, total: 25) + fake_action = OpenStruct.new(total_count: 25) + task.stubs(:main_action).returns(fake_action) + + task.state = 'stopped' + expected_result = result_base.merge(cancelled: 23) + assert_equal expected_result, task.sub_tasks_counts + + task.state = 'pending' + expected_result = result_base.merge(pending: 23) + assert_equal expected_result, task.sub_tasks_counts + end + end + end + + describe 'recurring task' do + let(:logic) { FactoryBot.build(:recurring_logic) } + let(:task) { FactoryBot.create(:dynflow_task) } + + it 'can indicate it is recurring' do + assert_not task.recurring? + task.add_missing_task_groups(logic.task_group) + task.reload + assert task.recurring? + end + end + + describe 'delayed task' do + let(:task) { FactoryBot.create(:some_task) } + + it 'can indicate it is delayed' do + assert_not task.delayed? + assert_equal 'Immediate', task.execution_type + task.start_at = Time.now.utc + 100 + assert task.delayed? + assert_equal 'Delayed', task.execution_type + end + end + + describe 'search for resource_ids' do + label = 'label1' + resource_ids = [1, 2] + resource_type = 'restype1' + + let(:task1_old) do + FactoryBot.create( + :task_with_links, + started_at: '2019-10-01 11:15:55', + ended_at: '2019-10-01 11:15:57', + resource_id: 1, + label: label, + resource_type: resource_type + ) + end + let(:task1_new) do + FactoryBot.create( + :task_with_links, + started_at: '2019-10-02 11:15:55', + ended_at: '2019-10-02 11:15:57', + resource_id: 1, + label: label, + resource_type: resource_type + ) + end + let(:task2) do + FactoryBot.create( + :task_with_links, + started_at: '2019-10-03 11:15:55', + ended_at: '2019-10-03 11:15:57', + resource_id: 2, + label: label, + resource_type: resource_type + ) end let(:task3) do FactoryBot.create( diff --git a/test/unit/triggering_test.rb b/test/unit/triggering_test.rb index 9ed7baf1c..6e511b4b1 100644 --- a/test/unit/triggering_test.rb +++ b/test/unit/triggering_test.rb @@ -10,14 +10,14 @@ class TriggeringTest < ActiveSupport::TestCase triggering = FactoryBot.build(:triggering, :future) assert_predicate(triggering, :valid?) triggering.start_before = triggering.start_at - 120 - refute_predicate(triggering, :valid?) + assert_not_predicate(triggering, :valid?) end it 'is invalid when recurring logic is invalid' do triggering = FactoryBot.build(:triggering, :recurring) assert_predicate(triggering, :valid?) triggering.recurring_logic.stubs(:valid?).returns(false) - refute_predicate(triggering, :valid?) + assert_not_predicate(triggering, :valid?) end it 'is valid when recurring logic has purpose' do @@ -30,7 +30,7 @@ class TriggeringTest < ActiveSupport::TestCase FactoryBot.create(:recurring_logic, :purpose => 'test', :state => 'active') logic = FactoryBot.build(:recurring_logic, :purpose => 'test', :state => 'active') triggering = FactoryBot.build(:triggering, :recurring_logic => logic, :mode => :recurring, :input_type => :cronline, :cronline => '* * * * *') - refute_predicate(triggering, :valid?) + assert_not_predicate(triggering, :valid?) end it 'is valid when recurring logic with given purpose exists and is not active or disabled' do diff --git a/test/unit/ui_notifications_test.rb b/test/unit/ui_notifications_test.rb index b73dbf9c8..4de43b102 100644 --- a/test/unit/ui_notifications_test.rb +++ b/test/unit/ui_notifications_test.rb @@ -24,13 +24,13 @@ class UiNotificationsTest < ActiveSupport::TestCase notification = user_notifications(admin_user).first assert_equal "There is 1 paused task in the system that need attention", notification.message links = notification.actions['links'] - assert_includes(links, {'href' => '/foreman_tasks/tasks?search=state%3Dpaused', - 'title' => 'List of tasks'}) - assert_includes(links, {'name' => 'troubleshooting', + assert_includes(links, { 'href' => '/foreman_tasks/tasks?search=state%3Dpaused', + 'title' => 'List of tasks' }) + assert_includes(links, { 'name' => 'troubleshooting', 'title' => 'Troubleshooting Documentation', 'description' => 'See %{link} for more details on how to resolve the issue', 'href' => "https://theforeman.org/manuals/#{SETTINGS[:version].short}/tasks_troubleshooting.html#", - 'external' => true}) + 'external' => true }) end it 'aggregates the notification when multiple tasks get paused' do