power_assert 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +2 -1
- data/Rakefile +1 -1
- data/lib/power_assert.rb +56 -21
- data/lib/power_assert/enable_tracepoint_events.rb +48 -0
- data/lib/power_assert/version.rb +1 -1
- data/test/test_power_assert.rb +82 -3
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 089a171012087ec11186283c05d7cd1b238d56c1
|
4
|
+
data.tar.gz: 6a970dc3416704997c85a5b8361f9481909e7658
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a26ee36c760f14be0a7d4c6ecce7fb8128e1e3834ade0f7ace29b4667885147d807d216d0bf0e95f87a59f8e9d2600c2f425091e8df581b191995d0e51ed825
|
7
|
+
data.tar.gz: 168aa6a21ba264001f63c52d1e66b56f263a4ec6593a23bad3c11e09e1f432960a8f9630e5e36c76d8efe872637bcdcc678b24ef32b3f881dc8cf3f80e5f45df
|
data/README.rdoc
CHANGED
@@ -7,9 +7,10 @@ Power Assert for Ruby.
|
|
7
7
|
* {test-unit-power_assert}[https://github.com/k-tsj/test-unit-power_assert]
|
8
8
|
* {minitest-power_assert}[https://github.com/hsbt/minitest-power_assert]
|
9
9
|
* {pry-power_assert}[https://github.com/yui-knk/pry-power_assert]
|
10
|
+
* {rspec-power_assert}[https://github.com/joker1007/rspec-power_assert]
|
10
11
|
* {power_p}[https://github.com/k-tsj/power_p]
|
11
12
|
|
12
13
|
== Reference
|
13
14
|
* {Power Assert in Ruby (at RubyKaigi 2014) // Speaker Deck}[https://speakerdeck.com/k_tsj/power-assert-in-ruby]
|
14
15
|
|
15
|
-
== Travis Build Status {<img src="https://secure.travis-ci.org/k-tsj/power_assert.png"/>}[http://travis-ci.org/k-tsj/power_assert]
|
16
|
+
== Travis Build Status {<img src="https://secure.travis-ci.org/k-tsj/power_assert.png?branch=master"/>}[http://travis-ci.org/k-tsj/power_assert]
|
data/Rakefile
CHANGED
@@ -4,6 +4,6 @@ require "rake/testtask"
|
|
4
4
|
task :default => :test
|
5
5
|
Rake::TestTask.new do |t|
|
6
6
|
# helper(simplecov) must be required before loading power_assert
|
7
|
-
t.ruby_opts = ["-w", "-r./test/helper"
|
7
|
+
t.ruby_opts = ["-w", "-r./test/helper"]
|
8
8
|
t.test_files = FileList["test/test_*.rb"]
|
9
9
|
end
|
data/lib/power_assert.rb
CHANGED
@@ -9,6 +9,7 @@ rescue
|
|
9
9
|
end
|
10
10
|
|
11
11
|
require 'power_assert/version'
|
12
|
+
require 'power_assert/enable_tracepoint_events'
|
12
13
|
require 'ripper'
|
13
14
|
|
14
15
|
module PowerAssert
|
@@ -21,14 +22,31 @@ module PowerAssert
|
|
21
22
|
yield configuration
|
22
23
|
end
|
23
24
|
|
24
|
-
def start(
|
25
|
-
|
25
|
+
def start(assertion_proc_or_source, assertion_method: nil, source_binding: TOPLEVEL_BINDING)
|
26
|
+
if respond_to?(:clear_global_method_cache, true)
|
27
|
+
clear_global_method_cache
|
28
|
+
end
|
29
|
+
yield Context.new(assertion_proc_or_source, assertion_method, source_binding)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
if defined?(RubyVM) and respond_to?(:using, true)
|
35
|
+
def clear_global_method_cache
|
36
|
+
class << Object.new
|
37
|
+
using Empty
|
38
|
+
end
|
39
|
+
end
|
26
40
|
end
|
27
41
|
end
|
28
42
|
|
29
43
|
Configuration = Struct.new(:lazy_inspection)
|
30
44
|
private_constant :Configuration
|
31
45
|
|
46
|
+
module Empty
|
47
|
+
end
|
48
|
+
private_constant :Empty
|
49
|
+
|
32
50
|
class InspectedValue
|
33
51
|
def initialize(value)
|
34
52
|
@value = value
|
@@ -40,6 +58,22 @@ module PowerAssert
|
|
40
58
|
end
|
41
59
|
private_constant :InspectedValue
|
42
60
|
|
61
|
+
class SafeInspectable
|
62
|
+
def initialize(value)
|
63
|
+
@value = value
|
64
|
+
end
|
65
|
+
|
66
|
+
def inspect
|
67
|
+
@value.inspect
|
68
|
+
rescue NoMethodError
|
69
|
+
InspectationFailure
|
70
|
+
end
|
71
|
+
end
|
72
|
+
private_constant :SafeInspectable
|
73
|
+
|
74
|
+
class InspectationFailure; end
|
75
|
+
private_constant :InspectationFailure
|
76
|
+
|
43
77
|
class Context
|
44
78
|
Value = Struct.new(:name, :value, :column)
|
45
79
|
Ident = Struct.new(:type, :name, :column)
|
@@ -49,26 +83,31 @@ module PowerAssert
|
|
49
83
|
|
50
84
|
attr_reader :message_proc
|
51
85
|
|
52
|
-
def initialize(
|
86
|
+
def initialize(assertion_proc_or_source, assertion_method, source_binding)
|
87
|
+
if assertion_proc_or_source.kind_of?(Proc)
|
88
|
+
@assertion_proc = assertion_proc_or_source
|
89
|
+
@line = nil
|
90
|
+
else
|
91
|
+
@assertion_proc = source_binding.eval "Proc.new {#{assertion_proc_or_source}}"
|
92
|
+
@line = assertion_proc_or_source
|
93
|
+
end
|
53
94
|
path = nil
|
54
95
|
lineno = nil
|
55
|
-
@line = nil
|
56
96
|
methods = nil
|
57
97
|
refs = nil
|
58
98
|
method_ids = nil
|
59
99
|
return_values = []
|
60
100
|
@base_caller_length = -1
|
61
|
-
@assertion_proc = assertion_proc
|
62
101
|
@assertion_method_name = assertion_method.to_s
|
63
102
|
@message_proc = -> {
|
64
103
|
return nil if @base_caller_length < 0
|
65
|
-
@message ||= build_assertion_message(@line || '', methods || [], return_values, refs || [], assertion_proc.binding).freeze
|
104
|
+
@message ||= build_assertion_message(@line || '', methods || [], return_values, refs || [], @assertion_proc.binding).freeze
|
66
105
|
}
|
67
|
-
@proc_local_variables = assertion_proc.binding.eval('local_variables').map(&:to_s)
|
106
|
+
@proc_local_variables = @assertion_proc.binding.eval('local_variables').map(&:to_s)
|
68
107
|
target_thread = Thread.current
|
69
108
|
@trace = TracePoint.new(:return, :c_return) do |tp|
|
70
109
|
next if method_ids and ! method_ids.include?(tp.method_id)
|
71
|
-
locs = tp.binding.eval('caller_locations')
|
110
|
+
locs = tp.binding.eval('::Kernel.caller_locations')
|
72
111
|
current_diff = locs.length - @base_caller_length
|
73
112
|
target_diff = TARGET_CALLER_DIFF[tp.event]
|
74
113
|
is_target_bmethod = current_diff < target_diff
|
@@ -77,13 +116,15 @@ module PowerAssert
|
|
77
116
|
unless path
|
78
117
|
path = locs[idx].path
|
79
118
|
lineno = locs[idx].lineno
|
80
|
-
@line
|
119
|
+
@line ||= open(path).each_line.drop(lineno - 1).first
|
81
120
|
idents = extract_idents(Ripper.sexp(@line))
|
82
121
|
methods, refs = idents.partition {|i| i.type == :method }
|
83
122
|
method_ids = methods.map(&:name).map(&:to_sym).uniq
|
84
123
|
end
|
85
124
|
if path == locs[idx].path and lineno == locs[idx].lineno
|
86
|
-
val = PowerAssert.configuration.lazy_inspection ?
|
125
|
+
val = PowerAssert.configuration.lazy_inspection ?
|
126
|
+
tp.return_value :
|
127
|
+
InspectedValue.new(SafeInspectable.new(tp.return_value).inspect)
|
87
128
|
return_values << Value[tp.method_id.to_s, val, nil]
|
88
129
|
end
|
89
130
|
end
|
@@ -115,10 +156,10 @@ module PowerAssert
|
|
115
156
|
ret << line.chomp
|
116
157
|
ret << sprintf(fmt, vals.each_with_object({}) {|v, h| h[v.column.to_s.to_sym] = '|' }).chomp
|
117
158
|
vals.each do |i|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
159
|
+
inspected_vals = vals.each_with_object({}) do |j, h|
|
160
|
+
h[j.column.to_s.to_sym] = [SafeInspectable.new(i.value).inspect, '|', ' '][i.column <=> j.column]
|
161
|
+
end
|
162
|
+
ret << sprintf(fmt, inspected_vals).rstrip
|
122
163
|
end
|
123
164
|
ret.join("\n")
|
124
165
|
end
|
@@ -186,7 +227,7 @@ module PowerAssert
|
|
186
227
|
when :program
|
187
228
|
_, ((tag0, (tag1, (tag2, (tag3, mname, _)), _), (tag4, _, ss))) = sexp
|
188
229
|
if tag0 == :method_add_block and tag1 == :method_add_arg and tag2 == :fcall and
|
189
|
-
tag3 == :@ident and mname == @assertion_method_name and (tag4 == :brace_block or tag4 == :do_block)
|
230
|
+
(tag3 == :@ident or tag3 == :@const) and mname == @assertion_method_name and (tag4 == :brace_block or tag4 == :do_block)
|
190
231
|
ss.flat_map {|s| extract_idents(s) }
|
191
232
|
else
|
192
233
|
_, (s, *) = sexp
|
@@ -254,9 +295,3 @@ module PowerAssert
|
|
254
295
|
end
|
255
296
|
private_constant :Context
|
256
297
|
end
|
257
|
-
|
258
|
-
if defined? RubyVM
|
259
|
-
RubyVM::InstructionSequence.compile_option = {
|
260
|
-
specialized_instruction: false
|
261
|
-
}
|
262
|
-
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
if defined? RubyVM
|
2
|
+
basic_classes = [
|
3
|
+
Fixnum, Float, String, Array, Hash, Bignum, Symbol, Time, Regexp
|
4
|
+
]
|
5
|
+
|
6
|
+
basic_operators = [
|
7
|
+
:+, :-, :*, :/, :%, :==, :===, :<, :<=, :<<, :[], :[]=,
|
8
|
+
:length, :size, :empty?, :succ, :>, :>=, :!, :!=, :=~, :freeze
|
9
|
+
]
|
10
|
+
|
11
|
+
# set redefined flag
|
12
|
+
basic_classes.each do |klass|
|
13
|
+
basic_operators.each do |bop|
|
14
|
+
if klass.public_method_defined?(bop)
|
15
|
+
klass.instance_method(bop).owner.module_eval do
|
16
|
+
public bop
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# bypass check_cfunc
|
23
|
+
verbose = $VERBOSE
|
24
|
+
begin
|
25
|
+
$VERBOSE = nil
|
26
|
+
module PowerAssert
|
27
|
+
refine BasicObject do
|
28
|
+
def !
|
29
|
+
end
|
30
|
+
|
31
|
+
def ==
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
refine Module do
|
36
|
+
def ==
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
ensure
|
41
|
+
$VERBOSE = verbose
|
42
|
+
end
|
43
|
+
|
44
|
+
# disable optimization
|
45
|
+
RubyVM::InstructionSequence.compile_option = {
|
46
|
+
specialized_instruction: false
|
47
|
+
}
|
48
|
+
end
|
data/lib/power_assert/version.rb
CHANGED
data/test/test_power_assert.rb
CHANGED
@@ -6,7 +6,7 @@ require 'set'
|
|
6
6
|
class TestPowerAssert < Test::Unit::TestCase
|
7
7
|
EXTRACT_METHODS_TEST = [
|
8
8
|
[[[:method, "c", 4], [:method, "b", 2], [:method, "d", 8], [:method, "a", 0]],
|
9
|
-
'a(b(c), d)
|
9
|
+
'a(b(c), d)'],
|
10
10
|
|
11
11
|
[[[:method, "a", 0], [:method, "b", 2], [:method, "d", 6], [:method, "c", 4]],
|
12
12
|
'a.b.c(d)'],
|
@@ -117,14 +117,27 @@ class TestPowerAssert < Test::Unit::TestCase
|
|
117
117
|
|
118
118
|
EXTRACT_METHODS_TEST.each_with_index do |(expect, source), idx|
|
119
119
|
define_method("test_extract_methods_#{'%03d' % idx}") do
|
120
|
-
pa = PowerAssert.const_get(:Context).new(-> { var = nil; -> { var } }.(), nil)
|
120
|
+
pa = PowerAssert.const_get(:Context).new(-> { var = nil; -> { var } }.(), nil, TOPLEVEL_BINDING)
|
121
121
|
pa.instance_variable_set(:@line, source)
|
122
122
|
pa.instance_variable_set(:@assertion_method_name, 'assertion_message')
|
123
123
|
assert_equal expect, pa.send(:extract_idents, Ripper.sexp(source)).map(&:to_a), source
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
|
127
|
+
class BasicObjectSubclass < BasicObject
|
128
|
+
def foo
|
129
|
+
"foo"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def assertion_message(source = nil, source_binding = TOPLEVEL_BINDING, &blk)
|
134
|
+
::PowerAssert.start(source || blk, assertion_method: __callee__, source_binding: source_binding) do |pa|
|
135
|
+
pa.yield
|
136
|
+
pa.message_proc.()
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def Assertion(&blk)
|
128
141
|
::PowerAssert.start(blk, assertion_method: __callee__) do |pa|
|
129
142
|
pa.yield
|
130
143
|
pa.message_proc.()
|
@@ -186,6 +199,24 @@ END
|
|
186
199
|
assertion_message { "0".class }
|
187
200
|
|
188
201
|
|
202
|
+
assert_equal <<END.chomp,
|
203
|
+
"0".class
|
204
|
+
|
|
205
|
+
String
|
206
|
+
END
|
207
|
+
Assertion {
|
208
|
+
"0".class
|
209
|
+
}
|
210
|
+
|
211
|
+
|
212
|
+
assert_equal <<END.chomp,
|
213
|
+
Assertion { "0".class }
|
214
|
+
|
|
215
|
+
String
|
216
|
+
END
|
217
|
+
Assertion { "0".class }
|
218
|
+
|
219
|
+
|
189
220
|
assert_equal <<END.chomp, assertion_message {
|
190
221
|
Set.new == Set.new([0])
|
191
222
|
| | | | |
|
@@ -233,6 +264,54 @@ END
|
|
233
264
|
END
|
234
265
|
bmethod
|
235
266
|
}
|
267
|
+
|
268
|
+
|
269
|
+
assert_equal <<END.chomp,
|
270
|
+
assertion_message { BasicObjectSubclass.new.foo }
|
271
|
+
| | |
|
272
|
+
| | "foo"
|
273
|
+
| PowerAssert::InspectationFailure
|
274
|
+
TestPowerAssert::BasicObjectSubclass
|
275
|
+
END
|
276
|
+
assertion_message { BasicObjectSubclass.new.foo }
|
277
|
+
|
278
|
+
|
279
|
+
if PowerAssert.respond_to?(:clear_global_method_cache, true)
|
280
|
+
3.times do
|
281
|
+
assert_equal <<END.chomp, assertion_message {
|
282
|
+
String == Array
|
283
|
+
| | |
|
284
|
+
| | Array
|
285
|
+
| false
|
286
|
+
String
|
287
|
+
END
|
288
|
+
String == Array
|
289
|
+
}
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
|
294
|
+
a = 0
|
295
|
+
@b = 1
|
296
|
+
@@c = 2
|
297
|
+
$d = 3
|
298
|
+
assert_equal <<END.chomp, assertion_message(<<END, binding)
|
299
|
+
String(a) + String(@b) + String(@@c) + String($d)
|
300
|
+
| | | | | | | | | | |
|
301
|
+
| | | | | | | | | | 3
|
302
|
+
| | | | | | | | | "3"
|
303
|
+
| | | | | | | | "0123"
|
304
|
+
| | | | | | | 2
|
305
|
+
| | | | | | "2"
|
306
|
+
| | | | | "012"
|
307
|
+
| | | | 1
|
308
|
+
| | | "1"
|
309
|
+
| | "01"
|
310
|
+
| 0
|
311
|
+
"0"
|
312
|
+
END
|
313
|
+
String(a) + String(@b) + String(@@c) + String($d)
|
314
|
+
END
|
236
315
|
end
|
237
316
|
|
238
317
|
def test_lazy_inspection
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: power_assert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kazuki Tsujimoto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-unit
|
@@ -71,6 +71,7 @@ files:
|
|
71
71
|
- README.rdoc
|
72
72
|
- Rakefile
|
73
73
|
- lib/power_assert.rb
|
74
|
+
- lib/power_assert/enable_tracepoint_events.rb
|
74
75
|
- lib/power_assert/version.rb
|
75
76
|
- power_assert.gemspec
|
76
77
|
- test/helper.rb
|
@@ -96,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
97
|
version: '0'
|
97
98
|
requirements: []
|
98
99
|
rubyforge_project:
|
99
|
-
rubygems_version: 2.
|
100
|
+
rubygems_version: 2.4.2
|
100
101
|
signing_key:
|
101
102
|
specification_version: 4
|
102
103
|
summary: Power Assert for Ruby
|