fail-fast 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Binary file
@@ -0,0 +1,6 @@
1
+ == 1.0.0 2008-11-29
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
5
+
6
+
@@ -0,0 +1,21 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ config/website.yml
7
+ lib/fail_fast.rb
8
+ script/console
9
+ script/destroy
10
+ script/generate
11
+ script/txt2html
12
+ spec/fail_fast_spec.rb
13
+ spec/spec.opts
14
+ spec/spec_helper.rb
15
+ tasks/rspec.rake
16
+ website/index.html
17
+ website/index.txt
18
+ website/javascripts/rounded_corners_lite.inc.js
19
+ website/stylesheets/screen.css
20
+ website/template.html.erb
21
+
@@ -0,0 +1,7 @@
1
+
2
+ For more information on fail-fast, see http://fail-fast.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
@@ -0,0 +1,87 @@
1
+ = fail-fast
2
+
3
+ * http://fail-fast.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ FailFast is a collection of assertion methods intended for lightweight contract checking.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * TODO More documentation
12
+
13
+ == SYNOPSIS:
14
+
15
+ def try
16
+ yield
17
+ rescue FailFast::AssertionFailureError
18
+ "<Assertion Failure>"
19
+ end
20
+
21
+ include FailFast::Assertions
22
+
23
+ try { assert(true) } # => true
24
+ try { assert(false) } # => "<Assertion Failure>"
25
+ try { assert(nil) } # => "<Assertion Failure>"
26
+
27
+ # We can check multiple values at once
28
+ try { assert("foo", :bar, 42) } # => 42
29
+ try { assert(1, 2, nil) } # => "<Assertion Failure>"
30
+
31
+ # assert_exists only checks for nil-ness - false is OK.
32
+ try { assert_exists(true) } # => true
33
+ try { assert_exists(false) } # => false
34
+ try { assert_exists(nil) } # => "<Assertion Failure>"
35
+
36
+ # check further constraints after verifying the object is non-nil
37
+ try { assert_exists(99) {|n| n > 100 } } # => "<Assertion Failure>"
38
+
39
+ # Assert that a collection is non-empty
40
+ try { assert_one_or_more([1]) } # => [1]
41
+ try { assert_one_or_more(:foo => :bar) } # => {:foo=>:bar}
42
+ try { assert_one_or_more([]) } # => "<Assertion Failure>"
43
+
44
+ # #deny is the opposite of #assert
45
+ try { deny(true) } # => "<Assertion Failure>"
46
+ try { deny(false) } # => false
47
+ try { deny(nil) } # => nil
48
+
49
+ # Assert that an object is hash-like and contains non-nil values for given keys
50
+ h = {:foo => 1, :bar => 2, :baz => nil}
51
+ try { assert_keys(h, :foo, :bar) } # => {:foo=>1, :bar=>2, :baz=>nil}
52
+ try { assert_keys(h, :baz) } # => "<Assertion Failure>"
53
+ try { assert_keys(h, :buz) } # => "<Assertion Failure>"
54
+
55
+
56
+ == REQUIREMENTS:
57
+
58
+ * None!
59
+
60
+ == INSTALL:
61
+
62
+ * sudo gem install fail-fast
63
+
64
+ == LICENSE:
65
+
66
+ (The MIT License)
67
+
68
+ Copyright (c) 2008 Avdi Grimm
69
+
70
+ Permission is hereby granted, free of charge, to any person obtaining
71
+ a copy of this software and associated documentation files (the
72
+ 'Software'), to deal in the Software without restriction, including
73
+ without limitation the rights to use, copy, modify, merge, publish,
74
+ distribute, sublicense, and/or sell copies of the Software, and to
75
+ permit persons to whom the Software is furnished to do so, subject to
76
+ the following conditions:
77
+
78
+ The above copyright notice and this permission notice shall be
79
+ included in all copies or substantial portions of the Software.
80
+
81
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
82
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
83
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
84
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
85
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
86
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
87
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,24 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/fail_fast'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('fail-fast', FailFast::VERSION) do |p|
7
+ p.developer('Avdi Grimm', 'avdi@avdi.org')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.rubyforge_name = p.name # TODO this is default value
10
+ p.extra_dev_deps = [
11
+ ['newgem', ">= #{::Newgem::VERSION}"]
12
+ ]
13
+
14
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
15
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
16
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
17
+ p.rsync_args = '-av --delete --ignore-errors'
18
+ end
19
+
20
+ require 'newgem/tasks' # load /tasks/*.rake
21
+ Dir['tasks/**/*.rake'].each { |t| load t }
22
+
23
+ # TODO - want other tests/tasks run by default? Add them to the list
24
+ # task :default => [:spec, :features]
@@ -0,0 +1,2 @@
1
+ host: avdi@rubyforge.org
2
+ remote_dir: /var/www/gforge-projects/fail-fast
@@ -0,0 +1,81 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module FailFast
5
+ VERSION = '1.0.0'
6
+
7
+ class AssertionFailureError < Exception
8
+ end
9
+
10
+ module Assertions
11
+
12
+ # Assert that no +values+ are nil or false. Returns the last value.
13
+ def assert(*values, &block)
14
+ iterate_and_return_last(values, block) do |v|
15
+ raise_assertion_error unless v
16
+ end
17
+ end
18
+
19
+ # The opposite of #assert.
20
+ def deny(*values)
21
+ assert(*values.map{ |v| !v})
22
+ assert(yield(*values)) if block_given?
23
+ values.last
24
+ end
25
+
26
+ # Assert that no +values+ are nil. Returns the last value.
27
+ def assert_exists(*values, &block)
28
+ iterate_and_return_last(values, block) { |value| deny(value.nil?) }
29
+ end
30
+
31
+ # Assert that +values+ are collections that contain at least one element.
32
+ # Returns the last value.
33
+ def assert_one_or_more(*values, &block)
34
+ iterate_and_return_last(values, block) do |value|
35
+ assert_exists(value)
36
+ deny(value.kind_of?(String))
37
+ deny(value.empty?)
38
+ end
39
+ end
40
+
41
+ # Assert that +hash+ exists, responds to #[], and contains a non-nil value
42
+ # for all +keys+. Returns +hash+.
43
+ def assert_keys(hash, *keys)
44
+ assert_exists(hash)
45
+ assert(hash.respond_to?(:[]))
46
+ values = keys.inject([]) { |vals, k| vals << assert_exists(hash[k]) }
47
+ assert(yield(*values)) if block_given?
48
+ hash
49
+ end
50
+
51
+ # Assert that +object+ responds to +messages+. Returns +object+.
52
+ def assert_respond_to(object, *messages)
53
+ messages.each do |message|
54
+ assert(object.respond_to?(message))
55
+ end
56
+ assert(yield(object)) if block_given?
57
+ object
58
+ end
59
+
60
+ private
61
+
62
+ def iterate_and_return_last(values, block = nil)
63
+ values.each { |v| yield(v) }
64
+ if block
65
+ raise_assertion_error unless block.call(*values)
66
+ end
67
+ values.last
68
+ end
69
+
70
+ def raise_assertion_error
71
+ error = FailFast::AssertionFailureError.new
72
+ backtrace = caller
73
+ trimmed_backtrace = []
74
+ trimmed_backtrace.unshift(backtrace.pop) until
75
+ backtrace.last.include?(__FILE__)
76
+ error.set_backtrace(trimmed_backtrace)
77
+ raise error
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/fail-fast.rb'}"
9
+ puts "Loading fail-fast gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ load File.dirname(__FILE__) + "/../Rakefile"
4
+ require 'rubyforge'
5
+ require 'redcloth'
6
+ require 'syntax/convertors/html'
7
+ require 'erb'
8
+
9
+ download = "http://rubyforge.org/projects/#{$hoe.rubyforge_name}"
10
+ version = $hoe.version
11
+
12
+ def rubyforge_project_id
13
+ RubyForge.new.configure.autoconfig["group_ids"][$hoe.rubyforge_name]
14
+ end
15
+
16
+ class Fixnum
17
+ def ordinal
18
+ # teens
19
+ return 'th' if (10..19).include?(self % 100)
20
+ # others
21
+ case self % 10
22
+ when 1: return 'st'
23
+ when 2: return 'nd'
24
+ when 3: return 'rd'
25
+ else return 'th'
26
+ end
27
+ end
28
+ end
29
+
30
+ class Time
31
+ def pretty
32
+ return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
33
+ end
34
+ end
35
+
36
+ def convert_syntax(syntax, source)
37
+ return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
38
+ end
39
+
40
+ if ARGV.length >= 1
41
+ src, template = ARGV
42
+ template ||= File.join(File.dirname(__FILE__), '/../website/template.html.erb')
43
+ else
44
+ puts("Usage: #{File.split($0).last} source.txt [template.html.erb] > output.html")
45
+ exit!
46
+ end
47
+
48
+ template = ERB.new(File.open(template).read)
49
+
50
+ title = nil
51
+ body = nil
52
+ File.open(src) do |fsrc|
53
+ title_text = fsrc.readline
54
+ body_text_template = fsrc.read
55
+ body_text = ERB.new(body_text_template).result(binding)
56
+ syntax_items = []
57
+ body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
58
+ ident = syntax_items.length
59
+ element, syntax, source = $1, $2, $3
60
+ syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
61
+ "syntax-temp-#{ident}"
62
+ }
63
+ title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
64
+ body = RedCloth.new(body_text).to_html
65
+ body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
66
+ end
67
+ stat = File.stat(src)
68
+ created = stat.ctime
69
+ modified = stat.mtime
70
+
71
+ $stdout << template.result(binding)
@@ -0,0 +1,315 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ module AssertionsSpecHelper
4
+ def do_success(&block)
5
+ do_assertion(@success_values.first, &block)
6
+ end
7
+ def do_failure(&block)
8
+ do_assertion(@failure_values.first, &block)
9
+ end
10
+ end
11
+
12
+ describe "any assertion", :shared => true do
13
+ it "on failure, should raise an exception with trimmed backtrace" do
14
+ begin
15
+ do_failure
16
+ rescue FailFast::AssertionFailureError => e
17
+ e.backtrace.first.should include(__FILE__)
18
+ end
19
+ end
20
+ end
21
+
22
+ describe "a basic assertion", :shared => true do
23
+ it "should raise FailFast::AssertionFailureError when it fails" do
24
+ @failure_values.each do |value|
25
+ lambda do
26
+ do_assertion(value)
27
+ end.should raise_error(FailFast::AssertionFailureError)
28
+ end
29
+ end
30
+
31
+ it "should not raise an exception when it succeeds" do
32
+ @success_values.each do |value|
33
+ lambda do
34
+ do_assertion(value)
35
+ end.should_not raise_error
36
+ end
37
+ end
38
+
39
+ it "should return its argument on success" do
40
+ @success_values.each do |value|
41
+ do_assertion(value).should equal(value)
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ describe "an assertion taking a block", :shared => true do
48
+ it "should fail if the block result is not true" do
49
+ lambda do
50
+ do_success { false }
51
+ end.should raise_error(FailFast::AssertionFailureError)
52
+ end
53
+ end
54
+
55
+ describe "an assertion yielding passed values", :shared => true do
56
+
57
+ it_should_behave_like "an assertion taking a block"
58
+
59
+ it "should yield values that pass the test" do
60
+ @success_values.each do |value|
61
+ did_yield = false
62
+ do_assertion(value) do |yielded_value|
63
+ did_yield = true
64
+ yielded_value.should equal(value)
65
+ true
66
+ end
67
+ did_yield.should be_true
68
+ end
69
+ end
70
+
71
+ it "should not yield values that fail the test" do
72
+ @failure_values.each do |value|
73
+ did_yield = false
74
+ lambda do
75
+ do_assertion(value) do |yielded_value|
76
+ did_yield = true
77
+ end
78
+ end.should raise_error(FailFast::AssertionFailureError)
79
+ did_yield.should be_false
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ describe "an assertion taking multiple values", :shared => true do
86
+ def gather_arguments(values)
87
+ args = []
88
+ # gather 3 arguments
89
+ 3.times do |i|
90
+ args[i] = values[i % values.size]
91
+ end
92
+ args
93
+ end
94
+
95
+ it "should not raise error if all values succeed test" do
96
+ values = gather_arguments(@success_values)
97
+ lambda { do_assertion(*values) }.should_not raise_error
98
+ end
99
+
100
+ it "should raise error if all values fail test" do
101
+ values = gather_arguments(@failure_values)
102
+ lambda { do_assertion(*values) }.should raise_error(FailFast::AssertionFailureError)
103
+ end
104
+
105
+ it "should raise error if one values fails test" do
106
+ values = gather_arguments(@success_values)
107
+ values[1] = @failure_values.first
108
+ lambda { do_assertion(*values) }.should raise_error(FailFast::AssertionFailureError)
109
+ end
110
+
111
+ it "should return the last argument on success" do
112
+ values = gather_arguments(@success_values)
113
+ do_assertion(*values).should equal(values.last)
114
+ end
115
+
116
+ end
117
+
118
+ describe FailFast::Assertions, "#assert" do
119
+
120
+ include FailFast::Assertions
121
+ include AssertionsSpecHelper
122
+
123
+ def do_assertion(*args, &block)
124
+ assert(*args, &block)
125
+ end
126
+
127
+ before :each do
128
+ @success_values = [true, "", 0]
129
+ @failure_values = [false, nil]
130
+ end
131
+
132
+ it_should_behave_like "any assertion"
133
+ it_should_behave_like "a basic assertion"
134
+ it_should_behave_like "an assertion taking multiple values"
135
+ it_should_behave_like "an assertion yielding passed values"
136
+ end
137
+
138
+ describe FailFast::Assertions, "#assert_exists" do
139
+
140
+ include FailFast::Assertions
141
+ include AssertionsSpecHelper
142
+
143
+ def do_assertion(*args, &block)
144
+ assert_exists(*args, &block)
145
+ end
146
+
147
+ before :each do
148
+ @success_values = ["foo", 123, false]
149
+ @failure_values = [nil]
150
+ end
151
+
152
+ it_should_behave_like "any assertion"
153
+ it_should_behave_like "a basic assertion"
154
+ it_should_behave_like "an assertion taking multiple values"
155
+ it_should_behave_like "an assertion yielding passed values"
156
+
157
+ end
158
+
159
+ describe FailFast::Assertions, "#assert_one_or_more" do
160
+
161
+ include FailFast::Assertions
162
+ include AssertionsSpecHelper
163
+
164
+ def do_assertion(*args, &block)
165
+ assert_one_or_more(*args, &block)
166
+ end
167
+
168
+ before :each do
169
+ @success_values = [[1], {:foo => :bar }]
170
+ @failure_values = [nil, [], "foo"]
171
+ end
172
+
173
+ it_should_behave_like "any assertion"
174
+ it_should_behave_like "a basic assertion"
175
+ it_should_behave_like "an assertion taking multiple values"
176
+ it_should_behave_like "an assertion yielding passed values"
177
+ end
178
+
179
+ describe FailFast::Assertions, "#deny" do
180
+
181
+ include FailFast::Assertions
182
+ include AssertionsSpecHelper
183
+
184
+ def do_assertion(*args, &block)
185
+ deny(*args, &block)
186
+ end
187
+
188
+ before :each do
189
+ @success_values = [false, nil]
190
+ @failure_values = [true, "", 0]
191
+ end
192
+
193
+ it_should_behave_like "any assertion"
194
+ it_should_behave_like "a basic assertion"
195
+ it_should_behave_like "an assertion taking multiple values"
196
+ it_should_behave_like "an assertion yielding passed values"
197
+ end
198
+
199
+ describe FailFast::Assertions, "#assert_keys" do
200
+
201
+ include FailFast::Assertions
202
+
203
+ def do_assertion(*args, &block)
204
+ assert_keys(*args, &block)
205
+ end
206
+
207
+ def do_success(&block)
208
+ assert_keys({}, &block)
209
+ end
210
+
211
+ def do_failure(&block)
212
+ assert_keys({}, :foo, &block)
213
+ end
214
+
215
+ it_should_behave_like "any assertion"
216
+ it_should_behave_like "an assertion taking a block"
217
+
218
+ it "should fail if a specified key does not exist" do
219
+ lambda { assert_keys({}, :foo) }.should raise_error(FailFast::AssertionFailureError)
220
+ end
221
+
222
+ it "should fail if a specified key is nil" do
223
+ lambda do
224
+ assert_keys({:foo => nil}, :foo)
225
+ end.should raise_error(FailFast::AssertionFailureError)
226
+ end
227
+
228
+ it "should fail if any of the specified keys are nil" do
229
+ lambda do
230
+ assert_keys({:foo => true, :bar => nil}, :foo, :bar)
231
+ end.should raise_error(FailFast::AssertionFailureError)
232
+ end
233
+
234
+ it "should fail if the given hash is nil" do
235
+ lambda do
236
+ assert_keys(nil)
237
+ end.should raise_error(FailFast::AssertionFailureError)
238
+ end
239
+
240
+ it "should fail if given something unlike a hash" do
241
+ lambda do
242
+ assert_keys(true)
243
+ end.should raise_error(FailFast::AssertionFailureError)
244
+ end
245
+
246
+ it "should succeed if no keys are given" do
247
+ lambda do
248
+ assert_keys({:foo => true, :bar => nil})
249
+ end.should_not raise_error
250
+ end
251
+
252
+ it "should yield key values if they all exist" do
253
+ did_yield = false
254
+ assert_keys({:foo => 23, :bar => 32}, :foo, :bar) do |x, y|
255
+ did_yield = true
256
+ x.should == 23
257
+ y.should == 32
258
+ true
259
+ end
260
+ did_yield.should be_true
261
+ end
262
+
263
+ it "should yield nothing if a key is missing" do
264
+ begin
265
+ did_yield = false
266
+ assert_keys({:foo => 23, :bar => 32}, :foo, :bar) do |x, y|
267
+ did_yield = true
268
+ end
269
+ rescue FailFast::AssertionFailureError
270
+ did_yield.should be_false
271
+ end
272
+ end
273
+
274
+ it "should return the hash" do
275
+ @hash = { :buz => 42 }
276
+ assert_keys(@hash, :buz).should equal(@hash)
277
+ end
278
+ end
279
+
280
+ describe FailFast::Assertions, "#assert_respond_to" do
281
+ include FailFast::Assertions
282
+
283
+ def do_assertion(object, &block)
284
+ assert_respond_to(object, :size, &block)
285
+ end
286
+
287
+ def do_success(&block)
288
+ assert_respond_to("foo", :size, &block)
289
+ end
290
+
291
+ def do_failure(&block)
292
+ assert_respond_to("foo", :bar, &block)
293
+ end
294
+
295
+ before :each do
296
+ @success_values = [[], ""]
297
+ @failure_values = [nil]
298
+ end
299
+
300
+ it_should_behave_like "any assertion"
301
+ it_should_behave_like "a basic assertion"
302
+ it_should_behave_like "an assertion taking a block"
303
+
304
+ it "should fail if ANY messages are not supported" do
305
+ lambda do
306
+ assert_respond_to("foo", :size, :bar)
307
+ end.should raise_error(FailFast::AssertionFailureError)
308
+ end
309
+ end
310
+
311
+ describe FailFast::AssertionFailureError do
312
+ it "should derive from Exception" do
313
+ FailFast::AssertionFailureError.superclass.should equal(Exception)
314
+ end
315
+ end