exception_extensions 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +8 -0
- data/exception_extensions.gemspec +1 -1
- data/test/test_exception_extensions.rb +129 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3c47e4bb28d9ae98c08a3615463ca6d6ea68077865d9b924e7de1f832ac8d81
|
4
|
+
data.tar.gz: da3808b89a03780cd2be5c1c6d1572f7bedc0f14835914e537416ae396e0c2f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 62e4fc9e0ac251808dd0066b8b04af90dafd518e0dc1d17192c2514397b27e55003780db474ed26166277d16eb1112b2e394679d132cee8e23c4b9183771d896
|
7
|
+
data.tar.gz: 5badd9bda7a3648965de8107d7aaf4a2812500a21a0869ae9531785c8575fde2cfe09acbd11d7d82d1b5b5ecdda1bae02cf55df8c58b50bf6bc05b88b563ffff
|
data/Rakefile
ADDED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |gem|
|
2
2
|
gem.name = 'exception_extensions'
|
3
|
-
gem.version = '1.0.
|
3
|
+
gem.version = '1.0.1'
|
4
4
|
gem.date = '2019-11-27'
|
5
5
|
gem.summary = 'Useful extensions for Ruby Exceptions'
|
6
6
|
gem.description = 'Useful extensions for Ruby Exceptions; Adds support for Exceptions with multiple causes (useful when executing fan-out operations) and Exception cause traversal.'
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'exception_extensions'
|
3
|
+
|
4
|
+
module ExceptionExtensions
|
5
|
+
class ExceptionExtensionsTest < Minitest::Test
|
6
|
+
|
7
|
+
def test_no_exception_path
|
8
|
+
assert ExceptionPathTraverser.new(nil).to_a.empty?
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_single_exception_path
|
12
|
+
exception = capture_exception { raise A }
|
13
|
+
exception_traverser = ExceptionPathTraverser.new(exception)
|
14
|
+
|
15
|
+
path_array = exception_traverser.to_a
|
16
|
+
assert_equal path_array.size, 1
|
17
|
+
|
18
|
+
path = path_array.first
|
19
|
+
assert_equal path.size, 1
|
20
|
+
assert_equal path.first, exception
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_linear_exception_path
|
24
|
+
exception = capture_exception { reraise_with(C) { reraise_with(B) { raise A } } }
|
25
|
+
exception_traverser = ExceptionPathTraverser.new(exception)
|
26
|
+
|
27
|
+
path_array = exception_traverser.to_a
|
28
|
+
assert_equal path_array.size, 1
|
29
|
+
|
30
|
+
path = path_array.first
|
31
|
+
assert_equal path.size, 3 # there are three exceptions - A, which is reraised with B, which is reraised with C
|
32
|
+
assert_equal path[0], exception
|
33
|
+
assert_equal path[1], exception.cause
|
34
|
+
assert_equal path[2], exception.cause.cause
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_branched_exception_path
|
38
|
+
threads = []
|
39
|
+
exceptions = []
|
40
|
+
exceptions_mutex = Mutex.new
|
41
|
+
threads << Thread.new do
|
42
|
+
capture_exception_in_array(exceptions, exceptions_mutex) { reraise_with(C) { reraise_with(B) { raise A } } }
|
43
|
+
end
|
44
|
+
threads << Thread.new do
|
45
|
+
capture_exception_in_array(exceptions, exceptions_mutex) { reraise_with(C) { reraise_with(F) { reraise_with(G) { raise H } } } }
|
46
|
+
end
|
47
|
+
threads << Thread.new do
|
48
|
+
capture_exception_in_array(exceptions, exceptions_mutex) { raise H }
|
49
|
+
end
|
50
|
+
threads << Thread.new do
|
51
|
+
capture_exception_in_array(exceptions, exceptions_mutex) do
|
52
|
+
internal_threads = []
|
53
|
+
internal_exceptions = []
|
54
|
+
internal_exceptions_mutex = Mutex.new
|
55
|
+
internal_threads << Thread.new do
|
56
|
+
capture_exception_in_array(internal_exceptions, internal_exceptions_mutex) { reraise_with(C) { reraise_with(B) { raise A } } }
|
57
|
+
end
|
58
|
+
internal_threads << Thread.new do
|
59
|
+
capture_exception_in_array(internal_exceptions, internal_exceptions_mutex) { raise H }
|
60
|
+
end
|
61
|
+
internal_threads.map(&:join)
|
62
|
+
raise I.new(internal_exceptions)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
threads.map(&:join)
|
66
|
+
exception = capture_exception do
|
67
|
+
reraise_with(D) do
|
68
|
+
raise E.new(exceptions)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
exception_traverser = ExceptionPathTraverser.new(exception)
|
72
|
+
path_array = exception_traverser.to_a
|
73
|
+
expected_path_classes = [[D, E, C, B, A], [D, E, C, F, G, H], [D, E, H], [D, E, I, C, B, A], [D, E, I, H]]
|
74
|
+
expected_number_of_paths = expected_path_classes.size
|
75
|
+
actual_path_classes = path_array.map { |path| path.map(&:class) }
|
76
|
+
actual_number_of_paths = actual_path_classes.size
|
77
|
+
assert_equal expected_number_of_paths, actual_number_of_paths
|
78
|
+
expected_path_classes.each do |path_class_array|
|
79
|
+
assert actual_path_classes.include?(path_class_array)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
class A < StandardError;
|
86
|
+
end
|
87
|
+
class B < StandardError;
|
88
|
+
end
|
89
|
+
class C < StandardError;
|
90
|
+
end
|
91
|
+
class D < StandardError;
|
92
|
+
end
|
93
|
+
class E < StandardErrorCollection;
|
94
|
+
end
|
95
|
+
class F < StandardError;
|
96
|
+
end
|
97
|
+
class G < StandardError;
|
98
|
+
end
|
99
|
+
class H < StandardError;
|
100
|
+
end
|
101
|
+
class I < StandardErrorCollection;
|
102
|
+
end
|
103
|
+
|
104
|
+
def capture_exception_in_array(array, mutex)
|
105
|
+
yield
|
106
|
+
rescue => exc
|
107
|
+
mutex.synchronize { array << exc }
|
108
|
+
end
|
109
|
+
|
110
|
+
def capture_exception
|
111
|
+
captured_exception = nil
|
112
|
+
begin
|
113
|
+
yield
|
114
|
+
rescue => exc
|
115
|
+
captured_exception = exc
|
116
|
+
end
|
117
|
+
captured_exception
|
118
|
+
end
|
119
|
+
|
120
|
+
def reraise_with(exc)
|
121
|
+
begin
|
122
|
+
yield
|
123
|
+
rescue
|
124
|
+
raise exc
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: exception_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cloud 66
|
@@ -20,12 +20,14 @@ files:
|
|
20
20
|
- ".gitignore"
|
21
21
|
- LICENSE
|
22
22
|
- README.md
|
23
|
+
- Rakefile
|
23
24
|
- exception_extensions.gemspec
|
24
25
|
- lib/exception_extensions.rb
|
25
26
|
- lib/exception_extensions/cause_enumerable.rb
|
26
27
|
- lib/exception_extensions/exception_path_traverser.rb
|
27
28
|
- lib/exception_extensions/exception_traverser.rb
|
28
29
|
- lib/exception_extensions/standard_error_collection.rb
|
30
|
+
- test/test_exception_extensions.rb
|
29
31
|
homepage: https://github.com/cloud66-oss/exception_extensions
|
30
32
|
licenses:
|
31
33
|
- Apache-2.0
|
@@ -45,8 +47,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
47
|
- !ruby/object:Gem::Version
|
46
48
|
version: '0'
|
47
49
|
requirements: []
|
48
|
-
|
49
|
-
rubygems_version: 2.7.9
|
50
|
+
rubygems_version: 3.0.4
|
50
51
|
signing_key:
|
51
52
|
specification_version: 4
|
52
53
|
summary: Useful extensions for Ruby Exceptions
|