diff options
Diffstat (limited to 'activejob/test')
-rw-r--r-- | activejob/test/adapters/qu.rb | 5 | ||||
-rw-r--r-- | activejob/test/cases/argument_serialization_test.rb | 58 | ||||
-rw-r--r-- | activejob/test/cases/exceptions_test.rb | 9 | ||||
-rw-r--r-- | activejob/test/cases/job_serialization_test.rb | 7 | ||||
-rw-r--r-- | activejob/test/cases/serializers_test.rb | 98 | ||||
-rw-r--r-- | activejob/test/cases/timezones_test.rb | 24 | ||||
-rw-r--r-- | activejob/test/integration/queuing_test.rb | 25 | ||||
-rw-r--r-- | activejob/test/jobs/retry_job.rb | 4 | ||||
-rw-r--r-- | activejob/test/jobs/timezone_dependent_job.rb | 22 | ||||
-rw-r--r-- | activejob/test/support/delayed_job/delayed/backend/test.rb | 4 | ||||
-rw-r--r-- | activejob/test/support/integration/adapters/qu.rb | 40 | ||||
-rw-r--r-- | activejob/test/support/integration/adapters/resque.rb | 14 | ||||
-rw-r--r-- | activejob/test/support/integration/adapters/sidekiq.rb | 12 | ||||
-rw-r--r-- | activejob/test/support/integration/dummy_app_template.rb | 3 | ||||
-rw-r--r-- | activejob/test/support/integration/helper.rb | 1 | ||||
-rw-r--r-- | activejob/test/support/integration/test_case_helpers.rb | 4 |
16 files changed, 259 insertions, 71 deletions
diff --git a/activejob/test/adapters/qu.rb b/activejob/test/adapters/qu.rb deleted file mode 100644 index 5b471fa347..0000000000 --- a/activejob/test/adapters/qu.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -require "qu-immediate" - -ActiveJob::Base.queue_adapter = :qu diff --git a/activejob/test/cases/argument_serialization_test.rb b/activejob/test/cases/argument_serialization_test.rb index 13e6fcb727..e5f1f087fe 100644 --- a/activejob/test/cases/argument_serialization_test.rb +++ b/activejob/test/cases/argument_serialization_test.rb @@ -12,7 +12,10 @@ class ArgumentSerializationTest < ActiveSupport::TestCase end [ nil, 1, 1.0, 1_000_000_000_000_000_000_000, - "a", true, false, BigDecimal.new(5), + "a", true, false, BigDecimal(5), + :a, 1.day, Date.new(2001, 2, 3), Time.new(2002, 10, 31, 2, 2, 2, "+02:00"), + DateTime.new(2001, 2, 3, 4, 5, 6, "+03:00"), + ActiveSupport::TimeWithZone.new(Time.utc(1999, 12, 31, 23, 59, 59), ActiveSupport::TimeZone["UTC"]), [ 1, "a" ], { "a" => 1 } ].each do |arg| @@ -21,7 +24,7 @@ class ArgumentSerializationTest < ActiveSupport::TestCase end end - [ :a, Object.new, self, Person.find("5").to_gid ].each do |arg| + [ Object.new, self, Person.find("5").to_gid ].each do |arg| test "does not serialize #{arg.class}" do assert_raises ActiveJob::SerializationError do ActiveJob::Arguments.serialize [ arg ] @@ -46,6 +49,49 @@ class ArgumentSerializationTest < ActiveSupport::TestCase assert_arguments_roundtrip([a: 1, "b" => 2]) end + test "serialize a hash" do + symbol_key = { a: 1 } + string_key = { "a" => 1 } + indifferent_access = { a: 1 }.with_indifferent_access + + assert_equal( + { "a" => 1, "_aj_symbol_keys" => ["a"] }, + ActiveJob::Arguments.serialize([symbol_key]).first + ) + assert_equal( + { "a" => 1, "_aj_symbol_keys" => [] }, + ActiveJob::Arguments.serialize([string_key]).first + ) + assert_equal( + { "a" => 1, "_aj_hash_with_indifferent_access" => true }, + ActiveJob::Arguments.serialize([indifferent_access]).first + ) + end + + test "deserialize a hash" do + symbol_key = { "a" => 1, "_aj_symbol_keys" => ["a"] } + string_key = { "a" => 1, "_aj_symbol_keys" => [] } + another_string_key = { "a" => 1 } + indifferent_access = { "a" => 1, "_aj_hash_with_indifferent_access" => true } + + assert_equal( + { a: 1 }, + ActiveJob::Arguments.deserialize([symbol_key]).first + ) + assert_equal( + { "a" => 1 }, + ActiveJob::Arguments.deserialize([string_key]).first + ) + assert_equal( + { "a" => 1 }, + ActiveJob::Arguments.deserialize([another_string_key]).first + ) + assert_equal( + { "a" => 1 }, + ActiveJob::Arguments.deserialize([indifferent_access]).first + ) + end + test "should maintain hash with indifferent access" do symbol_key = { a: 1 } string_key = { "a" => 1 } @@ -56,6 +102,14 @@ class ArgumentSerializationTest < ActiveSupport::TestCase assert_instance_of ActiveSupport::HashWithIndifferentAccess, perform_round_trip([indifferent_access]).first end + test "should maintain time with zone" do + Time.use_zone "Alaska" do + time_with_zone = Time.new(2002, 10, 31, 2, 2, 2).in_time_zone + assert_instance_of ActiveSupport::TimeWithZone, perform_round_trip([time_with_zone]).first + assert_arguments_unchanged time_with_zone + end + end + test "should disallow non-string/symbol hash keys" do assert_raises ActiveJob::SerializationError do ActiveJob::Arguments.serialize [ { 1 => 2 } ] diff --git a/activejob/test/cases/exceptions_test.rb b/activejob/test/cases/exceptions_test.rb index 7a3c372143..bc33d79f61 100644 --- a/activejob/test/cases/exceptions_test.rb +++ b/activejob/test/cases/exceptions_test.rb @@ -58,10 +58,17 @@ class ExceptionsTest < ActiveJob::TestCase end end + test "custom handling of discarded job" do + perform_enqueued_jobs do + RetryJob.perform_later "CustomDiscardableError", 2 + assert_equal "Dealt with a job that was discarded in a custom way", JobBuffer.last_value + end + end + test "custom handling of job that exceeds retry attempts" do perform_enqueued_jobs do RetryJob.perform_later "CustomCatchError", 6 - assert_equal "Dealt with a job that failed to retry in a custom way after 6 attempts", JobBuffer.last_value + assert_equal "Dealt with a job that failed to retry in a custom way after 6 attempts. Message: CustomCatchError", JobBuffer.last_value end end diff --git a/activejob/test/cases/job_serialization_test.rb b/activejob/test/cases/job_serialization_test.rb index 440051c427..5c9994508e 100644 --- a/activejob/test/cases/job_serialization_test.rb +++ b/activejob/test/cases/job_serialization_test.rb @@ -54,4 +54,11 @@ class JobSerializationTest < ActiveSupport::TestCase job.provider_job_id = "some value set by adapter" assert_equal job.provider_job_id, job.serialize["provider_job_id"] end + + test "serialize stores the current timezone" do + Time.use_zone "Hawaii" do + job = HelloJob.new + assert_equal "Hawaii", job.serialize["timezone"] + end + end end diff --git a/activejob/test/cases/serializers_test.rb b/activejob/test/cases/serializers_test.rb new file mode 100644 index 0000000000..bee0c061bd --- /dev/null +++ b/activejob/test/cases/serializers_test.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +require "helper" +require "active_job/serializers" + +class SerializersTest < ActiveSupport::TestCase + class DummyValueObject + attr_accessor :value + + def initialize(value) + @value = value + end + + def ==(other) + self.value == other.value + end + end + + class DummySerializer < ActiveJob::Serializers::ObjectSerializer + def serialize(object) + super({ "value" => object.value }) + end + + def deserialize(hash) + DummyValueObject.new(hash["value"]) + end + + private + + def klass + DummyValueObject + end + end + + setup do + @value_object = DummyValueObject.new 123 + @original_serializers = ActiveJob::Serializers.serializers + end + + teardown do + ActiveJob::Serializers._additional_serializers = @original_serializers + end + + test "can't serialize unknown object" do + assert_raises ActiveJob::SerializationError do + ActiveJob::Serializers.serialize @value_object + end + end + + test "will serialize objects with serializers registered" do + ActiveJob::Serializers.add_serializers DummySerializer + + assert_equal( + { "_aj_serialized" => "SerializersTest::DummySerializer", "value" => 123 }, + ActiveJob::Serializers.serialize(@value_object) + ) + end + + test "won't deserialize unknown hash" do + hash = { "_dummy_serializer" => 123, "_aj_symbol_keys" => [] } + error = assert_raises(ArgumentError) do + ActiveJob::Serializers.deserialize(hash) + end + assert_equal( + 'Serializer name is not present in the argument: {"_dummy_serializer"=>123, "_aj_symbol_keys"=>[]}', + error.message + ) + end + + test "won't deserialize unknown serializer" do + hash = { "_aj_serialized" => "DoNotExist", "value" => 123 } + error = assert_raises(ArgumentError) do + ActiveJob::Serializers.deserialize(hash) + end + assert_equal( + "Serializer DoNotExist is not known", + error.message + ) + end + + test "will deserialize know serialized objects" do + ActiveJob::Serializers.add_serializers DummySerializer + hash = { "_aj_serialized" => "SerializersTest::DummySerializer", "value" => 123 } + assert_equal DummyValueObject.new(123), ActiveJob::Serializers.deserialize(hash) + end + + test "adds new serializer" do + ActiveJob::Serializers.add_serializers DummySerializer + assert ActiveJob::Serializers.serializers.include?(DummySerializer) + end + + test "can't add serializer with the same key twice" do + ActiveJob::Serializers.add_serializers DummySerializer + assert_no_difference(-> { ActiveJob::Serializers.serializers.size }) do + ActiveJob::Serializers.add_serializers DummySerializer + end + end +end diff --git a/activejob/test/cases/timezones_test.rb b/activejob/test/cases/timezones_test.rb new file mode 100644 index 0000000000..e2095b020d --- /dev/null +++ b/activejob/test/cases/timezones_test.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require "helper" +require "jobs/timezone_dependent_job" + +class TimezonesTest < ActiveSupport::TestCase + setup do + JobBuffer.clear + end + + test "it performs the job in the given timezone" do + job = TimezoneDependentJob.new("2018-01-01T00:00:00Z") + job.timezone = "London" + job.perform_now + + assert_equal "Happy New Year!", JobBuffer.last_value + + job = TimezoneDependentJob.new("2018-01-01T00:00:00Z") + job.timezone = "Eastern Time (US & Canada)" + job.perform_now + + assert_equal "Just 5 hours to go", JobBuffer.last_value + end +end diff --git a/activejob/test/integration/queuing_test.rb b/activejob/test/integration/queuing_test.rb index 0d8aa336a6..32afb5ca62 100644 --- a/activejob/test/integration/queuing_test.rb +++ b/activejob/test/integration/queuing_test.rb @@ -45,6 +45,13 @@ class QueuingTest < ActiveSupport::TestCase end end + test "should supply a wrapped class name to DelayedJob" do + skip unless adapter_is?(:delayed_job) + ::HelloJob.perform_later + job = Delayed::Job.first + assert_match(/HelloJob \[[0-9a-f-]+\] from DelayedJob\(default\) with arguments: \[\]/, job.name) + end + test "resque JobWrapper should have instance variable queue" do skip unless adapter_is?(:resque) job = ::HelloJob.set(wait: 5.seconds).perform_later @@ -75,7 +82,7 @@ class QueuingTest < ActiveSupport::TestCase end test "should supply a provider_job_id when available for immediate jobs" do - skip unless adapter_is?(:async, :delayed_job, :sidekiq, :qu, :que, :queue_classic) + skip unless adapter_is?(:async, :delayed_job, :sidekiq, :que, :queue_classic) test_job = TestJob.perform_later @id assert test_job.provider_job_id, "Provider job id should be set by provider" end @@ -103,6 +110,22 @@ class QueuingTest < ActiveSupport::TestCase end end + test "current timezone is kept while running perform_later" do + skip if adapter_is?(:inline) + + begin + current_zone = Time.zone + Time.zone = "Hawaii" + + TestJob.perform_later @id + wait_for_jobs_to_finish_for(5.seconds) + assert job_executed + assert_equal "Hawaii", job_executed_in_timezone + ensure + Time.zone = current_zone + end + end + test "should run job with higher priority first" do skip unless adapter_is?(:delayed_job, :que) diff --git a/activejob/test/jobs/retry_job.rb b/activejob/test/jobs/retry_job.rb index a12d09779b..82b80fe12b 100644 --- a/activejob/test/jobs/retry_job.rb +++ b/activejob/test/jobs/retry_job.rb @@ -10,6 +10,7 @@ class ExponentialWaitTenAttemptsError < StandardError; end class CustomWaitTenAttemptsError < StandardError; end class CustomCatchError < StandardError; end class DiscardableError < StandardError; end +class CustomDiscardableError < StandardError; end class RetryJob < ActiveJob::Base retry_on DefaultsError @@ -17,8 +18,9 @@ class RetryJob < ActiveJob::Base retry_on ShortWaitTenAttemptsError, wait: 1.second, attempts: 10 retry_on ExponentialWaitTenAttemptsError, wait: :exponentially_longer, attempts: 10 retry_on CustomWaitTenAttemptsError, wait: ->(executions) { executions * 2 }, attempts: 10 - retry_on(CustomCatchError) { |job, exception| JobBuffer.add("Dealt with a job that failed to retry in a custom way after #{job.arguments.second} attempts") } + retry_on(CustomCatchError) { |job, exception| JobBuffer.add("Dealt with a job that failed to retry in a custom way after #{job.arguments.second} attempts. Message: #{exception.message}") } discard_on DiscardableError + discard_on(CustomDiscardableError) { |job, exception| JobBuffer.add("Dealt with a job that was discarded in a custom way") } def perform(raising, attempts) if executions < attempts diff --git a/activejob/test/jobs/timezone_dependent_job.rb b/activejob/test/jobs/timezone_dependent_job.rb new file mode 100644 index 0000000000..41f473d533 --- /dev/null +++ b/activejob/test/jobs/timezone_dependent_job.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require_relative "../support/job_buffer" + +class TimezoneDependentJob < ActiveJob::Base + def perform(now) + now = now.in_time_zone + new_year = localtime(2018, 1, 1) + + if now >= new_year + JobBuffer.add("Happy New Year!") + else + JobBuffer.add("Just #{(new_year - now).div(3600)} hours to go") + end + end + + private + + def localtime(*args) + Time.zone ? Time.zone.local(*args) : Time.utc(*args) + end +end diff --git a/activejob/test/support/delayed_job/delayed/backend/test.rb b/activejob/test/support/delayed_job/delayed/backend/test.rb index 4721c1cc17..1691896b7c 100644 --- a/activejob/test/support/delayed_job/delayed/backend/test.rb +++ b/activejob/test/support/delayed_job/delayed/backend/test.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -#copied from https://github.com/collectiveidea/delayed_job/blob/master/spec/delayed/backend/test.rb +# copied from https://github.com/collectiveidea/delayed_job/blob/master/spec/delayed/backend/test.rb require "ostruct" # An in-memory backend suitable only for testing. Tries to behave as if it were an ORM. @@ -77,7 +77,7 @@ module Delayed self.locked_by = worker end - return true + true end def self.db_time_now diff --git a/activejob/test/support/integration/adapters/qu.rb b/activejob/test/support/integration/adapters/qu.rb deleted file mode 100644 index 67db03e279..0000000000 --- a/activejob/test/support/integration/adapters/qu.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -module QuJobsManager - def setup - require "qu-rails" - require "qu-redis" - ActiveJob::Base.queue_adapter = :qu - ENV["REDISTOGO_URL"] = "redis://127.0.0.1:6379/12" - backend = Qu::Backend::Redis.new - backend.namespace = "active_jobs_int_test" - Qu.backend = backend - Qu.logger = Rails.logger - Qu.interval = 0.5 - unless can_run? - puts "Cannot run integration tests for qu. To be able to run integration tests for qu you need to install and start redis.\n" - exit - end - end - - def clear_jobs - Qu.clear "integration_tests" - end - - def start_workers - @thread = Thread.new { Qu::Worker.new("integration_tests").start } - end - - def stop_workers - @thread.kill - end - - def can_run? - begin - Qu.backend.connection.client.connect - rescue - return false - end - true - end -end diff --git a/activejob/test/support/integration/adapters/resque.rb b/activejob/test/support/integration/adapters/resque.rb index 484b476567..2ed8302277 100644 --- a/activejob/test/support/integration/adapters/resque.rb +++ b/activejob/test/support/integration/adapters/resque.rb @@ -3,11 +3,12 @@ module ResqueJobsManager def setup ActiveJob::Base.queue_adapter = :resque - Resque.redis = Redis::Namespace.new "active_jobs_int_test", redis: Redis.connect(url: "redis://:password@127.0.0.1:6379/12", thread_safe: true) + Resque.redis = Redis::Namespace.new "active_jobs_int_test", redis: Redis.new(url: "redis://127.0.0.1:6379/12", thread_safe: true) Resque.logger = Rails.logger unless can_run? puts "Cannot run integration tests for resque. To be able to run integration tests for resque you need to install and start redis.\n" - exit + status = ENV["CI"] ? false : true + exit status end end @@ -41,11 +42,8 @@ module ResqueJobsManager end def can_run? - begin - Resque.redis.client.connect - rescue - return false - end - true + Resque.redis.ping == "PONG" + rescue + false end end diff --git a/activejob/test/support/integration/adapters/sidekiq.rb b/activejob/test/support/integration/adapters/sidekiq.rb index ceb7fb61f2..c79de12eaf 100644 --- a/activejob/test/support/integration/adapters/sidekiq.rb +++ b/activejob/test/support/integration/adapters/sidekiq.rb @@ -5,20 +5,13 @@ require "sidekiq/api" require "sidekiq/testing" Sidekiq::Testing.disable! -Sidekiq.configure_server do |config| - config.redis = { url: "redis://:password@127.0.0.1:6379/12" } -end - -Sidekiq.configure_client do |config| - config.redis = { url: "redis://:password@127.0.0.1:6379/12" } -end - module SidekiqJobsManager def setup ActiveJob::Base.queue_adapter = :sidekiq unless can_run? puts "Cannot run integration tests for sidekiq. To be able to run integration tests for sidekiq you need to install and start redis.\n" - exit + status = ENV["CI"] ? false : true + exit status end end @@ -58,6 +51,7 @@ module SidekiqJobsManager self_write.puts("TERM") end + require "sidekiq/cli" require "sidekiq/launcher" sidekiq = Sidekiq::Launcher.new(queues: ["integration_tests"], environment: "test", diff --git a/activejob/test/support/integration/dummy_app_template.rb b/activejob/test/support/integration/dummy_app_template.rb index ac382bd1b7..b56dd3e591 100644 --- a/activejob/test/support/integration/dummy_app_template.rb +++ b/activejob/test/support/integration/dummy_app_template.rb @@ -4,8 +4,6 @@ if ENV["AJ_ADAPTER"] == "delayed_job" generate "delayed_job:active_record", "--quiet" end -rails_command("db:migrate") - initializer "activejob.rb", <<-CODE require "#{File.expand_path("jobs_manager.rb", __dir__)}" JobsManager.current_manager.setup @@ -23,6 +21,7 @@ class TestJob < ActiveJob::Base File.open(Rails.root.join("tmp/\#{x}.new"), "wb+") do |f| f.write Marshal.dump({ "locale" => I18n.locale.to_s || "en", + "timezone" => Time.zone.try(:name) || "UTC", "executed_at" => Time.now.to_r }) end diff --git a/activejob/test/support/integration/helper.rb b/activejob/test/support/integration/helper.rb index a058da141f..a02d874e2e 100644 --- a/activejob/test/support/integration/helper.rb +++ b/activejob/test/support/integration/helper.rb @@ -18,6 +18,7 @@ Rails::Generators::AppGenerator.start args require "#{dummy_app_path}/config/environment.rb" ActiveRecord::Migrator.migrations_paths = [ Rails.root.join("db/migrate").to_s ] +ActiveRecord::Tasks::DatabaseTasks.migrate require "rails/test_help" Rails.backtrace_cleaner.remove_silencers! diff --git a/activejob/test/support/integration/test_case_helpers.rb b/activejob/test/support/integration/test_case_helpers.rb index f02a32a38e..3d9b265b66 100644 --- a/activejob/test/support/integration/test_case_helpers.rb +++ b/activejob/test/support/integration/test_case_helpers.rb @@ -62,4 +62,8 @@ module TestCaseHelpers def job_executed_in_locale(id = @id) job_data(id)["locale"] end + + def job_executed_in_timezone(id = @id) + job_data(id)["timezone"] + end end |