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
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ module TouchableSpec
5
+ module Embedded
6
+ class Building
7
+ include Mongoid::Document
8
+ include Mongoid::Timestamps
9
+
10
+ embeds_many :entrances
11
+ embeds_many :floors
12
+ end
13
+
14
+ class Entrance
15
+ include Mongoid::Document
16
+ include Mongoid::Timestamps
17
+
18
+ embedded_in :building
19
+ end
20
+
21
+ class Floor
22
+ include Mongoid::Document
23
+ include Mongoid::Timestamps
24
+
25
+ embedded_in :building, touch: true
26
+ end
27
+ end
28
+
29
+ module Referenced
30
+ class Building
31
+ include Mongoid::Document
32
+ include Mongoid::Timestamps
33
+
34
+ has_many :entrances, inverse_of: :building
35
+ has_many :floors, inverse_of: :building
36
+ end
37
+
38
+ class Entrance
39
+ include Mongoid::Document
40
+ include Mongoid::Timestamps
41
+
42
+ belongs_to :building
43
+ end
44
+
45
+ class Floor
46
+ include Mongoid::Document
47
+ include Mongoid::Timestamps
48
+
49
+ belongs_to :building, touch: true
50
+ end
51
+ end
52
+ end
@@ -37,7 +37,7 @@ describe Mongoid::Validatable do
37
37
  end
38
38
 
39
39
  let(:documents) do
40
- Mongoid::Association::Referenced::HasMany::Targets::Enumerable.new([ address ])
40
+ Mongoid::Association::Referenced::HasMany::Enumerable.new([ address ])
41
41
  end
42
42
 
43
43
  before do
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2020 MongoDB, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ desired_version, arch = ARGV
4
+ if arch.nil?
5
+ STDERR.puts "Usage: get-mongodb-download-url desired-version arch"
6
+ exit 1
7
+ end
8
+
9
+ $: << File.join(File.dirname(__FILE__), '../lib')
10
+ require 'mrss/server_version_registry'
11
+
12
+ begin
13
+ puts Mrss::ServerVersionRegistry.new(desired_version, arch).download_url
14
+ rescue Mrss::ServerVersionRegistry::Error => exc
15
+ STDERR.puts "Error: #{exc}"
16
+ exit 2
17
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ autoload :ChildProcess, 'childprocess'
5
+ autoload :Tempfile, 'tempfile'
6
+
7
+ module Mrss
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 SpawnError, "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 SpawnError,"Failed to execute: #{args}"
76
+ end
77
+ output
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # ClusterConfig requires ClientRegistry class provided by the host project.
5
+
6
+ require 'singleton'
7
+
8
+ module Mrss
9
+ class ClusterConfig
10
+ include Singleton
11
+ include RSpec::Core::Pending
12
+
13
+ def single_server?
14
+ determine_cluster_config
15
+ @single_server
16
+ end
17
+
18
+ def replica_set_name
19
+ determine_cluster_config
20
+ @replica_set_name
21
+ end
22
+
23
+ def server_version
24
+ determine_cluster_config
25
+ @server_version
26
+ end
27
+
28
+ def enterprise?
29
+ determine_cluster_config
30
+ @enterprise
31
+ end
32
+
33
+ def short_server_version
34
+ server_version.split('.')[0..1].join('.')
35
+ end
36
+
37
+ def fcv
38
+ determine_cluster_config
39
+ @fcv
40
+ end
41
+
42
+ # Per https://jira.mongodb.org/browse/SERVER-39052, working with FCV
43
+ # in sharded topologies is annoying. Also, FCV doesn't exist in servers
44
+ # less than 3.4. This method returns FCV on 3.4+ servers when in single
45
+ # or RS topologies, and otherwise returns the major.minor server version.
46
+ def fcv_ish
47
+ if server_version.nil?
48
+ raise "Deployment server version not known - check that connection to deployment succeeded"
49
+ end
50
+
51
+ if server_version >= '3.4' && topology != :sharded
52
+ fcv
53
+ else
54
+ if short_server_version == '4.1'
55
+ '4.2'
56
+ else
57
+ short_server_version
58
+ end
59
+ end
60
+ end
61
+
62
+ # @return [ Mongo::Address ] The address of the primary in the deployment.
63
+ def primary_address
64
+ determine_cluster_config
65
+ @primary_address
66
+ end
67
+
68
+ def primary_address_str
69
+ determine_cluster_config
70
+ @primary_address.seed
71
+ end
72
+
73
+ def primary_address_host
74
+ both = primary_address_str
75
+ both.split(':').first
76
+ end
77
+
78
+ def primary_address_port
79
+ both = primary_address_str
80
+ both.split(':')[1] || 27017
81
+ end
82
+
83
+ def primary_description
84
+ determine_cluster_config
85
+ @primary_description
86
+ end
87
+
88
+ def server_parameters
89
+ determine_cluster_config
90
+ @server_parameters
91
+ end
92
+
93
+ # Try running a command on the admin database to see if the mongod was
94
+ # started with auth.
95
+ def auth_enabled?
96
+ if @auth_enabled.nil?
97
+ @auth_enabled = begin
98
+ basic_client.use(:admin).command(getCmdLineOpts: 1).first["argv"].include?("--auth")
99
+ rescue => e
100
+ e.message =~ /(not authorized)|(unauthorized)|(no users authenticated)|(requires authentication)/
101
+ end
102
+ end
103
+ @auth_enabled
104
+ end
105
+
106
+ def topology
107
+ determine_cluster_config
108
+ @topology
109
+ end
110
+
111
+ def storage_engine
112
+ @storage_engine ||= begin
113
+ # 2.6 does not have wired tiger
114
+ if short_server_version == '2.6'
115
+ :mmapv1
116
+ else
117
+ client = ClientRegistry.instance.global_client('root_authorized')
118
+ if topology == :sharded
119
+ shards = client.use(:admin).command(listShards: 1).first
120
+ if shards['shards'].empty?
121
+ raise 'Shards are empty'
122
+ end
123
+ shard = shards['shards'].first
124
+ address_str = shard['host'].sub(/^.*\//, '').sub(/,.*/, '')
125
+ client = ClusterTools.instance.direct_client(address_str,
126
+ SpecConfig.instance.test_options.merge(SpecConfig.instance.auth_options).merge(connect: :direct))
127
+ end
128
+ rv = client.use(:admin).command(serverStatus: 1).first
129
+ rv = rv['storageEngine']['name']
130
+ rv_map = {
131
+ 'wiredTiger' => :wired_tiger,
132
+ 'mmapv1' => :mmapv1,
133
+ }
134
+ rv_map[rv] || rv
135
+ end
136
+ end
137
+ end
138
+
139
+ # This method returns an alternate address for connecting to the configured
140
+ # deployment. For example, if the replica set is configured with nodes at
141
+ # of localhost:27017 and so on, this method will return 127.0.0.:27017.
142
+ #
143
+ # Note that the "alternate" refers to replica set configuration, not the
144
+ # addresses specified in test suite configuration. If the deployment topology
145
+ # is not a replica set, "alternate" refers to test suite configuration as
146
+ # this is the only configuration available.
147
+ def alternate_address
148
+ @alternate_address ||= begin
149
+ address = primary_address_host
150
+ str = case address
151
+ when '127.0.0.1'
152
+ 'localhost'
153
+ when /^(\d+\.){3}\d+$/
154
+ skip 'This test requires a hostname or 127.0.0.1 as address'
155
+ else
156
+ # We don't know if mongod is listening on ipv4 or ipv6, in principle.
157
+ # Our tests use ipv4, so hardcode that for now.
158
+ # To support both we need to try both addresses which will make this
159
+ # test more complicated.
160
+ #
161
+ # JRuby chokes on primary_address_port as the port (e.g. 27017).
162
+ # Since the port does not actually matter, use a common port like 80.
163
+ resolved_address = Addrinfo.getaddrinfo(address, 80, Socket::PF_INET).first.ip_address
164
+ if resolved_address.include?(':')
165
+ "[#{resolved_address}]"
166
+ else
167
+ resolved_address
168
+ end
169
+ end + ":#{primary_address_port}"
170
+ Mongo::Address.new(str)
171
+ end
172
+ end
173
+
174
+ private
175
+
176
+ def determine_cluster_config
177
+ return if @primary_address
178
+
179
+ # Run all commands to figure out the cluster configuration from the same
180
+ # client. This is somewhat wasteful when running a single test, but reduces
181
+ # test runtime for the suite overall because all commands are sent on the
182
+ # same connection rather than each command connecting to the cluster by
183
+ # itself.
184
+ client = ClientRegistry.instance.global_client('root_authorized')
185
+
186
+ primary = client.cluster.next_primary
187
+ @primary_address = primary.address
188
+ @primary_description = primary.description
189
+ @replica_set_name = client.cluster.topology.replica_set_name
190
+
191
+ @topology ||= begin
192
+ topology = client.cluster.topology.class.name.sub(/.*::/, '')
193
+ topology = topology.gsub(/([A-Z])/) { |match| '_' + match.downcase }.sub(/^_/, '')
194
+ if topology =~ /^replica_set/
195
+ topology = 'replica_set'
196
+ end
197
+ topology.to_sym
198
+ end
199
+
200
+ @single_server = client.cluster.servers_list.length == 1
201
+
202
+ build_info = client.database.command(buildInfo: 1).first
203
+
204
+ @server_version = build_info['version']
205
+ @enterprise = build_info['modules'] && build_info['modules'].include?('enterprise')
206
+
207
+ @server_parameters = client.use(:admin).command(getParameter: '*').first
208
+
209
+ if @topology != :sharded && short_server_version >= '3.4'
210
+ rv = @server_parameters['featureCompatibilityVersion']
211
+ @fcv = rv['version'] || rv
212
+ end
213
+ end
214
+
215
+ def basic_client
216
+ # Do not cache the result here so that if the client gets closed,
217
+ # client registry reconnects it in subsequent tests
218
+ ClientRegistry.instance.global_client('basic')
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,354 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ module Mrss
5
+ module Constraints
6
+ def min_server_version(version)
7
+ unless version =~ /\A\d+\.\d+\z/
8
+ raise ArgumentError, "Version can only be major.minor: #{version}"
9
+ end
10
+
11
+ before(:all) do
12
+ if version > ClusterConfig.instance.server_version
13
+ skip "Server version #{version} or higher required, we have #{ClusterConfig.instance.server_version}"
14
+ end
15
+ end
16
+ end
17
+
18
+ def max_server_version(version)
19
+ unless version =~ /\A\d+\.\d+\z/
20
+ raise ArgumentError, "Version can only be major.minor: #{version}"
21
+ end
22
+
23
+ before(:all) do
24
+ if version < ClusterConfig.instance.short_server_version
25
+ skip "Server version #{version} or lower required, we have #{ClusterConfig.instance.server_version}"
26
+ end
27
+ end
28
+ end
29
+
30
+ def min_server_fcv(version)
31
+ unless version =~ /\A\d+\.\d+\z/
32
+ raise ArgumentError, "FCV can only be major.minor: #{version}"
33
+ end
34
+
35
+ before(:all) do
36
+ unless ClusterConfig.instance.fcv_ish >= version
37
+ skip "FCV #{version} or higher required, we have #{ClusterConfig.instance.fcv_ish} (server #{ClusterConfig.instance.server_version})"
38
+ end
39
+ end
40
+ end
41
+
42
+ def max_server_fcv(version)
43
+ unless version =~ /\A\d+\.\d+\z/
44
+ raise ArgumentError, "Version can only be major.minor: #{version}"
45
+ end
46
+
47
+ before(:all) do
48
+ if version < ClusterConfig.instance.fcv_ish
49
+ skip "FCV #{version} or lower required, we have #{ClusterConfig.instance.fcv_ish} (server #{ClusterConfig.instance.server_version})"
50
+ end
51
+ end
52
+ end
53
+
54
+ def require_topology(*topologies)
55
+ invalid_topologies = topologies - [:single, :replica_set, :sharded]
56
+
57
+ unless invalid_topologies.empty?
58
+ raise ArgumentError, "Invalid topologies requested: #{invalid_topologies.join(', ')}"
59
+ end
60
+
61
+ before(:all) do
62
+ unless topologies.include?(topology = ClusterConfig.instance.topology)
63
+ skip "Topology #{topologies.join(' or ')} required, we have #{topology}"
64
+ end
65
+ end
66
+ end
67
+
68
+ def max_example_run_time(timeout)
69
+ around do |example|
70
+ TimeoutInterrupt.timeout(timeout, TimeoutInterrupt::Error.new("Test execution terminated after #{timeout} seconds")) do
71
+ example.run
72
+ end
73
+ end
74
+ end
75
+
76
+ def require_transaction_support
77
+ before(:all) do
78
+ case ClusterConfig.instance.topology
79
+ when :single
80
+ skip 'Transactions tests require a replica set (4.0+) or a sharded cluster (4.2+)'
81
+ when :replica_set
82
+ unless ClusterConfig.instance.server_version >= '4.0'
83
+ skip 'Transactions tests in a replica set topology require server 4.0+'
84
+ end
85
+ when :sharded
86
+ unless ClusterConfig.instance.server_version >= '4.2'
87
+ skip 'Transactions tests in a sharded cluster topology require server 4.2+'
88
+ end
89
+ else
90
+ raise NotImplementedError
91
+ end
92
+ end
93
+ end
94
+
95
+ # Fail command fail point was added to mongod in 4.0 and to mongos in 4.2.
96
+ def require_fail_command
97
+ require_transaction_support
98
+ end
99
+
100
+ def require_tls
101
+ before(:all) do
102
+ unless SpecConfig.instance.ssl?
103
+ skip "SSL not enabled"
104
+ end
105
+ end
106
+ end
107
+
108
+ def require_no_tls
109
+ before(:all) do
110
+ if SpecConfig.instance.ssl?
111
+ skip "SSL enabled"
112
+ end
113
+ end
114
+ end
115
+
116
+ def require_retry_writes
117
+ before(:all) do
118
+ unless SpecConfig.instance.retry_writes?
119
+ skip "Retry writes is disabled"
120
+ end
121
+ end
122
+ end
123
+
124
+ def require_no_retry_writes
125
+ before(:all) do
126
+ if SpecConfig.instance.retry_writes?
127
+ skip "Retry writes is enabled"
128
+ end
129
+ end
130
+ end
131
+
132
+ def require_compression
133
+ before(:all) do
134
+ if SpecConfig.instance.compressors.nil?
135
+ skip "Compression is not enabled"
136
+ end
137
+ end
138
+ end
139
+
140
+ def require_zlib_compression
141
+ before(:all) do
142
+ compressors = SpecConfig.instance.compressors
143
+ unless compressors && compressors.include?('zlib')
144
+ skip "Zlib compression is not enabled"
145
+ end
146
+ end
147
+ end
148
+
149
+ def require_snappy_compression
150
+ before(:all) do
151
+ compressors = SpecConfig.instance.compressors
152
+ unless compressors && compressors.include?('snappy')
153
+ skip "Snappy compression is not enabled"
154
+ end
155
+ end
156
+ end
157
+
158
+ def require_no_snappy_compression
159
+ before(:all) do
160
+ compressors = SpecConfig.instance.compressors
161
+ if compressors && compressors.include?('snappy')
162
+ skip "Snappy compression is enabled"
163
+ end
164
+ end
165
+ end
166
+
167
+ def require_zstd_compression
168
+ before(:all) do
169
+ compressors = SpecConfig.instance.compressors
170
+ unless compressors && compressors.include?('zstd')
171
+ skip "Zstd compression is not enabled"
172
+ end
173
+ end
174
+ end
175
+
176
+ def require_no_zstd_compression
177
+ before(:all) do
178
+ compressors = SpecConfig.instance.compressors
179
+ if compressors && compressors.include?('zstd')
180
+ skip "Zstd compression is enabled"
181
+ end
182
+ end
183
+ end
184
+
185
+ def require_no_compression
186
+ before(:all) do
187
+ if SpecConfig.instance.compressors
188
+ skip "Compression is enabled"
189
+ end
190
+ end
191
+ end
192
+
193
+ def ruby_version_gte(version)
194
+ before(:all) do
195
+ if RUBY_VERSION < version
196
+ skip "Ruby version #{version} or higher required"
197
+ end
198
+ end
199
+ end
200
+
201
+ def ruby_version_lt(version)
202
+ before(:all) do
203
+ if RUBY_VERSION >= version
204
+ skip "Ruby version less than #{version} required"
205
+ end
206
+ end
207
+ end
208
+
209
+ def require_auth(*values)
210
+ before(:all) do
211
+ if values.any?
212
+ unless values.include?(ENV['AUTH'])
213
+ msg = values.map { |v| "AUTH=#{v}" }.join(' or ')
214
+ skip "This test requires #{msg}"
215
+ end
216
+ else
217
+ unless ENV['AUTH'] == 'auth' || SpecConfig.instance.user || ClusterConfig.instance.auth_enabled?
218
+ skip "Auth required"
219
+ end
220
+ end
221
+ end
222
+ end
223
+
224
+ def require_no_auth
225
+ before(:all) do
226
+ if (ENV['AUTH'] && ENV['AUTH'] != 'noauth') || SpecConfig.instance.user || ClusterConfig.instance.auth_enabled?
227
+ skip "Auth not allowed"
228
+ end
229
+ end
230
+ end
231
+
232
+ def require_x509_auth
233
+ before(:all) do
234
+ unless SpecConfig.instance.x509_auth?
235
+ skip "X.509 auth required"
236
+ end
237
+ end
238
+ end
239
+
240
+ def require_no_external_user
241
+ before(:all) do
242
+ if SpecConfig.instance.external_user?
243
+ skip "External user configurations are not compatible with this test"
244
+ end
245
+ end
246
+ end
247
+
248
+ # Can the driver specify a write concern that won't be overridden?
249
+ # (mongos 4.0+ overrides the write concern)
250
+ def require_set_write_concern
251
+ before(:all) do
252
+ if ClusterConfig.instance.topology == :sharded && ClusterConfig.instance.short_server_version >= '4.0'
253
+ skip "mongos 4.0+ overrides write concern"
254
+ end
255
+ end
256
+ end
257
+
258
+ def require_multi_shard
259
+ before(:all) do
260
+ if ClusterConfig.instance.topology == :sharded && SpecConfig.instance.addresses.length == 1
261
+ skip 'Test requires a minimum of two shards if run in sharded topology'
262
+ end
263
+ end
264
+ end
265
+
266
+ def require_no_multi_shard
267
+ before(:all) do
268
+ if ClusterConfig.instance.topology == :sharded && SpecConfig.instance.addresses.length > 1
269
+ skip 'Test requires a single shard if run in sharded topology'
270
+ end
271
+ end
272
+ end
273
+
274
+ def require_wired_tiger
275
+ before(:all) do
276
+ if ClusterConfig.instance.storage_engine != :wired_tiger
277
+ skip 'Test requires WiredTiger storage engine'
278
+ end
279
+ end
280
+ end
281
+
282
+ def require_wired_tiger_on_36
283
+ before(:all) do
284
+ if ClusterConfig.instance.short_server_version >= '3.6'
285
+ if ClusterConfig.instance.storage_engine != :wired_tiger
286
+ skip 'Test requires WiredTiger storage engine on 3.6+ servers'
287
+ end
288
+ end
289
+ end
290
+ end
291
+
292
+ def require_mmapv1
293
+ before(:all) do
294
+ if ClusterConfig.instance.storage_engine != :mmapv1
295
+ skip 'Test requires MMAPv1 storage engine'
296
+ end
297
+ end
298
+ end
299
+
300
+ def require_enterprise
301
+ before(:all) do
302
+ unless ClusterConfig.instance.enterprise?
303
+ skip 'Test requires enterprise build of MongoDB'
304
+ end
305
+ end
306
+ end
307
+
308
+ # Integration tests for SRV polling require internet connectivity to
309
+ # look up SRV records and a sharded cluster configured on default port on
310
+ # localhost (localhost:27017, localhost:27018).
311
+ def require_default_port_deployment
312
+ # Because the DNS records at test1.test.build.10gen.cc point to
313
+ # localhost:27017 & localhost:27018, the test suite must have been
314
+ # configured to use these addresses
315
+ before(:all) do
316
+ have_default_port = SpecConfig.instance.addresses.any? do |address|
317
+ %w(127.0.0.1 127.0.0.1:27017 localhost localhost:27017).include?(address)
318
+ end
319
+ unless have_default_port
320
+ skip 'This test requires the test suite to be configured for localhost:27017'
321
+ end
322
+ end
323
+ end
324
+
325
+ # Some tests perform assertions on what the driver is logging.
326
+ # Some test configurations, for example OCSP with unknown response,
327
+ # produce warnings due to optional checks failing.
328
+ # This constraint skips tests that issue logging assertions on configurations
329
+ # that may produce non-test-originated log entries.
330
+ def require_warning_clean
331
+ before(:all) do
332
+ if ENV['OCSP_STATUS'] == 'unknown'
333
+ skip 'Unknown OCSP status is not global warning-clean'
334
+ end
335
+ end
336
+ end
337
+
338
+ def require_required_api_version
339
+ before(:all) do
340
+ unless ENV['API_VERSION_REQUIRED'] == '1'
341
+ skip 'Set API_VERSION_REQUIRED=1 to run this test'
342
+ end
343
+ end
344
+ end
345
+
346
+ def require_no_required_api_version
347
+ before(:all) do
348
+ if ENV['API_VERSION_REQUIRED'] == '1'
349
+ skip 'Cannot have API_VERSION_REQUIRED=1 to run this test'
350
+ end
351
+ end
352
+ end
353
+ end
354
+ end