caricature 0.7.2 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/README.rdoc +97 -97
  2. data/Rakefile +310 -310
  3. data/caricature.gemspec +110 -106
  4. data/lib/caricature.rb +3 -1
  5. data/lib/caricature/bacon.rb +2 -2
  6. data/lib/caricature/bacon/integration.rb +75 -55
  7. data/lib/caricature/clr.rb +4 -3
  8. data/lib/caricature/clr/aspnet_mvc.rb +3 -3
  9. data/lib/caricature/clr/descriptor.rb +106 -39
  10. data/lib/caricature/clr/event_verification.rb +57 -0
  11. data/lib/caricature/clr/expectation.rb +101 -0
  12. data/lib/caricature/clr/isolation.rb +49 -13
  13. data/lib/caricature/clr/isolator.rb +141 -5
  14. data/lib/caricature/clr/messenger.rb +6 -0
  15. data/lib/caricature/clr/method_call_recorder.rb +97 -0
  16. data/lib/caricature/core_ext.rb +11 -0
  17. data/lib/{core_ext → caricature/core_ext}/array.rb +0 -0
  18. data/lib/{core_ext → caricature/core_ext}/class.rb +0 -0
  19. data/lib/{core_ext → caricature/core_ext}/hash.rb +0 -0
  20. data/lib/{core_ext → caricature/core_ext}/module.rb +0 -0
  21. data/lib/{core_ext → caricature/core_ext}/object.rb +0 -0
  22. data/lib/{core_ext → caricature/core_ext}/string.rb +0 -0
  23. data/lib/{core_ext → caricature/core_ext}/system/string.rb +0 -0
  24. data/lib/{core_ext → caricature/core_ext}/system/type.rb +6 -0
  25. data/lib/caricature/expectation.rb +108 -66
  26. data/lib/caricature/isolator.rb +3 -3
  27. data/lib/caricature/method_call_recorder.rb +32 -4
  28. data/lib/caricature/rspec/integration.rb +118 -77
  29. data/lib/caricature/version.rb +5 -5
  30. data/spec/bacon/integration/callback_spec.rb +156 -156
  31. data/spec/bacon/integration/clr_to_clr_spec.rb +1 -2
  32. data/spec/bacon/integration/event_spec.rb +98 -0
  33. data/spec/bacon/integration/indexer_spec.rb +1 -1
  34. data/spec/bacon/spec_helper.rb +4 -4
  35. data/spec/bacon/unit/descriptor_spec.rb +95 -42
  36. data/spec/bacon/unit/expectation_spec.rb +2 -2
  37. data/spec/bacon/unit/interop_spec.rb +1 -14
  38. data/spec/bacon/unit/isolation_spec.rb +1 -1
  39. data/spec/bacon/unit/isolator_spec.rb +5 -5
  40. data/spec/bin/ClrModels.dll +0 -0
  41. data/spec/models/ClrModels.cs +32 -8
  42. data/spec/models/ruby_models.rb +150 -150
  43. data/spec/rspec/integration/callback_spec.rb +156 -156
  44. data/spec/rspec/integration/indexer_spec.rb +1 -1
  45. data/spec/rspec/spec_helper.rb +12 -6
  46. data/spec/rspec/unit/descriptor_spec.rb +93 -42
  47. data/spec/rspec/unit/event_spec.rb +17 -0
  48. data/spec/rspec/unit/interop_spec.rb +0 -13
  49. data/spec/spec_helper.rb +14 -14
  50. metadata +20 -22
  51. data/lib/core_ext/core_ext.rb +0 -8
  52. data/spec/bin/ClrModels.dll.mdb +0 -0
@@ -0,0 +1,97 @@
1
+ module Caricature
2
+
3
+ # A recording that represents an event raise
4
+ # it contains argument variations that can be matched too
5
+ class EventRaiseRecording
6
+
7
+ # gets or sets the event name
8
+ attr_accessor :event_name
9
+
10
+ # gets or sets the amount of times the event was raised
11
+ attr_accessor :count
12
+
13
+ # gets or sets the arguments for this event raise
14
+ attr_accessor :args
15
+
16
+ # gets or sets the block for this event raise
17
+ attr_accessor :handler
18
+
19
+ # Initializes a new instance of a method call recording
20
+ # every time a method gets called in an isolated object
21
+ # this gets stored in the method call recorder
22
+ # It expects a +method_name+ at the very least.
23
+ def initialize(event_name, count=0)
24
+ @event_name = event_name
25
+ @count = count
26
+ @variations = []
27
+ end
28
+
29
+ # add args
30
+ def args
31
+ @variations
32
+ end
33
+
34
+ # indicates if it has an argument variation
35
+ def has_argument_variations?
36
+ @variations.size > 1
37
+ end
38
+
39
+ # add an argument variation
40
+ def add_argument_variation(args, block)
41
+ variation = find_argument_variations args
42
+ if variation.empty?
43
+ @variations << ArgumentRecording.new(args, @variations.size+1, block) if variation == []
44
+ else
45
+ variation.first.call_number += 1
46
+ end
47
+ end
48
+
49
+ # finds an argument variation that matches the provided +args+
50
+ def find_argument_variations(args)
51
+ return @variations if args.first.is_a?(Symbol) and args.last == :any
52
+ @variations.select { |ar| ar.args == args }
53
+ end
54
+
55
+ end
56
+
57
+ class MethodCallRecorder
58
+
59
+ def event_raises
60
+ @event_raises ||= {}
61
+ end
62
+
63
+ def record_event_raise(event_name, mode, *args, &handler)
64
+ en_sym = event_name.to_sym
65
+ event_raises[mode] ||= {}
66
+ ev = (event_raises[mode][en_sym] ||= EventRaiseRecording.new(event_name))
67
+ ev.count += 1
68
+ ev.add_argument_variation args, handler
69
+ end
70
+
71
+ def event_error
72
+ @event_error
73
+ end
74
+
75
+ # returns whether the event was actually raised with the specified constraints
76
+ def event_raised?(event_name, mode = :instance, *args)
77
+ mc = event_raises[mode][event_name.to_s.to_sym]
78
+ if mc
79
+ vari = mc.find_argument_variations(args)
80
+ result = vari.any? { |agv| agv == args }
81
+ return result if result
82
+ if args.size == 1 and args.last.is_a?(Hash)
83
+ result = vari.any? do |agv|
84
+ agv.args.last.is_a?(Hash) and args.last.all? { |k, v| agv.args.last[k] == v }
85
+ end
86
+ end
87
+ @event_error = "Event Arguments don't match for #{event_name}.\n\nYou expected:\n#{args.join(", ")}.\n\nI did find the following variations:\n#{mc.args.collect {|ar| ar.args.join(', ') }.join(' and ')}" unless result
88
+ result
89
+ else
90
+ @event_error = "Couldn't find an event with name #{event_name}"
91
+ return !!mc
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/core_ext/string'
2
+ require File.dirname(__FILE__) + '/core_ext/class'
3
+ require File.dirname(__FILE__) + '/core_ext/module'
4
+ require File.dirname(__FILE__) + '/core_ext/object'
5
+ require File.dirname(__FILE__) + '/core_ext/array'
6
+ require File.dirname(__FILE__) + '/core_ext/hash'
7
+
8
+ if defined? IRONRUBY_VERSION
9
+ require File.dirname(__FILE__) + '/core_ext/system/string'
10
+ require File.dirname(__FILE__) + '/core_ext/system/type'
11
+ end
@@ -16,6 +16,12 @@ module System
16
16
  self.get_properties + iface_properties.flatten
17
17
  end
18
18
 
19
+ def collect_interface_events
20
+ iface_events = []
21
+ iface_events += self.get_interfaces.collect { |t| t.collect_interface_events }
22
+ self.get_events + iface_events.flatten.uniq
23
+ end
24
+
19
25
  end
20
26
 
21
27
  end
@@ -35,58 +35,66 @@ module Caricature
35
35
  # contains the syntax for building up an expectation
36
36
  # This is shared between the +ExpecationBuilder+ and the +Expectation+
37
37
  module ExpectationSyntax
38
+
38
39
  # tell the expection which arguments it needs to respond to
39
40
  # there is a magic argument here +any+ which configures
40
41
  # the expectation to respond to any arguments
41
- def with(*args, &b)
42
- @any_args = args.first.is_a?(Symbol) and args.first == :any
43
- @args = args
44
- @callback = b unless b.nil?
42
+ def with(*ags, &b)
43
+ collected[:any_args] = ags.first.is_a?(Symbol) and ags.first == :any
44
+ collected[:args] = ags
45
+ collected[:callback] = b unless b.nil?
45
46
  self
46
47
  end
47
48
 
48
49
  # tell the expectation it nees to return this value or the value returned by the block
49
50
  # you provide to this method.
50
51
  def return(value=nil, &b)
51
- @return_value = value
52
- @return_callback = b if b
52
+ collected[:return_value] = value
53
+ collected[:return_callback] = b if b
53
54
  self
54
55
  end
55
56
 
56
57
  # Sets up arguments for the block that is being passed into the isolated method call
57
- def pass_block(*args, &b)
58
- @any_block_args = args.first.is_a?(Symbol) and args.first == :any
59
- @block_args = args
60
- @block_callback = b unless b.nil?
58
+ def pass_block(*ags, &b)
59
+ collected[:any_block_args] = ags.first.is_a?(Symbol) and args.first == :any
60
+ collected[:block_args] = ags
61
+ collected[:block_callback] = b unless b.nil?
61
62
  self
62
63
  end
63
64
 
64
65
  # tell the expectation it needs to raise an error with the specified arguments
65
66
  alias_method :actual_raise, :raise
66
67
  def raise(*args)
67
- @error_args = args
68
+ collected[:error_args] = args
68
69
  self
69
70
  end
70
-
71
+
71
72
  # tell the expecation it needs to call the super before the expectation exectution
72
73
  def super_before(&b)
73
- @super = :before
74
- @block = b if b
74
+ collected[:super] = :before
75
+ collected[:block] = b if b
75
76
  self
76
77
  end
77
-
78
+
78
79
  # tell the expectation it needs to call the super after the expecation execution
79
80
  def super_after(&b)
80
- @super = :after
81
- @block = b if b
81
+ collected[:super] = :after
82
+ collected[:block] = b if b
82
83
  self
83
84
  end
84
85
 
85
86
  # indicates whether this expectation should match with any arguments
86
87
  # or only for the specified arguments
87
88
  def any_args?
88
- @any_args
89
+ collected[:any_args]
89
90
  end
91
+
92
+
93
+ private
94
+
95
+ def collected
96
+ @collected ||= {}
97
+ end
90
98
  end
91
99
 
92
100
  # A description of an expectation.
@@ -95,106 +103,140 @@ module Caricature
95
103
 
96
104
  include ExpectationSyntax
97
105
 
98
- # gets the method_name to which this expectation needs to listen to
99
- attr_reader :method_name
100
-
101
- # the arguments that this expectation needs to be constrained by
102
- attr_reader :args
103
-
104
106
  # the error_args that this expectation will raise an error with
105
- attr_reader :error_args
107
+ def error_args
108
+ collected[:error_args]
109
+ end
106
110
 
107
111
  # the value that this expecation will return when executed
108
- attr_reader :return_value
112
+ def return_value
113
+ collected[:return_value]
114
+ end
109
115
 
110
116
  # indicator for the mode to call the super +:before+, +:after+ and +nil+
111
- attr_reader :super
112
-
117
+ def super
118
+ collected[:super]
119
+ end
120
+
113
121
  # contains the callback if one is given
114
- attr_reader :callback
122
+ def callback
123
+ collected[:callback]
124
+ end
115
125
 
116
126
  # contains the callback that is used to return the value when this expectation
117
127
  # is executed
118
- attr_reader :return_callback
128
+ def return_callback
129
+ collected[:return_callback]
130
+ end
119
131
 
120
132
  # contains the arguments that will be passed on to the block
121
- attr_reader :block_args
133
+ def block_args
134
+ collected[:block_args]
135
+ end
122
136
 
123
137
  # The block that will be used as value provider for the block in the method
124
- attr_reader :block_callback
138
+ def block_callback
139
+ collected[:block_callback]
140
+ end
125
141
 
126
142
  # the block that will be used
127
- attr_accessor :block
128
-
129
-
143
+ def block
144
+ collected[:block]
145
+ end
146
+
147
+ # sets the block callback
148
+ def block=(val)
149
+ collected[:block] = val
150
+ end
151
+
152
+ # gets the method_name to which this expectation needs to listen to
153
+ def method_name
154
+ collected[:method_name]
155
+ end
156
+
157
+ # the arguments that this expectation needs to be constrained by
158
+ def args
159
+ collected[:args]
160
+ end
161
+
130
162
  # Initializes a new instance of an expectation
131
- def initialize(*args)
132
- @method_name, @args, @error_args, @return_value, @return_callback,
133
- @super, @callback, @block_args, @block_callback, @block = *args
134
- @any_args = true
163
+ def initialize(options={})
164
+ collected[:any_args] = true
165
+ collected.merge!(options)
135
166
  end
136
-
167
+
137
168
  # indicates whether this expecation will raise an event.
138
169
  def has_error_args?
139
- !@error_args.nil?
170
+ !collected[:error_args].nil?
140
171
  end
141
172
 
142
173
  # indicates whether this expectation will return a value.
143
174
  def has_return_value?
144
- !@return_value.nil?
175
+ !collected[:return_value].nil?
145
176
  end
146
177
 
147
178
  # call the super before the expectation
148
179
  def super_before?
149
- @super == :before
180
+ collected[:super] == :before
150
181
  end
151
182
 
152
183
  # indicates whether super needs to be called somewhere
153
184
  def call_super?
154
- !@super.nil?
185
+ !collected[:super].nil?
155
186
  end
156
187
 
157
188
  # indicates whether this expecation has a callback it needs to execute
158
189
  def has_callback?
159
- !@callback.nil?
190
+ !collected[:callback].nil?
160
191
  end
161
-
192
+
162
193
  # indicates whether this expectation has a block as value provider for the method call block
163
194
  def has_block_callback?
164
- !@block_callback.nil?
195
+ !collected[:block_callback].nil?
165
196
  end
166
197
 
167
198
  # a flag to indicate it has a return value callback
168
199
  def has_return_callback?
169
- !@return_callback.nil?
200
+ !collected[:return_callback].nil?
170
201
  end
171
202
 
172
203
  # executes this expectation with its configuration
173
204
  def execute(*margs,&b)
174
- ags = any_args? ? (margs.empty? ? :any : margs) : args
175
- actual_raise *@error_args if has_error_args?
176
- callback.call(*ags) if has_callback?
177
-
178
- if b
179
- if has_block_callback?
180
- b.call(*@block_callback.call)
181
- else
182
- b.call(*@block_args)
183
- end
184
- end
205
+ ags = any_args? ? :any : (margs.empty? ? collected[:args] : margs)
206
+ do_raise_error
207
+ do_callback(ags)
208
+ do_block_callback(&b)
209
+ do_event_raise if respond_to?(:events)
185
210
 
186
- return @return_callback.call(*margs) if has_return_callback?
211
+ return collected[:return_callback].call(*margs) if has_return_callback?
187
212
  return return_value if has_return_value?
188
213
  nil
189
214
  end
190
215
 
191
- def to_s
216
+ def to_s #:nodoc:
192
217
  "<Caricature::Expecation, method_name: #{method_name}, args: #{args}, error args: #{error_args}>"
193
218
  end
194
-
195
- def inspect
196
- to_s
219
+ alias :inspect :to_s
220
+
221
+
222
+ private
223
+
224
+ def do_raise_error #:nodoc:
225
+ actual_raise *collected[:error_args] if has_error_args?
226
+ end
227
+
228
+ def do_callback(ags) #:nodoc:
229
+ callback.call(*ags) if has_callback?
197
230
  end
231
+
232
+ def do_block_callback(&b) #:nodoc:
233
+ if b
234
+ ags = has_block_callback? ? collected[:block_callback].call : collected[:block_args]
235
+ b.call(*ags)
236
+ end
237
+ end
238
+
239
+
198
240
  end
199
241
 
200
242
  # Constructs the expecation object.
@@ -207,14 +249,14 @@ module Caricature
207
249
  # this builder is passed into the block to allow only certain
208
250
  # operations in the block.
209
251
  def initialize(method_name)
210
- @method_name, @args, @any_args = method_name, [], true
252
+ @collected = { :method_name => method_name, :args => [], :any_args => true }
211
253
  end
212
254
 
213
255
 
214
256
 
215
257
  # build up the expectation with the provided arguments
216
258
  def build
217
- Expectation.new @method_name, @args, @error_args, @return_value, @return_callback, @super, @callback, @block_args, @block_callback, @block
259
+ Expectation.new collected
218
260
  end
219
261
 
220
262
  end
@@ -214,6 +214,7 @@ module Caricature
214
214
  pxy.instance_variable_set("@___context___", context)
215
215
  pxy
216
216
  end
217
+
217
218
 
218
219
  class << self
219
220
 
@@ -280,17 +281,16 @@ module Caricature
280
281
  def initialize(*args)
281
282
  self
282
283
  end
283
-
284
+
284
285
  cmembers.each do |mn|
285
286
  mn = mn.name.to_s.to_sym
286
287
  define_cmethod mn do |*args|
288
+ return if mn.to_s =~ /$(singleton_)?method_added/ and args.first.to_s =~ /$(singleton_)?method_added/
287
289
  b = nil
288
290
  b = Proc.new { yield } if block_given?
289
291
  isolation_context.send_class_message(mn, nil, *args, &b)
290
292
  end
291
293
  end
292
-
293
-
294
294
 
295
295
  end
296
296