mongo-lyon 1.2.4

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.
Files changed (87) hide show
  1. data/LICENSE.txt +190 -0
  2. data/README.md +344 -0
  3. data/Rakefile +202 -0
  4. data/bin/mongo_console +34 -0
  5. data/docs/1.0_UPGRADE.md +21 -0
  6. data/docs/CREDITS.md +123 -0
  7. data/docs/FAQ.md +116 -0
  8. data/docs/GridFS.md +158 -0
  9. data/docs/HISTORY.md +225 -0
  10. data/docs/REPLICA_SETS.md +72 -0
  11. data/docs/TUTORIAL.md +247 -0
  12. data/docs/WRITE_CONCERN.md +28 -0
  13. data/lib/mongo.rb +77 -0
  14. data/lib/mongo/collection.rb +872 -0
  15. data/lib/mongo/connection.rb +875 -0
  16. data/lib/mongo/cursor.rb +449 -0
  17. data/lib/mongo/db.rb +607 -0
  18. data/lib/mongo/exceptions.rb +68 -0
  19. data/lib/mongo/gridfs/grid.rb +106 -0
  20. data/lib/mongo/gridfs/grid_ext.rb +57 -0
  21. data/lib/mongo/gridfs/grid_file_system.rb +145 -0
  22. data/lib/mongo/gridfs/grid_io.rb +394 -0
  23. data/lib/mongo/gridfs/grid_io_fix.rb +38 -0
  24. data/lib/mongo/repl_set_connection.rb +342 -0
  25. data/lib/mongo/util/conversions.rb +89 -0
  26. data/lib/mongo/util/core_ext.rb +60 -0
  27. data/lib/mongo/util/pool.rb +185 -0
  28. data/lib/mongo/util/server_version.rb +71 -0
  29. data/lib/mongo/util/support.rb +82 -0
  30. data/lib/mongo/util/uri_parser.rb +181 -0
  31. data/lib/mongo/version.rb +3 -0
  32. data/mongo.gemspec +34 -0
  33. data/test/auxillary/1.4_features.rb +166 -0
  34. data/test/auxillary/authentication_test.rb +68 -0
  35. data/test/auxillary/autoreconnect_test.rb +41 -0
  36. data/test/auxillary/repl_set_auth_test.rb +58 -0
  37. data/test/auxillary/slave_connection_test.rb +36 -0
  38. data/test/auxillary/threaded_authentication_test.rb +101 -0
  39. data/test/bson/binary_test.rb +15 -0
  40. data/test/bson/bson_test.rb +614 -0
  41. data/test/bson/byte_buffer_test.rb +190 -0
  42. data/test/bson/hash_with_indifferent_access_test.rb +38 -0
  43. data/test/bson/json_test.rb +17 -0
  44. data/test/bson/object_id_test.rb +154 -0
  45. data/test/bson/ordered_hash_test.rb +197 -0
  46. data/test/collection_test.rb +893 -0
  47. data/test/connection_test.rb +303 -0
  48. data/test/conversions_test.rb +120 -0
  49. data/test/cursor_fail_test.rb +75 -0
  50. data/test/cursor_message_test.rb +43 -0
  51. data/test/cursor_test.rb +457 -0
  52. data/test/db_api_test.rb +715 -0
  53. data/test/db_connection_test.rb +15 -0
  54. data/test/db_test.rb +287 -0
  55. data/test/grid_file_system_test.rb +244 -0
  56. data/test/grid_io_test.rb +120 -0
  57. data/test/grid_test.rb +200 -0
  58. data/test/load/thin/load.rb +24 -0
  59. data/test/load/unicorn/load.rb +23 -0
  60. data/test/replica_sets/connect_test.rb +86 -0
  61. data/test/replica_sets/connection_string_test.rb +32 -0
  62. data/test/replica_sets/count_test.rb +35 -0
  63. data/test/replica_sets/insert_test.rb +53 -0
  64. data/test/replica_sets/pooled_insert_test.rb +55 -0
  65. data/test/replica_sets/query_secondaries.rb +96 -0
  66. data/test/replica_sets/query_test.rb +51 -0
  67. data/test/replica_sets/replication_ack_test.rb +66 -0
  68. data/test/replica_sets/rs_test_helper.rb +27 -0
  69. data/test/safe_test.rb +68 -0
  70. data/test/support/hash_with_indifferent_access.rb +199 -0
  71. data/test/support/keys.rb +45 -0
  72. data/test/support_test.rb +19 -0
  73. data/test/test_helper.rb +83 -0
  74. data/test/threading/threading_with_large_pool_test.rb +90 -0
  75. data/test/threading_test.rb +87 -0
  76. data/test/tools/auth_repl_set_manager.rb +14 -0
  77. data/test/tools/repl_set_manager.rb +266 -0
  78. data/test/unit/collection_test.rb +130 -0
  79. data/test/unit/connection_test.rb +98 -0
  80. data/test/unit/cursor_test.rb +99 -0
  81. data/test/unit/db_test.rb +96 -0
  82. data/test/unit/grid_test.rb +49 -0
  83. data/test/unit/pool_test.rb +9 -0
  84. data/test/unit/repl_set_connection_test.rb +72 -0
  85. data/test/unit/safe_test.rb +125 -0
  86. data/test/uri_test.rb +91 -0
  87. metadata +202 -0
@@ -0,0 +1,199 @@
1
+ # Note: HashWithIndifferentAccess is so commonly used
2
+ # that we always need to make sure that the driver works
3
+ # with it.
4
+ #require File.join(File.dirname(__FILE__), 'keys.rb')
5
+
6
+ # This class has dubious semantics and we only have it so that
7
+ # people can write params[:key] instead of params['key']
8
+ # and they get the same value for both keys.
9
+
10
+ class Hash
11
+ # Return a new hash with all keys converted to strings.
12
+ def stringify_keys
13
+ dup.stringify_keys!
14
+ end
15
+
16
+ # Destructively convert all keys to strings.
17
+ def stringify_keys!
18
+ keys.each do |key|
19
+ self[key.to_s] = delete(key)
20
+ end
21
+ self
22
+ end
23
+
24
+ # Return a new hash with all keys converted to symbols, as long as
25
+ # they respond to +to_sym+.
26
+ def symbolize_keys
27
+ dup.symbolize_keys!
28
+ end
29
+
30
+ # Destructively convert all keys to symbols, as long as they respond
31
+ # to +to_sym+.
32
+ def symbolize_keys!
33
+ keys.each do |key|
34
+ self[(key.to_sym rescue key) || key] = delete(key)
35
+ end
36
+ self
37
+ end
38
+
39
+ alias_method :to_options, :symbolize_keys
40
+ #alias_method :to_options!, :symbolize_keys!
41
+
42
+ # Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
43
+ # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
44
+ # as keys, this will fail.
45
+ #
46
+ # ==== Examples
47
+ # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
48
+ # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
49
+ # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
50
+ def assert_valid_keys(*valid_keys)
51
+ unknown_keys = keys - [valid_keys].flatten
52
+ raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
53
+ end
54
+ end
55
+
56
+ module ActiveSupport
57
+ class HashWithIndifferentAccess < Hash
58
+ def extractable_options?
59
+ true
60
+ end
61
+
62
+ def initialize(constructor = {})
63
+ if constructor.is_a?(Hash)
64
+ super()
65
+ update(constructor)
66
+ else
67
+ super(constructor)
68
+ end
69
+ end
70
+
71
+ def default(key = nil)
72
+ if key.is_a?(Symbol) && include?(key = key.to_s)
73
+ self[key]
74
+ else
75
+ super
76
+ end
77
+ end
78
+
79
+ def self.new_from_hash_copying_default(hash)
80
+ ActiveSupport::HashWithIndifferentAccess.new(hash).tap do |new_hash|
81
+ new_hash.default = hash.default
82
+ end
83
+ end
84
+
85
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
86
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
87
+
88
+ # Assigns a new value to the hash:
89
+ #
90
+ # hash = HashWithIndifferentAccess.new
91
+ # hash[:key] = "value"
92
+ #
93
+ def []=(key, value)
94
+ regular_writer(convert_key(key), convert_value(value))
95
+ end
96
+
97
+ # Updates the instantized hash with values from the second:
98
+ #
99
+ # hash_1 = HashWithIndifferentAccess.new
100
+ # hash_1[:key] = "value"
101
+ #
102
+ # hash_2 = HashWithIndifferentAccess.new
103
+ # hash_2[:key] = "New Value!"
104
+ #
105
+ # hash_1.update(hash_2) # => {"key"=>"New Value!"}
106
+ #
107
+ def update(other_hash)
108
+ other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
109
+ self
110
+ end
111
+
112
+ alias_method :merge!, :update
113
+
114
+ # Checks the hash for a key matching the argument passed in:
115
+ #
116
+ # hash = HashWithIndifferentAccess.new
117
+ # hash["key"] = "value"
118
+ # hash.key? :key # => true
119
+ # hash.key? "key" # => true
120
+ #
121
+ def key?(key)
122
+ super(convert_key(key))
123
+ end
124
+
125
+ alias_method :include?, :key?
126
+ alias_method :has_key?, :key?
127
+ alias_method :member?, :key?
128
+
129
+ # Fetches the value for the specified key, same as doing hash[key]
130
+ def fetch(key, *extras)
131
+ super(convert_key(key), *extras)
132
+ end
133
+
134
+ # Returns an array of the values at the specified indices:
135
+ #
136
+ # hash = HashWithIndifferentAccess.new
137
+ # hash[:a] = "x"
138
+ # hash[:b] = "y"
139
+ # hash.values_at("a", "b") # => ["x", "y"]
140
+ #
141
+ def values_at(*indices)
142
+ indices.collect {|key| self[convert_key(key)]}
143
+ end
144
+
145
+ # Returns an exact copy of the hash.
146
+ def dup
147
+ HashWithIndifferentAccess.new(self)
148
+ end
149
+
150
+ # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash
151
+ # Does not overwrite the existing hash.
152
+ def merge(hash)
153
+ self.dup.update(hash)
154
+ end
155
+
156
+ # Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second.
157
+ # This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess.
158
+ def reverse_merge(other_hash)
159
+ super self.class.new_from_hash_copying_default(other_hash)
160
+ end
161
+
162
+ def reverse_merge!(other_hash)
163
+ replace(reverse_merge( other_hash ))
164
+ end
165
+
166
+ # Removes a specified key from the hash.
167
+ def delete(key)
168
+ super(convert_key(key))
169
+ end
170
+
171
+ def stringify_keys!; self end
172
+ def stringify_keys; dup end
173
+ def symbolize_keys; to_hash.symbolize_keys end
174
+ def to_options!; self end
175
+
176
+ # Convert to a Hash with String keys.
177
+ def to_hash
178
+ Hash.new(default).merge!(self)
179
+ end
180
+
181
+ protected
182
+ def convert_key(key)
183
+ key.kind_of?(Symbol) ? key.to_s : key
184
+ end
185
+
186
+ def convert_value(value)
187
+ case value
188
+ when Hash
189
+ self.class.new_from_hash_copying_default(value)
190
+ when Array
191
+ value.collect { |e| e.is_a?(Hash) ? self.class.new_from_hash_copying_default(e) : e }
192
+ else
193
+ value
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
@@ -0,0 +1,45 @@
1
+ class Hash
2
+ # Return a new hash with all keys converted to strings.
3
+ def stringify_keys
4
+ dup.stringify_keys!
5
+ end
6
+
7
+ # Destructively convert all keys to strings.
8
+ def stringify_keys!
9
+ keys.each do |key|
10
+ self[key.to_s] = delete(key)
11
+ end
12
+ self
13
+ end
14
+
15
+ # Return a new hash with all keys converted to symbols, as long as
16
+ # they respond to +to_sym+.
17
+ def symbolize_keys
18
+ dup.symbolize_keys!
19
+ end
20
+
21
+ # Destructively convert all keys to symbols, as long as they respond
22
+ # to +to_sym+.
23
+ def symbolize_keys!
24
+ keys.each do |key|
25
+ self[(key.to_sym rescue key) || key] = delete(key)
26
+ end
27
+ self
28
+ end
29
+
30
+ alias_method :to_options, :symbolize_keys
31
+ #alias_method :to_options!, :symbolize_keys!
32
+
33
+ # Validate all keys in a hash match *valid keys, raising ArgumentError on a mismatch.
34
+ # Note that keys are NOT treated indifferently, meaning if you use strings for keys but assert symbols
35
+ # as keys, this will fail.
36
+ #
37
+ # ==== Examples
38
+ # { :name => "Rob", :years => "28" }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key(s): years"
39
+ # { :name => "Rob", :age => "28" }.assert_valid_keys("name", "age") # => raises "ArgumentError: Unknown key(s): name, age"
40
+ # { :name => "Rob", :age => "28" }.assert_valid_keys(:name, :age) # => passes, raises nothing
41
+ def assert_valid_keys(*valid_keys)
42
+ unknown_keys = keys - [valid_keys].flatten
43
+ raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty?
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+ require './test/test_helper'
2
+
3
+ class SupportTest < Test::Unit::TestCase
4
+ include Mongo
5
+
6
+ def test_command_response_succeeds
7
+ assert Support.ok?('ok' => 1)
8
+ assert Support.ok?('ok' => 1.0)
9
+ assert Support.ok?('ok' => true)
10
+ end
11
+
12
+ def test_command_response_fails
13
+ assert !Support.ok?('ok' => 0)
14
+ assert !Support.ok?('ok' => 0.0)
15
+ assert !Support.ok?('ok' => 0.0)
16
+ assert !Support.ok?('ok' => 'str')
17
+ assert !Support.ok?('ok' => false)
18
+ end
19
+ end
@@ -0,0 +1,83 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'rubygems' if ENV['C_EXT']
3
+ require 'mongo'
4
+ require 'test/unit'
5
+
6
+ begin
7
+ require 'rubygems'
8
+ require 'shoulda'
9
+ require 'mocha'
10
+ rescue LoadError
11
+ puts <<MSG
12
+
13
+ This test suite requires shoulda and mocha.
14
+ You can install them as follows:
15
+ gem install shoulda
16
+ gem install mocha
17
+
18
+ MSG
19
+ exit
20
+ end
21
+
22
+ require 'bson_ext/cbson' if !(RUBY_PLATFORM =~ /java/) && ENV['C_EXT']
23
+
24
+ unless defined? MONGO_TEST_DB
25
+ MONGO_TEST_DB = 'ruby-test-db'
26
+ end
27
+
28
+ unless defined? TEST_PORT
29
+ TEST_PORT = ENV['MONGO_RUBY_DRIVER_PORT'] ? ENV['MONGO_RUBY_DRIVER_PORT'].to_i : Mongo::Connection::DEFAULT_PORT
30
+ end
31
+
32
+ unless defined? TEST_HOST
33
+ TEST_HOST = ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost'
34
+ end
35
+
36
+ class Test::Unit::TestCase
37
+ include Mongo
38
+ include BSON
39
+
40
+ def self.standard_connection(options={})
41
+ Connection.new(TEST_HOST, TEST_PORT, options)
42
+ end
43
+
44
+ def standard_connection(options={})
45
+ self.class.standard_connection(options)
46
+ end
47
+
48
+ def self.host_port
49
+ "#{mongo_host}:#{mongo_port}"
50
+ end
51
+
52
+ def self.mongo_host
53
+ TEST_HOST
54
+ end
55
+
56
+ def self.mongo_port
57
+ TEST_PORT
58
+ end
59
+
60
+ def host_port
61
+ self.class.host_port
62
+ end
63
+
64
+ def mongo_host
65
+ self.class.mongo_host
66
+ end
67
+
68
+ def mongo_port
69
+ self.class.mongo_port
70
+ end
71
+
72
+
73
+ def assert_raise_error(klass, message)
74
+ begin
75
+ yield
76
+ rescue => e
77
+ assert_equal klass, e.class
78
+ assert e.message.include?(message), "#{e.message} does not include #{message}."
79
+ else
80
+ flunk "Expected assertion #{klass} but none was raised."
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,90 @@
1
+ require './test/test_helper'
2
+
3
+ # Essentialy the same as test_threading.rb but with an expanded pool for
4
+ # testing multiple connections.
5
+ class TestThreadingLargePool < Test::Unit::TestCase
6
+
7
+ include Mongo
8
+
9
+ @@db = standard_connection(:pool_size => 50, :timeout => 60).db(MONGO_TEST_DB)
10
+ @@coll = @@db.collection('thread-test-collection')
11
+
12
+ def set_up_safe_data
13
+ @@db.drop_collection('duplicate')
14
+ @@db.drop_collection('unique')
15
+ @duplicate = @@db.collection('duplicate')
16
+ @unique = @@db.collection('unique')
17
+
18
+ @duplicate.insert("test" => "insert")
19
+ @duplicate.insert("test" => "update")
20
+ @unique.insert("test" => "insert")
21
+ @unique.insert("test" => "update")
22
+ @unique.create_index("test", :unique => true)
23
+ end
24
+
25
+ def test_safe_update
26
+ set_up_safe_data
27
+ threads = []
28
+ 300.times do |i|
29
+ threads[i] = Thread.new do
30
+ if i % 2 == 0
31
+ assert_raise Mongo::OperationFailure do
32
+ @unique.update({"test" => "insert"}, {"$set" => {"test" => "update"}}, :safe => true)
33
+ end
34
+ else
35
+ @duplicate.update({"test" => "insert"}, {"$set" => {"test" => "update"}}, :safe => true)
36
+ end
37
+ end
38
+ end
39
+
40
+ 300.times do |i|
41
+ threads[i].join
42
+ end
43
+ end
44
+
45
+ def test_safe_insert
46
+ set_up_safe_data
47
+ threads = []
48
+ 300.times do |i|
49
+ threads[i] = Thread.new do
50
+ if i % 2 == 0
51
+ assert_raise Mongo::OperationFailure do
52
+ @unique.insert({"test" => "insert"}, :safe => true)
53
+ end
54
+ else
55
+ @duplicate.insert({"test" => "insert"}, :safe => true)
56
+ end
57
+ end
58
+ end
59
+
60
+ 300.times do |i|
61
+ threads[i].join
62
+ end
63
+ end
64
+
65
+ def test_threading
66
+ @@coll.drop
67
+ @@coll = @@db.collection('thread-test-collection')
68
+
69
+ 1000.times do |i|
70
+ @@coll.insert("x" => i)
71
+ end
72
+
73
+ threads = []
74
+
75
+ 10.times do |i|
76
+ threads[i] = Thread.new do
77
+ sum = 0
78
+ @@coll.find().each do |document|
79
+ sum += document["x"]
80
+ end
81
+ assert_equal 499500, sum
82
+ end
83
+ end
84
+
85
+ 10.times do |i|
86
+ threads[i].join
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,87 @@
1
+ require './test/test_helper'
2
+
3
+ class TestThreading < Test::Unit::TestCase
4
+
5
+ include Mongo
6
+
7
+ @@db = standard_connection(:pool_size => 1, :timeout => 30).db(MONGO_TEST_DB)
8
+ @@coll = @@db.collection('thread-test-collection')
9
+
10
+ def set_up_safe_data
11
+ @@db.drop_collection('duplicate')
12
+ @@db.drop_collection('unique')
13
+ @duplicate = @@db.collection('duplicate')
14
+ @unique = @@db.collection('unique')
15
+
16
+ @duplicate.insert("test" => "insert")
17
+ @duplicate.insert("test" => "update")
18
+ @unique.insert("test" => "insert")
19
+ @unique.insert("test" => "update")
20
+ @unique.create_index("test", :unique => true)
21
+ end
22
+
23
+ def test_safe_update
24
+ set_up_safe_data
25
+ threads = []
26
+ 100.times do |i|
27
+ threads[i] = Thread.new do
28
+ if i % 2 == 0
29
+ assert_raise Mongo::OperationFailure do
30
+ @unique.update({"test" => "insert"}, {"$set" => {"test" => "update"}}, :safe => true)
31
+ end
32
+ else
33
+ @duplicate.update({"test" => "insert"}, {"$set" => {"test" => "update"}}, :safe => true)
34
+ end
35
+ end
36
+ end
37
+
38
+ 100.times do |i|
39
+ threads[i].join
40
+ end
41
+ end
42
+
43
+ def test_safe_insert
44
+ set_up_safe_data
45
+ threads = []
46
+ 100.times do |i|
47
+ threads[i] = Thread.new do
48
+ if i % 2 == 0
49
+ assert_raise Mongo::OperationFailure do
50
+ @unique.insert({"test" => "insert"}, :safe => true)
51
+ end
52
+ else
53
+ @duplicate.insert({"test" => "insert"}, :safe => true)
54
+ end
55
+ end
56
+ end
57
+
58
+ 100.times do |i|
59
+ threads[i].join
60
+ end
61
+ end
62
+
63
+ def test_threading
64
+ @@coll.drop
65
+ @@coll = @@db.collection('thread-test-collection')
66
+
67
+ 1000.times do |i|
68
+ @@coll.insert("x" => i)
69
+ end
70
+
71
+ threads = []
72
+
73
+ 10.times do |i|
74
+ threads[i] = Thread.new do
75
+ sum = 0
76
+ @@coll.find().each do |document|
77
+ sum += document["x"]
78
+ end
79
+ assert_equal 499500, sum
80
+ end
81
+ end
82
+
83
+ 10.times do |i|
84
+ threads[i].join
85
+ end
86
+ end
87
+ end