mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
acd462fc23
Ref: https://github.com/rails/rails/pull/43282 Ref: https://github.com/rails/rails/pull/43561 It can be legitimate for subscriber to want to bubble up some exception to the caller, so wrapping it change the exception class which might break the calling code expecting a specific error. We can minimize this by only using InstrumentationSubscriberError when more than one subscriber raised.
200 lines
5.7 KiB
Ruby
200 lines
5.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative "../abstract_unit"
|
|
|
|
module ActiveSupport
|
|
module Notifications
|
|
class EventedTest < ActiveSupport::TestCase
|
|
# we expect all exception types to be handled, so test with the most basic type
|
|
class BadListenerException < Exception; end
|
|
|
|
class Listener
|
|
attr_reader :events
|
|
|
|
def initialize
|
|
@events = []
|
|
end
|
|
|
|
def start(name, id, payload)
|
|
@events << [:start, name, id, payload]
|
|
end
|
|
|
|
def finish(name, id, payload)
|
|
@events << [:finish, name, id, payload]
|
|
end
|
|
end
|
|
|
|
class ListenerWithTimedSupport < Listener
|
|
def call(name, start, finish, id, payload)
|
|
@events << [:call, name, start, finish, id, payload]
|
|
end
|
|
end
|
|
|
|
class BadStartListener < Listener
|
|
def start(name, id, payload)
|
|
raise BadListenerException
|
|
end
|
|
|
|
def finish(name, id, payload)
|
|
end
|
|
end
|
|
|
|
class BadFinishListener < Listener
|
|
def start(name, id, payload)
|
|
end
|
|
|
|
def finish(name, id, payload)
|
|
raise BadListenerException
|
|
end
|
|
end
|
|
|
|
def test_evented_listener
|
|
notifier = Fanout.new
|
|
listener = Listener.new
|
|
notifier.subscribe "hi", listener
|
|
notifier.start "hi", 1, {}
|
|
notifier.start "hi", 2, {}
|
|
notifier.finish "hi", 2, {}
|
|
notifier.finish "hi", 1, {}
|
|
|
|
assert_equal 4, listener.events.length
|
|
assert_equal [
|
|
[:start, "hi", 1, {}],
|
|
[:start, "hi", 2, {}],
|
|
[:finish, "hi", 2, {}],
|
|
[:finish, "hi", 1, {}],
|
|
], listener.events
|
|
end
|
|
|
|
def test_evented_listener_no_events
|
|
notifier = Fanout.new
|
|
listener = Listener.new
|
|
notifier.subscribe "hi", listener
|
|
notifier.start "world", 1, {}
|
|
assert_equal 0, listener.events.length
|
|
end
|
|
|
|
def test_listen_to_everything
|
|
notifier = Fanout.new
|
|
listener = Listener.new
|
|
notifier.subscribe nil, listener
|
|
notifier.start "hello", 1, {}
|
|
notifier.start "world", 1, {}
|
|
notifier.finish "world", 1, {}
|
|
notifier.finish "hello", 1, {}
|
|
|
|
assert_equal 4, listener.events.length
|
|
assert_equal [
|
|
[:start, "hello", 1, {}],
|
|
[:start, "world", 1, {}],
|
|
[:finish, "world", 1, {}],
|
|
[:finish, "hello", 1, {}],
|
|
], listener.events
|
|
end
|
|
|
|
def test_listen_start_multiple_exception_consistency
|
|
notifier = Fanout.new
|
|
listener = Listener.new
|
|
notifier.subscribe nil, BadStartListener.new
|
|
notifier.subscribe nil, BadStartListener.new
|
|
notifier.subscribe nil, listener
|
|
|
|
error = assert_raises InstrumentationSubscriberError do
|
|
notifier.start "hello", 1, {}
|
|
end
|
|
assert_instance_of BadListenerException, error.cause
|
|
|
|
error = assert_raises InstrumentationSubscriberError do
|
|
notifier.start "world", 1, {}
|
|
end
|
|
assert_instance_of BadListenerException, error.cause
|
|
|
|
notifier.finish "world", 1, {}
|
|
notifier.finish "hello", 1, {}
|
|
|
|
assert_equal 4, listener.events.length
|
|
assert_equal [
|
|
[:start, "hello", 1, {}],
|
|
[:start, "world", 1, {}],
|
|
[:finish, "world", 1, {}],
|
|
[:finish, "hello", 1, {}],
|
|
], listener.events
|
|
end
|
|
|
|
def test_listen_finish_multiple_exception_consistency
|
|
notifier = Fanout.new
|
|
listener = Listener.new
|
|
notifier.subscribe nil, BadFinishListener.new
|
|
notifier.subscribe nil, BadFinishListener.new
|
|
notifier.subscribe nil, listener
|
|
|
|
notifier.start "hello", 1, {}
|
|
notifier.start "world", 1, {}
|
|
error = assert_raises InstrumentationSubscriberError do
|
|
notifier.finish "world", 1, {}
|
|
end
|
|
assert_instance_of BadListenerException, error.cause
|
|
|
|
error = assert_raises InstrumentationSubscriberError do
|
|
notifier.finish "hello", 1, {}
|
|
end
|
|
assert_instance_of BadListenerException, error.cause
|
|
|
|
assert_equal 4, listener.events.length
|
|
assert_equal [
|
|
[:start, "hello", 1, {}],
|
|
[:start, "world", 1, {}],
|
|
[:finish, "world", 1, {}],
|
|
[:finish, "hello", 1, {}],
|
|
], listener.events
|
|
end
|
|
|
|
def test_evented_listener_priority
|
|
notifier = Fanout.new
|
|
listener = ListenerWithTimedSupport.new
|
|
notifier.subscribe "hi", listener
|
|
|
|
notifier.start "hi", 1, {}
|
|
notifier.finish "hi", 1, {}
|
|
|
|
assert_equal [
|
|
[:start, "hi", 1, {}],
|
|
[:finish, "hi", 1, {}]
|
|
], listener.events
|
|
end
|
|
|
|
def test_listen_to_regexp
|
|
notifier = Fanout.new
|
|
listener = Listener.new
|
|
notifier.subscribe(/[a-z]*.world/, listener)
|
|
notifier.start("hi.world", 1, {})
|
|
notifier.finish("hi.world", 2, {})
|
|
notifier.start("hello.world", 1, {})
|
|
notifier.finish("hello.world", 2, {})
|
|
|
|
assert_equal [
|
|
[:start, "hi.world", 1, {}],
|
|
[:finish, "hi.world", 2, {}],
|
|
[:start, "hello.world", 1, {}],
|
|
[:finish, "hello.world", 2, {}]
|
|
], listener.events
|
|
end
|
|
|
|
def test_listen_to_regexp_with_exclusions
|
|
notifier = Fanout.new
|
|
listener = Listener.new
|
|
notifier.subscribe(/[a-z]*.world/, listener)
|
|
notifier.unsubscribe("hi.world")
|
|
notifier.start("hi.world", 1, {})
|
|
notifier.finish("hi.world", 2, {})
|
|
notifier.start("hello.world", 1, {})
|
|
notifier.finish("hello.world", 2, {})
|
|
|
|
assert_equal [
|
|
[:start, "hello.world", 1, {}],
|
|
[:finish, "hello.world", 2, {}]
|
|
], listener.events
|
|
end
|
|
end
|
|
end
|
|
end
|