fail-fast 1.0.0

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