rspec-core 3.2.3 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Changelog.md +75 -0
- data/README.md +137 -20
- data/lib/rspec/autorun.rb +1 -0
- data/lib/rspec/core.rb +8 -16
- data/lib/rspec/core/backtrace_formatter.rb +1 -3
- data/lib/rspec/core/bisect/coordinator.rb +66 -0
- data/lib/rspec/core/bisect/example_minimizer.rb +130 -0
- data/lib/rspec/core/bisect/runner.rb +139 -0
- data/lib/rspec/core/bisect/server.rb +61 -0
- data/lib/rspec/core/bisect/subset_enumerator.rb +39 -0
- data/lib/rspec/core/configuration.rb +134 -5
- data/lib/rspec/core/configuration_options.rb +21 -10
- data/lib/rspec/core/example.rb +84 -50
- data/lib/rspec/core/example_group.rb +46 -18
- data/lib/rspec/core/example_status_persister.rb +235 -0
- data/lib/rspec/core/filter_manager.rb +43 -28
- data/lib/rspec/core/flat_map.rb +2 -0
- data/lib/rspec/core/formatters.rb +30 -20
- data/lib/rspec/core/formatters/base_text_formatter.rb +1 -0
- data/lib/rspec/core/formatters/bisect_formatter.rb +68 -0
- data/lib/rspec/core/formatters/bisect_progress_formatter.rb +115 -0
- data/lib/rspec/core/formatters/deprecation_formatter.rb +0 -1
- data/lib/rspec/core/formatters/documentation_formatter.rb +0 -4
- data/lib/rspec/core/formatters/exception_presenter.rb +389 -0
- data/lib/rspec/core/formatters/fallback_message_formatter.rb +28 -0
- data/lib/rspec/core/formatters/helpers.rb +22 -2
- data/lib/rspec/core/formatters/html_formatter.rb +1 -4
- data/lib/rspec/core/formatters/html_printer.rb +2 -6
- data/lib/rspec/core/formatters/json_formatter.rb +6 -4
- data/lib/rspec/core/formatters/snippet_extractor.rb +12 -7
- data/lib/rspec/core/hooks.rb +8 -2
- data/lib/rspec/core/memoized_helpers.rb +77 -17
- data/lib/rspec/core/metadata.rb +24 -10
- data/lib/rspec/core/metadata_filter.rb +16 -3
- data/lib/rspec/core/mutex.rb +63 -0
- data/lib/rspec/core/notifications.rb +84 -189
- data/lib/rspec/core/option_parser.rb +105 -32
- data/lib/rspec/core/ordering.rb +28 -25
- data/lib/rspec/core/profiler.rb +32 -0
- data/lib/rspec/core/project_initializer/spec/spec_helper.rb +6 -1
- data/lib/rspec/core/rake_task.rb +6 -20
- data/lib/rspec/core/reentrant_mutex.rb +52 -0
- data/lib/rspec/core/reporter.rb +65 -17
- data/lib/rspec/core/runner.rb +38 -14
- data/lib/rspec/core/set.rb +49 -0
- data/lib/rspec/core/shared_example_group.rb +3 -1
- data/lib/rspec/core/shell_escape.rb +49 -0
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/world.rb +31 -20
- metadata +35 -7
- metadata.gz.sig +0 -0
- data/lib/rspec/core/backport_random.rb +0 -339
data/lib/rspec/core/runner.rb
CHANGED
@@ -17,20 +17,23 @@ module RSpec
|
|
17
17
|
return
|
18
18
|
end
|
19
19
|
|
20
|
-
at_exit
|
21
|
-
# Don't bother running any specs and just let the program terminate
|
22
|
-
# if we got here due to an unrescued exception (anything other than
|
23
|
-
# SystemExit, which is raised when somebody calls Kernel#exit).
|
24
|
-
next unless $!.nil? || $!.is_a?(SystemExit)
|
25
|
-
|
26
|
-
# We got here because either the end of the program was reached or
|
27
|
-
# somebody called Kernel#exit. Run the specs and then override any
|
28
|
-
# existing exit status with RSpec's exit status if any specs failed.
|
29
|
-
invoke
|
30
|
-
end
|
20
|
+
at_exit { perform_at_exit }
|
31
21
|
@installed_at_exit = true
|
32
22
|
end
|
33
23
|
|
24
|
+
# @private
|
25
|
+
def self.perform_at_exit
|
26
|
+
# Don't bother running any specs and just let the program terminate
|
27
|
+
# if we got here due to an unrescued exception (anything other than
|
28
|
+
# SystemExit, which is raised when somebody calls Kernel#exit).
|
29
|
+
return unless $!.nil? || $!.is_a?(SystemExit)
|
30
|
+
|
31
|
+
# We got here because either the end of the program was reached or
|
32
|
+
# somebody called Kernel#exit. Run the specs and then override any
|
33
|
+
# existing exit status with RSpec's exit status if any specs failed.
|
34
|
+
invoke
|
35
|
+
end
|
36
|
+
|
34
37
|
# Runs the suite of specs and exits the process with an appropriate exit
|
35
38
|
# code.
|
36
39
|
def self.invoke
|
@@ -83,7 +86,9 @@ module RSpec
|
|
83
86
|
# @param out [IO] output stream
|
84
87
|
def run(err, out)
|
85
88
|
setup(err, out)
|
86
|
-
run_specs(@world.ordered_example_groups)
|
89
|
+
run_specs(@world.ordered_example_groups).tap do
|
90
|
+
persist_example_statuses
|
91
|
+
end
|
87
92
|
end
|
88
93
|
|
89
94
|
# Wires together the various configuration objects and state holders.
|
@@ -112,6 +117,19 @@ module RSpec
|
|
112
117
|
end
|
113
118
|
end
|
114
119
|
|
120
|
+
private
|
121
|
+
|
122
|
+
def persist_example_statuses
|
123
|
+
return unless (path = @configuration.example_status_persistence_file_path)
|
124
|
+
|
125
|
+
ExampleStatusPersister.persist(@world.all_examples, path)
|
126
|
+
rescue SystemCallError => e
|
127
|
+
RSpec.warning "Could not write example statuses to #{path} (configured as " \
|
128
|
+
"`config.example_status_persistence_file_path`) due to a " \
|
129
|
+
"system error: #{e.inspect}. Please check that the config " \
|
130
|
+
"option is set to an accessible, valid file path", :call_site => nil
|
131
|
+
end
|
132
|
+
|
115
133
|
# @private
|
116
134
|
def self.disable_autorun!
|
117
135
|
@autorun_disabled = true
|
@@ -144,8 +162,14 @@ module RSpec
|
|
144
162
|
|
145
163
|
# @private
|
146
164
|
def self.trap_interrupt
|
147
|
-
trap('INT')
|
148
|
-
|
165
|
+
trap('INT') { handle_interrupt }
|
166
|
+
end
|
167
|
+
|
168
|
+
# @private
|
169
|
+
def self.handle_interrupt
|
170
|
+
if RSpec.world.wants_to_quit
|
171
|
+
exit!(1)
|
172
|
+
else
|
149
173
|
RSpec.world.wants_to_quit = true
|
150
174
|
STDERR.puts "\nRSpec is shutting down and will print the summary report... Interrupt again to force quit."
|
151
175
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Core
|
3
|
+
# @private
|
4
|
+
#
|
5
|
+
# We use this to replace `::Set` so we can have the advantage of
|
6
|
+
# constant time key lookups for unique arrays but without the
|
7
|
+
# potential to pollute a developers environment with an extra
|
8
|
+
# piece of the stdlib. This helps to prevent false positive
|
9
|
+
# builds.
|
10
|
+
#
|
11
|
+
class Set
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
def initialize(array=[])
|
15
|
+
@values = {}
|
16
|
+
merge(array)
|
17
|
+
end
|
18
|
+
|
19
|
+
def empty?
|
20
|
+
@values.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def <<(key)
|
24
|
+
@values[key] = true
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def delete(key)
|
29
|
+
@values.delete(key)
|
30
|
+
end
|
31
|
+
|
32
|
+
def each(&block)
|
33
|
+
@values.keys.each(&block)
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def include?(key)
|
38
|
+
@values.key?(key)
|
39
|
+
end
|
40
|
+
|
41
|
+
def merge(values)
|
42
|
+
values.each do |key|
|
43
|
+
@values[key] = true
|
44
|
+
end
|
45
|
+
self
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -80,7 +80,7 @@ module RSpec
|
|
80
80
|
# @see ExampleGroup.include_context
|
81
81
|
def shared_examples(name, *args, &block)
|
82
82
|
top_level = self == ExampleGroup
|
83
|
-
if top_level && RSpec.
|
83
|
+
if top_level && RSpec::Support.thread_local_data[:in_example_group]
|
84
84
|
raise "Creating isolated shared examples from within a context is " \
|
85
85
|
"not allowed. Remove `RSpec.` prefix or move this to a " \
|
86
86
|
"top-level scope."
|
@@ -195,10 +195,12 @@ module RSpec
|
|
195
195
|
if Proc.method_defined?(:source_location)
|
196
196
|
def ensure_block_has_source_location(_block); end
|
197
197
|
else # for 1.8.7
|
198
|
+
# :nocov:
|
198
199
|
def ensure_block_has_source_location(block)
|
199
200
|
source_location = yield.split(':')
|
200
201
|
block.extend Module.new { define_method(:source_location) { source_location } }
|
201
202
|
end
|
203
|
+
# :nocov:
|
202
204
|
end
|
203
205
|
end
|
204
206
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Core
|
3
|
+
# @private
|
4
|
+
# Deals with the fact that `shellwords` only works on POSIX systems.
|
5
|
+
module ShellEscape
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def quote(argument)
|
9
|
+
"'#{argument.gsub("'", "\\\\'")}'"
|
10
|
+
end
|
11
|
+
|
12
|
+
if RSpec::Support::OS.windows?
|
13
|
+
# :nocov:
|
14
|
+
alias escape quote
|
15
|
+
# :nocov:
|
16
|
+
else
|
17
|
+
require 'shellwords'
|
18
|
+
|
19
|
+
def escape(shell_command)
|
20
|
+
shell_command.shellescape
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Known shells that require quoting: zsh, csh, tcsh.
|
25
|
+
#
|
26
|
+
# Feel free to add other shells to this list that are known to
|
27
|
+
# allow `rspec ./some_spec.rb[1:1]` syntax without quoting the id.
|
28
|
+
#
|
29
|
+
# @private
|
30
|
+
SHELLS_ALLOWING_UNQUOTED_IDS = %w[ bash ksh fish ]
|
31
|
+
|
32
|
+
def conditionally_quote(id)
|
33
|
+
return id if shell_allows_unquoted_ids?
|
34
|
+
quote(id)
|
35
|
+
end
|
36
|
+
|
37
|
+
def shell_allows_unquoted_ids?
|
38
|
+
# Note: ENV['SHELL'] isn't necessarily the shell the user is currently running.
|
39
|
+
# According to http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html:
|
40
|
+
# "This variable shall represent a pathname of the user's preferred command language interpreter."
|
41
|
+
#
|
42
|
+
# It's the best we can easily do, though. We err on the side of safety (quoting
|
43
|
+
# the id when not actually needed) so it's not a big deal if the user is actually
|
44
|
+
# using a different shell.
|
45
|
+
SHELLS_ALLOWING_UNQUOTED_IDS.include?(ENV['SHELL'].to_s.split('/').last)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/rspec/core/version.rb
CHANGED
data/lib/rspec/core/world.rb
CHANGED
@@ -13,22 +13,12 @@ module RSpec
|
|
13
13
|
def initialize(configuration=RSpec.configuration)
|
14
14
|
@configuration = configuration
|
15
15
|
@example_groups = []
|
16
|
+
@example_group_counts_by_spec_file = Hash.new(0)
|
16
17
|
@filtered_examples = Hash.new do |hash, group|
|
17
|
-
hash[group] =
|
18
|
-
examples = group.examples.dup
|
19
|
-
examples = filter_manager.prune(examples)
|
20
|
-
examples.uniq!
|
21
|
-
examples
|
22
|
-
end
|
18
|
+
hash[group] = filter_manager.prune(group.examples)
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
26
|
-
# @private
|
27
|
-
# Used internally to clear remaining groups when fail_fast is set.
|
28
|
-
def clear_remaining_example_groups
|
29
|
-
example_groups.clear
|
30
|
-
end
|
31
|
-
|
32
22
|
# @api private
|
33
23
|
#
|
34
24
|
# Apply ordering strategy from configuration to example groups.
|
@@ -55,9 +45,15 @@ module RSpec
|
|
55
45
|
# Register an example group.
|
56
46
|
def register(example_group)
|
57
47
|
example_groups << example_group
|
48
|
+
@example_group_counts_by_spec_file[example_group.metadata[:file_path]] += 1
|
58
49
|
example_group
|
59
50
|
end
|
60
51
|
|
52
|
+
# @private
|
53
|
+
def num_example_groups_defined_in(file)
|
54
|
+
@example_group_counts_by_spec_file[file]
|
55
|
+
end
|
56
|
+
|
61
57
|
# @private
|
62
58
|
def shared_example_group_registry
|
63
59
|
@shared_example_group_registry ||= SharedExampleGroup::Registry.new
|
@@ -81,6 +77,16 @@ module RSpec
|
|
81
77
|
inject(0) { |a, e| a + e.filtered_examples.size }
|
82
78
|
end
|
83
79
|
|
80
|
+
# @private
|
81
|
+
def all_example_groups
|
82
|
+
FlatMap.flat_map(example_groups) { |g| g.descendants }
|
83
|
+
end
|
84
|
+
|
85
|
+
# @private
|
86
|
+
def all_examples
|
87
|
+
FlatMap.flat_map(all_example_groups) { |g| g.examples }
|
88
|
+
end
|
89
|
+
|
84
90
|
# @api private
|
85
91
|
#
|
86
92
|
# Find line number of previous declaration.
|
@@ -99,6 +105,7 @@ module RSpec
|
|
99
105
|
#
|
100
106
|
# Notify reporter of filters.
|
101
107
|
def announce_filters
|
108
|
+
fail_if_config_and_cli_options_invalid
|
102
109
|
filter_announcements = []
|
103
110
|
|
104
111
|
announce_inclusion_filter filter_announcements
|
@@ -112,7 +119,7 @@ module RSpec
|
|
112
119
|
end
|
113
120
|
end
|
114
121
|
|
115
|
-
if @configuration.run_all_when_everything_filtered? && example_count.zero?
|
122
|
+
if @configuration.run_all_when_everything_filtered? && example_count.zero? && !@configuration.only_failures?
|
116
123
|
reporter.message("#{everything_filtered_message}; ignoring #{inclusion_filter.description}")
|
117
124
|
filtered_examples.clear
|
118
125
|
inclusion_filter.clear
|
@@ -123,13 +130,7 @@ module RSpec
|
|
123
130
|
example_groups.clear
|
124
131
|
if filter_manager.empty?
|
125
132
|
reporter.message("No examples found.")
|
126
|
-
elsif exclusion_filter.empty?
|
127
|
-
message = everything_filtered_message
|
128
|
-
if @configuration.run_all_when_everything_filtered?
|
129
|
-
message << "; ignoring #{inclusion_filter.description}"
|
130
|
-
end
|
131
|
-
reporter.message(message)
|
132
|
-
elsif inclusion_filter.empty?
|
133
|
+
elsif exclusion_filter.empty? || inclusion_filter.empty?
|
133
134
|
reporter.message(everything_filtered_message)
|
134
135
|
end
|
135
136
|
end
|
@@ -162,6 +163,16 @@ module RSpec
|
|
162
163
|
def declaration_line_numbers
|
163
164
|
@declaration_line_numbers ||= FlatMap.flat_map(example_groups, &:declaration_line_numbers)
|
164
165
|
end
|
166
|
+
|
167
|
+
def fail_if_config_and_cli_options_invalid
|
168
|
+
return unless @configuration.only_failures_but_not_configured?
|
169
|
+
|
170
|
+
reporter.abort_with(
|
171
|
+
"\nTo use `--only-failures`, you must first set " \
|
172
|
+
"`config.example_status_persistence_file_path`.",
|
173
|
+
1 # exit code
|
174
|
+
)
|
175
|
+
end
|
165
176
|
end
|
166
177
|
end
|
167
178
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Baker
|
@@ -46,7 +46,7 @@ cert_chain:
|
|
46
46
|
ZsVDj6a7lH3cNqtWXZxrb2wO38qV5AkYj8SQK7Hj3/Yui9myUX3crr+PdetazSqQ
|
47
47
|
F3MdtaDehhjC
|
48
48
|
-----END CERTIFICATE-----
|
49
|
-
date: 2015-
|
49
|
+
date: 2015-06-12 00:00:00.000000000 Z
|
50
50
|
dependencies:
|
51
51
|
- !ruby/object:Gem::Dependency
|
52
52
|
name: rspec-support
|
@@ -54,14 +54,14 @@ dependencies:
|
|
54
54
|
requirements:
|
55
55
|
- - "~>"
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: 3.
|
57
|
+
version: 3.3.0
|
58
58
|
type: :runtime
|
59
59
|
prerelease: false
|
60
60
|
version_requirements: !ruby/object:Gem::Requirement
|
61
61
|
requirements:
|
62
62
|
- - "~>"
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: 3.
|
64
|
+
version: 3.3.0
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
66
|
name: rake
|
67
67
|
requirement: !ruby/object:Gem::Requirement
|
@@ -188,6 +188,20 @@ dependencies:
|
|
188
188
|
- - "~>"
|
189
189
|
- !ruby/object:Gem::Version
|
190
190
|
version: 0.9.0
|
191
|
+
- !ruby/object:Gem::Dependency
|
192
|
+
name: thread_order
|
193
|
+
requirement: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - "~>"
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: 1.1.0
|
198
|
+
type: :development
|
199
|
+
prerelease: false
|
200
|
+
version_requirements: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - "~>"
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: 1.1.0
|
191
205
|
description: BDD for Ruby. RSpec runner and example groups.
|
192
206
|
email: rspec@googlegroups.com
|
193
207
|
executables:
|
@@ -203,22 +217,31 @@ files:
|
|
203
217
|
- exe/rspec
|
204
218
|
- lib/rspec/autorun.rb
|
205
219
|
- lib/rspec/core.rb
|
206
|
-
- lib/rspec/core/backport_random.rb
|
207
220
|
- lib/rspec/core/backtrace_formatter.rb
|
221
|
+
- lib/rspec/core/bisect/coordinator.rb
|
222
|
+
- lib/rspec/core/bisect/example_minimizer.rb
|
223
|
+
- lib/rspec/core/bisect/runner.rb
|
224
|
+
- lib/rspec/core/bisect/server.rb
|
225
|
+
- lib/rspec/core/bisect/subset_enumerator.rb
|
208
226
|
- lib/rspec/core/configuration.rb
|
209
227
|
- lib/rspec/core/configuration_options.rb
|
210
228
|
- lib/rspec/core/drb.rb
|
211
229
|
- lib/rspec/core/dsl.rb
|
212
230
|
- lib/rspec/core/example.rb
|
213
231
|
- lib/rspec/core/example_group.rb
|
232
|
+
- lib/rspec/core/example_status_persister.rb
|
214
233
|
- lib/rspec/core/filter_manager.rb
|
215
234
|
- lib/rspec/core/flat_map.rb
|
216
235
|
- lib/rspec/core/formatters.rb
|
217
236
|
- lib/rspec/core/formatters/base_formatter.rb
|
218
237
|
- lib/rspec/core/formatters/base_text_formatter.rb
|
238
|
+
- lib/rspec/core/formatters/bisect_formatter.rb
|
239
|
+
- lib/rspec/core/formatters/bisect_progress_formatter.rb
|
219
240
|
- lib/rspec/core/formatters/console_codes.rb
|
220
241
|
- lib/rspec/core/formatters/deprecation_formatter.rb
|
221
242
|
- lib/rspec/core/formatters/documentation_formatter.rb
|
243
|
+
- lib/rspec/core/formatters/exception_presenter.rb
|
244
|
+
- lib/rspec/core/formatters/fallback_message_formatter.rb
|
222
245
|
- lib/rspec/core/formatters/helpers.rb
|
223
246
|
- lib/rspec/core/formatters/html_formatter.rb
|
224
247
|
- lib/rspec/core/formatters/html_printer.rb
|
@@ -237,20 +260,25 @@ files:
|
|
237
260
|
- lib/rspec/core/mocking_adapters/null.rb
|
238
261
|
- lib/rspec/core/mocking_adapters/rr.rb
|
239
262
|
- lib/rspec/core/mocking_adapters/rspec.rb
|
263
|
+
- lib/rspec/core/mutex.rb
|
240
264
|
- lib/rspec/core/notifications.rb
|
241
265
|
- lib/rspec/core/option_parser.rb
|
242
266
|
- lib/rspec/core/ordering.rb
|
243
267
|
- lib/rspec/core/pending.rb
|
268
|
+
- lib/rspec/core/profiler.rb
|
244
269
|
- lib/rspec/core/project_initializer.rb
|
245
270
|
- lib/rspec/core/project_initializer/.rspec
|
246
271
|
- lib/rspec/core/project_initializer/spec/spec_helper.rb
|
247
272
|
- lib/rspec/core/rake_task.rb
|
273
|
+
- lib/rspec/core/reentrant_mutex.rb
|
248
274
|
- lib/rspec/core/reporter.rb
|
249
275
|
- lib/rspec/core/ruby_project.rb
|
250
276
|
- lib/rspec/core/runner.rb
|
251
277
|
- lib/rspec/core/sandbox.rb
|
278
|
+
- lib/rspec/core/set.rb
|
252
279
|
- lib/rspec/core/shared_context.rb
|
253
280
|
- lib/rspec/core/shared_example_group.rb
|
281
|
+
- lib/rspec/core/shell_escape.rb
|
254
282
|
- lib/rspec/core/test_unit_assertions_adapter.rb
|
255
283
|
- lib/rspec/core/version.rb
|
256
284
|
- lib/rspec/core/warnings.rb
|
@@ -275,10 +303,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
275
303
|
- !ruby/object:Gem::Version
|
276
304
|
version: '0'
|
277
305
|
requirements: []
|
278
|
-
rubyforge_project:
|
306
|
+
rubyforge_project:
|
279
307
|
rubygems_version: 2.2.2
|
280
308
|
signing_key:
|
281
309
|
specification_version: 4
|
282
|
-
summary: rspec-core-3.
|
310
|
+
summary: rspec-core-3.3.0
|
283
311
|
test_files: []
|
284
312
|
has_rdoc:
|
metadata.gz.sig
CHANGED
Binary file
|
@@ -1,339 +0,0 @@
|
|
1
|
-
module RSpec
|
2
|
-
module Core
|
3
|
-
# @private
|
4
|
-
#
|
5
|
-
# Methods used internally by the backports.
|
6
|
-
#
|
7
|
-
# This code was (mostly) ported from the backports gem found at
|
8
|
-
# https://github.com/marcandre/backports which is subject to this license:
|
9
|
-
#
|
10
|
-
# =========================================================================
|
11
|
-
#
|
12
|
-
# Copyright (c) 2009 Marc-Andre Lafortune
|
13
|
-
#
|
14
|
-
# Permission is hereby granted, free of charge, to any person obtaining
|
15
|
-
# a copy of this software and associated documentation files (the
|
16
|
-
# "Software"), to deal in the Software without restriction, including
|
17
|
-
# without limitation the rights to use, copy, modify, merge, publish,
|
18
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
19
|
-
# permit persons to whom the Software is furnished to do so, subject to
|
20
|
-
# the following conditions:
|
21
|
-
#
|
22
|
-
# The above copyright notice and this permission notice shall be
|
23
|
-
# included in all copies or substantial portions of the Software.
|
24
|
-
#
|
25
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
26
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
27
|
-
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
28
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
29
|
-
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
30
|
-
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
31
|
-
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
32
|
-
#
|
33
|
-
# =========================================================================
|
34
|
-
#
|
35
|
-
# The goal is to provide a random number generator in Ruby versions that do
|
36
|
-
# not have one. This was added to support localization of random spec
|
37
|
-
# ordering.
|
38
|
-
#
|
39
|
-
# These were in multiple files in backports, but merged into one here.
|
40
|
-
module Backports
|
41
|
-
# Helper method to coerce a value into a specific class.
|
42
|
-
# Raises a TypeError if the coercion fails or the returned value
|
43
|
-
# is not of the right class.
|
44
|
-
# (from Rubinius)
|
45
|
-
def self.coerce_to(obj, cls, meth)
|
46
|
-
return obj if obj.kind_of?(cls)
|
47
|
-
|
48
|
-
begin
|
49
|
-
ret = obj.__send__(meth)
|
50
|
-
rescue Exception => e
|
51
|
-
raise TypeError, "Coercion error: #{obj.inspect}.#{meth} => #{cls} failed:\n" \
|
52
|
-
"(#{e.message})"
|
53
|
-
end
|
54
|
-
raise TypeError, "Coercion error: obj.#{meth} did NOT return a #{cls} (was #{ret.class})" unless ret.kind_of? cls
|
55
|
-
ret
|
56
|
-
end
|
57
|
-
|
58
|
-
# @private
|
59
|
-
def self.coerce_to_int(obj)
|
60
|
-
coerce_to(obj, Integer, :to_int)
|
61
|
-
end
|
62
|
-
|
63
|
-
# Used internally to make it easy to deal with optional arguments.
|
64
|
-
# (from Rubinius)
|
65
|
-
Undefined = Object.new
|
66
|
-
|
67
|
-
# @private
|
68
|
-
class Random
|
69
|
-
# @private
|
70
|
-
# An implementation of Mersenne Twister MT19937 in Ruby.
|
71
|
-
class MT19937
|
72
|
-
STATE_SIZE = 624
|
73
|
-
LAST_STATE = STATE_SIZE - 1
|
74
|
-
PAD_32_BITS = 0xffffffff
|
75
|
-
|
76
|
-
# See seed=
|
77
|
-
def initialize(seed)
|
78
|
-
self.seed = seed
|
79
|
-
end
|
80
|
-
|
81
|
-
LAST_31_BITS = 0x7fffffff
|
82
|
-
OFFSET = 397
|
83
|
-
|
84
|
-
# Generates a completely new state out of the previous one.
|
85
|
-
def next_state
|
86
|
-
STATE_SIZE.times do |i|
|
87
|
-
mix = @state[i] & 0x80000000 | @state[i+1 - STATE_SIZE] & 0x7fffffff
|
88
|
-
@state[i] = @state[i+OFFSET - STATE_SIZE] ^ (mix >> 1)
|
89
|
-
@state[i] ^= 0x9908b0df if mix.odd?
|
90
|
-
end
|
91
|
-
@last_read = -1
|
92
|
-
end
|
93
|
-
|
94
|
-
# Seed must be either an Integer (only the first 32 bits will be used)
|
95
|
-
# or an Array of Integers (of which only the first 32 bits will be
|
96
|
-
# used).
|
97
|
-
#
|
98
|
-
# No conversion or type checking is done at this level.
|
99
|
-
def seed=(seed)
|
100
|
-
case seed
|
101
|
-
when Integer
|
102
|
-
@state = Array.new(STATE_SIZE)
|
103
|
-
@state[0] = seed & PAD_32_BITS
|
104
|
-
(1..LAST_STATE).each do |i|
|
105
|
-
@state[i] = (1812433253 * (@state[i-1] ^ @state[i-1]>>30) + i)& PAD_32_BITS
|
106
|
-
end
|
107
|
-
@last_read = LAST_STATE
|
108
|
-
when Array
|
109
|
-
self.seed = 19650218
|
110
|
-
i=1
|
111
|
-
j=0
|
112
|
-
[STATE_SIZE, seed.size].max.times do
|
113
|
-
@state[i] = (@state[i] ^ (@state[i-1] ^ @state[i-1]>>30) * 1664525) + j + seed[j] & PAD_32_BITS
|
114
|
-
if (i+=1) >= STATE_SIZE
|
115
|
-
@state[0] = @state[-1]
|
116
|
-
i = 1
|
117
|
-
end
|
118
|
-
j = 0 if (j+=1) >= seed.size
|
119
|
-
end
|
120
|
-
(STATE_SIZE-1).times do
|
121
|
-
@state[i] = (@state[i] ^ (@state[i-1] ^ @state[i-1]>>30) * 1566083941) - i & PAD_32_BITS
|
122
|
-
if (i+=1) >= STATE_SIZE
|
123
|
-
@state[0] = @state[-1]
|
124
|
-
i = 1
|
125
|
-
end
|
126
|
-
end
|
127
|
-
@state[0] = 0x80000000
|
128
|
-
else
|
129
|
-
raise ArgumentError, "Seed must be an Integer or an Array"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# Returns a random Integer from the range 0 ... (1 << 32).
|
134
|
-
def random_32_bits
|
135
|
-
next_state if @last_read >= LAST_STATE
|
136
|
-
@last_read += 1
|
137
|
-
y = @state[@last_read]
|
138
|
-
# Tempering
|
139
|
-
y ^= (y >> 11)
|
140
|
-
y ^= (y << 7) & 0x9d2c5680
|
141
|
-
y ^= (y << 15) & 0xefc60000
|
142
|
-
y ^= (y >> 18)
|
143
|
-
end
|
144
|
-
|
145
|
-
# Supplement the MT19937 class with methods to do
|
146
|
-
# conversions the same way as MRI.
|
147
|
-
# No argument checking is done here either.
|
148
|
-
|
149
|
-
FLOAT_FACTOR = 1.0/9007199254740992.0
|
150
|
-
# Generates a random number on [0, 1) with 53-bit resolution.
|
151
|
-
def random_float
|
152
|
-
((random_32_bits >> 5) * 67108864.0 + (random_32_bits >> 6)) * FLOAT_FACTOR;
|
153
|
-
end
|
154
|
-
|
155
|
-
# Returns an integer within 0...upto.
|
156
|
-
def random_integer(upto)
|
157
|
-
n = upto - 1
|
158
|
-
nb_full_32 = 0
|
159
|
-
while n > PAD_32_BITS
|
160
|
-
n >>= 32
|
161
|
-
nb_full_32 += 1
|
162
|
-
end
|
163
|
-
mask = mask_32_bits(n)
|
164
|
-
begin
|
165
|
-
rand = random_32_bits & mask
|
166
|
-
nb_full_32.times do
|
167
|
-
rand <<= 32
|
168
|
-
rand |= random_32_bits
|
169
|
-
end
|
170
|
-
end until rand < upto
|
171
|
-
rand
|
172
|
-
end
|
173
|
-
|
174
|
-
def random_bytes(nb)
|
175
|
-
nb_32_bits = (nb + 3) / 4
|
176
|
-
random = nb_32_bits.times.map { random_32_bits }
|
177
|
-
random.pack("L" * nb_32_bits)[0, nb]
|
178
|
-
end
|
179
|
-
|
180
|
-
def state_as_bignum
|
181
|
-
b = 0
|
182
|
-
@state.each_with_index do |val, i|
|
183
|
-
b |= val << (32 * i)
|
184
|
-
end
|
185
|
-
b
|
186
|
-
end
|
187
|
-
|
188
|
-
def left # It's actually the number of words left + 1, as per MRI...
|
189
|
-
MT19937::STATE_SIZE - @last_read
|
190
|
-
end
|
191
|
-
|
192
|
-
def marshal_dump
|
193
|
-
[state_as_bignum, left]
|
194
|
-
end
|
195
|
-
|
196
|
-
def marshal_load(ary)
|
197
|
-
b, left = ary
|
198
|
-
@last_read = MT19937::STATE_SIZE - left
|
199
|
-
@state = Array.new(STATE_SIZE)
|
200
|
-
STATE_SIZE.times do |i|
|
201
|
-
@state[i] = b & PAD_32_BITS
|
202
|
-
b >>= 32
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
# Convert an Integer seed of arbitrary size to either a single 32 bit
|
207
|
-
# integer, or an Array of 32 bit integers.
|
208
|
-
def self.convert_seed(seed)
|
209
|
-
seed = seed.abs
|
210
|
-
long_values = []
|
211
|
-
begin
|
212
|
-
long_values << (seed & PAD_32_BITS)
|
213
|
-
seed >>= 32
|
214
|
-
end until seed == 0
|
215
|
-
|
216
|
-
# Done to allow any kind of sequence of integers.
|
217
|
-
long_values.pop if long_values[-1] == 1 && long_values.size > 1
|
218
|
-
|
219
|
-
long_values.size > 1 ? long_values : long_values.first
|
220
|
-
end
|
221
|
-
|
222
|
-
def self.[](seed)
|
223
|
-
new(convert_seed(seed))
|
224
|
-
end
|
225
|
-
|
226
|
-
private
|
227
|
-
|
228
|
-
MASK_BY = [1,2,4,8,16]
|
229
|
-
def mask_32_bits(n)
|
230
|
-
MASK_BY.each do |shift|
|
231
|
-
n |= n >> shift
|
232
|
-
end
|
233
|
-
n
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
# @private
|
238
|
-
# Implementation corresponding to the actual Random class of Ruby
|
239
|
-
# The actual random generator (mersenne twister) is in MT19937.
|
240
|
-
# Ruby specific conversions are handled in bits_and_bytes.
|
241
|
-
# The high level stuff (argument checking) is done here.
|
242
|
-
module Implementation
|
243
|
-
attr_reader :seed
|
244
|
-
|
245
|
-
def initialize(seed = 0)
|
246
|
-
super()
|
247
|
-
seed_rand seed
|
248
|
-
end
|
249
|
-
|
250
|
-
def seed_rand(new_seed = 0)
|
251
|
-
new_seed = Backports.coerce_to_int(new_seed)
|
252
|
-
@seed = nil unless defined?(@seed)
|
253
|
-
old, @seed = @seed, new_seed.nonzero? || Random.new_seed
|
254
|
-
@mt = MT19937[ @seed ]
|
255
|
-
old
|
256
|
-
end
|
257
|
-
|
258
|
-
def rand(limit = Backports::Undefined)
|
259
|
-
case limit
|
260
|
-
when Backports::Undefined
|
261
|
-
@mt.random_float
|
262
|
-
when Float
|
263
|
-
limit * @mt.random_float unless limit <= 0
|
264
|
-
when Range
|
265
|
-
_rand_range(limit)
|
266
|
-
else
|
267
|
-
limit = Backports.coerce_to_int(limit)
|
268
|
-
@mt.random_integer(limit) unless limit <= 0
|
269
|
-
end || raise(ArgumentError, "invalid argument #{limit}")
|
270
|
-
end
|
271
|
-
|
272
|
-
def bytes(nb)
|
273
|
-
nb = Backports.coerce_to_int(nb)
|
274
|
-
raise ArgumentError, "negative size" if nb < 0
|
275
|
-
@mt.random_bytes(nb)
|
276
|
-
end
|
277
|
-
|
278
|
-
def ==(other)
|
279
|
-
other.is_a?(Random) &&
|
280
|
-
seed == other.seed &&
|
281
|
-
left == other.send(:left) &&
|
282
|
-
state == other.send(:state)
|
283
|
-
end
|
284
|
-
|
285
|
-
def marshal_dump
|
286
|
-
@mt.marshal_dump << @seed
|
287
|
-
end
|
288
|
-
|
289
|
-
def marshal_load(ary)
|
290
|
-
@seed = ary.pop
|
291
|
-
@mt = MT19937.allocate
|
292
|
-
@mt.marshal_load(ary)
|
293
|
-
end
|
294
|
-
|
295
|
-
private
|
296
|
-
|
297
|
-
def state
|
298
|
-
@mt.state_as_bignum
|
299
|
-
end
|
300
|
-
|
301
|
-
def left
|
302
|
-
@mt.left
|
303
|
-
end
|
304
|
-
|
305
|
-
def _rand_range(limit)
|
306
|
-
range = limit.end - limit.begin
|
307
|
-
if (!range.is_a?(Float)) && range.respond_to?(:to_int) && range = Backports.coerce_to_int(range)
|
308
|
-
range += 1 unless limit.exclude_end?
|
309
|
-
limit.begin + @mt.random_integer(range) unless range <= 0
|
310
|
-
elsif range = Backports.coerce_to(range, Float, :to_f)
|
311
|
-
if range < 0
|
312
|
-
nil
|
313
|
-
elsif limit.exclude_end?
|
314
|
-
limit.begin + @mt.random_float * range unless range <= 0
|
315
|
-
else
|
316
|
-
# cheat a bit... this will reduce the nb of random bits
|
317
|
-
loop do
|
318
|
-
r = @mt.random_float * range * 1.0001
|
319
|
-
break limit.begin + r unless r > range
|
320
|
-
end
|
321
|
-
end
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
def self.new_seed
|
327
|
-
(2 ** 62) + Kernel.rand(2 ** 62)
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
class Random
|
332
|
-
include Implementation
|
333
|
-
class << self
|
334
|
-
include Implementation
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
end
|
339
|
-
end
|