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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1afb2223a3e268c8295564a49a13c7feff085da7
4
- data.tar.gz: d37fc4cfd92f123df5863ce90ed70e68da566a34
3
+ metadata.gz: 089a171012087ec11186283c05d7cd1b238d56c1
4
+ data.tar.gz: 6a970dc3416704997c85a5b8361f9481909e7658
5
5
  SHA512:
6
- metadata.gz: 72b22a8fe4dcf9905a19b22b6081af7273fdba4ddfdea9b7cca07c852ed3c6a5bfb5ab2db6042079a95e4e78f18736d0a034a7384aec170eab6ca16b32a4cfa5
7
- data.tar.gz: 4946106cb77a3f81a457a8585f63e1c58ae81a2773d9065e58dce7e95b1a422cfa549668f38b4e5e5af1e2eb064b17bfa4abe63d60fe6a8d99d7abde86e7c33e
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", "-rpower_assert"]
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(assertion_proc, assertion_method: nil)
25
- yield Context.new(assertion_proc, assertion_method)
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(assertion_proc, assertion_method)
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 = open(path).each_line.drop(lineno - 1).first
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 ? tp.return_value : InspectedValue.new(tp.return_value.inspect)
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
- ret << sprintf(fmt,
119
- vals.each_with_object({}) do |j, h|
120
- h[j.column.to_s.to_sym] = [i.value.inspect, '|', ' '][i.column <=> j.column]
121
- end).rstrip
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
@@ -1,3 +1,3 @@
1
1
  module PowerAssert
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -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
- def assertion_message(&blk)
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.1.4
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-09-27 00:00:00.000000000 Z
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.2.2
100
+ rubygems_version: 2.4.2
100
101
  signing_key:
101
102
  specification_version: 4
102
103
  summary: Power Assert for Ruby