armin-joellenbeck-rdbc 0.2.2 → 0.2.3

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/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: