caricature 0.7.1 → 0.7.2

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.
Files changed (50) hide show
  1. data/Rakefile +47 -40
  2. data/caricature.gemspec +50 -17
  3. data/lib/caricature.rb +9 -1
  4. data/lib/caricature/bacon/integration.rb +3 -5
  5. data/lib/caricature/clr/isolation.rb +1 -1
  6. data/lib/caricature/method_call_recorder.rb +7 -2
  7. data/lib/caricature/rspec.rb +1 -0
  8. data/lib/caricature/rspec/integration.rb +77 -0
  9. data/lib/caricature/verification.rb +9 -1
  10. data/lib/caricature/version.rb +1 -1
  11. data/lib/core_ext/class.rb +1 -1
  12. data/lib/core_ext/module.rb +1 -1
  13. data/lib/core_ext/object.rb +2 -2
  14. data/spec/{integration → bacon/integration}/callback_spec.rb +1 -1
  15. data/spec/{integration → bacon/integration}/clr_to_clr_spec.rb +1 -1
  16. data/spec/{integration → bacon/integration}/clr_to_ruby_spec.rb +1 -1
  17. data/spec/{integration → bacon/integration}/indexer_spec.rb +1 -1
  18. data/spec/{integration → bacon/integration}/ruby_to_ruby_spec.rb +1 -1
  19. data/spec/bacon/spec_helper.rb +5 -0
  20. data/spec/{unit → bacon/unit}/core_ext_spec.rb +13 -13
  21. data/spec/{unit → bacon/unit}/descriptor_spec.rb +1 -1
  22. data/spec/{unit → bacon/unit}/expectation_spec.rb +1 -1
  23. data/spec/{unit → bacon/unit}/interop_spec.rb +3 -3
  24. data/spec/{unit → bacon/unit}/isolation_spec.rb +1 -1
  25. data/spec/{unit → bacon/unit}/isolator_spec.rb +1 -1
  26. data/spec/{unit → bacon/unit}/messaging_spec.rb +1 -1
  27. data/spec/{unit → bacon/unit}/method_call_spec.rb +2 -2
  28. data/spec/{unit → bacon/unit}/sword_spec.rb +1 -1
  29. data/spec/{unit → bacon/unit}/verification_spec.rb +1 -1
  30. data/spec/bin/ClrModels.dll +0 -0
  31. data/spec/bin/ClrModels.dll.mdb +0 -0
  32. data/spec/{bacon_helper.rb → models/ruby_models.rb} +9 -26
  33. data/spec/rspec/integration/callback_spec.rb +157 -0
  34. data/spec/rspec/integration/clr_to_clr_spec.rb +255 -0
  35. data/spec/rspec/integration/clr_to_ruby_spec.rb +228 -0
  36. data/spec/rspec/integration/indexer_spec.rb +28 -0
  37. data/spec/rspec/integration/ruby_to_ruby_spec.rb +272 -0
  38. data/spec/rspec/spec_helper.rb +6 -0
  39. data/spec/rspec/unit/core_ext_spec.rb +87 -0
  40. data/spec/rspec/unit/descriptor_spec.rb +160 -0
  41. data/spec/rspec/unit/expectation_spec.rb +301 -0
  42. data/spec/rspec/unit/interop_spec.rb +43 -0
  43. data/spec/rspec/unit/isolation_spec.rb +87 -0
  44. data/spec/rspec/unit/isolator_spec.rb +220 -0
  45. data/spec/rspec/unit/messaging_spec.rb +311 -0
  46. data/spec/rspec/unit/method_call_spec.rb +343 -0
  47. data/spec/rspec/unit/sword_spec.rb +40 -0
  48. data/spec/rspec/unit/verification_spec.rb +104 -0
  49. data/spec/spec_helper.rb +15 -0
  50. metadata +37 -18
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe "Event handling" do
4
+
5
+
6
+
7
+ describe "for precompiled CLR classes" do
8
+
9
+ before do
10
+ @warrior = ClrModels::ExposingWarrior.new
11
+ end
12
+
13
+ it "should subscribe to an event" do
14
+ ClrModels::ExposedChangedSubscriber.new(@warrior)
15
+ @warrior.has_event_subscriptions.should be_true
16
+ end
17
+
18
+ it "should not raise an error when subcribing to an event" do
19
+ lambda { ClrModels::ExposedChangedSubscriber.new(@warrior) }.should_not raise_error
20
+ end
21
+
22
+ it "should handle an event when raised" do
23
+ subscriber = ClrModels::ExposedChangedSubscriber.new(@warrior)
24
+ @warrior.change_is_exposed
25
+ subscriber.counter.should == 1
26
+ end
27
+
28
+ end
29
+
30
+ describe "for an IR generated interface proxy" do
31
+
32
+ before do
33
+ @proxy = isolate ClrModels::IExposingWarrior
34
+ end
35
+
36
+ # apparently events don't work yet in IronRuby.. keeping this spec here to find out when it does
37
+ # it "should not raise an error when subcribing to an event" do
38
+ # lambda { ClrModels::ExposedChangedSubscriber.new(@proxy) }.should_not raise_error
39
+ # end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,87 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe "Caricature::Isolation" do
4
+
5
+ describe "when creating an isolation for ruby objects" do
6
+
7
+ it "should not raise" do
8
+ lambda { Caricature::Isolation.for(Soldier) }.should_not raise_error
9
+ end
10
+
11
+ end
12
+
13
+ describe "after creation of the isolation for a ruby object" do
14
+
15
+ before do
16
+ @isolator = Caricature::Isolation.for(Soldier)
17
+ end
18
+
19
+ it "should create a proxy" do
20
+ @isolator.should_not be_nil
21
+ end
22
+
23
+ describe "when asked to stub a method" do
24
+
25
+ it "should create an expectation with a block" do
26
+ nm = "What's in a name"
27
+ expectation = @isolator.when_receiving(:name) do |cl|
28
+ cl.return(nm)
29
+ end
30
+ expectation.method_name.should == :name
31
+ expectation.should be_has_return_value
32
+ expectation.return_value.should == nm
33
+ end
34
+
35
+ it "should create an expectation without a block" do
36
+ nm = "What's in a name"
37
+ expectation = @isolator.when_receiving(:name).return(nm)
38
+ expectation.method_name.should == :name
39
+ expectation.should be_has_return_value
40
+ expectation.return_value.should == nm
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ describe "when creating an isolation for CLR objects" do
47
+
48
+ it "should not raise" do
49
+ lambda { Caricature::Isolation.for(ClrModels::Ninja) }.should_not raise_error
50
+ end
51
+
52
+ end
53
+
54
+ describe "after creation of the isolation for a CLR object" do
55
+
56
+ before do
57
+ @isolator = Caricature::Isolation.for(ClrModels::Ninja)
58
+ end
59
+
60
+ it "should create a proxy" do
61
+ @isolator.should_not be_nil
62
+ end
63
+
64
+ describe "when asked to stub a method" do
65
+
66
+ it "should create an expectation with a block" do
67
+ nm = "What's in a name"
68
+ expectation = @isolator.when_receiving(:name) do |cl|
69
+ cl.return(nm)
70
+ end
71
+ expectation.method_name.should == :name
72
+ expectation.should be_has_return_value
73
+ expectation.return_value.should == nm
74
+ end
75
+
76
+ it "should create an expectation without a block" do
77
+ nm = "What's in a name"
78
+ expectation = @isolator.when_receiving(:name).return(nm)
79
+ expectation.method_name.should == :name
80
+ expectation.should be_has_return_value
81
+ expectation.return_value.should == nm
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -0,0 +1,220 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ class TestIsolation
4
+ attr_accessor :instance, :expectations
5
+ def initialize(instance, expectations)
6
+ @instance, @expectations = instance, expectations
7
+ end
8
+ def send_message(method_name, return_type, *args, &b)
9
+ internal_send method_name, :internal, return_type, *args, &b
10
+ end
11
+ def send_class_message(method_name, return_type, *args, &b)
12
+ internal_send method_name, :class, return_type, *args, &b
13
+ end
14
+ def internal_send(method_name, mode, return_type, *args, &b)
15
+ exp = expectations.find(method_name, mode, *args)
16
+ if exp
17
+ res = instance.__send__(method_name, *args, &b) if exp.super_before?
18
+ res = exp.execute(*args)
19
+ res = instance.__send__(method_name, *args, &b) if !exp.super_before? and exp.call_super?
20
+ res
21
+ else
22
+ rt = nil
23
+ is_value_type = return_type && return_type != System::Void.to_clr_type && return_type.is_value_type
24
+ rt = System::Activator.create_instance(return_type) if is_value_type
25
+ rt
26
+ end
27
+ end
28
+ end
29
+
30
+ describe "Caricature::RubyIsolator" do
31
+
32
+ before do
33
+ @subj = Soldier.new
34
+ res = Caricature::RubyIsolator.for Caricature::IsolatorContext.new(@subj)
35
+ iso = TestIsolation.new res.subject, Caricature::Expectations.new
36
+ @proxy = res.isolation
37
+ @proxy.class.instance_variable_set("@___context___", iso)
38
+ end
39
+
40
+
41
+ describe "when invoking a method" do
42
+
43
+ before do
44
+ @proxy.name
45
+ end
46
+
47
+ it "should return nil" do
48
+ @proxy.name.should be_nil
49
+ end
50
+
51
+ end
52
+
53
+ describe "when isolating a class with class members" do
54
+
55
+ before do
56
+ res = Caricature::RubyIsolator.for Caricature::IsolatorContext.new(DaggerWithClassMembers)
57
+ iso = TestIsolation.new res.subject, Caricature::Expectations.new
58
+ @proxy = res.isolation
59
+ @proxy.class.instance_variable_set("@___context___", iso)
60
+ end
61
+
62
+ it "should return nil for the class method" do
63
+
64
+ @proxy.class.class_name.should be_nil
65
+
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ describe "Caricature::RecordingClrProxy" do
72
+
73
+ describe "for an instance of a CLR class" do
74
+
75
+ before do
76
+ @ninja = ClrModels::Ninja.new
77
+ @ninja.name = "Nakiro"
78
+ context = Caricature::IsolatorContext.new(@ninja)
79
+ res = Caricature::ClrIsolator.for context
80
+ iso = TestIsolation.new res.subject, Caricature::Expectations.new
81
+ @proxy = res.isolation
82
+ @proxy.class.instance_variable_set("@___context___", iso)
83
+ end
84
+
85
+ it "should create a proxy" do
86
+
87
+ @proxy.___super___.name.should == @ninja.name
88
+ @proxy.___super___.id.should == 1
89
+ end
90
+
91
+ describe "when invoking a method" do
92
+
93
+ before do
94
+ @proxy.name
95
+ end
96
+
97
+ it "should return nil" do
98
+ @proxy.name.should be_nil
99
+ end
100
+
101
+ end
102
+
103
+ describe "when isolating a class with class members" do
104
+
105
+ before do
106
+ res = Caricature::ClrIsolator.for Caricature::IsolatorContext.new(ClrModels::SwordWithStatics)
107
+ iso = TestIsolation.new res.subject, Caricature::Expectations.new
108
+ @proxy = res.isolation
109
+ @proxy.class.instance_variable_set("@___context___", iso)
110
+ end
111
+
112
+ it "should return nil for the class method" do
113
+
114
+ @proxy.class.class_naming.should be_nil
115
+
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+
122
+ describe "for a CLR class" do
123
+
124
+ before do
125
+ @recorder = Caricature::MethodCallRecorder.new
126
+ context = Caricature::IsolatorContext.new(ClrModels::Ninja, @recorder)
127
+ res = Caricature::ClrIsolator.for context
128
+ iso = TestIsolation.new res.subject, Caricature::Expectations.new
129
+ @proxy = res.isolation
130
+ @proxy.class.instance_variable_set("@___context___", iso)
131
+ end
132
+
133
+ it "should create a proxy" do
134
+
135
+ @proxy.class.superclass.should == ClrModels::Ninja
136
+
137
+ end
138
+
139
+
140
+ end
141
+
142
+ describe "for a CLR interface" do
143
+
144
+ before do
145
+ res = Caricature::ClrInterfaceIsolator.for Caricature::IsolatorContext.new(ClrModels::IWarrior)
146
+ @proxy = res.isolation
147
+ end
148
+
149
+ it "should create a proxy" do
150
+ @proxy.class.to_s.should match(/^IWarrior/)
151
+ end
152
+
153
+ it "should create a method on the proxy" do
154
+ @proxy.should respond_to(:is_killed_by)
155
+ end
156
+
157
+ it "should create a getter for a property on the proxy" do
158
+ @proxy.should respond_to(:id)
159
+ end
160
+
161
+ it "should create a setter for a writable property on the proxy" do
162
+ @proxy.should respond_to(:name=)
163
+ end
164
+
165
+ end
166
+
167
+ describe "for a CLR Interface with an event" do
168
+
169
+ before do
170
+ res = Caricature::ClrInterfaceIsolator.for Caricature::IsolatorContext.new(ClrModels::IExposing)
171
+ @proxy = res.isolation
172
+ end
173
+
174
+ it "should create an add method for the event" do
175
+ @proxy.should respond_to(:add_is_exposed_changed)
176
+ end
177
+
178
+ it "should create a remove method for the event" do
179
+ @proxy.should respond_to(:remove_is_exposed_changed)
180
+ end
181
+
182
+ end
183
+
184
+ describe "for CLR interface recursion" do
185
+
186
+ before do
187
+ res = Caricature::ClrInterfaceIsolator.for Caricature::IsolatorContext.new(ClrModels::IExposingWarrior)
188
+ @proxy = res.isolation
189
+ end
190
+
191
+ it "should create a method defined on the CLR interface" do
192
+ @proxy.should respond_to(:own_method)
193
+ end
194
+
195
+ it "should create a method defined on one of the composing interfaces" do
196
+ @proxy.should respond_to(:some_method)
197
+ end
198
+
199
+ it "should create a method defined on one of the topmost composing interfaces" do
200
+ @proxy.should respond_to(:is_killed_by)
201
+ end
202
+
203
+ it "should create an add method for an event defined on a composing interface" do
204
+ @proxy.should respond_to(:add_is_exposed_changed)
205
+ end
206
+
207
+ it "should create a remove method for an event defined on a composing interface" do
208
+ @proxy.should respond_to(:remove_is_exposed_changed)
209
+ end
210
+
211
+ it "should create a getter for a property on the proxy" do
212
+ @proxy.should respond_to(:id)
213
+ end
214
+
215
+ it "should create a setter for a writable property on the proxy" do
216
+ @proxy.should respond_to(:name=)
217
+ end
218
+ end
219
+
220
+ end
@@ -0,0 +1,311 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ class EmptyExpectations
4
+
5
+ def find(method_name, *args, &b)
6
+ nil
7
+ end
8
+ end
9
+
10
+ class ReturnValueExpecation
11
+
12
+ def initialize
13
+ @super_before_called = false
14
+ @call_super_called = false
15
+ @called_super_after = false
16
+ end
17
+
18
+ def block
19
+ nil
20
+ end
21
+
22
+ def super_before?
23
+ @super_before_called = true
24
+ false
25
+ end
26
+
27
+ def call_super?
28
+ @call_super_called = true
29
+ false
30
+ end
31
+
32
+ def have_called_super_before?
33
+ @super_before_called
34
+ end
35
+
36
+ def have_called_call_super?
37
+ @super_before_called && @called_super_after
38
+ end
39
+
40
+ def execute(*args)
41
+ @called_super_after = !@call_super_called
42
+ 5
43
+ end
44
+ end
45
+
46
+ class ReturnValueExpectations
47
+
48
+ def expectation
49
+ @expectation ||= ReturnValueExpecation.new
50
+ @expectation
51
+ end
52
+ def find(method_name, *args, &b)
53
+ return expectation if method_name == :a_message
54
+ nil
55
+ end
56
+ end
57
+
58
+ class PassThruBlockExpectation
59
+
60
+ def block
61
+ @block
62
+ end
63
+
64
+ def block=(val)
65
+ @block=val
66
+ end
67
+
68
+ def block_args
69
+ [5,6,7]
70
+ end
71
+
72
+ def execute(*args, &b)
73
+ b.call *block_args
74
+ end
75
+
76
+ def super_before?
77
+ false
78
+ end
79
+
80
+ def call_super?
81
+ false
82
+ end
83
+
84
+ end
85
+
86
+ class CallingBlock
87
+ def a_message(*args, &b)
88
+ b.call(7,8,9)
89
+ end
90
+ end
91
+
92
+ class BlockExpectation
93
+ def block
94
+ lambda { |*args| return args }
95
+ end
96
+
97
+ def super_before?
98
+ false
99
+ end
100
+
101
+ def call_super?
102
+ true
103
+ end
104
+
105
+ def execute(*args, &b)
106
+
107
+ end
108
+
109
+ end
110
+
111
+ class BlockExpectations
112
+
113
+ def initialize(pass_thru=true)
114
+ @pass_thru = pass_thru
115
+ end
116
+
117
+ def expectation
118
+ @expectation ||= (@pass_thru ? PassThruBlockExpectation.new : BlockExpectation.new)
119
+ @expectation
120
+ end
121
+ def find(method_name, *args, &b)
122
+ return expectation if method_name == :a_message
123
+ nil
124
+ end
125
+ end
126
+
127
+
128
+ describe "Caricature::Messenger strategies" do
129
+
130
+ describe "Caricature::RubyMessenger" do
131
+
132
+ it "should return nil for any method name not in the expectation collection" do
133
+ messenger = Caricature::RubyMessenger.new EmptyExpectations.new
134
+ messenger.deliver(:a_message, nil).should be_nil
135
+ end
136
+
137
+ describe "when an expectation with a return value has been defined" do
138
+
139
+ before do
140
+ @messenger = Caricature::RubyMessenger.new ReturnValueExpectations.new
141
+ end
142
+
143
+ it "should return the a value when specified by the expecation" do
144
+ @messenger.deliver(:a_message, nil).should_not be_nil
145
+ end
146
+
147
+ it "should return the value specified by the expecation" do
148
+ @messenger.deliver(:a_message, nil).should == 5
149
+ end
150
+
151
+ it "should call super_before before executing the expectation" do
152
+ @messenger.deliver(:a_message, nil)
153
+ @messenger.expectations.expectation.should be_have_called_super_before
154
+ end
155
+
156
+ it "should call call_super? after executing the expectation" do
157
+ @messenger.deliver(:a_message, nil)
158
+ @messenger.expectations.expectation.should be_have_called_call_super
159
+ end
160
+
161
+ end
162
+
163
+ describe "when an expectation with a block has been defined" do
164
+
165
+ it "should invoke the block that is passed with the args from the expectation only once" do
166
+ messenger = Caricature::RubyMessenger.new BlockExpectations.new
167
+ messenger.recorder = Caricature::MethodCallRecorder.new
168
+ counter = 0
169
+ arguments = []
170
+ messenger.deliver(:a_message, nil) do |*args|
171
+ counter += 1
172
+ arguments = args
173
+ end
174
+ counter.should == 1
175
+ [5,6,7].should == arguments
176
+ end
177
+
178
+ it "should call the block that is defined on the expectation by super when call super is enabled" do
179
+ exp = BlockExpectations.new(false)
180
+ messenger = Caricature::RubyMessenger.new exp, CallingBlock.new
181
+ result = messenger.deliver(:a_message, nil, exp.expectation)
182
+ [7,8,9].should == result
183
+ end
184
+
185
+ end
186
+
187
+
188
+ end
189
+
190
+ describe "Caricature::ClrClassMessenger" do
191
+
192
+ it "should return nil for any method name not in the expectation collection" do
193
+ messenger = Caricature::ClrClassMessenger.new EmptyExpectations.new
194
+ messenger.deliver(:a_message, nil).should be_nil
195
+ end
196
+
197
+ it "should return the default value for a value type return type" do
198
+ messenger = Caricature::ClrClassMessenger.new EmptyExpectations.new
199
+ messenger.deliver(:a_message, System::Int32.to_clr_type).should == 0
200
+ end
201
+
202
+ describe "when an expectation with a return value has been defined" do
203
+
204
+ before do
205
+ @messenger = Caricature::ClrClassMessenger.new ReturnValueExpectations.new
206
+ end
207
+
208
+ it "should return the a value when specified by the expecation" do
209
+ @messenger.deliver(:a_message, nil).should_not be_nil
210
+ end
211
+
212
+ it "should return the value specified by the expecation" do
213
+ @messenger.deliver(:a_message, nil).should == 5
214
+ end
215
+
216
+ it "should call super_before before executing the expectation" do
217
+ @messenger.deliver(:a_message, nil)
218
+ @messenger.expectations.expectation.should be_have_called_super_before
219
+ end
220
+
221
+ it "should call call_super? after executing the expectation" do
222
+ @messenger.deliver(:a_message, nil)
223
+ @messenger.expectations.expectation.should be_have_called_call_super
224
+ end
225
+
226
+ end
227
+
228
+ describe "when an expectation with a block has been defined" do
229
+
230
+ it "should invoke the block that is passed with the args from the expectation only once" do
231
+ messenger = Caricature::ClrClassMessenger.new BlockExpectations.new
232
+ messenger.recorder = Caricature::MethodCallRecorder.new
233
+ counter = 0
234
+ arguments = []
235
+ messenger.deliver(:a_message, nil) do |*args|
236
+ counter += 1
237
+ arguments = args
238
+ end
239
+ counter.should == 1
240
+ [5,6,7].should == arguments
241
+ end
242
+
243
+ it "should call the block that is defined on the expectation by super when call super is enabled" do
244
+ messenger = Caricature::ClrClassMessenger.new BlockExpectations.new(false), CallingBlock.new
245
+ result = messenger.deliver(:a_message, nil)
246
+ [7,8,9].should == result
247
+ end
248
+
249
+ end
250
+
251
+ end
252
+
253
+ describe "Caricature::ClrInterfaceMessenger" do
254
+
255
+ it "should return nil for any method name not in the expectation collection" do
256
+ messenger = Caricature::ClrInterfaceMessenger.new EmptyExpectations.new
257
+ messenger.deliver(:a_message, nil).should be_nil
258
+ end
259
+
260
+ it "should return the default value for a value type return type" do
261
+ messenger = Caricature::ClrClassMessenger.new EmptyExpectations.new
262
+ messenger.deliver(:a_message, System::Int32.to_clr_type).should == 0
263
+ end
264
+
265
+ describe "when an expectation with a return value has been defined" do
266
+
267
+ before do
268
+ @messenger = Caricature::ClrInterfaceMessenger.new ReturnValueExpectations.new
269
+ end
270
+
271
+ it "should return the a value when specified by the expecation" do
272
+ @messenger.deliver(:a_message, nil).should_not be_nil
273
+ end
274
+
275
+ it "should return the value specified by the expecation" do
276
+ @messenger.deliver(:a_message, nil).should == 5
277
+ end
278
+
279
+ it "should not call super_before before executing the expectation" do
280
+ @messenger.deliver(:a_message, nil)
281
+ @messenger.expectations.expectation.should_not be_have_called_super_before
282
+ end
283
+
284
+ it "should not call call_super? after executing the expectation" do
285
+ @messenger.deliver(:a_message, nil)
286
+ @messenger.expectations.expectation.should_not be_have_called_call_super
287
+ end
288
+
289
+ end
290
+
291
+ describe "when an expectation with a block has been defined" do
292
+
293
+ it "should invoke the block that is passed with the args from the expectation only once" do
294
+ exp = BlockExpectations.new
295
+ messenger = Caricature::ClrInterfaceMessenger.new exp
296
+ messenger.recorder = Caricature::MethodCallRecorder.new
297
+ counter = 0
298
+ arguments = []
299
+ messenger.deliver(:a_message, nil, exp.expectation) do |*args|
300
+ counter += 1
301
+ arguments = args
302
+ end
303
+ counter.should == 1
304
+ [5,6,7].should == arguments
305
+ end
306
+
307
+ end
308
+
309
+ end
310
+
311
+ end