mongoid 7.2.0.rc1 → 7.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +45 -10
  5. data/lib/config/locales/en.yml +2 -2
  6. data/lib/mongoid/association/accessors.rb +1 -1
  7. data/lib/mongoid/association/constrainable.rb +1 -1
  8. data/lib/mongoid/association/depending.rb +4 -4
  9. data/lib/mongoid/association/embedded/batchable.rb +1 -1
  10. data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
  11. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
  12. data/lib/mongoid/association/nested/many.rb +1 -1
  13. data/lib/mongoid/association/nested/one.rb +4 -2
  14. data/lib/mongoid/association/proxy.rb +6 -1
  15. data/lib/mongoid/association/referenced/auto_save.rb +2 -2
  16. data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
  17. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  18. data/lib/mongoid/association/referenced/has_one/buildable.rb +8 -0
  19. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  20. data/lib/mongoid/association/referenced/has_one/proxy.rb +6 -1
  21. data/lib/mongoid/attributes.rb +32 -14
  22. data/lib/mongoid/attributes/projector.rb +120 -0
  23. data/lib/mongoid/cacheable.rb +2 -2
  24. data/lib/mongoid/clients.rb +1 -1
  25. data/lib/mongoid/clients/factory.rb +22 -8
  26. data/lib/mongoid/config.rb +19 -2
  27. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  28. data/lib/mongoid/copyable.rb +6 -2
  29. data/lib/mongoid/criteria.rb +4 -5
  30. data/lib/mongoid/criteria/findable.rb +1 -1
  31. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  32. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  33. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  34. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  35. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  36. data/lib/mongoid/criteria/queryable/selector.rb +0 -4
  37. data/lib/mongoid/document.rb +4 -17
  38. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  39. data/lib/mongoid/evolvable.rb +1 -1
  40. data/lib/mongoid/extensions.rb +1 -0
  41. data/lib/mongoid/extensions/boolean.rb +1 -2
  42. data/lib/mongoid/extensions/false_class.rb +1 -1
  43. data/lib/mongoid/extensions/hash.rb +2 -2
  44. data/lib/mongoid/extensions/true_class.rb +1 -1
  45. data/lib/mongoid/fields.rb +46 -5
  46. data/lib/mongoid/inspectable.rb +1 -1
  47. data/lib/mongoid/interceptable.rb +3 -1
  48. data/lib/mongoid/matcher.rb +26 -43
  49. data/lib/mongoid/matcher/bits.rb +41 -0
  50. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  51. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  52. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  53. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  54. data/lib/mongoid/matcher/elem_match.rb +2 -1
  55. data/lib/mongoid/matcher/expression.rb +9 -14
  56. data/lib/mongoid/matcher/field_expression.rb +4 -5
  57. data/lib/mongoid/matcher/field_operator.rb +13 -11
  58. data/lib/mongoid/matcher/mod.rb +17 -0
  59. data/lib/mongoid/matcher/type.rb +99 -0
  60. data/lib/mongoid/persistable/deletable.rb +1 -2
  61. data/lib/mongoid/persistable/destroyable.rb +8 -2
  62. data/lib/mongoid/persistable/updatable.rb +27 -2
  63. data/lib/mongoid/query_cache.rb +35 -29
  64. data/lib/mongoid/reloadable.rb +5 -0
  65. data/lib/mongoid/selectable.rb +5 -7
  66. data/lib/mongoid/shardable.rb +21 -5
  67. data/lib/mongoid/stringified_symbol.rb +53 -0
  68. data/lib/mongoid/touchable.rb +23 -4
  69. data/lib/mongoid/version.rb +1 -1
  70. data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
  71. data/spec/README.md +19 -4
  72. data/spec/integration/app_spec.rb +175 -88
  73. data/spec/integration/associations/embeds_many_spec.rb +68 -0
  74. data/spec/integration/associations/embeds_one_spec.rb +24 -0
  75. data/spec/integration/associations/has_many_spec.rb +60 -0
  76. data/spec/integration/associations/has_one_spec.rb +108 -0
  77. data/spec/integration/callbacks_models.rb +49 -0
  78. data/spec/integration/callbacks_spec.rb +216 -0
  79. data/spec/integration/criteria/date_field_spec.rb +1 -1
  80. data/spec/integration/document_spec.rb +30 -0
  81. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  82. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  83. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  84. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  85. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  86. data/spec/integration/matcher_operator_data/elem_match.yml +46 -0
  87. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  88. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  89. data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
  90. data/spec/integration/matcher_operator_data/in.yml +16 -0
  91. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  92. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  93. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  94. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  95. data/spec/integration/matcher_operator_data/type.yml +70 -0
  96. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  97. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  98. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  99. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  100. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  101. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  102. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  103. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  104. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  105. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  106. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  107. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  108. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  109. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  110. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  111. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  112. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  113. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  114. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  115. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  116. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  117. data/spec/integration/stringified_symbol_field_spec.rb +190 -0
  118. data/spec/lite_spec_helper.rb +9 -7
  119. data/spec/mongoid/association/depending_spec.rb +391 -352
  120. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
  121. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  122. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
  123. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  124. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  125. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
  126. data/spec/mongoid/association/referenced/has_many_models.rb +12 -0
  127. data/spec/mongoid/association/referenced/has_one_models.rb +20 -0
  128. data/spec/mongoid/association/referenced/has_one_spec.rb +1 -1
  129. data/spec/mongoid/atomic/paths_spec.rb +105 -12
  130. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  131. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  132. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  133. data/spec/mongoid/attributes_spec.rb +333 -0
  134. data/spec/mongoid/clients/factory_spec.rb +48 -0
  135. data/spec/mongoid/config_spec.rb +32 -0
  136. data/spec/mongoid/contextual/atomic_spec.rb +17 -4
  137. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  138. data/spec/mongoid/copyable_spec.rb +44 -17
  139. data/spec/mongoid/copyable_spec_models.rb +14 -0
  140. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  141. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  142. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  143. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  144. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +265 -24
  145. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  146. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  147. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  148. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  149. data/spec/mongoid/criteria_spec.rb +0 -275
  150. data/spec/mongoid/document_fields_spec.rb +26 -0
  151. data/spec/mongoid/document_spec.rb +13 -13
  152. data/spec/mongoid/equality_spec.rb +0 -1
  153. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  154. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  155. data/spec/mongoid/extensions/string_spec.rb +5 -5
  156. data/spec/mongoid/extensions/stringified_symbol_spec.rb +85 -0
  157. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  158. data/spec/mongoid/fields/localized_spec.rb +4 -4
  159. data/spec/mongoid/fields_spec.rb +4 -4
  160. data/spec/mongoid/inspectable_spec.rb +12 -4
  161. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  162. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
  163. data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
  164. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  165. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  166. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  167. data/spec/mongoid/persistable/settable_spec.rb +30 -0
  168. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  169. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  170. data/spec/mongoid/reloadable_spec.rb +18 -1
  171. data/spec/mongoid/shardable_spec.rb +44 -0
  172. data/spec/mongoid/touchable_spec.rb +104 -16
  173. data/spec/mongoid/touchable_spec_models.rb +52 -0
  174. data/spec/mongoid/validatable_spec.rb +1 -1
  175. data/spec/shared/LICENSE +20 -0
  176. data/spec/shared/bin/get-mongodb-download-url +17 -0
  177. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  178. data/spec/shared/lib/mrss/cluster_config.rb +221 -0
  179. data/spec/shared/lib/mrss/constraints.rb +354 -0
  180. data/spec/shared/lib/mrss/docker_runner.rb +265 -0
  181. data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
  182. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  183. data/spec/shared/lib/mrss/spec_organizer.rb +162 -0
  184. data/spec/shared/lib/mrss/utils.rb +15 -0
  185. data/spec/shared/share/Dockerfile.erb +231 -0
  186. data/spec/shared/shlib/distro.sh +73 -0
  187. data/spec/shared/shlib/server.sh +290 -0
  188. data/spec/shared/shlib/set_env.sh +128 -0
  189. data/spec/spec_helper.rb +7 -1
  190. data/spec/support/client_registry.rb +9 -0
  191. data/spec/support/constraints.rb +0 -226
  192. data/spec/support/models/bolt.rb +8 -0
  193. data/spec/support/models/customer.rb +11 -0
  194. data/spec/support/models/customer_address.rb +12 -0
  195. data/spec/support/models/dictionary.rb +6 -0
  196. data/spec/support/models/hole.rb +13 -0
  197. data/spec/support/models/mop.rb +9 -0
  198. data/spec/support/models/nut.rb +8 -0
  199. data/spec/support/models/order.rb +11 -0
  200. data/spec/support/models/person.rb +8 -0
  201. data/spec/support/models/sealer.rb +8 -0
  202. data/spec/support/models/series.rb +1 -0
  203. data/spec/support/models/shirt.rb +12 -0
  204. data/spec/support/models/spacer.rb +8 -0
  205. data/spec/support/models/threadlocker.rb +8 -0
  206. data/spec/support/models/washer.rb +8 -0
  207. data/spec/support/models/wiki_page.rb +1 -0
  208. data/spec/support/spec_config.rb +8 -0
  209. metadata +655 -507
  210. metadata.gz.sig +0 -0
  211. data/spec/support/child_process_helper.rb +0 -79
  212. data/spec/support/cluster_config.rb +0 -158
  213. data/spec/support/lite_constraints.rb +0 -22
  214. data/spec/support/spec_organizer.rb +0 -130
metadata.gz.sig CHANGED
Binary file
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
- # encoding: utf-8
3
-
4
- gem 'childprocess'
5
- require 'childprocess'
6
- require 'tempfile'
7
-
8
- module ChildProcessHelper
9
- class SpawnError < StandardError; end
10
-
11
- module_function def call(cmd, env: nil, cwd: nil)
12
- process = ChildProcess.new(*cmd)
13
- process.io.inherit!
14
- if cwd
15
- process.cwd = cwd
16
- end
17
- if env
18
- env.each do |k, v|
19
- process.environment[k.to_s] = v
20
- end
21
- end
22
- process.start
23
- process.wait
24
- process
25
- end
26
-
27
- module_function def check_call(cmd, env: nil, cwd: nil)
28
- process = call(cmd, env: env, cwd: cwd)
29
- unless process.exit_code == 0
30
- raise "Failed to execute: #{cmd}"
31
- end
32
- end
33
-
34
- module_function def get_output(cmd, env: nil, cwd: nil)
35
- process = ChildProcess.new(*cmd)
36
- process.io.inherit!
37
- if cwd
38
- process.cwd = cwd
39
- end
40
- if env
41
- env.each do |k, v|
42
- process.environment[k.to_s] = v
43
- end
44
- end
45
-
46
- output = ''
47
- r, w = IO.pipe
48
-
49
- begin
50
- process.io.stdout = w
51
- process.start
52
- w.close
53
-
54
- thread = Thread.new do
55
- begin
56
- loop do
57
- output << r.readpartial(16384)
58
- end
59
- rescue EOFError
60
- end
61
- end
62
-
63
- process.wait
64
- thread.join
65
- ensure
66
- r.close
67
- end
68
-
69
- [process, output]
70
- end
71
-
72
- module_function def check_output(*args)
73
- process, output = get_output(*args)
74
- unless process.exit_code == 0
75
- raise "Failed to execute: #{args}"
76
- end
77
- output
78
- end
79
- end
@@ -1,158 +0,0 @@
1
- # frozen_string_literal: true
2
- # encoding: utf-8
3
-
4
- require 'singleton'
5
-
6
- class ClusterConfig
7
- include Singleton
8
-
9
- def single_server?
10
- determine_cluster_config
11
- @single_server
12
- end
13
-
14
- def replica_set_name
15
- determine_cluster_config
16
- @replica_set_name
17
- end
18
-
19
- def server_version
20
- determine_cluster_config
21
- @server_version
22
- end
23
-
24
- def short_server_version
25
- server_version.split('.')[0..1].join('.')
26
- end
27
-
28
- def fcv
29
- determine_cluster_config
30
- @fcv
31
- end
32
-
33
- # Per https://jira.mongodb.org/browse/SERVER-39052, working with FCV
34
- # in sharded topologies is annoying. Also, FCV doesn't exist in servers
35
- # less than 3.4. This method returns FCV on 3.4+ servers when in single
36
- # or RS topologies, and otherwise returns the major.minor server version.
37
- def fcv_ish
38
- if server_version >= '3.4' && topology != :sharded
39
- fcv
40
- else
41
- if short_server_version == '4.1'
42
- '4.2'
43
- else
44
- short_server_version
45
- end
46
- end
47
- end
48
-
49
- def primary_address
50
- determine_cluster_config
51
- @primary_address
52
- end
53
-
54
- def primary_address_str
55
- determine_cluster_config
56
- @primary_address.seed
57
- end
58
-
59
- def primary_address_host
60
- both = primary_address_str
61
- both.split(':').first
62
- end
63
-
64
- def primary_address_port
65
- both = primary_address_str
66
- both.split(':')[1] || 27017
67
- end
68
-
69
- def primary_description
70
- determine_cluster_config
71
- @primary_description
72
- end
73
-
74
- # Try running a command on the admin database to see if the mongod was
75
- # started with auth.
76
- def auth_enabled?
77
- if @auth_enabled.nil?
78
- @auth_enabled = begin
79
- basic_client.use(:admin).command(getCmdLineOpts: 1).first["argv"].include?("--auth")
80
- rescue => e
81
- e.message =~ /(not authorized)|(unauthorized)|(no users authenticated)|(requires authentication)/
82
- end
83
- end
84
- @auth_enabled
85
- end
86
-
87
- def topology
88
- determine_cluster_config
89
- @topology
90
- end
91
-
92
- def storage_engine
93
- @storage_engine ||= begin
94
- # 2.6 does not have wired tiger
95
- if short_server_version == '2.6'
96
- :mmapv1
97
- else
98
- client = ClientRegistry.instance.global_client('root_authorized')
99
- if topology == :sharded
100
- shards = client.use(:admin).command(listShards: 1).first
101
- shard = shards['shards'].first
102
- address_str = shard['host'].sub(/\A.*\//, '').sub(/,.*/, '')
103
- client = ClusterTools.instance.direct_client(address_str,
104
- SpecConfig.instance.test_options.merge(SpecConfig.instance.auth_options).merge(connect: :direct))
105
- end
106
- rv = client.use(:admin).command(serverStatus: 1).first
107
- rv = rv['storageEngine']['name']
108
- rv_map = {
109
- 'wiredTiger' => :wired_tiger,
110
- 'mmapv1' => :mmapv1,
111
- }
112
- rv_map[rv] || rv
113
- end
114
- end
115
- end
116
-
117
- private
118
-
119
- def determine_cluster_config
120
- return if @primary_address
121
-
122
- # Run all commands to figure out the cluster configuration from the same
123
- # client. This is somewhat wasteful when running a single test, but reduces
124
- # test runtime for the suite overall because all commands are sent on the
125
- # same connection rather than each command connecting to the cluster by
126
- # itself.
127
- client = Mongoid::Clients.default
128
-
129
- primary = client.cluster.next_primary
130
- @primary_address = primary.address
131
- @primary_description = primary.description
132
- @replica_set_name = client.cluster.topology.replica_set_name
133
-
134
- @topology ||= begin
135
- topology = client.cluster.topology.class.name.sub(/.*::/, '')
136
- topology = topology.gsub(/([A-Z])/) { |match| '_' + match.downcase }.sub(/\A_/, '')
137
- if topology =~ /\Areplica_set/
138
- topology = 'replica_set'
139
- end
140
- topology.to_sym
141
- end
142
-
143
- @single_server = client.cluster.send(:servers_list).length == 1
144
-
145
- @server_version = client.database.command(buildInfo: 1).first['version']
146
-
147
- if @topology != :sharded && short_server_version >= '3.4'
148
- rv = client.use(:admin).command(getParameter: 1, featureCompatibilityVersion: 1).first['featureCompatibilityVersion']
149
- @fcv = rv['version'] || rv
150
- end
151
- end
152
-
153
- def basic_client
154
- # Do not cache the result here so that if the client gets closed,
155
- # client registry reconnects it in subsequent tests
156
- ClientRegistry.instance.global_client('basic')
157
- end
158
- end
@@ -1,22 +0,0 @@
1
- module LiteConstraints
2
- # Constrain tests that use TimeoutInterrupt to MRI (and Unix)
3
- def only_mri
4
- before do
5
- unless SpecConfig.instance.mri?
6
- skip "MRI required, we have #{SpecConfig.instance.platform}"
7
- end
8
- end
9
- end
10
-
11
- # This is for marking tests that fail on jruby that should
12
- # in principle work (as opposed to being fundamentally incompatible
13
- # with jruby).
14
- # Often times these failures happen only in Evergreen.
15
- def fails_on_jruby
16
- before do
17
- unless SpecConfig.instance.mri?
18
- skip "Fails on jruby"
19
- end
20
- end
21
- end
22
- end
@@ -1,130 +0,0 @@
1
- require 'support/child_process_helper'
2
- require 'json'
3
-
4
- autoload :FileUtils, 'fileutils'
5
- autoload :Find, 'find'
6
-
7
- # Organizes and runs all of the tests in the test suite in batches.
8
- #
9
- # Organizing the tests in batches serves two purposes:
10
- #
11
- # 1. This allows running unit tests before integration tests, therefore
12
- # in theory revealing failures quicker on average.
13
- # 2. This allows running some tests that have high intermittent failure rate
14
- # in their own test process.
15
- #
16
- # This class aggregates RSpec results after the test runs.
17
- class SpecOrganizer
18
- CLASSIFIERS = [
19
- [%r,^mongoid/attribute,, :attributes],
20
- [%r,^mongoid/association/[or],, :associations_referenced],
21
- [%r,^mongoid/association,, :associations],
22
- [%r,^mongoid,, :unit],
23
- [%r,^integration,, :integration],
24
- [%r,^rails,, :rails],
25
- ]
26
-
27
- RUN_PRIORITY = %i(
28
- unit attributes associations_referenced associations
29
- integration rails
30
- )
31
-
32
- SPEC_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
33
- ROOT = File.expand_path(File.join(SPEC_ROOT, '..'))
34
- RSPEC_JSON_PATH = File.join(ROOT, 'tmp/rspec.json')
35
- RSPEC_ALL_JSON_PATH = File.join(ROOT, 'tmp/rspec-all.json')
36
-
37
- def run
38
- FileUtils.rm_f(RSPEC_ALL_JSON_PATH)
39
-
40
- buckets = {}
41
- Find.find(SPEC_ROOT) do |path|
42
- next unless File.file?(path)
43
- next unless path =~ /_spec\.rb\z/
44
- rel_path = path[(SPEC_ROOT.length + 1)..path.length]
45
-
46
- found = false
47
- CLASSIFIERS.each do |(regexp, category)|
48
- if regexp =~ rel_path
49
- buckets[category] ||= []
50
- buckets[category] << rel_path
51
- found = true
52
- break
53
- end
54
- end
55
-
56
- unless found
57
- buckets[nil] ||= []
58
- buckets[nil] << rel_path
59
- end
60
- end
61
-
62
- failed = []
63
-
64
- RUN_PRIORITY.each do |category|
65
- if files = buckets.delete(category)
66
- unless run_files(category, files)
67
- failed << category
68
- end
69
- end
70
- end
71
- if files = buckets.delete(nil)
72
- unless run_files('remaining', files)
73
- failed << 'remaining'
74
- end
75
- end
76
-
77
- unless buckets.empty?
78
- raise "Some buckets were not executed: #{buckets.keys.map(&:to_s).join(', ')}"
79
- end
80
-
81
- if failed.any?
82
- raise "The following buckets failed: #{failed.map(&:to_s).join(', ')}"
83
- end
84
- end
85
-
86
- def run_files(category, paths)
87
- paths = paths.map do |path|
88
- File.join('spec', path)
89
- end
90
-
91
- puts "Running #{category.to_s.gsub('_', ' ')} tests"
92
- FileUtils.rm_f(RSPEC_JSON_PATH)
93
- cmd = %w(rspec) + paths
94
-
95
- begin
96
- ChildProcessHelper.check_call(cmd)
97
- ensure
98
- if File.exist?(RSPEC_JSON_PATH)
99
- if File.exist?(RSPEC_ALL_JSON_PATH)
100
- merge_rspec_results
101
- else
102
- FileUtils.cp(RSPEC_JSON_PATH, RSPEC_ALL_JSON_PATH)
103
- end
104
- end
105
- end
106
-
107
- true
108
- rescue ChildProcessHelper::SpawnError
109
- false
110
- end
111
-
112
- def merge_rspec_results
113
- all = JSON.parse(File.read(RSPEC_ALL_JSON_PATH))
114
- new = JSON.parse(File.read(RSPEC_JSON_PATH))
115
- all['examples'] += new.delete('examples')
116
- new.delete('summary').each do |k, v|
117
- all['summary'][k] += v
118
- end
119
- new.delete('version')
120
- new.delete('summary_line')
121
- unless new.empty?
122
- raise "Unhandled rspec results keys: #{new.keys.join(', ')}"
123
- end
124
- # We do not merge summary lines, delete them from aggregated results
125
- all.delete('summary_line')
126
- File.open(RSPEC_ALL_JSON_PATH, 'w') do |f|
127
- f << JSON.dump(all)
128
- end
129
- end
130
- end