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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dfb5b463a7673303ecb39d0e5a569ad931c1812aae80e5f2be7134071d9ef54b
4
- data.tar.gz: 4b6fead438c2bfdfd27f16597ff4b5cee62be1f0865af63e89c09055ca2cd803
3
+ metadata.gz: c3c47e4bb28d9ae98c08a3615463ca6d6ea68077865d9b924e7de1f832ac8d81
4
+ data.tar.gz: da3808b89a03780cd2be5c1c6d1572f7bedc0f14835914e537416ae396e0c2f3
5
5
  SHA512:
6
- metadata.gz: 5fcfe20cc361dfd5f8aca25c6fae7f6890986016515504409ebba8a89dcc91328d54b07b1ad312a2f5e7df858a7d45e765f74f523d14c2f80afaba8e6f9342ea
7
- data.tar.gz: '003586d841061f163a08b1e60b0190da3cfc27d3f3e645bd3ef2538ab72fb6a9492c43943e1c94f52ba7dd45806e79af5b3989cccff6dd061f3f2d535d01eac3'
6
+ metadata.gz: 62e4fc9e0ac251808dd0066b8b04af90dafd518e0dc1d17192c2514397b27e55003780db474ed26166277d16eb1112b2e394679d132cee8e23c4b9183771d896
7
+ data.tar.gz: 5badd9bda7a3648965de8107d7aaf4a2812500a21a0869ae9531785c8575fde2cfe09acbd11d7d82d1b5b5ecdda1bae02cf55df8c58b50bf6bc05b88b563ffff
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'exception_extensions'
3
- gem.version = '1.0.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.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
- rubyforge_project:
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