power_assert 0.1.4 → 0.2.0
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/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
|