diff options
author | David RodrÃguez <[email protected]> | 2023-06-30 21:22:32 +0200 |
---|---|---|
committer | Hiroshi SHIBATA <[email protected]> | 2023-12-13 12:16:55 +0900 |
commit | a7c9163b5d87c0420e54cd75668bceb8f39a578a (patch) | |
tree | e96aedac02e9249b7b130dc43be49343d2b75cdf | |
parent | 90317472e87692fff1c864d129d60130dc3bab2c (diff) |
[rubygems/rubygems] Vendor timeout in RubyGems too
https://github.com/rubygems/rubygems/commit/e2e7440ede
-rw-r--r-- | lib/rubygems/command_manager.rb | 4 | ||||
-rw-r--r-- | lib/rubygems/gemcutter_utilities/webauthn_poller.rb | 4 | ||||
-rw-r--r-- | lib/rubygems/net-http/lib/net/http.rb | 24 | ||||
-rw-r--r-- | lib/rubygems/net-http/lib/net/http/responses.rb | 4 | ||||
-rw-r--r-- | lib/rubygems/net-protocol/lib/net/protocol.rb | 14 | ||||
-rw-r--r-- | lib/rubygems/remote_fetcher.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/request.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/timeout.rb | 3 | ||||
-rw-r--r-- | lib/rubygems/timeout/lib/timeout.rb | 199 | ||||
-rw-r--r-- | test/rubygems/test_gem_remote_fetcher.rb | 4 | ||||
-rw-r--r-- | test/rubygems/test_gem_request_connection_pools.rb | 6 | ||||
-rw-r--r-- | test/rubygems/test_gem_silent_ui.rb | 1 | ||||
-rw-r--r-- | test/rubygems/test_gem_stream_ui.rb | 14 | ||||
-rw-r--r-- | test/rubygems/test_webauthn_poller.rb | 8 |
14 files changed, 245 insertions, 44 deletions
diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb index 1028283ffa..ee28dce626 100644 --- a/lib/rubygems/command_manager.rb +++ b/lib/rubygems/command_manager.rb @@ -106,7 +106,7 @@ class Gem::CommandManager # Register all the subcommands supported by the gem command. def initialize - require "timeout" + require_relative "timeout" @commands = {} BUILTIN_COMMANDS.each do |name| @@ -149,7 +149,7 @@ class Gem::CommandManager def run(args, build_args=nil) process_args(args, build_args) - rescue StandardError, Timeout::Error => ex + rescue StandardError, Gem::Timeout::Error => ex if ex.respond_to?(:detailed_message) msg = ex.detailed_message(highlight: false).sub(/\A(.*?)(?: \(.+?\))/) { $1 } else diff --git a/lib/rubygems/gemcutter_utilities/webauthn_poller.rb b/lib/rubygems/gemcutter_utilities/webauthn_poller.rb index 6d875e84f2..0fdd1d5bf4 100644 --- a/lib/rubygems/gemcutter_utilities/webauthn_poller.rb +++ b/lib/rubygems/gemcutter_utilities/webauthn_poller.rb @@ -37,13 +37,13 @@ module Gem::GemcutterUtilities thread.abort_on_exception = true thread.report_on_exception = false thread[:otp] = new(options, host).poll_for_otp(webauthn_url, credentials) - rescue Gem::WebauthnVerificationError, Timeout::Error => e + rescue Gem::WebauthnVerificationError, Gem::Timeout::Error => e thread[:error] = e end end def poll_for_otp(webauthn_url, credentials) - Timeout.timeout(TIMEOUT_IN_SECONDS) do + Gem::Timeout.timeout(TIMEOUT_IN_SECONDS) do loop do response = webauthn_verification_poll_response(webauthn_url, credentials) raise Gem::WebauthnVerificationError, response.message unless response.is_a?(Gem::Net::HTTPSuccess) diff --git a/lib/rubygems/net-http/lib/net/http.rb b/lib/rubygems/net-http/lib/net/http.rb index c1ec1e20ef..be932ed854 100644 --- a/lib/rubygems/net-http/lib/net/http.rb +++ b/lib/rubygems/net-http/lib/net/http.rb @@ -46,7 +46,7 @@ module Gem::Net #:nodoc: # == Strategies # # - If you will make only a few GET requests, - # consider using {OpenURI}[https://docs.ruby-lang.org/en/master/OpenURI.html]. + # consider using {OpenURI}[rdoc-ref:OpenURI]. # - If you will make only a few requests of all kinds, # consider using the various singleton convenience methods in this class. # Each of the following methods automatically starts and finishes @@ -106,7 +106,7 @@ module Gem::Net #:nodoc: # It consists of some or all of: scheme, hostname, path, query, and fragment; # see {URI syntax}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax]. # - # A Ruby {URI::Generic}[https://docs.ruby-lang.org/en/master/URI/Generic.html] object + # A Ruby {URI::Generic}[rdoc-ref:URI::Generic] object # represents an internet URI. # It provides, among others, methods # +scheme+, +hostname+, +path+, +query+, and +fragment+. @@ -1217,7 +1217,7 @@ module Gem::Net #:nodoc: # - The name of an encoding. # - An alias for an encoding name. # - # See {Encoding}[https://docs.ruby-lang.org/en/master/Encoding.html]. + # See {Encoding}[rdoc-ref:Encoding]. # # Examples: # @@ -1308,7 +1308,7 @@ module Gem::Net #:nodoc: # Sets the maximum number of times to retry an idempotent request in case of # \Gem::Net::ReadTimeout, IOError, EOFError, Errno::ECONNRESET, # Errno::ECONNABORTED, Errno::EPIPE, OpenSSL::SSL::SSLError, - # Timeout::Error. + # Gem::Timeout::Error. # The initial value is 1. # # Argument +retries+ must be a non-negative numeric value: @@ -1490,11 +1490,11 @@ module Gem::Net #:nodoc: attr_accessor :cert_store # Sets or returns the available SSL ciphers. - # See {OpenSSL::SSL::SSLContext#ciphers=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-ciphers-3D]. + # See {OpenSSL::SSL::SSLContext#ciphers=}[rdoc-ref:OpenSSL::SSL::SSLContext#ciphers-3D]. attr_accessor :ciphers # Sets or returns the extra X509 certificates to be added to the certificate chain. - # See {OpenSSL::SSL::SSLContext#add_certificate}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-add_certificate]. + # See {OpenSSL::SSL::SSLContext#add_certificate}[rdoc-ref:OpenSSL::SSL::SSLContext#add_certificate]. attr_accessor :extra_chain_cert # Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object. @@ -1504,15 +1504,15 @@ module Gem::Net #:nodoc: attr_accessor :ssl_timeout # Sets or returns the SSL version. - # See {OpenSSL::SSL::SSLContext#ssl_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-ssl_version-3D]. + # See {OpenSSL::SSL::SSLContext#ssl_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#ssl_version-3D]. attr_accessor :ssl_version # Sets or returns the minimum SSL version. - # See {OpenSSL::SSL::SSLContext#min_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-min_version-3D]. + # See {OpenSSL::SSL::SSLContext#min_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#min_version-3D]. attr_accessor :min_version # Sets or returns the maximum SSL version. - # See {OpenSSL::SSL::SSLContext#max_version=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#method-i-max_version-3D]. + # See {OpenSSL::SSL::SSLContext#max_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#max_version-3D]. attr_accessor :max_version # Sets or returns the callback for the server certification verification. @@ -1528,7 +1528,7 @@ module Gem::Net #:nodoc: # Sets or returns whether to verify that the server certificate is valid # for the hostname. - # See {OpenSSL::SSL::SSLContext#verify_hostname=}[https://docs.ruby-lang.org/en/master/OpenSSL/SSL/SSLContext.html#attribute-i-verify_mode]. + # See {OpenSSL::SSL::SSLContext#verify_hostname=}[rdoc-ref:OpenSSL::SSL::SSLContext#attribute-i-verify_mode]. attr_accessor :verify_hostname # Returns the X509 certificate chain (an array of strings) @@ -1598,7 +1598,7 @@ module Gem::Net #:nodoc: end debug "opening connection to #{conn_addr}:#{conn_port}..." - s = Timeout.timeout(@open_timeout, Gem::Net::OpenTimeout) { + s = Gem::Timeout.timeout(@open_timeout, Gem::Net::OpenTimeout) { begin TCPSocket.open(conn_addr, conn_port, @local_host, @local_port) rescue => e @@ -2358,7 +2358,7 @@ module Gem::Net #:nodoc: Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE, Errno::ETIMEDOUT, # avoid a dependency on OpenSSL defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : IOError, - Timeout::Error => exception + Gem::Timeout::Error => exception if count < max_retries && IDEMPOTENT_METHODS_.include?(req.method) count += 1 @socket.close if @socket diff --git a/lib/rubygems/net-http/lib/net/http/responses.rb b/lib/rubygems/net-http/lib/net/http/responses.rb index c2814544d4..95ce9dd46a 100644 --- a/lib/rubygems/net-http/lib/net/http/responses.rb +++ b/lib/rubygems/net-http/lib/net/http/responses.rb @@ -589,7 +589,7 @@ module Gem::Net HAS_BODY = true end - # Response class for <tt>Request Timeout</tt> responses (status code 408). + # Response class for <tt>Request Gem::Timeout</tt> responses (status code 408). # # The server timed out waiting for the request. # @@ -980,7 +980,7 @@ module Gem::Net HAS_BODY = true end - # Response class for <tt>Gateway Timeout</tt> responses (status code 504). + # Response class for <tt>Gateway Gem::Timeout</tt> responses (status code 504). # # The server was acting as a gateway or proxy # and did not receive a timely response from the upstream server. diff --git a/lib/rubygems/net-protocol/lib/net/protocol.rb b/lib/rubygems/net-protocol/lib/net/protocol.rb index e21f4af705..53d34d8d98 100644 --- a/lib/rubygems/net-protocol/lib/net/protocol.rb +++ b/lib/rubygems/net-protocol/lib/net/protocol.rb @@ -20,7 +20,7 @@ # require 'socket' -require 'timeout' +require_relative '../../../timeout/lib/timeout' require 'io/wait' module Gem::Net # :nodoc: @@ -68,16 +68,16 @@ module Gem::Net # :nodoc: ProtocRetryError = ProtoRetriableError ## - # OpenTimeout, a subclass of Timeout::Error, is raised if a connection cannot + # OpenTimeout, a subclass of Gem::Timeout::Error, is raised if a connection cannot # be created within the open_timeout. - class OpenTimeout < Timeout::Error; end + class OpenTimeout < Gem::Timeout::Error; end ## - # ReadTimeout, a subclass of Timeout::Error, is raised if a chunk of the + # ReadTimeout, a subclass of Gem::Timeout::Error, is raised if a chunk of the # response cannot be read within the read_timeout. - class ReadTimeout < Timeout::Error + class ReadTimeout < Gem::Timeout::Error def initialize(io = nil) @io = io end @@ -93,10 +93,10 @@ module Gem::Net # :nodoc: end ## - # WriteTimeout, a subclass of Timeout::Error, is raised if a chunk of the + # WriteTimeout, a subclass of Gem::Timeout::Error, is raised if a chunk of the # response cannot be written within the write_timeout. Not raised on Windows. - class WriteTimeout < Timeout::Error + class WriteTimeout < Gem::Timeout::Error def initialize(io = nil) @io = io end diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 71b7ec2c1a..8f14d7bc8d 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -261,7 +261,7 @@ class Gem::RemoteFetcher end data - rescue Timeout::Error, IOError, SocketError, SystemCallError, + rescue Gem::Timeout::Error, IOError, SocketError, SystemCallError, *(OpenSSL::SSL::SSLError if Gem::HAVE_OPENSSL) => e raise FetchError.new("#{e.class}: #{e}", uri) end diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb index b44d9d6611..dec0c35c63 100644 --- a/lib/rubygems/request.rb +++ b/lib/rubygems/request.rb @@ -244,7 +244,7 @@ class Gem::Request # HACK: work around EOFError bug in Gem::Net::HTTP # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible # to install gems. - rescue EOFError, Timeout::Error, + rescue EOFError, Gem::Timeout::Error, Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE requests = @requests[connection.object_id] diff --git a/lib/rubygems/timeout.rb b/lib/rubygems/timeout.rb new file mode 100644 index 0000000000..33c54a2aa4 --- /dev/null +++ b/lib/rubygems/timeout.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +require_relative "timeout/lib/timeout" diff --git a/lib/rubygems/timeout/lib/timeout.rb b/lib/rubygems/timeout/lib/timeout.rb new file mode 100644 index 0000000000..24d877b994 --- /dev/null +++ b/lib/rubygems/timeout/lib/timeout.rb @@ -0,0 +1,199 @@ +# frozen_string_literal: true +# Timeout long-running blocks +# +# == Synopsis +# +# require 'rubygems/timeout/lib/timeout' +# status = Gem::Timeout::timeout(5) { +# # Something that should be interrupted if it takes more than 5 seconds... +# } +# +# == Description +# +# Gem::Timeout provides a way to auto-terminate a potentially long-running +# operation if it hasn't finished in a fixed amount of time. +# +# Previous versions didn't use a module for namespacing, however +# #timeout is provided for backwards compatibility. You +# should prefer Gem::Timeout.timeout instead. +# +# == Copyright +# +# Copyright:: (C) 2000 Network Applied Communication Laboratory, Inc. +# Copyright:: (C) 2000 Information-technology Promotion Agency, Japan + +module Gem::Timeout + VERSION = "0.4.1" + + # Internal error raised to when a timeout is triggered. + class ExitException < Exception + def exception(*) + self + end + end + + # Raised by Gem::Timeout.timeout when the block times out. + class Error < RuntimeError + def self.handle_timeout(message) + exc = ExitException.new(message) + + begin + yield exc + rescue ExitException => e + raise new(message) if exc.equal?(e) + raise + end + end + end + + # :stopdoc: + CONDVAR = ConditionVariable.new + QUEUE = Queue.new + QUEUE_MUTEX = Mutex.new + TIMEOUT_THREAD_MUTEX = Mutex.new + @timeout_thread = nil + private_constant :CONDVAR, :QUEUE, :QUEUE_MUTEX, :TIMEOUT_THREAD_MUTEX + + class Request + attr_reader :deadline + + def initialize(thread, timeout, exception_class, message) + @thread = thread + @deadline = GET_TIME.call(Process::CLOCK_MONOTONIC) + timeout + @exception_class = exception_class + @message = message + + @mutex = Mutex.new + @done = false # protected by @mutex + end + + def done? + @mutex.synchronize do + @done + end + end + + def expired?(now) + now >= @deadline + end + + def interrupt + @mutex.synchronize do + unless @done + @thread.raise @exception_class, @message + @done = true + end + end + end + + def finished + @mutex.synchronize do + @done = true + end + end + end + private_constant :Request + + def self.create_timeout_thread + watcher = Thread.new do + requests = [] + while true + until QUEUE.empty? and !requests.empty? # wait to have at least one request + req = QUEUE.pop + requests << req unless req.done? + end + closest_deadline = requests.min_by(&:deadline).deadline + + now = 0.0 + QUEUE_MUTEX.synchronize do + while (now = GET_TIME.call(Process::CLOCK_MONOTONIC)) < closest_deadline and QUEUE.empty? + CONDVAR.wait(QUEUE_MUTEX, closest_deadline - now) + end + end + + requests.each do |req| + req.interrupt if req.expired?(now) + end + requests.reject!(&:done?) + end + end + ThreadGroup::Default.add(watcher) unless watcher.group.enclosed? + watcher.name = "Gem::Timeout stdlib thread" + watcher.thread_variable_set(:"\0__detached_thread__", true) + watcher + end + private_class_method :create_timeout_thread + + def self.ensure_timeout_thread_created + unless @timeout_thread and @timeout_thread.alive? + TIMEOUT_THREAD_MUTEX.synchronize do + unless @timeout_thread and @timeout_thread.alive? + @timeout_thread = create_timeout_thread + end + end + end + end + + # We keep a private reference so that time mocking libraries won't break + # Gem::Timeout. + GET_TIME = Process.method(:clock_gettime) + private_constant :GET_TIME + + # :startdoc: + + # Perform an operation in a block, raising an error if it takes longer than + # +sec+ seconds to complete. + # + # +sec+:: Number of seconds to wait for the block to terminate. Any number + # may be used, including Floats to specify fractional seconds. A + # value of 0 or +nil+ will execute the block without any timeout. + # +klass+:: Exception Class to raise if the block fails to terminate + # in +sec+ seconds. Omitting will use the default, Gem::Timeout::Error + # +message+:: Error message to raise with Exception Class. + # Omitting will use the default, "execution expired" + # + # Returns the result of the block *if* the block completed before + # +sec+ seconds, otherwise throws an exception, based on the value of +klass+. + # + # The exception thrown to terminate the given block cannot be rescued inside + # the block unless +klass+ is given explicitly. However, the block can use + # ensure to prevent the handling of the exception. For that reason, this + # method cannot be relied on to enforce timeouts for untrusted blocks. + # + # If a scheduler is defined, it will be used to handle the timeout by invoking + # Scheduler#timeout_after. + # + # Note that this is both a method of module Gem::Timeout, so you can <tt>include + # Gem::Timeout</tt> into your classes so they have a #timeout method, as well as + # a module method, so you can call it directly as Gem::Timeout.timeout(). + def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ + return yield(sec) if sec == nil or sec.zero? + + message ||= "execution expired" + + if Fiber.respond_to?(:current_scheduler) && (scheduler = Fiber.current_scheduler)&.respond_to?(:timeout_after) + return scheduler.timeout_after(sec, klass || Error, message, &block) + end + + Gem::Timeout.ensure_timeout_thread_created + perform = Proc.new do |exc| + request = Request.new(Thread.current, sec, exc, message) + QUEUE_MUTEX.synchronize do + QUEUE << request + CONDVAR.signal + end + begin + return yield(sec) + ensure + request.finished + end + end + + if klass + perform.call(klass) + else + Error.handle_timeout(message, &perform) + end + end + module_function :timeout +end diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb index 9c879ed428..42565b0b16 100644 --- a/test/rubygems/test_gem_remote_fetcher.rb +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -554,7 +554,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== @fetcher = fetcher def fetcher.fetch_http(uri, mtime = nil, head = nil) - raise Timeout::Error, "timed out" + raise Gem::Timeout::Error, "timed out" end url = "http://example.com/uri" @@ -563,7 +563,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== fetcher.fetch_path url end - assert_match(/Timeout::Error: timed out \(#{Regexp.escape url}\)\z/, + assert_match(/Gem::Timeout::Error: timed out \(#{Regexp.escape url}\)\z/, e.message) assert_equal url, e.uri end diff --git a/test/rubygems/test_gem_request_connection_pools.rb b/test/rubygems/test_gem_request_connection_pools.rb index a3d9b79f35..4e1e7de07b 100644 --- a/test/rubygems/test_gem_request_connection_pools.rb +++ b/test/rubygems/test_gem_request_connection_pools.rb @@ -2,7 +2,7 @@ require_relative "helper" require "rubygems/request" -require "timeout" +require "rubygems/timeout" class TestGemRequestConnectionPool < Gem::TestCase class FakeHttp @@ -141,8 +141,8 @@ class TestGemRequestConnectionPool < Gem::TestCase pool.checkout Thread.new do - assert_raise(Timeout::Error) do - Timeout.timeout(1) do + assert_raise(Gem::Timeout::Error) do + Gem::Timeout.timeout(1) do pool.checkout end end diff --git a/test/rubygems/test_gem_silent_ui.rb b/test/rubygems/test_gem_silent_ui.rb index 94411f30b3..001a73eb51 100644 --- a/test/rubygems/test_gem_silent_ui.rb +++ b/test/rubygems/test_gem_silent_ui.rb @@ -2,7 +2,6 @@ require_relative "helper" require "rubygems/user_interaction" -require "timeout" class TestGemSilentUI < Gem::TestCase def setup diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb index 00cc64629a..e34110fe84 100644 --- a/test/rubygems/test_gem_stream_ui.rb +++ b/test/rubygems/test_gem_stream_ui.rb @@ -2,7 +2,7 @@ require_relative "helper" require "rubygems/user_interaction" -require "timeout" +require "rubygems/timeout/lib/timeout" class TestGemStreamUI < Gem::TestCase # increase timeout with RJIT for --jit-wait testing @@ -40,7 +40,7 @@ class TestGemStreamUI < Gem::TestCase end def test_ask - Timeout.timeout(5) do + Gem::Timeout.timeout(5) do expected_answer = "Arthur, King of the Britons" @in.string = "#{expected_answer}\n" actual_answer = @sui.ask("What is your name?") @@ -51,14 +51,14 @@ class TestGemStreamUI < Gem::TestCase def test_ask_no_tty @in.tty = false - Timeout.timeout(SHORT_TIMEOUT) do + Gem::Timeout.timeout(SHORT_TIMEOUT) do answer = @sui.ask("what is your favorite color?") assert_nil answer end end def test_ask_for_password - Timeout.timeout(5) do + Gem::Timeout.timeout(5) do expected_answer = "Arthur, King of the Britons" @in.string = "#{expected_answer}\n" actual_answer = @sui.ask_for_password("What is your name?") @@ -69,7 +69,7 @@ class TestGemStreamUI < Gem::TestCase def test_ask_for_password_no_tty @in.tty = false - Timeout.timeout(SHORT_TIMEOUT) do + Gem::Timeout.timeout(SHORT_TIMEOUT) do answer = @sui.ask_for_password("what is the airspeed velocity of an unladen swallow?") assert_nil answer end @@ -78,7 +78,7 @@ class TestGemStreamUI < Gem::TestCase def test_ask_yes_no_no_tty_with_default @in.tty = false - Timeout.timeout(SHORT_TIMEOUT) do + Gem::Timeout.timeout(SHORT_TIMEOUT) do answer = @sui.ask_yes_no("do coconuts migrate?", false) assert_equal false, answer @@ -90,7 +90,7 @@ class TestGemStreamUI < Gem::TestCase def test_ask_yes_no_no_tty_without_default @in.tty = false - Timeout.timeout(SHORT_TIMEOUT) do + Gem::Timeout.timeout(SHORT_TIMEOUT) do assert_raise(Gem::OperationNotSupportedError) do @sui.ask_yes_no("do coconuts migrate?") end diff --git a/test/rubygems/test_webauthn_poller.rb b/test/rubygems/test_webauthn_poller.rb index 23c24faa11..23290d8ea1 100644 --- a/test/rubygems/test_webauthn_poller.rb +++ b/test/rubygems/test_webauthn_poller.rb @@ -45,8 +45,8 @@ class WebauthnPollerTest < Gem::TestCase end def test_poll_thread_timeout_error - raise_error = ->(*_args) { raise Timeout::Error, "execution expired" } - Timeout.stub(:timeout, raise_error) do + raise_error = ->(*_args) { raise Gem::Timeout::Error, "execution expired" } + Gem::Timeout.stub(:timeout, raise_error) do thread = Gem::GemcutterUtilities::WebauthnPoller.poll_thread({}, @host, @webauthn_url, @credentials) thread.join assert_equal thread[:error].message, "execution expired" @@ -72,8 +72,8 @@ class WebauthnPollerTest < Gem::TestCase msg: "OK" ) - assert_raise Timeout::Error do - Timeout.timeout(0.1) do + assert_raise Gem::Timeout::Error do + Gem::Timeout.timeout(0.1) do Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials) end end |