lodestone-assert-agile 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ 0.4.1 Updated README
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2008 Matt Petty (matt@kizmeta.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,16 @@
1
+ A fork of Phlip's assert2 (http://assert2.rubyforge.org) with bug fixes and merged assert_latest
2
+
3
+ assert { foo == 42 }
4
+
5
+ # For Rails or anything responding to .maximum and .find
6
+ assert_latest Account, User do
7
+ account = Account.create(:name => 'Foo Mart')
8
+ account.users.create(:login => 'foo-guy')
9
+ end
10
+
11
+ # You can grab the created records thusly:
12
+ account, user = assert_latest Account, User do
13
+ account = Account.create(:name => 'Foo Mart')
14
+ account.users.create(:login => 'foo-guy')
15
+ end
16
+
data/Rakefile ADDED
File without changes
@@ -0,0 +1,32 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "assert-agile"
3
+ s.version = "0.4.1"
4
+ s.date = "2008-11-07"
5
+ s.summary = "Assert with radioactive spider power."
6
+ s.email = "matt@kizmeta.com"
7
+ s.homepage = "http://github.com/lodestone/assert-agile"
8
+ s.description = "Assertion Sugar. Better block assertions - Forked from assert2.rubyforge.org"
9
+ s.has_rdoc = true
10
+ s.authors = ["Matt Petty"]
11
+ s.files = [
12
+ "CHANGELOG",
13
+ "LICENSE",
14
+ "assert-agile.gemspec",
15
+ "init.rb",
16
+ "install.rb",
17
+ "lib/assert_agile.rb",
18
+ "lib/assert_latest_and_greatest.rb",
19
+ "lib/ruby_reflector.rb",
20
+ "Rakefile",
21
+ "README",
22
+ "tasks/assert_agile_tasks.rb",
23
+ "test/assert_agile_test.rb",
24
+ "uninstall.rb"
25
+ ]
26
+ s.test_files = ["test/assert_agile_test.rb"]
27
+ s.rdoc_options = ["--main", "README"]
28
+ s.extra_rdoc_files = ["CHANGELOG", "README"]
29
+ s.add_dependency("diff-lcs", ["> 0.0.0"])
30
+ s.add_dependency("mime-types", ["> 0.0.0"])
31
+ s.add_dependency("open4", ["> 0.0.0"])
32
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'assert_agile' if RAILS_ENV == 'test'
data/install.rb ADDED
File without changes
@@ -0,0 +1,219 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/ruby_reflector'
3
+ require File.dirname(__FILE__) + '/assert_latest_and_greatest'
4
+
5
+
6
+ # FIXME evaluate parts[3]
7
+ # ERGO if the block is a block, decorate with do-end
8
+ # ERGO decorate assert_latest's block at fault time
9
+
10
+ module AssertAgile
11
+
12
+ include RubyNodeReflector
13
+ include Coulor #:nodoc:
14
+ include AssertLatestAndGreatest
15
+ # This assertion calls a block, and faults if this returns
16
+ # +false+ or +nil+. The fault diagnostic will reflect the
17
+ # intermediate value of every variable and expression in the
18
+ # block.
19
+ #
20
+ # The first argument can be a diagnostic string:
21
+ #
22
+ # assert("foo failed"){ foo() }
23
+ #
24
+ # The fault diagnostic will print that line.
25
+ #
26
+ # The next time you think to write any of these assertions...
27
+ #
28
+ # - +assert+
29
+ # - +assert_equal+
30
+ # - +assert_instance_of+
31
+ # - +assert_kind_of+
32
+ # - +assert_operator+
33
+ # - +assert_match+
34
+ # - +assert_not_nil+
35
+ #
36
+ # use <code>assert{ 2.0 }</code> instead.
37
+ #
38
+ # If no block is provided, the assertion calls +assert_classic+,
39
+ # which simulates RubyUnit's standard <code>assert()</code>.
40
+ #
41
+ # Note: This only works for Ruby 1.8.6 so far...
42
+ #
43
+ def assert(*args, &block)
44
+ if block
45
+ assert_ args.first, '', &block
46
+ else
47
+ assert_classic *args
48
+ end
49
+ end
50
+
51
+ # The new <code>assert()</code> calls this to interpret
52
+ # blocks of assertive statements.
53
+ #
54
+ def assert_(diagnostic = nil, twizzler = '_', &block)
55
+ # puts reflect(&block) # activate this line and test to see all your successes!
56
+ result = nil
57
+
58
+ begin
59
+ result = block.call
60
+ rescue => e
61
+ diagnostic = [diagnostic, e.inspect, *e.backtrace].compact.join("\n\t")
62
+ _flunk_2_0("\nassert#{ twizzler }{ ", diagnostic, block, result)
63
+ end
64
+
65
+ add_assertion and return if result
66
+ _flunk_2_0("assert#{ twizzler }{ ", diagnostic, block, result)
67
+ end
68
+
69
+ # This assertion replaces:
70
+ #
71
+ # - +assert_nil+
72
+ # - +assert_no_match+
73
+ # - +assert_not_equal+
74
+ #
75
+ # It faults, and prints its block's contents and values,
76
+ # if its block returns non-+false+ and non-+nil+.
77
+ #
78
+ def deny(diagnostic = nil, &block)
79
+ # "None shall pass!" --the Black Knight
80
+ # puts reflect(&block) # activate this line and test to see all your denials!
81
+ result = nil
82
+
83
+ begin
84
+ result = block.call
85
+ rescue => e
86
+ diagnostic = [diagnostic, e.inspect, *e.backtrace].compact.join("\n\t")
87
+ _flunk_2_0("\ndeny{ ", diagnostic, block, result)
88
+ end
89
+
90
+ return unless result
91
+ _flunk_2_0('deny{ ', diagnostic, block, result)
92
+ end # "You're a looney!" -- King Arthur
93
+
94
+ # Assert that a block raises a given Exception type matching
95
+ # a given message
96
+ #
97
+ # * +types+ - single exception class or array of classes
98
+ # * +matcher+ - Regular Expression to match the inner_text of XML nodes
99
+ # * +diagnostic+ - optional string to add to failure message
100
+ # * +block+ - Ruby statements that should raise an exception
101
+ #
102
+ # Examples:
103
+ # %transclude AssertXPathSuite#test_assert_raise_message_detects_assertion_failure
104
+ #
105
+ # %transclude AssertXPathSuite#test_assert_raise_message_raises_message
106
+ #
107
+ # See: {assert_raise - Don't Just Say "No"}[http://www.oreillynet.com/onlamp/blog/2007/07/assert_raise_on_ruby_dont_just.html]
108
+ #
109
+ def assert_raise_message(types, matcher, diagnostic = nil, &block)
110
+ args = [types].flatten + [diagnostic]
111
+ exception = assert_raise(*args, &block)
112
+
113
+ assert_match matcher,
114
+ exception.message,
115
+ [ diagnostic,
116
+ "incorrect #{ exception.class.name
117
+ } message raised from block:",
118
+ "\t"+reflect_source(&block).split("\n").join("\n\t")
119
+ ].compact.join("\n")
120
+
121
+ return exception
122
+ end
123
+
124
+ def deny_raise_message(types, matcher, diagnostic = nil, &block) #:nodoc:
125
+ exception = assert_raise_message(types, //, diagnostic, &block)
126
+
127
+ assert_no_match matcher,
128
+ exception.message,
129
+ [ diagnostic,
130
+ "exception #{ exception.class.name
131
+ } with this message should not raise from block:",
132
+ "\t"+reflect_source(&block).split("\n").join("\n\t")
133
+ ].compact.join("\n")
134
+
135
+ return exception.message
136
+ end
137
+
138
+ def assert_flunked(gripe, diagnostic = nil, &block) #:nodoc:
139
+ assert_raise_message Test::Unit::AssertionFailedError,
140
+ gripe,
141
+ diagnostic,
142
+ &block
143
+ end
144
+
145
+ def deny_flunked(gripe, diagnostic = nil, &block) #:nodoc:
146
+ deny_raise_message Test::Unit::AssertionFailedError,
147
+ gripe,
148
+ diagnostic,
149
+ &block
150
+ end # ERGO move to assert{ 2.0 }, reflect, and leave there!
151
+
152
+ # This is a copy of the classic assert, so your pre�xisting
153
+ # +assert+ calls will not change their behavior
154
+ #
155
+ def assert_classic(boolean, message=nil)
156
+ _wrap_assertion do
157
+ assert_block("assert<classic> should not be called with a block.") { !block_given? }
158
+ assert_block(build_message(message, "<?> is not true.", boolean)) { boolean }
159
+ end
160
+ end
161
+
162
+ # wrap this common idiom:
163
+ # foo = assemble()
164
+ # deny{ foo.bar() }
165
+ # foo.activate()
166
+ # assert{ foo.bar() }
167
+ #
168
+ # that becomes:
169
+ # foo = assemble()
170
+ #
171
+ # assert_yin_yang proc{ foo.bar() } do
172
+ # foo.activate()
173
+ # end
174
+ #
175
+ def assert_yin_yang(*args, &block)
176
+ # prock, diagnostic = nil, &block)
177
+ procks, diagnostic = args.partition{|p| p.respond_to? :call }
178
+ block ||= procks.shift
179
+ source = reflect_source(&block)
180
+ fuss = [diagnostic, "fault before calling:", source].compact.join("\n")
181
+ procks.each do |prock| deny(fuss, &prock); end
182
+ block.call
183
+ fuss = [diagnostic, "fault after calling:", source].compact.join("\n")
184
+ procks.each do |prock| assert(fuss, &prock); end
185
+ end
186
+
187
+ # the prock assertion must pass on both sides of the called block
188
+ #
189
+ def deny_yin_yang(prock, diagnostic = nil, &block)
190
+ source = reflect_source(&block)
191
+ fuss = [diagnostic, "fault before calling:", source].compact.join("\n")
192
+ assert fuss, &prock
193
+ block.call
194
+ fuss = [diagnostic, "fault after calling:", source].compact.join("\n")
195
+ assert fuss, &prock
196
+ end
197
+
198
+ private
199
+ def build_message_(diagnostic, reflection)
200
+ diagnostic = nil if diagnostic == ''
201
+ return [diagnostic, reflection].compact.join("\n")
202
+ end
203
+
204
+ def _flunk_2_0(polarity, diagnostic, block, result)
205
+ rf = RubyReflector.new(block)
206
+ effect = " - should #{ 'not ' if polarity =~ /deny/ }pass\n"
207
+
208
+ report = magenta(polarity) + bold(rf.result) + magenta(" }") +
209
+ red(arrow_result(result) + effect) +
210
+ rf.format_evaluations
211
+
212
+ flunk build_message_(diagnostic, report)
213
+ end
214
+
215
+ end # "Eagle-eyes it!"
216
+
217
+ class Test::Unit::TestCase #:nodoc:
218
+ include AssertAgile
219
+ end
@@ -0,0 +1,65 @@
1
+
2
+ module AssertLatestAndGreatest
3
+
4
+ # This collects every model in the given class that appears while its block runs
5
+ def assert_latest(*models, &block)
6
+ models, diagnostic = _get_latest_args(models, 'assert')
7
+ latests = get_latest(models, &block)
8
+ latests.compact.length == models.length and add_assertion or
9
+ _flunk_latest(models, latests, diagnostic, true, block)
10
+ return *latests
11
+ end
12
+
13
+ def _get_latest_args(models, what) #:nodoc:
14
+ diagnostic = nil
15
+ diagnostic = models.pop if models.last.kind_of? String
16
+
17
+ unless models.length > 0 and
18
+ (diagnostic.nil? or diagnostic.kind_of? String)
19
+ raise "call #{ what }_latest(models..., diagnostic) with any number " +
20
+ 'of Model classes, followed by an optional diagnostic message'
21
+ end
22
+ return models, diagnostic
23
+ end
24
+ private :_get_latest_args
25
+
26
+ def deny_latest(*models, &block)
27
+ models, diagnostic = _get_latest_args(models, 'deny')
28
+ latests = get_latest(models, &block)
29
+ return if latests.compact.empty?
30
+ models = [latests].flatten.compact.map(&:class)
31
+ _flunk_latest(models, latests, diagnostic, false, block)
32
+ end
33
+
34
+ def get_latest(models, &block)
35
+ max_ids = models.map{|model| model.maximum(:id) || 0 }
36
+ block.call
37
+ index = -1
38
+ return models.map{|model|
39
+ any = *model.find( :all,
40
+ :conditions => "id > #{max_ids[index += 1]}",
41
+ :order => "id asc" )
42
+ any # * returns nil for [],
43
+ # one object for [x],
44
+ # or an array with more than one item
45
+ }
46
+ end
47
+
48
+ def _flunk_latest(models, latests, diagnostic, polarity, block) #:nodoc:
49
+ model_names = models.map(&:name)
50
+ model_names.each_with_index do |it, index|
51
+ model_names[index] = nil if !!latests[index] == polarity
52
+ end
53
+ model_names = model_names.compact.join(', ')
54
+ rationale = "should#{ ' not' unless polarity
55
+ } create new #{ model_names
56
+ } record(s) in block:\n\t\t#{
57
+ reflect_source(&block).gsub("\n", "\n\t\t")
58
+ }\n"
59
+ # RubyNodeReflector::RubyReflector.new(block, false).result }"
60
+ # note we don't evaluate...
61
+ flunk build_message(diagnostic, rationale)
62
+ end
63
+ private :_flunk_latest
64
+
65
+ end
@@ -0,0 +1,831 @@
1
+ require 'rubygems'
2
+ require 'rubynode'
3
+ require 'pp'
4
+
5
+
6
+ module RubyNodeReflector
7
+
8
+ # ERGO
9
+ # :bmethod => [:cval],
10
+ # :cfunc => [:argc, :cfnc],
11
+ # :cref => [:next, :clss],
12
+ # :defs => [:mid, :defn, :recv],
13
+ # :dmethod => [:cval],
14
+ # :dot2 => [:beg, :end],
15
+ # :dot3 => [:beg, :end],
16
+ # :dregx_once => [:next, :lit, :cflag],
17
+ # :fbody => [:orig, :mid, :head],
18
+ # :flip2 => [:cnt, :beg, :end],
19
+ # :flip3 => [:cnt, :beg, :end],
20
+ # :gasgn => [:vid, :value], # entry not supported
21
+ # :ifunc => [:tval, :state, :cfnc],
22
+ # :lasgn => [:vid, :cnt, :value],
23
+ # :last => [],
24
+ # :match => [:lit],
25
+ # :memo => {:u1_value=>:u1_value}, # different uses in enum.c, variabe.c and eval.c ...
26
+ # :method => [:body, :noex, :cnt], # cnt seems to be always 0 in 1.8.4
27
+ # :module => [:cpath, :body],
28
+ # :next => [:stts],
29
+ # :opt_n => [:body],
30
+ # :to_ary => [:head],
31
+
32
+ # This +reflect+s a block of code, by evaluating it, reflecting its
33
+ # source, and reflecting all its intermediate values
34
+ #
35
+ def reflect(&block)
36
+ result = block.call
37
+ rf = RubyReflector.new(block)
38
+
39
+ begin
40
+ waz = rf.colorize?
41
+ rf.colorize(false)
42
+ return rf.result + arrow_result(result) + "\n" + rf.format_evaluations
43
+ ensure
44
+ rf.colorize(waz)
45
+ end
46
+ end
47
+
48
+ def arrow_result(result) #:nodoc:
49
+ return "\t--> #{ result.inspect }"
50
+ end
51
+ private :arrow_result
52
+
53
+ # This +reflect+s a block of code, /without/ evaluating it.
54
+ # The function only compiles the source and reflects it as
55
+ # a string of disassembled Ruby
56
+ #
57
+ def reflect_source(&block)
58
+ return RubyReflector.new(block, false).result
59
+ end
60
+
61
+ # This compiles a string and +reflect+s its source...
62
+ # as another string.
63
+ #
64
+ def reflect_string(string)
65
+ rf = RubyReflector.new(proc{})
66
+ rf.reflect_values = false
67
+ # pp string.parse_to_nodes.transform
68
+ got = rf.reflect_nodes(string.parse_to_nodes)
69
+ return got
70
+ end
71
+
72
+ module Coulor #:nodoc:
73
+ def colorize(we_color)
74
+ @@we_color = we_color
75
+ end
76
+ unless defined? BOLD
77
+ BOLD = "\e[1m"
78
+ CLEAR = "\e[0m"
79
+ end # ERGO modularize these; anneal with Win32
80
+ def colour(text, colour_code)
81
+ return colour_code + text + CLEAR if colorize?
82
+ return text
83
+ end
84
+ def colorize? # ERGO how other libraries set these options transparent??
85
+ we_color = (@@we_color rescue true ) # ERGO parens needed?
86
+ return (we_color == :always or we_color && $stdout.tty?)
87
+ end
88
+ def bold(text)
89
+ return BOLD + text + CLEAR if colorize?
90
+ return text
91
+ end
92
+ def green(text); colour(text, "\e[32m"); end
93
+ def red(text); colour(text, "\e[31m"); end
94
+ def magenta(text); colour(text, "\e[35m"); end
95
+ def blue(text); colour(text, "\e[34m"); end
96
+ def orange(text); colour(text, "\e[3Bm"); end
97
+ end
98
+
99
+ class RubyReflector # turn hamburger back into live cattle
100
+ include Coulor
101
+ attr_reader :evaluations,
102
+ :result
103
+ attr_writer :reflect_values
104
+
105
+ def initialize(block, reflect_values = true) # note that a block, from your context, is not optional
106
+ @reflect_values = reflect_values
107
+ @evaluations = []
108
+ @result = ''
109
+ @block = block
110
+ @line = 0
111
+ reflect_nodes(@block.body_node)
112
+ end
113
+
114
+ def reflect_nodes(body_node)
115
+ return unless body_node
116
+ @transformation = body_node.transform(:include_node => true)
117
+ return @result = _send(@transformation)
118
+ rescue
119
+ puts "\nOffending line: #{ @line }"
120
+ # pp @transformation
121
+ # puts @result
122
+ raise
123
+ end
124
+
125
+ def eval_intermediate_guarded(expression)
126
+ begin
127
+ intermediate = eval(expression, @block.binding)
128
+ @evaluations << [expression, intermediate, nil]
129
+ rescue SyntaxError => e
130
+ if e.message.index('syntax error, unexpected \',\'') and expression !~ /\[ /
131
+ return eval_intermediate_guarded('[ ' + expression + ' ]')
132
+ end # faint prayer to infinite recursion diety here! (-;
133
+
134
+ @evaluations << [expression, nil, e.message]
135
+ rescue => e
136
+ @evaluations << [expression, nil, e.message]
137
+ end
138
+ end
139
+
140
+ def eval_intermediate(expression)
141
+ eval_intermediate_guarded(expression) if @reflect_values
142
+ return expression
143
+ end
144
+
145
+ def short_inspect(intermediate)
146
+ pretty = intermediate.inspect
147
+ # ERGO Proc is prob'ly rare here!
148
+ pretty = { '#<Proc' => '<Proc>' }.fetch(pretty.split(':').first, pretty)
149
+ prettier = pretty[0..90]
150
+ prettier << '*** ' unless prettier == pretty
151
+ return prettier
152
+ end
153
+ private :short_inspect
154
+
155
+ # ERGO spew the backrefs (?) any regular expression matchers may emit!
156
+ # ERGO don't eval the caller of a block without its block!
157
+
158
+ def format_evaluations
159
+ max_line = @evaluations.map{|exp, val, prob| exp.length}.sort.last
160
+ already = {}
161
+ lines = []
162
+
163
+ @evaluations.each do |exp, val, prob|
164
+ line = " #{ exp.center(max_line) } "
165
+
166
+ line << if prob then
167
+ orange('--? ' + prob)
168
+ else
169
+ green('--> ') + bold(short_inspect(val))
170
+ end
171
+
172
+ lines << line unless already[line] == true
173
+ already[line] = true
174
+ end
175
+
176
+ return lines.compact.join("\n")
177
+ end
178
+
179
+ def _send(node, thence = '')
180
+ return '' unless node
181
+ return node.to_s + thence if node.class == Symbol
182
+ target = :"_#{ node.first }"
183
+ last = node.last
184
+ (@line = last[:node].line) rescue nil
185
+ exp = send(target, last)
186
+ exp << thence if exp.length > 0
187
+ return exp
188
+ end
189
+
190
+ %w( args beg body cond cpath defn else end ensr
191
+ first head iter ivar lit mid next second
192
+ stts recv resq rest value var vid ).each do |sender|
193
+ define_method sender + '_' do |node, *args|
194
+ return _send(node[sender.to_sym], *args)
195
+ end
196
+ end
197
+
198
+ ########################################################
199
+ #### structures
200
+
201
+ def _block(node)
202
+ return node.map{|n| _send(n, "\n") }.join
203
+ end
204
+
205
+ def _module(node, what = 'module')
206
+ return what + ' ' + cpath_(node) + "\n" +
207
+ body_(node) +
208
+ "\nend\n"
209
+ end
210
+
211
+ def _method(node)
212
+ p node
213
+ return ''
214
+ end
215
+
216
+ def _class(node); _module(node, 'class'); end
217
+ def _self(node); 'self'; end
218
+ def _defn(node); _defs(node); end
219
+ def _super(node); 'super(' + args_(node) + ')'; end
220
+ def _zsuper(node); 'super'; end
221
+ def _begin(node); "begin\n" + body_(node) + "\nend\n"; end
222
+ def _ensure(node); head_(node) + "\nensure\n" + ensr_(node); end
223
+
224
+ def _sclass(node)
225
+ return 'class << ' + recv_(node) +
226
+ head_body(node) +
227
+ "end\n"
228
+ end
229
+
230
+ class ScopeMethod #:nodoc:
231
+ # this is complex because Ruby gloms several different
232
+ # kinds of variables into one "scope" token, and they
233
+ # don't directly match their layout in the source code
234
+
235
+ def _scopic(ref, node)
236
+ @ref = ref
237
+ @node = node
238
+ @expression = ''
239
+ @previously = false
240
+ @block_arg = false
241
+ @splat_arg = false
242
+ @previous_splat = false
243
+
244
+ if @node[:tbl]
245
+ @expression << '('
246
+ render_argument_list
247
+ @expression << ')'
248
+ end
249
+
250
+ @expression << "\n"
251
+ @expression << @ref.next_(@node)
252
+ return @expression
253
+ end
254
+
255
+ def ulterior_comma(token)
256
+ @expression << ', ' if @index > 0
257
+ @expression << token
258
+ @index = 0
259
+ end
260
+
261
+ def possible_comma(token)
262
+ @expression << ', ' if @index > 0
263
+ @expression << @ref._send(token)
264
+ end
265
+
266
+ def render_argument_list
267
+ @nekst = @node[:next]
268
+ @block = @nekst.last if @nekst && @nekst.first == :block
269
+ @args = @block.first.last if @block && @block.first.first == :args
270
+ @rest = @args[:rest] if @args
271
+ @opt = @args[:opt] if @args
272
+
273
+ @node[:tbl].each_with_index do |_n, _index|
274
+ @n, @index = _n, _index
275
+ render_argument
276
+ break if @block_arg
277
+ end
278
+ end
279
+
280
+ def render_argument
281
+ @splat_arg = @block_arg = false
282
+
283
+ if @rest and @rest.first == :lasgn and
284
+ (@n == nil or @rest.last[:vid] == @n)
285
+ ulterior_comma('*')
286
+ @splat_arg = true
287
+ end
288
+
289
+ if @block and (ba = @block[1]) and
290
+ ba.first == :block_arg and ba.last[:vid] == @n
291
+ ulterior_comma('&')
292
+ @block_arg = true
293
+ end
294
+
295
+ # ERGO Ruby 1.9 changes these rules!!
296
+
297
+ if !@previous_splat or @block_arg
298
+ if @opt and @opt.first == :block and # ERGO why a @block??
299
+ (lasgn = @opt.last.first).first == :lasgn and
300
+ lasgn.last[:vid] == @n
301
+ @previously = true
302
+ possible_comma(@opt.last.first)
303
+ else
304
+ possible_comma(@n)
305
+ @expression << ' = nil' if @previously and !@block_arg and !@splat_arg
306
+ end
307
+
308
+ @previous_splat ||= @splat_arg
309
+ end
310
+ end
311
+ end
312
+
313
+ def _scope(node)
314
+ return ScopeMethod.new._scopic(self, node)
315
+ end
316
+
317
+ def _defs(node)
318
+ return 'def ' + recv_(node, '.') + mid_(node) +
319
+ defn_(node) +
320
+ "end\n"
321
+ end
322
+
323
+ def _rescue(node)
324
+ if node[:else] == false and node[:head] and
325
+ node[:resq] and node[:head].first == :vcall
326
+ return head_(node) + ' rescue ' + resq_(node)
327
+ else
328
+ exp = head_(node) +
329
+ else_(node) +
330
+ "rescue"
331
+ if node[:resq] and node[:resq].first == :resbody
332
+ body = node[:resq].last
333
+ exp << ' ' + args_(body) if body and body[:args]
334
+ end
335
+ return exp + "\n" + resq_(node)
336
+ end
337
+ end
338
+
339
+ def _resbody(node)
340
+ return body_(node)
341
+ # already emitted: head_(node) + ' ' + args_(node)
342
+ end
343
+
344
+ def _yield(node)
345
+ exp = 'yield'
346
+ exp << '(' + head_(node) + ')' if node[:head]
347
+ return exp
348
+ end
349
+
350
+ def _alias(node)
351
+ return "alias #{ lit_(node[:new].last) } #{ lit_(node[:old].last) }"
352
+ end
353
+
354
+ def _valias(node)
355
+ return "alias #{ node[:new] } #{ node[:old] }"
356
+ end
357
+
358
+ ########################################################
359
+ #### control flow
360
+
361
+ def _if(node)
362
+ expression = '( if ' + eval_parenz{cond_(node)} + ' then '
363
+ expression << eval_parenz{body_(node)} if node[:body]
364
+ expression << ' else ' +
365
+ eval_parenz{else_(node)} if node[:else]
366
+ expression << ' end )'
367
+ return expression
368
+ end
369
+
370
+ def _while(node, concept = 'while')
371
+ return '( ' + concept + ' ' + cond_(node) +
372
+ head_body(node) +
373
+ "\nend )"
374
+ end
375
+
376
+ def _for(node)
377
+ return '( for ' + var_(node) + ' in ' + iter_(node) + "\n" +
378
+ body_(node) + "\n" +
379
+ 'end )'
380
+ end
381
+
382
+ def _args(node); return ''; end # _call and _fcall insert the real args
383
+ def _until(node); _while(node, 'until'); end
384
+ def _break(node); 'break'; end
385
+ def _next(node); 'next' ; end
386
+ def _case(node); '( case ' + head_body(node) + "\nend )"; end
387
+ def _when(node); 'when ' + head_body(node) + "\n" + next_(node); end
388
+ def _retry(node); 'retry'; end
389
+ def _redo(node); 'redo'; end
390
+ def head_body(node); head_(node) + "\n" + body_(node); end
391
+
392
+ def _return(node)
393
+ exp = 'return'
394
+ return exp unless stts = node[:stts]
395
+ exp << ' '
396
+
397
+ if stts.first == :array
398
+ exp << '[' + stts_(node) + ']'
399
+ elsif stts.first == :svalue
400
+ exp << stts_(node)
401
+ else
402
+ exp << eval_parenz{stts_(node)}
403
+ end
404
+
405
+ return exp
406
+ end
407
+
408
+ def _postexe(node)
409
+ raise '_postexe called with unexpected arguments' unless node == {} or node.keys == [:node]
410
+ return 'END'
411
+ end
412
+
413
+ # :argscat => [:body, :head],
414
+
415
+ ########################################################
416
+ #### assignments
417
+
418
+ def _dasgn_curr(node)
419
+ expression = vid_(node)
420
+ return expression unless value = node[:value]
421
+ expression << ' = '
422
+ we_b_array = value.first == :array
423
+ expression << nest_if(we_b_array, '[', ']'){ value_(node) }
424
+ return expression
425
+ end
426
+
427
+ def _cdecl(node)
428
+ return _send(node[ node[:vid] == 0 ? :else : :vid ]) + ' = ' + value_(node)
429
+ end
430
+
431
+ def _dasgn(node); _dasgn_curr(node); end
432
+ def _iasgn(node); _dasgn_curr(node); end
433
+ def _gasgn(node); _dasgn_curr(node); end
434
+ def _lasgn(node); _dasgn_curr(node); end
435
+ def _cvasgn(node); _dasgn_curr(node); end
436
+
437
+ def _op_asgn2(node)
438
+ expression = ''
439
+
440
+ if node[:recv].first == :self
441
+ expression << 'self'
442
+ else
443
+ expression << recv_(node)
444
+ end
445
+
446
+ expression << '.'
447
+ expression << vid_(node[:next].last) + ' ||= ' + value_(node)
448
+ return expression
449
+ end
450
+
451
+ ########################################################
452
+ #### operators
453
+
454
+ def _and(node, und = 'and')
455
+ return eval_intermediate( '( ' +
456
+ eval_parenz{ first_(node)} + ' ' + und + ' ' +
457
+ eval_parenz{second_(node)} + ' )' )
458
+ end
459
+
460
+ def _back_ref(node); '$' + node[:nth].chr; end
461
+ def _colon2(node); head_(node, '::') + mid_(node); end
462
+ def _colon3(node); '::' + mid_(node); end
463
+ def _cvar(node); _lvar(node); end
464
+ def _cvdecl(node); vid_(node) + ' = ' + value_(node); end
465
+ def _defined(node); 'defined? ' + head_(node); end
466
+ def _dot2(node); '( ' + beg_(node) + ' .. ' + end_(node) + ' )'; end
467
+ def _dot3(node); '( ' + beg_(node) + ' ... ' + end_(node) + ' )'; end
468
+ def _dregx(node); _dstr(node, '/'); end
469
+ def _dregx_once(node); _dstr(node, '/'); end
470
+ def _dsym(node); ':' + _lit(node[:lit]) + ' ' + rest_(node); end
471
+ def _dvar(node); eval_intermediate(vid_(node)); end
472
+ def _dxstr(node); _dstr(node, '`'); end
473
+ def eval_parenz; eval_intermediate('( ' + yield + ' )'); end
474
+ def _evstr(node); body_(node); end
475
+ def _false(nada); 'false'; end
476
+ def _gvar(node); vid_(node); end
477
+ def _ivar(node); _dvar(node); end
478
+ def _lit(node); node[:lit].inspect; end
479
+ def _lvar(node); eval_intermediate(vid_(node)); end
480
+ def _match(node); node[:lit].inspect; end
481
+ def neg_one(node); node == -1 ? '' : _send(node); end
482
+ def _nil(nada); 'nil' ; end
483
+ def _not(node); '(not(' + body_(node) + '))'; end
484
+ def _nth_ref(node); "$#{ node[:nth] }"; end # ERGO eval it?
485
+ def _op_asgn_and(node); _op_asgn_or(node, ' &&= '); end
486
+ def _or(node); _and(node, 'or'); end
487
+ def _str(node); _lit(node); end
488
+ def _svalue(node); head_(node); end
489
+ def _to_ary(node); head_(node); end
490
+ def _true(nada); 'true' ; end
491
+ def _undef(node); 'undef ' + mid_(node); end
492
+ def _vcall(node); mid_(node); end
493
+ def we_b(node); node.first.first; end
494
+ def _xstr(node); '`' + scrape_literal(node) + '`'; end
495
+ def _zarray(node); return '[]'; end
496
+
497
+ def _flip2(node) # ERGO what the heck is this??
498
+ p node
499
+ p node.keys
500
+ return ''
501
+ end
502
+
503
+ def _masgn(node)
504
+
505
+ #{:value=>
506
+ # [:splat,
507
+ # {:head=>
508
+ # [:fcall,
509
+ # {:mid=>:calc_stack,
510
+ # :args=>
511
+ # [:array,
512
+ # [[:vcall, {:mid=>:insn}],
513
+ # [:vcall, {:mid=>:from}],
514
+ # [:vcall, {:mid=>:after}],
515
+ # [:vcall, {:mid=>:opops}]]]}]}],
516
+ # :args=>false,
517
+ # :head=>
518
+ # [:array,
519
+ # [[:dasgn_curr, {:value=>false, :vid=>:name}],
520
+ # [:dasgn_curr, {:value=>false, :vid=>:pops}],
521
+ # [:dasgn_curr, {:value=>false, :vid=>:rets}],
522
+ # [:dasgn_curr, {:value=>false, :vid=>:pushs1}],
523
+ # [:dasgn_curr, {:value=>false, :vid=>:pushs2}]]]}
524
+
525
+ value, head, args = node.values_at(:value, :head, :args)
526
+
527
+ if value
528
+ return '( ' + head_(node) + ' = *' + head_(value.last) + ' )' if value.first == :splat
529
+
530
+ if head and args
531
+ exp = head_(node)
532
+ return exp + ', * = ' + value_(node) if args == -1
533
+ return exp + ', *' + args_(node) + ' = ' + value_(node)
534
+ end
535
+
536
+ return '( ' + head_(node) + ' = ' + value_(node) + ' )' if args == false
537
+ end
538
+
539
+ if value == false and head == false and args
540
+ return '*' + neg_one(args)
541
+ end
542
+
543
+ if head.kind_of?(Array) and head.first == :array
544
+ return head.last.map{|n|
545
+ nest_if(n.first == :masgn, '(', ')'){ _send(n) }
546
+ }.join(', ')
547
+ end
548
+
549
+ if head == false and args and value
550
+ return '*' + args_(node) + ' = ' + value_(node)
551
+ end
552
+
553
+ return head_(node)
554
+ end
555
+
556
+ def _splat(node)
557
+ if (head = node[:head]) and
558
+ ((we_b_array = head.first == :array) or head.first == :lvar)
559
+ return '*' + nest_if(we_b_array, '[', ']'){ head_(node) }
560
+ end
561
+
562
+ return '*' + head_(node)
563
+ end # ERGO raise if any other key!
564
+
565
+ def _const(node)
566
+ expression = vid_(node)
567
+ q = eval(expression, @block.binding)
568
+ eval_intermediate(expression) unless q.kind_of?(Module)
569
+ return expression
570
+ rescue # ERGO will someone need to see whatever this was?
571
+ return expression
572
+ end
573
+
574
+ def scrape_literal(node, regex = false)
575
+ lit = node[:lit].inspect.gsub(/^"/, '').gsub(/"$/, '')
576
+ lit.gsub!('\\\\', '\\') if regex
577
+ return lit
578
+ end
579
+
580
+ def _dstr(node, delim = '"')
581
+ regex = delim == '/'
582
+ expression = delim + scrape_literal(node, regex)
583
+
584
+ if node[:next] and node[:next].first == :array
585
+ (node[:next].last || []).each do |n|
586
+ expression << if n.first == :str
587
+ scrape_literal(n.last, regex)
588
+ else
589
+ '#{ ' + _send(n) + ' }'
590
+ end
591
+ end
592
+ end
593
+
594
+ return eval_intermediate(expression + delim)
595
+ end
596
+
597
+ def _retry(node)
598
+ raise '_retry called with unexpected arguments' unless node == {} or node.keys == [:node]
599
+ return 'retry'
600
+ end
601
+
602
+ def recv_zero_self(node, plus = '')
603
+ recv = node[:recv]
604
+ return 'self' + plus if recv == 0
605
+ return recv_(node, plus)
606
+ end
607
+
608
+ def _attrasgn(node)
609
+ recv, args = node.values_at(:recv, :args)
610
+
611
+ if args
612
+ if args.first == :array
613
+ if node[:mid].class == Symbol
614
+ if node[:mid] == :'[]='
615
+ return recv_zero_self(node) + '[' +
616
+ _send(args.last.first) + '] = ' +
617
+ _send(args.last.last)
618
+ end
619
+ return recv_zero_self(node, '.') + mid_(node) + '(' + _send(args.last.last) + ')'
620
+ end
621
+ end
622
+
623
+ return recv_zero_self(node) +
624
+ '[' + head_(args.last) + '] = ' +
625
+ body_(args.last)
626
+ end
627
+
628
+ return recv_zero_self(node, '.') + node[:mid].to_s.gsub(/=$/, '')
629
+ end
630
+
631
+ def _op_asgn_or(node, op = ' ||= ')
632
+ # CONSIDER what be :aid?
633
+ #{:value=>[:lasgn, {:value=>[:str, {:lit=>"vm_opts.h"}], :cnt=>2, :vid=>:file}],
634
+ # :aid=>0,
635
+ # :head=>[:lvar, {:cnt=>2, :vid=>:file}]}
636
+ return head_(node) + op + value_(node[:value].last)
637
+ end
638
+
639
+ def fcall_args(node = nil, methodic = false)
640
+ expression = ''
641
+ return expression unless node
642
+ expression << ' ' unless methodic
643
+ return expression + nest_if(methodic, '(', ')'){ _send(node) }
644
+ end
645
+
646
+ def _fcall(node)
647
+ exp = mid_(node) + fcall_args(node[:args], true)
648
+ eval_intermediate(exp) unless %w(lambda proc).include?(exp)
649
+ return exp
650
+ end
651
+
652
+ def _block_pass(node)
653
+ fcall = node[:iter].last
654
+ return eval_intermediate(recv_(fcall, '.') +
655
+ mid_(fcall) + '(' + args_(fcall, ', ') +
656
+ '&' + body_(node) + ')' )
657
+ end
658
+
659
+ def _iter(node)
660
+ var = node[:var]
661
+
662
+ return eval_intermediate(
663
+ iter_(node) +
664
+ '{' +
665
+ nest_if(var != false, '|', '|'){ var_(node) unless var == 0 } +
666
+ nest_if(node[:body] , ' ', ' '){ body_(node) } +
667
+ '}')
668
+ end
669
+
670
+ def _array(node)
671
+ nest_if we_b(node) == :array, '[', ']' do
672
+ node.map{ |z|
673
+ exp = _send(z)
674
+ exp << ', ' unless z.object_id == node.last.object_id
675
+ exp
676
+ }.join
677
+ end
678
+ end
679
+
680
+ def _hash(node)
681
+ return '{}' unless node[:head] and (array = node[:head].last)
682
+ expression = '{ '
683
+
684
+ array.in_groups_of 2 do |key, value|
685
+ expression << _send(key) + ' => ' + _send(value)
686
+ expression << ', ' if value != array.last
687
+ end
688
+
689
+ return expression + ' }'
690
+ end
691
+
692
+ def _match2(node)
693
+ # ERGO should this work like match3?
694
+ return recv_(node) + ' =~ ' + value_(node)
695
+ end
696
+
697
+ def we_b_op(node)
698
+ return node[:mid] && node[:mid].to_s !~ /^[a-z]/i
699
+ end
700
+
701
+ def _match3(node)
702
+ # ERGO do :lit and :value exclude each other?
703
+ return recv_(node) + ' =~ ' + _send(node[:lit] || node[:value])
704
+ end
705
+
706
+ def _block_arg(node) # is this ever called?
707
+ return '' # note that _scope should not take care of this
708
+ end
709
+
710
+ class CallMethod
711
+ def bracket_args
712
+ return false unless @mid == '[]'
713
+ @expression << '[' + @ref.args_(@node) + ']'
714
+ return true
715
+ end
716
+
717
+ def insert_method_call
718
+ @expression << '.'
719
+ @expression << @mid
720
+ @expression << '(' + @ref.args_(@node) + ')'
721
+ @ref.eval_intermediate(@expression) if @methodic
722
+ end
723
+
724
+ def operator_and_arguments
725
+ @mid = @ref.mid_(@node)
726
+
727
+ unless bracket_args
728
+ @methodic = @mid =~ /[a-z]/i
729
+
730
+ if @methodic
731
+ insert_method_call
732
+ else
733
+ @expression << ' '
734
+ @expression << @mid
735
+ @expression << ' '
736
+ nest_args
737
+ end
738
+ end
739
+ end
740
+
741
+ def nest_args
742
+ return unless @args = @node[:args]
743
+
744
+ nest_me = @args.first == :array &&
745
+ @args.last.length == 1 &&
746
+ (call = @args.last.first).first == :call &&
747
+ @ref.we_b_op(call.last)
748
+
749
+ exp = @ref.nest_if(nest_me, '( ', ' )'){ @ref.args_(@node) }
750
+ @ref.eval_intermediate(exp) if nest_me
751
+ @expression << exp
752
+ end
753
+
754
+ def caller(ref, node)
755
+ @ref, @node = ref, node
756
+ @expression = ''
757
+ @recv = @node[:recv]
758
+
759
+ if @recv.first == :block_pass
760
+ @expression << @ref.recv_(@node)
761
+ operator_and_arguments
762
+ else
763
+ nest_me = @recv.first == :call && @ref.we_b_op(@recv.last)
764
+
765
+ exp = if @recv.first == :array
766
+ @ref.nest_if(true, '[ ', ' ]'){ @ref.recv_(node) }
767
+ else
768
+ exp2 = @ref.nest_if(nest_me, '( ', ' )'){ @ref.recv_(node) }
769
+ @ref.eval_intermediate(exp2) if nest_me
770
+ exp2
771
+ end
772
+
773
+ @expression << exp
774
+ operator_and_arguments
775
+ end
776
+ return @expression
777
+ end
778
+ end
779
+
780
+ def _call(node); CallMethod.new.caller(self, node); end
781
+
782
+ def nest_if(condition, before, after, &block)
783
+ exp = ''
784
+ exp << before if condition
785
+ exp << (block.call || '')
786
+ exp << after if condition
787
+ return exp
788
+ end
789
+
790
+ def _op_asgn1(node) # ERGO just look up the list of these?
791
+ return '' unless args = node[:args]
792
+ exp = recv_(node)
793
+
794
+ if [:'-', :'+', :'*', :'**', :'/', :^, :|, :&,
795
+ :'<<', :'>>',
796
+ ].include?(node[:mid]) and
797
+ node[:recv] and args.first == :argscat
798
+
799
+ return exp +
800
+ "[#{ body_(args.last) }] #{ node[:mid] }= " + head_(args.last)
801
+ end
802
+
803
+ raise "unexpected mid value #{ node[:mid].inspect } in opcode for X= " unless node[:mid] == 0
804
+
805
+ if args.first == :argscat and args.last[:body]
806
+ exp << '[' + body_(args.last) + ']'
807
+ exp << ' ||= ' + head_(args.last)
808
+ else
809
+ raise "unexpected arguments in opcode for ||= "
810
+ end
811
+
812
+ return exp
813
+ end
814
+
815
+ def _argscat(node)
816
+ return head_(node) + ', *' +
817
+ nest_if(node[:body].first == :array, '[', ']'){ body_(node) }
818
+ end
819
+
820
+ end
821
+
822
+ end
823
+
824
+ class Array
825
+ def in_groups_of(number, fill_with = nil, &block)
826
+ require 'enumerator'
827
+ collection = dup
828
+ collection << fill_with until collection.size.modulo(number).zero?
829
+ collection.each_slice(number, &block)
830
+ end
831
+ end
File without changes
File without changes
data/uninstall.rb ADDED
File without changes
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lodestone-assert-agile
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.1
5
+ platform: ruby
6
+ authors:
7
+ - Matt Petty
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-11-07 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: diff-lcs
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">"
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.0
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: mime-types
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">"
30
+ - !ruby/object:Gem::Version
31
+ version: 0.0.0
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: open4
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.0
41
+ version:
42
+ description: Assertion Sugar. Better block assertions - Forked from assert2.rubyforge.org
43
+ email: matt@kizmeta.com
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ extra_rdoc_files:
49
+ - CHANGELOG
50
+ - README
51
+ files:
52
+ - CHANGELOG
53
+ - LICENSE
54
+ - assert-agile.gemspec
55
+ - init.rb
56
+ - install.rb
57
+ - lib/assert_agile.rb
58
+ - lib/assert_latest_and_greatest.rb
59
+ - lib/ruby_reflector.rb
60
+ - Rakefile
61
+ - README
62
+ - tasks/assert_agile_tasks.rb
63
+ - test/assert_agile_test.rb
64
+ - uninstall.rb
65
+ has_rdoc: true
66
+ homepage: http://github.com/lodestone/assert-agile
67
+ post_install_message:
68
+ rdoc_options:
69
+ - --main
70
+ - README
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.2.0
89
+ signing_key:
90
+ specification_version: 2
91
+ summary: Assert with radioactive spider power.
92
+ test_files:
93
+ - test/assert_agile_test.rb