invoca-utils 0.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 +7 -0
- data/.gitignore +23 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +25 -0
- data/Rakefile +18 -0
- data/invoca-utils.gemspec +30 -0
- data/lib/invoca/utils/diff.rb +377 -0
- data/lib/invoca/utils/log_error_stub.rb +84 -0
- data/lib/invoca/utils/version.rb +5 -0
- data/lib/invoca/utils.rb +10 -0
- data/test/test_helper.rb +5 -0
- data/test/unit/utils_test.rb +5 -0
- metadata +170 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 60e1c062370766eca1fa617f36be49862eaf88ac
|
4
|
+
data.tar.gz: e459f4db3a562dd66d965f781471931b69721f22
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 13f0207b9e47f0197970d027c6ce5956a8513f9cc4d6771a880470d57ef0bc0f54cc851b3220d683b98025790d49ff2f05c21a19c34e1ce4887073c10f83ea0f
|
7
|
+
data.tar.gz: 917afbc8c609b0361cc3a5e1c373c7164de6b2350c6f2209ca3ede0288393c9c3b8d4e02e50625b85bd89973302e15fe0559f570af9cd4846d8c907c94126bcd
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
.DS_Store
|
2
|
+
*.gem
|
3
|
+
*.rbc
|
4
|
+
.bundle
|
5
|
+
.config
|
6
|
+
.yardoc
|
7
|
+
Gemfile.lock
|
8
|
+
InstalledFiles
|
9
|
+
_yardoc
|
10
|
+
coverage
|
11
|
+
doc/
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
*.bundle
|
20
|
+
*.so
|
21
|
+
*.o
|
22
|
+
*.a
|
23
|
+
mkmf.log
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Invoca, Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Invoca::Utils
|
2
|
+
|
3
|
+
A public collection of helpers used in multiple project.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'invoca-utils'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install invoca-utils
|
18
|
+
|
19
|
+
## Contributing
|
20
|
+
|
21
|
+
1. Fork it ( https://github.com/[my-github-username]/invoca-utils/fork )
|
22
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
23
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
24
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
25
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
namespace :test do
|
6
|
+
|
7
|
+
Rake::TestTask.new do |t|
|
8
|
+
t.name = :unit
|
9
|
+
t.libs << "test"
|
10
|
+
t.pattern = 'test/unit/**/*_test.rb'
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
Rake::Task['test:unit'].comment = "Run the unit tests"
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
task :default => 'test:unit'
|
18
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'invoca/utils/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "invoca-utils"
|
8
|
+
spec.version = Invoca::Utils::VERSION
|
9
|
+
spec.authors = ["Cary Penniman"]
|
10
|
+
spec.email = ["cpenniman@invoca.com"]
|
11
|
+
spec.summary = %q{A public collection of helpers used in multiple projects}
|
12
|
+
spec.description = %q{A public collection of helpers used in multiple projects}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
|
24
|
+
spec.add_development_dependency "test-unit", "= 1.2.3"
|
25
|
+
spec.add_development_dependency "rr", "=1.1.2"
|
26
|
+
spec.add_development_dependency "shoulda", "= 3.5.0"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
spec.add_development_dependency "ruby-prof"
|
29
|
+
spec.add_development_dependency "minitest"
|
30
|
+
end
|
@@ -0,0 +1,377 @@
|
|
1
|
+
# adapted from http://users.cybercity.dk/~dsl8950/ruby/diff-0.3.tar.gz
|
2
|
+
|
3
|
+
class Diff
|
4
|
+
|
5
|
+
VERSION = 0.3
|
6
|
+
|
7
|
+
def self.lcs(a, b)
|
8
|
+
astart = 0
|
9
|
+
bstart = 0
|
10
|
+
afinish = a.length-1
|
11
|
+
bfinish = b.length-1
|
12
|
+
lcs = []
|
13
|
+
|
14
|
+
# First we prune off any common elements at the beginning
|
15
|
+
while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
|
16
|
+
lcs[astart] = bstart
|
17
|
+
astart += 1
|
18
|
+
bstart += 1
|
19
|
+
end
|
20
|
+
|
21
|
+
# now the end
|
22
|
+
while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
|
23
|
+
lcs[afinish] = bfinish
|
24
|
+
afinish -= 1
|
25
|
+
bfinish -= 1
|
26
|
+
end
|
27
|
+
|
28
|
+
bmatches = reverse_hash(b, bstart..bfinish)
|
29
|
+
thresh = []
|
30
|
+
links = []
|
31
|
+
|
32
|
+
(astart..afinish).each { |aindex|
|
33
|
+
aelem = a[aindex]
|
34
|
+
next unless bmatches.has_key? aelem
|
35
|
+
k = nil
|
36
|
+
bmatches[aelem].reverse.each { |bindex|
|
37
|
+
if k && (thresh[k] > bindex) && (thresh[k-1] < bindex)
|
38
|
+
thresh[k] = bindex
|
39
|
+
else
|
40
|
+
k = replacenextlarger(thresh, bindex, k)
|
41
|
+
end
|
42
|
+
links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
if !thresh.empty?
|
47
|
+
link = links[thresh.length-1]
|
48
|
+
while link
|
49
|
+
lcs[link[1]] = link[2]
|
50
|
+
link = link[0]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
return lcs
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.nested_compare( subtractions, additions, index )
|
58
|
+
subtraction = subtractions[index]
|
59
|
+
addition = additions[index]
|
60
|
+
if subtraction.is_a?( Array ) && addition.is_a?( Array )
|
61
|
+
return "Nested array diff:\n#{ compare( subtraction, addition ) }\n"
|
62
|
+
elsif subtraction.is_a?( Hash ) && addition.is_a?( Hash )
|
63
|
+
return "Nested hash diff:\n#{ compare( subtraction, addition ) }\n"
|
64
|
+
else
|
65
|
+
""
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.format(value)
|
70
|
+
value.is_a?(Numeric) || value.is_a?(String) ? value : value.inspect
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.compare arg1, arg2, options={}
|
74
|
+
result = ''
|
75
|
+
if arg1 != arg2
|
76
|
+
if arg1.class == arg2.class || (arg1.is_a?(Hash) && arg2.is_a?(Hash)) || (arg1.is_a?(Array) && arg2.is_a?(Array)) # Hash and Array are equivalent when specialized
|
77
|
+
case arg1
|
78
|
+
when Array
|
79
|
+
diff_obj = Diff.new(arg1, arg2)
|
80
|
+
summary = diff_obj.summary
|
81
|
+
curr_diff = nil
|
82
|
+
(arg1 + [nil]).each_with_index do |arg, index|
|
83
|
+
if curr_diff.nil? || index > curr_diff[1].last
|
84
|
+
curr_diff = summary.shift
|
85
|
+
end
|
86
|
+
unless curr_diff && (curr_diff[1].first..curr_diff[1].last) === index
|
87
|
+
result << " #{format arg}\n" unless arg.nil? || options[:short_description]
|
88
|
+
end
|
89
|
+
if curr_diff && curr_diff[1].first == index
|
90
|
+
verb, a_range, b_range, del, add = curr_diff
|
91
|
+
result <<
|
92
|
+
case verb
|
93
|
+
when 'd'
|
94
|
+
del.map { |t| "- #{format t}\n"}.join
|
95
|
+
when 'a'
|
96
|
+
add.map { |t| "+ #{format t}\n"}.join +
|
97
|
+
(arg.nil? ? '' : " #{format arg}\n")
|
98
|
+
when 'c'
|
99
|
+
del.map_with_index { |t,index| "- #{format t}\n#{ nested_compare( del, add, index ) }"}.join +
|
100
|
+
add.map_with_index { |t,index| "+ #{format t}\n"}.join
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
summary.empty? or raise "Summary left: #{summary.inspect}"
|
105
|
+
when Hash
|
106
|
+
arg1.each do |key, value|
|
107
|
+
if arg2.has_key? key
|
108
|
+
result += "[#{key.inspect}] #{compare value, arg2[key]};\n" if value != arg2[key]
|
109
|
+
else
|
110
|
+
result += "[#{key.inspect}] expected #{value.inspect}, was missing;\n"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
(arg2.keys - arg1.keys).each do |key|
|
114
|
+
result += "[#{key.inspect}] not expected, was #{arg2[key].inspect};\n"
|
115
|
+
end
|
116
|
+
else
|
117
|
+
result = "expected #{arg1.inspect}, was #{arg2.inspect} "
|
118
|
+
end
|
119
|
+
elsif arg1.class.in?([Float,BigDecimal]) && arg2.class.in?([Float,BigDecimal])
|
120
|
+
result = "expected #{arg1.class}: #{arg1.to_s}, was #{arg2.class}: #{arg2.to_s} "
|
121
|
+
else
|
122
|
+
result = "expected #{arg1.class}:#{arg1.inspect}, was #{arg2.class}:#{arg2.inspect} "
|
123
|
+
end
|
124
|
+
end
|
125
|
+
result
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
def makediff(a, b)
|
130
|
+
lcs = self.class.lcs(a, b)
|
131
|
+
ai = bi = 0
|
132
|
+
while ai < lcs.length
|
133
|
+
if lcs[ai]
|
134
|
+
while bi < lcs[ai]
|
135
|
+
discardb(bi, b[bi])
|
136
|
+
bi += 1
|
137
|
+
end
|
138
|
+
match
|
139
|
+
bi += 1
|
140
|
+
else
|
141
|
+
discarda(ai, a[ai])
|
142
|
+
end
|
143
|
+
ai += 1
|
144
|
+
end
|
145
|
+
while ai < a.length
|
146
|
+
discarda(ai, a[ai])
|
147
|
+
ai += 1
|
148
|
+
end
|
149
|
+
while bi < b.length
|
150
|
+
discardb(bi, b[bi])
|
151
|
+
bi += 1
|
152
|
+
end
|
153
|
+
match
|
154
|
+
end
|
155
|
+
|
156
|
+
def compact!
|
157
|
+
diffs = []
|
158
|
+
@diffs.each do |diff|
|
159
|
+
puts "compacting #{diff.inspect}"
|
160
|
+
i = 0
|
161
|
+
curdiff = []
|
162
|
+
while i < diff.length
|
163
|
+
action = diff[i][0]
|
164
|
+
s = @difftype.is_a?(String) ? diff[i][2,1] : [diff[i][2]]
|
165
|
+
offset = diff[i][1]
|
166
|
+
last = offset
|
167
|
+
i += 1
|
168
|
+
while diff[i] && diff[i][0] == action && diff[i][1] == last+1
|
169
|
+
s << diff[i][2]
|
170
|
+
last = diff[i][1]
|
171
|
+
i += 1
|
172
|
+
end
|
173
|
+
curdiff.push [action, offset, s]
|
174
|
+
end
|
175
|
+
diffs.push curdiff
|
176
|
+
end
|
177
|
+
@diffs = diffs
|
178
|
+
self
|
179
|
+
end
|
180
|
+
|
181
|
+
def compact
|
182
|
+
result = self.dup
|
183
|
+
result.compact!
|
184
|
+
result
|
185
|
+
end
|
186
|
+
|
187
|
+
def summary
|
188
|
+
result = []
|
189
|
+
b_offset = 0
|
190
|
+
@diffs.each do |block|
|
191
|
+
del = []
|
192
|
+
add = []
|
193
|
+
block.each do |diff|
|
194
|
+
case diff[0]
|
195
|
+
when "-"
|
196
|
+
del << diff[2]
|
197
|
+
when "+"
|
198
|
+
add << diff[2]
|
199
|
+
end
|
200
|
+
end
|
201
|
+
first = block[0][1]
|
202
|
+
verb, a_range, b_range =
|
203
|
+
if del.empty?
|
204
|
+
[ 'a', [first-b_offset,first-b_offset], [first, first+add.size-1] ]
|
205
|
+
elsif add.empty?
|
206
|
+
[ 'd', [first, first+del.size-1], [first+b_offset, first+b_offset] ]
|
207
|
+
else
|
208
|
+
[ 'c', [first, first+del.size-1], [first+b_offset, first+b_offset+add.size-1] ]
|
209
|
+
end
|
210
|
+
b_offset = b_offset + add.size - del.size
|
211
|
+
result << [verb, a_range, b_range, del, add]
|
212
|
+
end
|
213
|
+
result
|
214
|
+
end
|
215
|
+
|
216
|
+
attr_reader :diffs, :difftype
|
217
|
+
|
218
|
+
def initialize(a, b)
|
219
|
+
@difftype = a.class
|
220
|
+
@diffs = []
|
221
|
+
@curdiffs = []
|
222
|
+
makediff(a, b)
|
223
|
+
end
|
224
|
+
|
225
|
+
def match
|
226
|
+
@diffs << @curdiffs unless @curdiffs.empty?
|
227
|
+
@curdiffs = []
|
228
|
+
end
|
229
|
+
|
230
|
+
def discarda(i, elem)
|
231
|
+
@curdiffs.push ['-', i, elem]
|
232
|
+
end
|
233
|
+
|
234
|
+
def discardb(i, elem)
|
235
|
+
@curdiffs.push ['+', i, elem]
|
236
|
+
end
|
237
|
+
|
238
|
+
def inspect
|
239
|
+
@diffs.inspect
|
240
|
+
end
|
241
|
+
|
242
|
+
# Create a hash that maps elements of the array to arrays of indices
|
243
|
+
# where the elements are found.
|
244
|
+
|
245
|
+
def self.reverse_hash(lhs, range = nil)
|
246
|
+
range ||= (0...lhs.length)
|
247
|
+
revmap = {}
|
248
|
+
range.each { |i|
|
249
|
+
elem = lhs[i]
|
250
|
+
if revmap.has_key? elem
|
251
|
+
revmap[elem].push i
|
252
|
+
else
|
253
|
+
revmap[elem] = [i]
|
254
|
+
end
|
255
|
+
}
|
256
|
+
return revmap
|
257
|
+
end
|
258
|
+
|
259
|
+
def self.replacenextlarger(lhs, value, high = nil)
|
260
|
+
high ||= lhs.length
|
261
|
+
if lhs.empty? || value > lhs[-1]
|
262
|
+
lhs.push value
|
263
|
+
return high
|
264
|
+
end
|
265
|
+
# binary search for replacement point
|
266
|
+
low = 0
|
267
|
+
while low < high
|
268
|
+
index = (high+low)/2
|
269
|
+
found = lhs[index]
|
270
|
+
return nil if value == found
|
271
|
+
if value > found
|
272
|
+
low = index + 1
|
273
|
+
else
|
274
|
+
high = index
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
lhs[low] = value
|
279
|
+
# $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_high-low} off )\n"
|
280
|
+
# $stderr.puts lhs.inspect
|
281
|
+
#gets
|
282
|
+
#p length - low
|
283
|
+
return low
|
284
|
+
end
|
285
|
+
|
286
|
+
def self.patch(lhs, diff)
|
287
|
+
newary = nil
|
288
|
+
if diff.difftype == String
|
289
|
+
newary = diff.difftype.new('')
|
290
|
+
else
|
291
|
+
newary = diff.difftype.new
|
292
|
+
end
|
293
|
+
ai = 0
|
294
|
+
bi = 0
|
295
|
+
diff.diffs.each { |d|
|
296
|
+
d.each { |mod|
|
297
|
+
case mod[0]
|
298
|
+
when '-'
|
299
|
+
while ai < mod[1]
|
300
|
+
newary << lhs[ai]
|
301
|
+
ai += 1
|
302
|
+
bi += 1
|
303
|
+
end
|
304
|
+
ai += 1
|
305
|
+
when '+'
|
306
|
+
while bi < mod[1]
|
307
|
+
newary << lhs[ai]
|
308
|
+
ai += 1
|
309
|
+
bi += 1
|
310
|
+
end
|
311
|
+
newary << mod[2]
|
312
|
+
bi += 1
|
313
|
+
else
|
314
|
+
raise "Unknown diff action"
|
315
|
+
end
|
316
|
+
}
|
317
|
+
}
|
318
|
+
while ai < lhs.length
|
319
|
+
newary << lhs[ai]
|
320
|
+
ai += 1
|
321
|
+
bi += 1
|
322
|
+
end
|
323
|
+
return newary
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
module Diffable
|
328
|
+
def diff(b)
|
329
|
+
Diff.new(self, b)
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
#
|
334
|
+
#class Array
|
335
|
+
# include Diffable
|
336
|
+
#end
|
337
|
+
#
|
338
|
+
#class String
|
339
|
+
# include Diffable
|
340
|
+
#end
|
341
|
+
|
342
|
+
=begin
|
343
|
+
= Diff
|
344
|
+
(({diff.rb})) - computes the differences between two arrays or
|
345
|
+
strings. Copyright (C) 2001 Lars Christensen
|
346
|
+
|
347
|
+
== Synopsis
|
348
|
+
|
349
|
+
diff = Diff.new(a, b)
|
350
|
+
b = a.patch(diff)
|
351
|
+
|
352
|
+
== Class Diff
|
353
|
+
=== Class Methods
|
354
|
+
--- Diff.new(a, b)
|
355
|
+
--- a.diff(b)
|
356
|
+
Creates a Diff object which represent the differences between
|
357
|
+
((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays
|
358
|
+
of any objects, strings, or object of any class that include
|
359
|
+
module ((|Diffable|))
|
360
|
+
|
361
|
+
== Module Diffable
|
362
|
+
The module ((|Diffable|)) is intended to be included in any class for
|
363
|
+
which differences are to be computed. Diffable is included into String
|
364
|
+
and Array when (({diff.rb})) is (({require}))'d.
|
365
|
+
|
366
|
+
Classes including Diffable should implement (({[]})) to get element at
|
367
|
+
integer indices, (({<<})) to append elements to the object and
|
368
|
+
(({ClassName#new})) should accept 0 arguments to create a new empty
|
369
|
+
object.
|
370
|
+
|
371
|
+
=== Instance Methods
|
372
|
+
--- Diffable#patch(diff)
|
373
|
+
Applies the differences from ((|diff|)) to the object ((|obj|))
|
374
|
+
and return the result. ((|obj|)) is not changed. ((|obj|)) and
|
375
|
+
can be either an array or a string, but must match the object
|
376
|
+
from which the ((|diff|)) was created.
|
377
|
+
=end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#
|
2
|
+
# Used by functional tests to track exceptions.
|
3
|
+
#
|
4
|
+
|
5
|
+
module LogErrorStub
|
6
|
+
class UnexpectedExceptionLogged < StandardError; end
|
7
|
+
class ExpectedExceptionNotLogged < StandardError; end
|
8
|
+
|
9
|
+
def setup_log_error_stub
|
10
|
+
clear_exception_whitelist
|
11
|
+
stub_log_error unless respond_to?(:dont_stub_log_error) && dont_stub_log_error
|
12
|
+
end
|
13
|
+
|
14
|
+
def teardown_log_error_stub
|
15
|
+
ExceptionHandling.stub_handler = nil
|
16
|
+
return unless @exception_whitelist
|
17
|
+
@exception_whitelist.each do |item|
|
18
|
+
add_failure("log_error expected #{item[1][:expected]} times with pattern: '#{item[0].is_a?(Regexp) ? item[0].source : item[0]}' #{item[1][:count]} found #{item[1][:found]}") unless item[1][:expected] == item[1][:found]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_accessor :exception_whitelist
|
23
|
+
|
24
|
+
#
|
25
|
+
# Call this function in your functional tests - usually first line after a "should" statement
|
26
|
+
# once called, you can then call expects_exception
|
27
|
+
# By stubbing log error, ExceptionHandling will keep a list of all expected exceptions and
|
28
|
+
# gracefully note their occurrence.
|
29
|
+
#
|
30
|
+
def stub_log_error
|
31
|
+
ExceptionHandling.stub_handler = self
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Gets called by ExceptionHandling::log_error in test mode.
|
36
|
+
# If you have called expects_exception then this function will simply note that an
|
37
|
+
# instance of that exception has occurred - otherwise it will raise (which will
|
38
|
+
# generally result in a 500 return code for your test request)
|
39
|
+
#
|
40
|
+
def handle_stub_log_error(exception_data, always_raise = false)
|
41
|
+
raise_unexpected_exception(exception_data) if always_raise || !exception_filtered?(exception_data)
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Did the calling code call expects_exception on this exception?
|
46
|
+
#
|
47
|
+
def exception_filtered?(exception_data)
|
48
|
+
@exception_whitelist && @exception_whitelist.any? do |expectation|
|
49
|
+
if expectation[0] === exception_data[:error]
|
50
|
+
expectation[1][:found] += 1
|
51
|
+
true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Call this from your test file to declare what exceptions you expect to raise.
|
58
|
+
#
|
59
|
+
def expects_exception(pattern, options = {})
|
60
|
+
@exception_whitelist ||= []
|
61
|
+
expected_count = options[:count] || 1
|
62
|
+
options = {:expected => expected_count, :found => 0}
|
63
|
+
if to_increment = @exception_whitelist.find {|ex| ex[0] == pattern}
|
64
|
+
to_increment[1][:expected] += expected_count
|
65
|
+
else
|
66
|
+
@exception_whitelist << [pattern, options]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def clear_exception_whitelist
|
71
|
+
@exception_whitelist = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def raise_unexpected_exception(exception_data)
|
77
|
+
raise(UnexpectedExceptionLogged,
|
78
|
+
exception_data[:error] + "\n" +
|
79
|
+
"---original backtrace---\n" +
|
80
|
+
exception_data[:backtrace].join("\n") + "\n" +
|
81
|
+
"------")
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/lib/invoca/utils.rb
ADDED
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: invoca-utils
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cary Penniman
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-08-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: test-unit
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.2.3
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.2.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rr
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.1.2
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.1.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: shoulda
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.5.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.5.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: ruby-prof
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: minitest
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: A public collection of helpers used in multiple projects
|
126
|
+
email:
|
127
|
+
- cpenniman@invoca.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- Gemfile
|
134
|
+
- LICENSE.txt
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- invoca-utils.gemspec
|
138
|
+
- lib/invoca/utils.rb
|
139
|
+
- lib/invoca/utils/diff.rb
|
140
|
+
- lib/invoca/utils/log_error_stub.rb
|
141
|
+
- lib/invoca/utils/version.rb
|
142
|
+
- test/test_helper.rb
|
143
|
+
- test/unit/utils_test.rb
|
144
|
+
homepage: ''
|
145
|
+
licenses:
|
146
|
+
- MIT
|
147
|
+
metadata: {}
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">="
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
requirements: []
|
163
|
+
rubyforge_project:
|
164
|
+
rubygems_version: 2.2.2
|
165
|
+
signing_key:
|
166
|
+
specification_version: 4
|
167
|
+
summary: A public collection of helpers used in multiple projects
|
168
|
+
test_files:
|
169
|
+
- test/test_helper.rb
|
170
|
+
- test/unit/utils_test.rb
|