rspec-mocks 3.8.2 → 3.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 863a1af1be0ed566b9345a1bdb9ec999137b959e8612b102d6af6e8b43ecd001
4
- data.tar.gz: 01f7282d03cea9cf658c3ada9bb008d7ab9f3d60313e092b9709a0b0e28685b3
3
+ metadata.gz: f53d2fe5ab69778d6528b80a08aaa48869a527c5185f715671c0d48beecf5db4
4
+ data.tar.gz: 8e06d4be6fbc3dec6cbbdf75d141638db33653579fcd95b4869cb41b97afb4e8
5
5
  SHA512:
6
- metadata.gz: 218a26419d38c53216a2c5a0275296b1c70239a240e0de6bc7cfbd8d837e703e2e1bd424fe11829400d7182c7f88a6d9690f4851f9883b8c87da6ae9c7e88378
7
- data.tar.gz: 4c746074ce149784310c2aec5b7d0ba5939106a07bcd23ba8b9d917756cd99c849a7befdd052c71b241fc21c066a337e0c1fb286442cb4099d2b72e2729315d8
6
+ metadata.gz: 6863b589a173e3985263e2b49c797389e7db68912df5f6f294f23833d66cbeb72b10b9b800cca08383322f1b1775b99f7514878663b715b48d4d6e39582b4836
7
+ data.tar.gz: 320ec537f1f7708bd0fb5317ab3878cb569f2a9dbd676b8b8512f36ece73f5efc0d9f7d85bb8b6b30ac145cc5ff3f10d13212897c19e6559a475526703325e1d
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,14 @@
1
+ ### 3.9.0 / 2019-10-07
2
+ [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.8.2...v3.9.0)
3
+
4
+ Enhancements:
5
+
6
+ * Improve thread safety of message expectations by using Mutex to prevent
7
+ deadlocking errors. (Ry Biesemeyer, #1236)
8
+ * Add the ability to use `time` as an alias for `times`. For example:
9
+ `expect(Class).to receive(:method).exactly(1).time`.
10
+ (Pistos, Benoit Tigeot, #1271)
11
+
1
12
  ### 3.8.2 / 2019-10-02
2
13
  [Full Changelog](http://github.com/rspec/rspec-mocks/compare/v3.8.1...v3.8.2)
3
14
 
data/README.md CHANGED
@@ -285,12 +285,15 @@ expect(double).to receive(:msg).with(hash_excluding(:a => 5)) # first arg is a h
285
285
  ```ruby
286
286
  expect(double).to receive(:msg).once
287
287
  expect(double).to receive(:msg).twice
288
+ expect(double).to receive(:msg).exactly(n).time
288
289
  expect(double).to receive(:msg).exactly(n).times
289
290
  expect(double).to receive(:msg).at_least(:once)
290
291
  expect(double).to receive(:msg).at_least(:twice)
292
+ expect(double).to receive(:msg).at_least(n).time
291
293
  expect(double).to receive(:msg).at_least(n).times
292
294
  expect(double).to receive(:msg).at_most(:once)
293
295
  expect(double).to receive(:msg).at_most(:twice)
296
+ expect(double).to receive(:msg).at_most(n).time
294
297
  expect(double).to receive(:msg).at_most(n).times
295
298
  ```
296
299
 
@@ -327,7 +330,7 @@ expect(double).to receive(:msg).and_return(value)
327
330
  expect(double).to receive(:msg).exactly(3).times.and_return(value1, value2, value3)
328
331
  # returns value1 the first time, value2 the second, etc
329
332
  expect(double).to receive(:msg).and_raise(error)
330
- # error can be an instantiated object or a class
333
+ # `error` can be an instantiated object (e.g. `StandardError.new(some_arg)`) or a class (e.g. `StandardError`)
331
334
  # if it is a class, it must be instantiable with no args
332
335
  expect(double).to receive(:msg).and_throw(:msg)
333
336
  expect(double).to receive(:msg).and_yield(values, to, yield)
@@ -41,6 +41,7 @@ module RSpec
41
41
  record :thrice
42
42
  record :exactly
43
43
  record :times
44
+ record :time
44
45
  record :never
45
46
  record :at_least
46
47
  record :at_most
@@ -5,7 +5,7 @@ module RSpec
5
5
  class HaveReceived
6
6
  include Matcher
7
7
 
8
- COUNT_CONSTRAINTS = %w[exactly at_least at_most times once twice thrice]
8
+ COUNT_CONSTRAINTS = %w[exactly at_least at_most times time once twice thrice]
9
9
  ARGS_CONSTRAINTS = %w[with]
10
10
  CONSTRAINTS = COUNT_CONSTRAINTS + ARGS_CONSTRAINTS + %w[ordered]
11
11
 
@@ -1,3 +1,5 @@
1
+ RSpec::Support.require_rspec_support 'mutex'
2
+
1
3
  module RSpec
2
4
  module Mocks
3
5
  # A message expectation that only allows concrete return values to be set
@@ -236,6 +238,7 @@ module RSpec
236
238
  self.inner_implementation_action = block
237
239
  self
238
240
  end
241
+ alias time times
239
242
 
240
243
  # Expect a message not to be received at all.
241
244
  #
@@ -357,6 +360,7 @@ module RSpec
357
360
  # some collaborators it delegates to for this stuff but for now this was
358
361
  # the simplest way to split the public from private stuff to make it
359
362
  # easier to publish the docs for the APIs we want published.
363
+ # rubocop:disable Metrics/ModuleLength
360
364
  module ImplementationDetails
361
365
  attr_accessor :error_generator, :implementation
362
366
  attr_reader :message
@@ -378,6 +382,7 @@ module RSpec
378
382
  @orig_object = @method_double.object
379
383
  @message = @method_double.method_name
380
384
  @actual_received_count = 0
385
+ @actual_received_count_write_mutex = Support::Mutex.new
381
386
  @expected_received_count = type == :expectation ? 1 : :any
382
387
  @argument_list_matcher = ArgumentListMatcher::MATCH_ALL
383
388
  @order_group = expectation_ordering
@@ -536,7 +541,9 @@ module RSpec
536
541
  end
537
542
 
538
543
  def increase_actual_received_count!
539
- @actual_received_count += 1
544
+ @actual_received_count_write_mutex.synchronize do
545
+ @actual_received_count += 1
546
+ end
540
547
  end
541
548
 
542
549
  private
@@ -567,7 +574,9 @@ module RSpec
567
574
  parent_stub.invoke(nil, *args, &block)
568
575
  end
569
576
  ensure
570
- @actual_received_count += increment
577
+ @actual_received_count_write_mutex.synchronize do
578
+ @actual_received_count += increment
579
+ end
571
580
  end
572
581
 
573
582
  def has_been_invoked?
@@ -626,6 +635,7 @@ module RSpec
626
635
  nil
627
636
  end
628
637
  end
638
+ # rubocop:enable Metrics/ModuleLength
629
639
 
630
640
  include ImplementationDetails
631
641
  end
@@ -9,6 +9,11 @@ module RSpec
9
9
  end
10
10
  end
11
11
 
12
+ unless defined?(Mutex)
13
+ Support.require_rspec_support 'mutex'
14
+ Mutex = Support::Mutex
15
+ end
16
+
12
17
  # @private
13
18
  def ensure_implemented(*_args)
14
19
  # noop for basic proxies, see VerifyingProxy for behaviour.
@@ -20,6 +25,7 @@ module RSpec
20
25
  @order_group = order_group
21
26
  @error_generator = ErrorGenerator.new(object)
22
27
  @messages_received = []
28
+ @messages_received_mutex = Mutex.new
23
29
  @options = options
24
30
  @null_object = false
25
31
  @method_doubles = Hash.new { |h, k| h[k] = MethodDouble.new(@object, k, self) }
@@ -90,27 +96,31 @@ module RSpec
90
96
  @error_generator.raise_expectation_on_unstubbed_method(expected_method_name)
91
97
  end
92
98
 
93
- @messages_received.each do |(actual_method_name, args, received_block)|
94
- next unless expectation.matches?(actual_method_name, *args)
99
+ @messages_received_mutex.synchronize do
100
+ @messages_received.each do |(actual_method_name, args, received_block)|
101
+ next unless expectation.matches?(actual_method_name, *args)
95
102
 
96
- expectation.safe_invoke(nil)
97
- block.call(*args, &received_block) if block
103
+ expectation.safe_invoke(nil)
104
+ block.call(*args, &received_block) if block
105
+ end
98
106
  end
99
107
  end
100
108
 
101
109
  # @private
102
110
  def check_for_unexpected_arguments(expectation)
103
- return if @messages_received.empty?
111
+ @messages_received_mutex.synchronize do
112
+ return if @messages_received.empty?
104
113
 
105
- return if @messages_received.any? { |method_name, args, _| expectation.matches?(method_name, *args) }
114
+ return if @messages_received.any? { |method_name, args, _| expectation.matches?(method_name, *args) }
106
115
 
107
- name_but_not_args, others = @messages_received.partition do |(method_name, args, _)|
108
- expectation.matches_name_but_not_args(method_name, *args)
109
- end
116
+ name_but_not_args, others = @messages_received.partition do |(method_name, args, _)|
117
+ expectation.matches_name_but_not_args(method_name, *args)
118
+ end
110
119
 
111
- return if name_but_not_args.empty? && !others.empty?
120
+ return if name_but_not_args.empty? && !others.empty?
112
121
 
113
- expectation.raise_unexpected_message_args_error(name_but_not_args.map { |args| args[1] })
122
+ expectation.raise_unexpected_message_args_error(name_but_not_args.map { |args| args[1] })
123
+ end
114
124
  end
115
125
 
116
126
  # @private
@@ -141,17 +151,23 @@ module RSpec
141
151
 
142
152
  # @private
143
153
  def reset
144
- @messages_received.clear
154
+ @messages_received_mutex.synchronize do
155
+ @messages_received.clear
156
+ end
145
157
  end
146
158
 
147
159
  # @private
148
160
  def received_message?(method_name, *args, &block)
149
- @messages_received.any? { |array| array == [method_name, args, block] }
161
+ @messages_received_mutex.synchronize do
162
+ @messages_received.any? { |array| array == [method_name, args, block] }
163
+ end
150
164
  end
151
165
 
152
166
  # @private
153
167
  def messages_arg_list
154
- @messages_received.map { |_, args, _| args }
168
+ @messages_received_mutex.synchronize do
169
+ @messages_received.map { |_, args, _| args }
170
+ end
155
171
  end
156
172
 
157
173
  # @private
@@ -162,7 +178,9 @@ module RSpec
162
178
  # @private
163
179
  def record_message_received(message, *args, &block)
164
180
  @order_group.invoked SpecificMessage.new(object, message, args)
165
- @messages_received << [message, args, block]
181
+ @messages_received_mutex.synchronize do
182
+ @messages_received << [message, args, block]
183
+ end
166
184
  end
167
185
 
168
186
  # @private
@@ -3,7 +3,7 @@ module RSpec
3
3
  # Version information for RSpec mocks.
4
4
  module Version
5
5
  # Version of RSpec mocks currently in use in SemVer format.
6
- STRING = '3.8.2'
6
+ STRING = '3.9.0'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-mocks
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.8.2
4
+ version: 3.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Baker
@@ -45,7 +45,7 @@ cert_chain:
45
45
  ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
46
46
  F3MdtaDehhjC
47
47
  -----END CERTIFICATE-----
48
- date: 2019-10-02 00:00:00.000000000 Z
48
+ date: 2019-10-07 00:00:00.000000000 Z
49
49
  dependencies:
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: rspec-support
@@ -53,14 +53,14 @@ dependencies:
53
53
  requirements:
54
54
  - - "~>"
55
55
  - !ruby/object:Gem::Version
56
- version: 3.8.0
56
+ version: 3.9.0
57
57
  type: :runtime
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - "~>"
62
62
  - !ruby/object:Gem::Version
63
- version: 3.8.0
63
+ version: 3.9.0
64
64
  - !ruby/object:Gem::Dependency
65
65
  name: diff-lcs
66
66
  requirement: !ruby/object:Gem::Requirement
@@ -194,7 +194,7 @@ licenses:
194
194
  - MIT
195
195
  metadata:
196
196
  bug_tracker_uri: https://github.com/rspec/rspec-mocks/issues
197
- changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.8.2/Changelog.md
197
+ changelog_uri: https://github.com/rspec/rspec-mocks/blob/v3.9.0/Changelog.md
198
198
  documentation_uri: https://rspec.info/documentation/
199
199
  mailing_list_uri: https://groups.google.com/forum/#!forum/rspec
200
200
  source_code_uri: https://github.com/rspec/rspec-mocks
@@ -217,5 +217,5 @@ requirements: []
217
217
  rubygems_version: 3.0.6
218
218
  signing_key:
219
219
  specification_version: 4
220
- summary: rspec-mocks-3.8.2
220
+ summary: rspec-mocks-3.9.0
221
221
  test_files: []
metadata.gz.sig CHANGED
Binary file