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 +37 -0
- data/lib/rdbc.rb +16 -0
- data/lib/rdbc/contract.rb +48 -0
- data/lib/rdbc/decorator.rb +25 -0
- data/lib/rdbc/translating.rb +51 -0
- data/spec/contract_spec.rb +2 -0
- data/spec/decorator_spec.rb +13 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/stack_spec.rb +96 -0
- data/spec/translating_spec.rb +46 -0
- metadata +13 -3
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,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
|
data/spec/spec_helper.rb
ADDED
data/spec/stack_spec.rb
ADDED
@@ -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.
|
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:
|