power_assert 0.1.1 → 0.1.2

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: 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