mongo-lyon 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
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