lodestone-assert-agile 0.4.1

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