power_assert 0.1.1 → 0.1.2

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
  SHA1:
3
- metadata.gz: 99b3895797c266648105fc96abdc122df93537d1
4
- data.tar.gz: a9af7c357642b19eadeace43da8ba2f1ee17d9fe
3
+ metadata.gz: c655c4859384e9b6f80ca57638052de99d3d8a9d
4
+ data.tar.gz: d6ece1d15b1e83133b2e77eef2c03b2ed1b441fe
5
5
  SHA512:
6
- metadata.gz: ae79bba8eb3a079bcf30df88ef0109be3de8848a2d5dcd4f7d1d5fdee731dcc20150a21e272ec54c7c19f70200c684df6972c23ee0c835113be6985c143f6f63
7
- data.tar.gz: 4f0f959d1a16f3ba502adfe0c73f92909d2c78a3383a2bbb9044e886d6c3e0c06a41dbf2b9a572b5bd6e8a411e5c060bd3e3e305d682428d0645dd321cd4b662
6
+ metadata.gz: 0f7e60fc27d31672583e8e9916192165bbb05e495ffb3a283a8d37012b136efab29a6acd36412450057bcaa1b19cf7bff5fa323092bf4e6a96dd1c94e044a940
7
+ data.tar.gz: 8df7fa120664045dcbae9fad42b8babd4c744daa76d50990cd35642b1e9c3c51b605f72940a3ce0400cd2ee7c0da0a051fec29d56bba2a6729356e3e44a28ed5
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  .bundle
2
+ coverage
2
3
  Gemfile.lock
3
4
  pkg/*
4
5
  vendor/*
data/README.rdoc CHANGED
@@ -4,5 +4,6 @@ Power Assert for Ruby.
4
4
 
5
5
  == Related Projects
6
6
  * {test-unit-power_assert}[https://github.com/k-tsj/test-unit-power_assert]
7
+ * {minitest-power_assert}[https://github.com/hsbt/minitest-power_assert]
7
8
 
8
9
  == Travis Build Status {<img src="https://secure.travis-ci.org/k-tsj/power_assert.png"/>}[http://travis-ci.org/k-tsj/power_assert]
data/Rakefile CHANGED
@@ -3,6 +3,7 @@ require "bundler/gem_tasks"
3
3
  require "rake/testtask"
4
4
  task :default => :test
5
5
  Rake::TestTask.new do |t|
6
- t.ruby_opts = ["-rpower_assert"]
6
+ # helper(simplecov) must be required before loading power_assert
7
+ t.ruby_opts = ["-r./test/helper", "-rpower_assert"]
7
8
  t.test_files = FileList["test/test_*.rb"]
8
9
  end
data/lib/power_assert.rb CHANGED
@@ -2,8 +2,13 @@
2
2
  #
3
3
  # Copyright (C) 2014 Kazuki Tsujimoto, All rights reserved.
4
4
 
5
+ begin
6
+ TracePoint.new(:return, :c_return) {}
7
+ rescue
8
+ raise LoadError, 'Fully compatible TracePoint API required'
9
+ end
10
+
5
11
  require 'power_assert/version'
6
- require 'power_assert/pattern_match'
7
12
 
8
13
  require 'ripper'
9
14
 
@@ -22,16 +27,22 @@ module PowerAssert
22
27
  def initialize(assertion_proc, assertion_method)
23
28
  path = nil
24
29
  lineno = nil
25
- line = nil
30
+ @line = nil
26
31
  methods = nil
27
32
  refs = nil
28
33
  method_ids = nil
29
34
  return_values = []
30
35
  @base_caller_length = -1
31
36
  @assertion_proc = assertion_proc
37
+ @assertion_method_name = assertion_method.to_s
32
38
  @message_proc = -> {
33
39
  @assertion_message ||=
34
- @base_caller_length > 0 ? assertion_message(line || '', methods || [], return_values, refs || [], assertion_proc.binding).freeze : nil
40
+ @base_caller_length > 0 ? assertion_message(@line || '',
41
+ methods || [],
42
+ return_values,
43
+ refs || [],
44
+ assertion_proc.binding).freeze :
45
+ nil
35
46
  }
36
47
  @proc_local_variables = assertion_proc.binding.eval('local_variables').map(&:to_s)
37
48
  @trace = TracePoint.new(:return, :c_return) do |tp|
@@ -39,14 +50,14 @@ module PowerAssert
39
50
  locs = tp.binding.eval('caller_locations')
40
51
  if locs.length - @base_caller_length == TARGET_CALLER_DIFF[tp.event]
41
52
  idx = TARGET_CALLER_INDEX[tp.event]
42
- path ||= locs[idx].path
43
- lineno ||= locs[idx].lineno
44
- line ||= open(path).each_line.drop(lineno - 1).first
45
- unless methods
46
- idents = extract_idents(Ripper.sexp(line), assertion_method)
53
+ unless path
54
+ path = locs[idx].path
55
+ lineno = locs[idx].lineno
56
+ @line = open(path).each_line.drop(lineno - 1).first
57
+ idents = extract_idents(Ripper.sexp(@line))
47
58
  methods, refs = idents.partition {|i| i.type == :method }
59
+ method_ids = methods.map(&:name).map(&:to_sym).uniq
48
60
  end
49
- method_ids ||= methods.map(&:name).map(&:to_sym).uniq
50
61
  if path == locs[idx].path and lineno == locs[idx].lineno
51
62
  return_values << Value[tp.method_id.to_s, tp.return_value, nil]
52
63
  end
@@ -91,123 +102,118 @@ module PowerAssert
91
102
  methods = methods.dup
92
103
  return_values.each do |val|
93
104
  idx = methods.index {|method| method.name == val.name }
94
- if idx and (m = methods.delete_at(idx)).column
95
- val.column = m.column
96
- else
97
- ridx = return_values.rindex {|i| i.name == val.name and i.column }
98
- method_name = val.name
99
- re = /
100
- #{'\b' if /\A\w/ =~ method_name}
101
- #{Regexp.escape(method_name)}
102
- #{'\b' if /\w\z/ =~ method_name}
103
- /x
104
- val.column = line.index(re, ridx ? return_values[ridx].column + 1 : 0)
105
+ if idx
106
+ val.column = methods.delete_at(idx).column
105
107
  end
106
108
  end
107
109
  end
108
110
 
109
- def extract_idents(sexp, assertion_method = nil)
110
- match(sexp) do
111
- with(_[:program,
112
- _[_[:method_add_block,
113
- _[:method_add_arg, _[:fcall, _[:@ident, assertion_method.to_s, _]], _],
114
- _[Or(:brace_block, :do_block), _, ss]]]]) do
111
+ def extract_idents(sexp)
112
+ tag, * = sexp
113
+ case tag
114
+ when :arg_paren, :assoc_splat, :fcall, :hash, :method_add_block, :string_literal
115
+ extract_idents(sexp[1])
116
+ when :assign, :massign
117
+ extract_idents(sexp[2])
118
+ when :assoclist_from_args, :bare_assoc_hash, :dyna_symbol, :paren, :string_embexpr,
119
+ :regexp_literal, :xstring_literal
120
+ sexp[1].flat_map {|s| extract_idents(s) }
121
+ when :assoc_new, :command, :dot2, :dot3, :string_content
122
+ sexp[1..-1].flat_map {|s| extract_idents(s) }
123
+ when :unary
124
+ handle_columnless_ident([], sexp[1], extract_idents(sexp[2]))
125
+ when :binary
126
+ handle_columnless_ident(extract_idents(sexp[1]), sexp[2], extract_idents(sexp[3]))
127
+ when :call
128
+ [sexp[1], sexp[3]].flat_map {|s| extract_idents(s) }
129
+ when :array
130
+ sexp[1] ? sexp[1].flat_map {|s| extract_idents(s) } : []
131
+ when :command_call
132
+ [sexp[1], sexp[4], sexp[3]].flat_map {|s| extract_idents(s) }
133
+ when :aref
134
+ handle_columnless_ident(extract_idents(sexp[1]), :[], extract_idents(sexp[2]))
135
+ when :program
136
+ _, ((tag0, (tag1, (tag2, (tag3, mname, _)), _), (tag4, _, ss))) = sexp
137
+ if tag0 == :method_add_block and tag1 == :method_add_arg and tag2 == :fcall and
138
+ tag3 == :@ident and mname == @assertion_method_name and (tag4 == :brace_block or tag4 == :do_block)
115
139
  ss.flat_map {|s| extract_idents(s) }
116
- end
117
- with(_[:program, _[s, *_]]) do
118
- extract_idents(s)
119
- end
120
- with(_[:method_add_arg, s0, s1]) do
121
- s0_idents = extract_idents(s0)
122
- s0_idents[0..-2] + extract_idents(s1) + [s0_idents[-1]]
123
- end
124
- with(_[:arg_paren, s]) do
140
+ else
141
+ _, (s, *) = sexp
125
142
  extract_idents(s)
126
143
  end
127
- with(_[:args_add_block, _[:args_add_star, ss0, *ss1], _]) do
144
+ when :method_add_arg
145
+ idents = extract_idents(sexp[1])
146
+ idents[0..-2] + extract_idents(sexp[2]) + [idents[-1]]
147
+ when :args_add_block
148
+ _, (tag, ss0, *ss1), _ = sexp
149
+ if tag == :args_add_star
128
150
  (ss0 + ss1).flat_map {|s| extract_idents(s) }
151
+ else
152
+ sexp[1].flat_map {|s| extract_idents(s) }
129
153
  end
130
- with(_[:args_add_block, ss, _]) do
131
- ss.flat_map {|s| extract_idents(s) }
132
- end
133
- with(_[:vcall, _[:@ident, name, _[_, column]]]) do
154
+ when :vcall
155
+ _, (tag, name, (_, column)) = sexp
156
+ if tag == :@ident
134
157
  [Ident[@proc_local_variables.include?(name) ? :ref : :method, name, column]]
158
+ else
159
+ []
135
160
  end
136
- with(_[:fcall, s]) do
137
- extract_idents(s)
138
- end
139
- with(_[:binary, *ss]) do
140
- ss.flat_map {|s| extract_idents(s) }
141
- end
142
- with(_[:call, s0, _, s1]) do
143
- [s0, s1].flat_map {|s| extract_idents(s) }
144
- end
145
- with(_[:method_add_block, s, _]) do
146
- extract_idents(s)
147
- end
148
- with(_[:hash, s]) do
149
- extract_idents(s)
150
- end
151
- with(_[:assoclist_from_args, ss]) do
152
- ss.flat_map {|s| extract_idents(s) }
153
- end
154
- with(_[:bare_assoc_hash, ss]) do
155
- ss.flat_map {|s| extract_idents(s) }
156
- end
157
- with(_[:assoc_new, *ss]) do
158
- ss.flat_map {|s| extract_idents(s) }
159
- end
160
- with(_[:assoc_splat, s]) do
161
- extract_idents(s)
162
- end
163
- with(_[:array, ss]) do
164
- ss.flat_map {|s| extract_idents(s) }
165
- end
166
- with(_[:string_literal, s]) do
167
- extract_idents(s)
168
- end
169
- with(_[:string_content, *ss]) do
170
- ss.flat_map {|s| extract_idents(s) }
171
- end
172
- with(_[:string_embexpr, _[*ss]]) do
173
- ss.flat_map {|s| extract_idents(s) }
174
- end
175
- with(_[:regexp_literal, ss, _]) do
176
- ss.flat_map {|s| extract_idents(s) }
177
- end
178
- with(_[:command, *ss]) do
179
- ss.flat_map {|s| extract_idents(s) }
180
- end
181
- with(_[:command_call, s0, _, s1, s2]) do
182
- [s0, s2, s1].flat_map {|s| extract_idents(s) }
183
- end
184
- with(_[:assign, _, s]) do
185
- extract_idents(s)
186
- end
187
- with(_[:massign, _, s]) do
188
- extract_idents(s)
189
- end
190
- with(_[:paren, ss]) do
191
- ss.flat_map {|s| extract_idents(s) }
192
- end
193
- with(_[:var_ref, _[:@kw, "self", _[_, column]]]) do
194
- [Ident[:ref, "self", column]]
195
- end
196
- with(_[:var_ref, _[Or(:@const, :@cvar, :@ivar, :@gvar), ref_name, _[_, column]]]) do
161
+ when :var_ref
162
+ _, (tag, ref_name, (_, column)) = sexp
163
+ case tag
164
+ when :@kw
165
+ if ref_name == 'self'
166
+ [Ident[:ref, 'self', column]]
167
+ else
168
+ []
169
+ end
170
+ when :@const, :@cvar, :@ivar, :@gvar
197
171
  [Ident[:ref, ref_name, column]]
198
- end
199
- with(_[:@ident, method_name, _[_, column]]) do
200
- [Ident[:method, method_name, column]]
201
- end
202
- with(_[:@const, method_name, _[_, column]]) do
203
- [Ident[:method, method_name, column]]
204
- end
205
- with(s & Symbol) do
206
- [Ident[:method, s.to_s, nil]]
207
- end
208
- with(_) do
172
+ else
209
173
  []
210
174
  end
175
+ when :@ident, :@const
176
+ _, method_name, (_, column) = sexp
177
+ [Ident[:method, method_name, column]]
178
+ else
179
+ []
180
+ end
181
+ end
182
+
183
+ def str_indices(str, re, offset, limit)
184
+ idx = str.index(re, offset)
185
+ if idx and idx <= limit
186
+ [idx, *str_indices(str, re, idx + 1, limit)]
187
+ else
188
+ []
189
+ end
190
+ end
191
+
192
+ MID2SRCTXT = {
193
+ :[] => '[',
194
+ :+@ => '+',
195
+ :-@ => '-'
196
+ }
197
+
198
+ def handle_columnless_ident(left_idents, mid, right_idents)
199
+ left_max = left_idents.max_by(&:column)
200
+ right_min = right_idents.min_by(&:column)
201
+ bg = left_max ? left_max.column + left_max.name.length : 0
202
+ ed = right_min ? right_min.column - 1 : @line.length - 1
203
+ mname = mid.to_s
204
+ srctxt = MID2SRCTXT[mid] || mname
205
+ re = /
206
+ #{'\b' if /\A\w/ =~ srctxt}
207
+ #{Regexp.escape(srctxt)}
208
+ #{'\b' if /\w\z/ =~ srctxt}
209
+ /x
210
+ indices = str_indices(@line, re, bg, ed)
211
+ if left_idents.empty? and right_idents.empty?
212
+ left_idents + right_idents
213
+ elsif left_idents.empty?
214
+ left_idents + right_idents + [Ident[:method, mname, indices.last]]
215
+ else
216
+ left_idents + right_idents + [Ident[:method, mname, indices.first]]
211
217
  end
212
218
  end
213
219
  end
@@ -219,6 +225,8 @@ module PowerAssert
219
225
  module_function :start
220
226
  end
221
227
 
222
- RubyVM::InstructionSequence.compile_option = {
223
- specialized_instruction: false
224
- }
228
+ if defined? RubyVM
229
+ RubyVM::InstructionSequence.compile_option = {
230
+ specialized_instruction: false
231
+ }
232
+ end
@@ -1,3 +1,3 @@
1
1
  module PowerAssert
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/power_assert.gemspec CHANGED
@@ -14,9 +14,9 @@ Gem::Specification.new do |s|
14
14
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{|f| File.basename(f) }
16
16
  s.require_paths = ['lib']
17
- s.add_runtime_dependency 'pattern-match', '>= 0.5.1'
18
17
  s.add_development_dependency 'test-unit'
19
18
  s.add_development_dependency 'rake'
19
+ s.add_development_dependency 'simplecov'
20
20
  s.extra_rdoc_files = ['README.rdoc']
21
21
  s.rdoc_options = ['--main', 'README.rdoc']
22
22
  end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ begin
2
+ if ENV['COVERAGE']
3
+ require 'simplecov'
4
+ SimpleCov.start do
5
+ add_filter '/test/'
6
+ add_filter '/vendor/'
7
+ end
8
+ end
9
+ rescue LoadError
10
+ end
@@ -50,7 +50,7 @@ class TestPowerAssert < Test::Unit::TestCase
50
50
  [[[:method, "b", 2], [:method, "c", 6], [:method, "d", 9], [:method, "e", 12], [:method, "g", 18], [:method, "i", 24], [:method, "j", 29], [:method, "a", 0]],
51
51
  'a(b, *c, d, e, f: g, h: i, **j)'],
52
52
 
53
- [[[:method, "a", 0], [:method, "==", nil], [:method, "b", 5], [:method, "+", nil], [:method, "c", 9]],
53
+ [[[:method, "a", 0], [:method, "b", 5], [:method, "c", 9], [:method, "+", 7], [:method, "==", 2]],
54
54
  'a == b + c'],
55
55
 
56
56
  [[[:ref, "var", 0], [:ref, "var", 8], [:method, "var", 4]],
@@ -67,17 +67,58 @@ class TestPowerAssert < Test::Unit::TestCase
67
67
 
68
68
  [[[:method, "b", 4]],
69
69
  '/a#{b}c/'],
70
+
71
+ [[],
72
+ '[]'],
73
+
74
+ [[[:method, "a", 0], [:method, "[]", 1]],
75
+ 'a[0]'],
76
+
77
+ # not supported
78
+ [[],
79
+ '[][]'],
80
+
81
+ # not supported
82
+ [[],
83
+ '{}[]'],
84
+
85
+ [[[:method, "a", 1], [:method, "!", 0]],
86
+ '!a'],
87
+
88
+ [[[:method, "a", 1], [:method, "+@", 0]],
89
+ '+a'],
90
+
91
+ [[[:method, "a", 1], [:method, "-@", 0]],
92
+ '-a'],
93
+
94
+ [[[:method, "a", 2], [:method, "!", 0], [:method, "b", 9], [:method, "+@", 8], [:method, "c", 15], [:method, "-@", 14],
95
+ [:method, "==", 11], [:method, "==", 4]],
96
+ '! a == (+b == -c)'],
97
+
98
+ [[[:method, "b", 6]],
99
+ '%x{a#{b}c}'],
100
+
101
+ [[[:method, "a", 0], [:method, "b", 3]],
102
+ "a..b"],
103
+
104
+ [[[:method, "a", 0], [:method, "b", 4]],
105
+ "a...b"],
106
+
107
+ [[[:method, "b", 5]],
108
+ ':"a#{b}c"'],
70
109
  ]
71
110
 
72
111
  EXTRACT_METHODS_TEST.each_with_index do |(expect, source), idx|
73
112
  define_method("test_extract_methods_#{'%03d' % idx}") do
74
113
  pa = PowerAssert.const_get(:Context).new(-> { var = nil; -> {} }.(), nil)
75
- assert_equal expect, pa.send(:extract_idents, Ripper.sexp(source), :assertion_message).map(&:to_a), source
114
+ pa.instance_variable_set(:@line, source)
115
+ pa.instance_variable_set(:@assertion_method_name, 'assertion_message')
116
+ assert_equal expect, pa.send(:extract_idents, Ripper.sexp(source)).map(&:to_a), source
76
117
  end
77
118
  end
78
119
 
79
120
  def assertion_message(&blk)
80
- ::PowerAssert.start(blk, assertion_method: __method__) do |pa|
121
+ ::PowerAssert.start(blk, assertion_method: __callee__) do |pa|
81
122
  pa.yield
82
123
  pa.message_proc.()
83
124
  end
@@ -145,5 +186,33 @@ END
145
186
  END
146
187
  Set.new == Set.new([0])
147
188
  }
189
+
190
+
191
+ var = [10,20]
192
+ assert_equal <<END.chomp, assertion_message {
193
+ var[0] == 0
194
+ | | |
195
+ | | false
196
+ | 10
197
+ [10, 20]
198
+ END
199
+ var[0] == 0
200
+ }
201
+
202
+ a = 1
203
+ assert_equal <<END.chomp, assertion_message {
204
+ ! a != (+a == -a)
205
+ | | | || | ||
206
+ | | | || | |1
207
+ | | | || | -1
208
+ | | | || false
209
+ | | | |1
210
+ | | | 1
211
+ | | false
212
+ | 1
213
+ false
214
+ END
215
+ ! a != (+a == -a)
216
+ }
148
217
  end
149
218
  end
metadata CHANGED
@@ -1,31 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: power_assert
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
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-06-01 00:00:00.000000000 Z
11
+ date: 2014-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: pattern-match
14
+ name: test-unit
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.5.1
20
- type: :runtime
19
+ version: '0'
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.5.1
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: test-unit
28
+ name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: simplecov
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -68,9 +68,9 @@ files:
68
68
  - README.rdoc
69
69
  - Rakefile
70
70
  - lib/power_assert.rb
71
- - lib/power_assert/pattern_match.rb
72
71
  - lib/power_assert/version.rb
73
72
  - power_assert.gemspec
73
+ - test/helper.rb
74
74
  - test/test_power_assert.rb
75
75
  homepage: https://github.com/k-tsj/power_assert
76
76
  licenses: []
@@ -1,16 +0,0 @@
1
- require 'pattern-match/core'
2
-
3
- class << Array
4
- include PatternMatch::Deconstructable
5
-
6
- def deconstruct(val)
7
- accept_self_instance_only(val)
8
- val
9
- end
10
-
11
- private
12
-
13
- def accept_self_instance_only(val)
14
- raise PatternMatch::PatternNotMatch unless val.kind_of?(self)
15
- end
16
- end