From 8e57887eee70e62245b8fd0eb6d95227a8baea61 Mon Sep 17 00:00:00 2001 From: CosmicOppai Date: Mon, 14 Oct 2024 14:45:33 +0530 Subject: [PATCH 1/8] added the check for negative sec --- lib/timeout.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/timeout.rb b/lib/timeout.rb index 6448f4f..17d7b21 100644 --- a/lib/timeout.rb +++ b/lib/timeout.rb @@ -164,6 +164,7 @@ def self.ensure_timeout_thread_created # Timeout into your classes so they have a #timeout method, as well as # a module method, so you can call it directly as Timeout.timeout(). def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ + raise ArgumentError, "Timeout sec must be a positive number" unless sec.is_a?(Numeric) && sec >= 0 return yield(sec) if sec == nil or sec.zero? message ||= "execution expired" From 834254497970b75e2a9376efdedc5b27f8a57723 Mon Sep 17 00:00:00 2001 From: CosmicOppai Date: Mon, 14 Oct 2024 16:23:53 +0530 Subject: [PATCH 2/8] refactor the change to keep the compatability with nil and type-errror and added tests --- lib/timeout.rb | 2 +- test/test_timeout.rb | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/timeout.rb b/lib/timeout.rb index 17d7b21..d7baa9a 100644 --- a/lib/timeout.rb +++ b/lib/timeout.rb @@ -164,7 +164,7 @@ def self.ensure_timeout_thread_created # Timeout into your classes so they have a #timeout method, as well as # a module method, so you can call it directly as Timeout.timeout(). def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ - raise ArgumentError, "Timeout sec must be a positive number" unless sec.is_a?(Numeric) && sec >= 0 + raise ArgumentError, "Timeout sec must be a positive number" if sec.is_a?(Numeric) && sec < 0 return yield(sec) if sec == nil or sec.zero? message ||= "execution expired" diff --git a/test/test_timeout.rb b/test/test_timeout.rb index 34966f9..888489f 100644 --- a/test/test_timeout.rb +++ b/test/test_timeout.rb @@ -1,6 +1,6 @@ # frozen_string_literal: false require 'test/unit' -require 'timeout' +require_relative '../lib/timeout' class TestTimeout < Test::Unit::TestCase @@ -31,6 +31,12 @@ def test_allows_nil_seconds end end + def test_raise_for_neg_second + assert_raise(ArgumentError) do + Timeout.timeout(-1) { sleep(0.01) } + end + end + def test_included c = Class.new do include Timeout From e8a7dbdb874ebfb8e15cb960ebdaff665f561cf8 Mon Sep 17 00:00:00 2001 From: CosmicOppai Date: Mon, 14 Oct 2024 16:24:21 +0530 Subject: [PATCH 3/8] refactor the change to keep the compatability with nil and type-errror and added tests --- test/test_timeout.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_timeout.rb b/test/test_timeout.rb index 888489f..d6c1a1f 100644 --- a/test/test_timeout.rb +++ b/test/test_timeout.rb @@ -1,6 +1,6 @@ # frozen_string_literal: false require 'test/unit' -require_relative '../lib/timeout' +require 'timeout' class TestTimeout < Test::Unit::TestCase From ffc8d7c003c88fa2fecdf3efcb7be2c9ad5c01f2 Mon Sep 17 00:00:00 2001 From: CosmicOppai Date: Tue, 15 Oct 2024 06:21:18 +0530 Subject: [PATCH 4/8] refactor the change to raise for nil and type-errror and added tests --- lib/timeout.rb | 4 ++-- test/test_timeout.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/timeout.rb b/lib/timeout.rb index d7baa9a..f2495d9 100644 --- a/lib/timeout.rb +++ b/lib/timeout.rb @@ -164,8 +164,8 @@ def self.ensure_timeout_thread_created # Timeout into your classes so they have a #timeout method, as well as # a module method, so you can call it directly as Timeout.timeout(). def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ - raise ArgumentError, "Timeout sec must be a positive number" if sec.is_a?(Numeric) && sec < 0 - return yield(sec) if sec == nil or sec.zero? + raise ArgumentError, "Timeout sec must be a positive number" unless sec.is_a?(Numeric) && sec >= 0 + return yield(sec) if sec.zero? message ||= "execution expired" diff --git a/test/test_timeout.rb b/test/test_timeout.rb index d6c1a1f..bc30363 100644 --- a/test/test_timeout.rb +++ b/test/test_timeout.rb @@ -26,7 +26,7 @@ def test_allows_zero_seconds end def test_allows_nil_seconds - assert_nothing_raised do + assert_raise(ArgumentError) do assert_equal :ok, Timeout.timeout(nil){:ok} end end @@ -120,7 +120,7 @@ def test_nested_timeout_which_error_bubbles_up def test_cannot_convert_into_time_interval bug3168 = '[ruby-dev:41010]' def (n = Object.new).zero?; false; end - assert_raise(TypeError, bug3168) {Timeout.timeout(n) { sleep 0.1 }} + assert_raise(ArgumentError, bug3168) {Timeout.timeout(n) { sleep 0.1 }} end def test_skip_rescue_standarderror From f992632cf396b659572384f0c171e2a1f2dfba09 Mon Sep 17 00:00:00 2001 From: CosmicOppai Date: Fri, 18 Oct 2024 01:08:38 +0530 Subject: [PATCH 5/8] updated doc and kept the nil compatiability --- lib/timeout.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/timeout.rb b/lib/timeout.rb index f2495d9..def80df 100644 --- a/lib/timeout.rb +++ b/lib/timeout.rb @@ -141,9 +141,10 @@ def self.ensure_timeout_thread_created # 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 + # +sec+:: Number of seconds to wait for the block to terminate. Any non-negative number + # or nil may be used, including Floats to specify fractional seconds. A # value of 0 or +nil+ will execute the block without any timeout. + # Any negative value will raise the ArgumentError # +klass+:: Exception Class to raise if the block fails to terminate # in +sec+ seconds. Omitting will use the default, Timeout::Error # +message+:: Error message to raise with Exception Class. @@ -164,8 +165,8 @@ def self.ensure_timeout_thread_created # Timeout into your classes so they have a #timeout method, as well as # a module method, so you can call it directly as Timeout.timeout(). def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ - raise ArgumentError, "Timeout sec must be a positive number" unless sec.is_a?(Numeric) && sec >= 0 - return yield(sec) if sec.zero? + raise ArgumentError, "Timeout sec must be a non-negative number" if sec && !(sec.is_a?(Numeric) && sec >= 0) + return yield(sec) if sec == nil or sec.zero? message ||= "execution expired" From c6d121aa1878d1c977d741c5cf17d4146dc69d22 Mon Sep 17 00:00:00 2001 From: CosmicOppai Date: Fri, 18 Oct 2024 01:10:34 +0530 Subject: [PATCH 6/8] updated tests --- test/test_timeout.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_timeout.rb b/test/test_timeout.rb index bc30363..0115686 100644 --- a/test/test_timeout.rb +++ b/test/test_timeout.rb @@ -26,7 +26,7 @@ def test_allows_zero_seconds end def test_allows_nil_seconds - assert_raise(ArgumentError) do + assert_nothing_raised do assert_equal :ok, Timeout.timeout(nil){:ok} end end From 4be6423de4fb144a9aa255ba541683b9c0fb16a4 Mon Sep 17 00:00:00 2001 From: Cosmic Oppai Date: Mon, 18 Nov 2024 15:35:47 +0530 Subject: [PATCH 7/8] updated doc string Co-authored-by: Jeremy Evans --- lib/timeout.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/timeout.rb b/lib/timeout.rb index def80df..23fbc3b 100644 --- a/lib/timeout.rb +++ b/lib/timeout.rb @@ -144,7 +144,7 @@ def self.ensure_timeout_thread_created # +sec+:: Number of seconds to wait for the block to terminate. Any non-negative number # or nil may be used, including Floats to specify fractional seconds. A # value of 0 or +nil+ will execute the block without any timeout. - # Any negative value will raise the ArgumentError + # Any negative number will raise an ArgumentError. # +klass+:: Exception Class to raise if the block fails to terminate # in +sec+ seconds. Omitting will use the default, Timeout::Error # +message+:: Error message to raise with Exception Class. From 7d2af46a00861322150a61bc1557e966c68dd102 Mon Sep 17 00:00:00 2001 From: Cosmic Oppai Date: Tue, 19 Nov 2024 01:56:21 +0530 Subject: [PATCH 8/8] removed the non numeric check Co-authored-by: Jeremy Evans --- lib/timeout.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/timeout.rb b/lib/timeout.rb index 23fbc3b..a1595a8 100644 --- a/lib/timeout.rb +++ b/lib/timeout.rb @@ -165,8 +165,8 @@ def self.ensure_timeout_thread_created # Timeout into your classes so they have a #timeout method, as well as # a module method, so you can call it directly as Timeout.timeout(). def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+ - raise ArgumentError, "Timeout sec must be a non-negative number" if sec && !(sec.is_a?(Numeric) && sec >= 0) return yield(sec) if sec == nil or sec.zero? + raise ArgumentError, "Timeout sec must be a non-negative number" if 0 > sec message ||= "execution expired"