graph_mediator 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,59 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe "mediated_transactions in different threads" do
4
+
5
+ before(:all) do
6
+ ActiveRecord::Base.establish_connection({'adapter' => 'sqlite3', 'database' => 'thread-test'})
7
+ end
8
+
9
+ after(:all) do
10
+ ActiveRecord::Base.establish_connection({'adapter' => 'sqlite3', 'database' => ':memory:'})
11
+ end
12
+
13
+ before(:each) do
14
+ load_traceable_callback_tester
15
+ @t = Traceable.new(:name => :gizmo)
16
+ @t.save_without_mediation!
17
+ end
18
+
19
+ after(:each) do
20
+ Object.__send__(:remove_const, :Traceable)
21
+ end
22
+
23
+ # This will produce two warnings regarding overlapping transactions
24
+ it "should be different instances" do
25
+ objectid1, objectid2 = nil, nil
26
+ mediator1, mediator2 = nil, nil
27
+
28
+ # puts 'start thread 1'
29
+ thread1 = Thread.new do
30
+ t1 = Traceable.find(@t.id)
31
+ # puts 'preparing to mediate transaction on thread 1'
32
+ mediator1 = t1.__send__(:_get_mediator)
33
+ # puts 'mediating transaction on thread 1'
34
+ Kernel.sleep(2)
35
+ # puts 'thread 1 finished'
36
+ end
37
+
38
+ # puts 'sleeping kernel 1'
39
+ Kernel.sleep(1)
40
+
41
+ # puts 'start thread 2'
42
+ thread2 = Thread.new do
43
+ t2 = Traceable.find(@t.id)
44
+ # puts 'preparing to mediate transaction on thread 2'
45
+ mediator2 = t2.__send__(:_get_mediator)
46
+ # puts 'mediating transaction on thread 2'
47
+ Kernel.sleep(1)
48
+ # puts 'thread 2 finished'
49
+ end
50
+
51
+ # puts 'finishing thread 1'
52
+ thread1.join
53
+ # puts 'finishing thread 2'
54
+ thread2.join
55
+ # pp mediator1, mediator2
56
+ mediator1.should_not equal(mediator2)
57
+ end
58
+
59
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe "GraphMediator validation scenarios" do
4
+
5
+ before(:each) do
6
+ load_traceable_callback_tester
7
+ end
8
+
9
+ after(:each) do
10
+ Object.__send__(:remove_const, :Traceable)
11
+ end
12
+
13
+ it "should not call after_mediation if validation fails" do
14
+ t = Traceable.new
15
+ t.save.should == false
16
+ @traceables_callbacks.should == [:before]
17
+ end
18
+
19
+ end
@@ -0,0 +1,170 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ module AliasMethodChainSpec # namespacing
4
+
5
+ describe "alias method chain" do
6
+
7
+ module ModifiedAliasMethodChain
8
+ # From Tammo Freese's patch:
9
+ # https://rails.lighthouseapp.com/projects/8994/tickets/285-alias_method_chain-limits-extensibility
10
+ def alias_method_chain(target, feature)
11
+ punctuation = nil
12
+ with_method, without_method = "#{target}_with_#{feature}#{punctuation}", "#{target}_without_#{feature}#{punctuation}"
13
+
14
+ method_defined_here = (instance_methods(false) + private_instance_methods(false)).include?(RUBY_VERSION < '1.9' ? target.to_s : target)
15
+ unless method_defined_here
16
+ module_eval <<-EOS
17
+ def #{target}(*args, &block)
18
+ super
19
+ end
20
+ EOS
21
+ end
22
+
23
+ alias_method without_method, target
24
+ # alias_method target, with_method
25
+
26
+ target_method_exists = (instance_methods + private_instance_methods).include?(RUBY_VERSION < '1.9' ? with_method : with_method.to_sym)
27
+ raise NameError unless target_method_exists
28
+
29
+ module_eval <<-EOS
30
+ def #{target}(*args, &block)
31
+ self.__send__(:'#{with_method}', *args, &block)
32
+ end
33
+ EOS
34
+ end
35
+ end
36
+
37
+ module BasicAliasMethodChain
38
+ def alias_method_chain(target, feature)
39
+ punctuation = nil
40
+ with_method, without_method = "#{target}_with_#{feature}#{punctuation}", "#{target}_without_#{feature}#{punctuation}"
41
+ alias_method without_method, target
42
+ alias_method target, with_method
43
+ end
44
+ end
45
+
46
+ module Bar
47
+ def bar
48
+ 'bar'
49
+ end
50
+ end
51
+
52
+ module Baz
53
+ def baz
54
+ 'baz'
55
+ end
56
+ end
57
+
58
+ module BazWithLess
59
+ def self.included(base)
60
+ base.alias_method_chain :baz, :less
61
+ end
62
+
63
+ def baz_with_less
64
+ baz_without_less + ' less'
65
+ end
66
+ end
67
+
68
+ class Foo
69
+ extend ModifiedAliasMethodChain
70
+ include Bar
71
+
72
+ def foo_with_more
73
+ foo_without_more + ' more'
74
+ end
75
+
76
+ def foo
77
+ 'foo'
78
+ end
79
+ alias_method_chain :foo, :more
80
+
81
+ def bar_with_less
82
+ bar_without_less + ' less'
83
+ end
84
+ alias_method_chain :bar, :less
85
+
86
+ include Baz
87
+ include BazWithLess
88
+ end
89
+
90
+ class FooBasic
91
+ extend BasicAliasMethodChain
92
+ include Bar
93
+
94
+ def foo_with_more
95
+ foo_without_more + ' more'
96
+ end
97
+
98
+ def foo
99
+ 'foo'
100
+ end
101
+ alias_method_chain :foo, :more
102
+
103
+ def bar_with_less
104
+ bar_without_less + ' less'
105
+ end
106
+ alias_method_chain :bar, :less
107
+
108
+ include Baz
109
+ include BazWithLess
110
+ end
111
+
112
+ it "test modified alias method chain" do
113
+ f = Foo.new
114
+ f.foo.should == 'foo more'
115
+ f.foo_without_more.should == 'foo'
116
+ f.foo_with_more.should == 'foo more'
117
+ f.bar.should == 'bar less'
118
+ f.bar_without_less.should == 'bar'
119
+ f.bar_with_less.should == 'bar less'
120
+ f.baz.should == 'baz less'
121
+ f.baz_without_less.should == 'baz'
122
+ f.baz_with_less.should == 'baz less'
123
+ Bar.class_eval do
124
+ def bar
125
+ 'new bar'
126
+ end
127
+ end
128
+ f.bar.should == 'new bar less'
129
+ f.bar_without_less.should == 'new bar'
130
+ f.bar_with_less.should == 'new bar less'
131
+ Foo.class_eval do
132
+ def baz_with_less
133
+ 'lesser'
134
+ end
135
+ end
136
+ f.baz_without_less.should == 'baz'
137
+ f.baz_with_less.should == 'lesser'
138
+ f.baz.should == 'lesser'
139
+ end
140
+
141
+ it "test basic alias method chain" do
142
+ f = FooBasic.new
143
+ f.foo.should == 'foo more'
144
+ f.foo_without_more.should == 'foo'
145
+ f.foo_with_more.should == 'foo more'
146
+ f.bar.should == 'bar less'
147
+ f.bar_without_less.should == 'bar'
148
+ f.bar_with_less.should == 'bar less'
149
+ Bar.class_eval do
150
+ def bar
151
+ 'new bar'
152
+ end
153
+ end
154
+ # no change
155
+ f.bar.should == 'bar less'
156
+ f.bar_without_less.should == 'bar'
157
+ f.bar_with_less.should == 'bar less'
158
+ Foo.class_eval do
159
+ def baz_with_less
160
+ raise
161
+ end
162
+ end
163
+ # no error
164
+ f.baz_without_less.should == 'baz'
165
+ f.baz_with_less.should == 'baz less'
166
+ f.baz.should == 'baz less'
167
+ end
168
+ end
169
+
170
+ end
@@ -0,0 +1,122 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ require 'investigation/self_decorating'
4
+
5
+ module DecoratingSubclassSpec # namespacing
6
+
7
+ describe "Decorating by extending object eigenclass" do
8
+
9
+ module Other
10
+
11
+ def dingo
12
+ super
13
+ end
14
+ # super fails in dingo_without_other (see above)
15
+ alias_method :dingo_without_other, :dingo
16
+
17
+ def dingo
18
+ super + " other"
19
+ end
20
+
21
+ def bat
22
+ 'bat'
23
+ end
24
+ end
25
+
26
+ class SuperClass
27
+ def dingo
28
+ 'dingo'
29
+ end
30
+ end
31
+
32
+ def reload_bar
33
+ Object.send(:remove_const, :Bar) if Object.const_defined?(:Bar)
34
+ instance_eval <<EOS
35
+ module ::Bar
36
+ def bar
37
+ 'modular bar'
38
+ end
39
+ end
40
+ EOS
41
+ end
42
+
43
+ class SubClass < SuperClass; end
44
+
45
+ before(:each) do
46
+ reload_bar
47
+ end
48
+
49
+ after(:all) do
50
+ Object.__send__(:remove_const, :Bar)
51
+ end
52
+
53
+ it "should extend Foo::Secret" do
54
+ f = SelfDecorating.new
55
+ f.foo.should == 'foo'
56
+ end
57
+
58
+ context "with a new SelfDecorating" do
59
+
60
+ before(:each) do
61
+ load('investigation/self_decorating.rb')
62
+ end
63
+
64
+ after(:each) do
65
+ Object.send(:remove_const, :SelfDecorating)
66
+ end
67
+
68
+ it "should be able to decorate methods in base after they are defined" do
69
+ SelfDecorating.send(:define_method, :bar) { 'bar' }
70
+ SelfDecorating.decorate :bar
71
+ f = SelfDecorating.new
72
+ f.bar.should == 'bar with secret'
73
+ f.bar_without_secret.should == 'bar'
74
+ end
75
+
76
+ it "should be able to decorate methods in Secret before they are defined" do
77
+ SelfDecorating.decorate :bar
78
+ SelfDecorating.send(:define_method, :bar) { 'bar' }
79
+ f = SelfDecorating.new
80
+ f.bar.should == 'bar with secret'
81
+ f.bar_without_secret.should == 'bar'
82
+ end
83
+
84
+ it "should not interfere with overrides in superclasses" do
85
+ SelfDecorating.class_eval { include Bar }
86
+ SelfDecorating.decorate :bar
87
+ f = SelfDecorating.new
88
+ f.bar.should == 'modular bar with secret'
89
+ f.bar_without_secret.should == 'modular bar'
90
+ Bar.class_eval { def bar; 'new bar'; end }
91
+ f.bar_without_secret.should == 'new bar'
92
+ f.bar.should == 'new bar with secret'
93
+ end
94
+
95
+ it "should not interfere with overrides in the base class" do
96
+ SelfDecorating.class_eval do
97
+ include Bar
98
+ def bar
99
+ "locally " + super
100
+ end
101
+ end
102
+ SelfDecorating.decorate :bar
103
+ f = SelfDecorating.new
104
+ f.bar.should == 'locally modular bar with secret'
105
+ f.bar_without_secret.should == 'locally modular bar'
106
+ end
107
+
108
+ end
109
+
110
+ it "should test overriding superclass methods in a module" do
111
+ s = SubClass.new
112
+ s.dingo.should == 'dingo'
113
+ SubClass.send(:include, Other)
114
+ s.dingo.should == 'dingo other'
115
+ # 1.8 bug - aliased method that calls super in a module
116
+ # http://redmine.ruby-lang.org/issues/show/734
117
+ lambda { s.dingo_without_other }.should raise_error(NoMethodError)
118
+ s.bat.should == 'bat'
119
+ end
120
+ end
121
+
122
+ end
@@ -0,0 +1,131 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ module InsertingSuperClassSpec # namespacing
4
+
5
+ describe "insert superclass" do
6
+
7
+ module Decorator
8
+ def decorate(*methods)
9
+ methods.each do |m|
10
+ alias_method "#{m}_without_decoration", m
11
+ define_method(m) do |*args,&block|
12
+ super + " decorated"
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ def reload_foo
19
+ [:Bar, :Foo, :SubFoo].each { |c| Object.send(:remove_const, c) if Object.const_defined?(c) }
20
+ instance_eval <<EOS
21
+ module ::Bar
22
+ def second; 'bar second'; end
23
+ end
24
+
25
+ module Baz
26
+ def super_method
27
+ 'super'
28
+ end
29
+ end
30
+
31
+ class ::Foo
32
+ extend Decorator
33
+ include Bar
34
+ include Baz
35
+ module DecorateMe
36
+ def first; 'first'; end
37
+ def second; super + ' overridden'; end
38
+ def third; 'third'; end
39
+ end
40
+ include DecorateMe
41
+
42
+ def local
43
+ 'local'
44
+ end
45
+
46
+ decorate :first, :second, :third, :super_method, :local
47
+
48
+ def third
49
+ 'broken'
50
+ end
51
+ end
52
+
53
+ class ::SubFoo < Foo
54
+ def first
55
+ 'sub ' + super
56
+ end
57
+ def first_without_decoration
58
+ 'sub ' + super
59
+ end
60
+ def second
61
+ 'sub ' + super
62
+ end
63
+ def second_without_decoration
64
+ 'sub ' + super
65
+ end
66
+ end
67
+ EOS
68
+ end
69
+
70
+ before(:each) do
71
+ reload_foo
72
+ end
73
+
74
+ after(:all) do
75
+ Object.__send__(:remove_const, :Bar)
76
+ Object.__send__(:remove_const, :Foo)
77
+ end
78
+
79
+ it "should decorate the declared methods" do
80
+ f = Foo.new
81
+ f.first.should == "first decorated"
82
+ f.first_without_decoration.should == "first"
83
+ end
84
+
85
+ it "should decorate superclass methods not declared in DecorateMe" do
86
+ # the same case as the DecorateMe module
87
+ f = Foo.new
88
+ f.super_method.should == "super decorated"
89
+ f.super_method_without_decoration.should == "super"
90
+ end
91
+
92
+ it "should not interfere with overrides of superclass methods in DecorateMe" do
93
+ f = Foo.new
94
+ f.second.should == "bar second overridden decorated"
95
+ f.second_without_decoration.should == "bar second overridden"
96
+ end
97
+
98
+ it "has the issue that it raises errors attempting to decorate methods defined only in the base class" do
99
+ f = Foo.new
100
+ lambda { f.local }.should raise_error(NoMethodError) # not .should == 'local decorated'
101
+ f.local_without_decoration.should.should == 'local'
102
+ end
103
+
104
+ it "has the issue that overrides in base class override decoration" do
105
+ f = Foo.new
106
+ f.third.should == 'broken' # not 'broken decorated'
107
+ f.third_without_decoration.should == 'third'
108
+ end
109
+
110
+ it "should not interfere with external overrides of superclasses methods" do
111
+ Bar.class_eval { def second; 'external'; end }
112
+ f = Foo.new
113
+ f.second.should == 'external overridden decorated'
114
+ f.second_without_decoration.should == 'external overridden'
115
+ end
116
+
117
+ it "should allow subclasses to override decoration" do
118
+ f = SubFoo.new
119
+ f.first.should == 'sub first decorated'
120
+ f.second.should == 'sub bar second overridden decorated'
121
+ end
122
+
123
+ it "should allow subclasses to override methods without decoration" do
124
+ f = SubFoo.new
125
+ f.first_without_decoration.should == 'sub first'
126
+ f.second_without_decoration.should == 'sub bar second overridden'
127
+ end
128
+
129
+ end
130
+
131
+ end