armin-joellenbeck-rdbc 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ require 'rake/gempackagetask'
2
+ require 'rake/rdoctask'
3
+ require 'spec/rake/spectask'
4
+
5
+ task :default => 'spec'
6
+
7
+ task :all => [:clobber, :spec, :doc, :package]
8
+
9
+ Spec::Rake::SpecTask.new do |t|
10
+ t.libs << 'spec' << 'lib'
11
+ t.ruby_opts << '-r' << 'spec_helper' << '-r' << 'rdbc'
12
+ t.spec_opts <<
13
+ '--color' <<
14
+ '--diff' << 'unified' <<
15
+ '--format' << 'progress'
16
+ end
17
+
18
+ Spec::Rake::SpecTask.new(:heckle) do |t|
19
+ t.libs << 'spec' << 'lib'
20
+ t.ruby_opts << '-r' << 'spec_helper' << '-r' << 'rdbc'
21
+ t.spec_opts << '--heckle' << ENV['HECKLE']
22
+ end
23
+
24
+ Rake::RDocTask.new(:doc) do |t|
25
+ t.rdoc_dir = 'doc'
26
+ t.rdoc_files.include('README.rdoc', 'lib/**/*.rb')
27
+ t.options = [
28
+ '--all',
29
+ '--charset', 'utf8',
30
+ '--inline-source',
31
+ '--main', 'README.rdoc',
32
+ '--title', 'Design by Contract for Ruby'
33
+ ]
34
+ end
35
+
36
+ Rake::GemPackageTask.new(eval(File.read('rdbc.gemspec'))) do |pkg|
37
+ end
data/lib/rdbc.rb ADDED
@@ -0,0 +1,16 @@
1
+ module Rdbc
2
+ autoload 'Contract', 'rdbc/contract'
3
+ autoload 'Decorator', 'rdbc/decorator'
4
+ autoload 'Translating', 'rdbc/translating'
5
+ end
6
+
7
+
8
+ class Class
9
+ def contract(contract_class)
10
+ old_new = self.method(:new)
11
+ (class << self; self; end).send(:define_method, :new) do |*args|
12
+ object = old_new.call(*args)
13
+ Rdbc::Decorator.new(object, contract_class.new)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ module Rdbc
2
+ class Contract
3
+ class << self
4
+ include Translating
5
+
6
+ def pre(method, &block)
7
+ define_method(method_pre(method), &block)
8
+ end
9
+
10
+ def post(method, &block)
11
+ define_method(method_post(method), &block)
12
+ end
13
+
14
+ def invariant(&block)
15
+ define_method(:invariant, &block)
16
+ end
17
+ end
18
+
19
+ include Translating
20
+
21
+ class AssertionFailed < RuntimeError
22
+ end
23
+
24
+ def assert(condition)
25
+ raise AssertionFailed unless condition
26
+ end
27
+
28
+ def send_method_pre(method, object, *args)
29
+ method_pre = method_pre(method)
30
+ if respond_to?(method_pre)
31
+ send(method_pre, object, *args)
32
+ end
33
+ end
34
+
35
+ def send_invariant(object)
36
+ if respond_to?(:invariant)
37
+ invariant(object)
38
+ end
39
+ end
40
+
41
+ def send_method_post(method, object_pre, object, exception, result, *args)
42
+ method_post = method_post(method)
43
+ if respond_to?(method_post)
44
+ send(method_post, object_pre, object, exception, result, *args)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ module Rdbc
2
+ class Decorator
3
+ def initialize(object, contract)
4
+ @object = object
5
+ @contract = contract
6
+ end
7
+
8
+ def method_missing(method, *args)
9
+ object_pre = @object.clone
10
+ @contract.send_method_pre(method, @object, *args)
11
+ exception = nil
12
+ begin
13
+ result = @object.send(method, *args)
14
+ rescue => exception
15
+ end
16
+ @contract.send_invariant(@object)
17
+ @contract.send_method_post(method, object_pre, @object, exception, result, *args)
18
+ if exception.nil?
19
+ result
20
+ else
21
+ raise exception
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,51 @@
1
+ module Rdbc
2
+ module Translating
3
+ def method_pre(method)
4
+ method_with_prefix(method, :pre)
5
+ end
6
+
7
+ def method_post(method)
8
+ method_with_prefix(method, :post)
9
+ end
10
+
11
+ def method_with_prefix(method, type)
12
+ operator = operator(method)
13
+ ( type.to_s + '_' +
14
+ if operator.nil?
15
+ method.to_s
16
+ else
17
+ 'op_' + operator.to_s
18
+ end
19
+ ).to_sym
20
+ end
21
+
22
+ def operator(method)
23
+ {
24
+ :[] => :element_read,
25
+ :[]= => :element_write,
26
+ :** => :power,
27
+ :~ => :not,
28
+ :+@ => :unary_plus,
29
+ :-@ => :unary_minus,
30
+ :* => :product,
31
+ :/ => :quotient,
32
+ :% => :modulo,
33
+ :+ => :plus,
34
+ :- => :minus,
35
+ :>> => :right_shift,
36
+ :<< => :left_shift,
37
+ :& => :and,
38
+ :^ => :xor,
39
+ :| => :or,
40
+ :<= => :less_or_equal,
41
+ :< => :less,
42
+ :> => :greater,
43
+ :>= => :greater_or_equal,
44
+ :<=> => :comparison,
45
+ :== => :eql,
46
+ :=== => :case_comparison,
47
+ :=~ => :match
48
+ }[method]
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,2 @@
1
+ describe Rdbc::Contract do
2
+ end
@@ -0,0 +1,13 @@
1
+ describe Rdbc::Decorator, 'calling the method :foo' do
2
+ before do
3
+ @object = Object.new
4
+ stub(@object).foo(:argument) { :result }
5
+ @contract = Rdbc::Contract.new
6
+ @decorator = Rdbc::Decorator.new(@object, @contract)
7
+ end
8
+
9
+ it 'should delegate to method :foo of the decorated object' do
10
+ mock(@object).foo(:argument) { :result }
11
+ @decorator.foo(:argument).should be_equal(:result)
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+
3
+ require 'rr'
4
+ require 'spec'
5
+
6
+ Spec::Runner.configure do |config|
7
+ config.mock_with :rr
8
+ end
@@ -0,0 +1,96 @@
1
+ class StackContract < Rdbc::Contract
2
+
3
+ post :push do |stack_pre, stack, exception, result, element|
4
+ assert(result.nil?)
5
+ assert(stack.top == element)
6
+ assert(stack.size ==stack_pre.size + 1)
7
+ end
8
+
9
+ pre :pop do |stack|
10
+ assert(stack.size >= 1)
11
+ end
12
+
13
+ post :pop do |stack_pre, stack, exception, result|
14
+ assert(result.nil?)
15
+ assert(stack_pre.size - 1 == stack.size)
16
+ end
17
+
18
+ pre :top do |stack|
19
+ assert(stack.size >= 1)
20
+ end
21
+
22
+ post :top do |stack_pre, stack, exception, result|
23
+ assert(stack_pre.size == stack.size)
24
+ end
25
+
26
+ invariant do |stack|
27
+ assert(stack.size >= 0)
28
+ end
29
+
30
+ end
31
+
32
+
33
+ class Stack
34
+
35
+ contract StackContract
36
+
37
+ def initialize
38
+ @objects = []
39
+ end
40
+
41
+ def initialize_copy(orig)
42
+ @objects = orig.objects
43
+ end
44
+
45
+ def objects
46
+ @objects.dup
47
+ end
48
+
49
+ def size
50
+ @objects.size
51
+ end
52
+
53
+ def empty?
54
+ size == 0
55
+ end
56
+
57
+ def top
58
+ @objects.last
59
+ end
60
+
61
+ def pop
62
+ @objects.pop
63
+ nil
64
+ end
65
+
66
+ def push(object)
67
+ @objects.push(object)
68
+ nil
69
+ end
70
+
71
+ end
72
+
73
+
74
+ describe 'A new Stack' do
75
+ before do
76
+ @stack = Stack.new
77
+ end
78
+
79
+ it 'should be empty.' do
80
+ @stack.empty?
81
+ end
82
+
83
+ it 'should have no object on its top' do
84
+ lambda{@stack.top}.should raise_error(Rdbc::Contract::AssertionFailed)
85
+ end
86
+
87
+ it 'should be so that no object can be popped' do
88
+ lambda{@stack.pop}.should raise_error(Rdbc::Contract::AssertionFailed)
89
+ end
90
+
91
+ it 'A pushed object should be on the top' do
92
+ object = Object.new
93
+ @stack.push(object)
94
+ @stack.top.should equal(object)
95
+ end
96
+ end
@@ -0,0 +1,46 @@
1
+ describe Rdbc::Translating do
2
+ before do
3
+ @translator = Object.new
4
+ @translator.extend(Rdbc::Translating)
5
+ end
6
+
7
+ it 'should give the pre method for a normal method' do
8
+ @translator.method_pre(:method).should == :pre_method
9
+ end
10
+
11
+ it 'should give the pre method for a question method' do
12
+ @translator.method_pre(:method?).should == :pre_method?
13
+ end
14
+
15
+ it 'should give the pre method for an exclamation method' do
16
+ @translator.method_pre(:method!).should == :pre_method!
17
+ end
18
+
19
+ it 'should give the pre method for an assignment method' do
20
+ @translator.method_pre(:method=).should == :pre_method=
21
+ end
22
+
23
+ it 'should give the pre method for an operator' do
24
+ @translator.method_pre(:+).should == :pre_op_plus
25
+ end
26
+
27
+ it 'should give the post method for a normal method' do
28
+ @translator.method_post(:method).should == :post_method
29
+ end
30
+
31
+ it 'should give the post method for a question method' do
32
+ @translator.method_post(:method?).should == :post_method?
33
+ end
34
+
35
+ it 'should give the post method for an exclamation method' do
36
+ @translator.method_post(:method!).should == :post_method!
37
+ end
38
+
39
+ it 'should give the post method for an assignment method' do
40
+ @translator.method_post(:method=).should == :post_method=
41
+ end
42
+
43
+ it 'should give the post method for an operator' do
44
+ @translator.method_post(:+).should == :post_op_plus
45
+ end
46
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: armin-joellenbeck-rdbc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Armin Joellenbeck
@@ -21,8 +21,18 @@ extensions: []
21
21
 
22
22
  extra_rdoc_files:
23
23
  - README.rdoc
24
- files: []
25
-
24
+ files:
25
+ - README.rdoc
26
+ - Rakefile
27
+ - lib/rdbc.rb
28
+ - lib/rdbc/contract.rb
29
+ - lib/rdbc/decorator.rb
30
+ - lib/rdbc/translating.rb
31
+ - spec/spec_helper.rb
32
+ - spec/stack_spec.rb
33
+ - spec/contract_spec.rb
34
+ - spec/decorator_spec.rb
35
+ - spec/translating_spec.rb
26
36
  has_rdoc: true
27
37
  homepage: http://github.com/armin-joellenbeck/rdbc/tree/master
28
38
  post_install_message: