mongo 1.8.0 → 1.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -29
- data/VERSION +1 -1
- data/lib/mongo.rb +3 -0
- data/lib/mongo/collection.rb +99 -49
- data/lib/mongo/cursor.rb +17 -17
- data/lib/mongo/db.rb +30 -14
- data/lib/mongo/gridfs/grid.rb +5 -3
- data/lib/mongo/gridfs/grid_file_system.rb +5 -3
- data/lib/mongo/gridfs/grid_io.rb +5 -3
- data/lib/mongo/legacy.rb +9 -2
- data/lib/mongo/mongo_client.rb +100 -72
- data/lib/mongo/mongo_replica_set_client.rb +46 -60
- data/lib/mongo/mongo_sharded_client.rb +5 -66
- data/lib/mongo/networking.rb +2 -1
- data/lib/mongo/util/node.rb +41 -42
- data/lib/mongo/util/pool.rb +15 -43
- data/lib/mongo/util/pool_manager.rb +16 -65
- data/lib/mongo/util/read_preference.rb +82 -0
- data/lib/mongo/util/sharding_pool_manager.rb +0 -86
- data/lib/mongo/util/ssl_socket.rb +2 -1
- data/lib/mongo/util/support.rb +8 -18
- data/lib/mongo/util/tcp_socket.rb +5 -4
- data/lib/mongo/util/thread_local_variable_manager.rb +29 -0
- data/lib/mongo/util/unix_socket.rb +23 -0
- data/lib/mongo/util/uri_parser.rb +31 -18
- data/lib/mongo/util/write_concern.rb +7 -2
- data/mongo.gemspec +1 -1
- data/test/auxillary/repl_set_auth_test.rb +2 -2
- data/test/bson/bson_test.rb +1 -1
- data/test/bson/byte_buffer_test.rb +24 -26
- data/test/bson/hash_with_indifferent_access_test.rb +11 -1
- data/test/functional/collection_test.rb +16 -16
- data/test/functional/connection_test.rb +1 -4
- data/test/functional/db_api_test.rb +14 -10
- data/test/functional/pool_test.rb +23 -31
- data/test/functional/timeout_test.rb +3 -5
- data/test/functional/uri_test.rb +10 -5
- data/test/replica_set/basic_test.rb +3 -8
- data/test/replica_set/client_test.rb +47 -31
- data/test/replica_set/complex_connect_test.rb +12 -10
- data/test/replica_set/connection_test.rb +8 -151
- data/test/replica_set/count_test.rb +9 -5
- data/test/replica_set/cursor_test.rb +17 -27
- data/test/replica_set/insert_test.rb +5 -10
- data/test/replica_set/query_test.rb +4 -9
- data/test/replica_set/read_preference_test.rb +200 -0
- data/test/replica_set/refresh_test.rb +54 -65
- data/test/replica_set/replication_ack_test.rb +16 -14
- data/test/sharded_cluster/basic_test.rb +30 -0
- data/test/test_helper.rb +33 -15
- data/test/threading/basic_test.rb +79 -0
- data/test/tools/mongo_config.rb +62 -22
- data/test/unit/client_test.rb +36 -14
- data/test/unit/collection_test.rb +23 -0
- data/test/unit/connection_test.rb +30 -14
- data/test/unit/cursor_test.rb +137 -7
- data/test/unit/db_test.rb +17 -4
- data/test/unit/grid_test.rb +2 -2
- data/test/unit/node_test.rb +2 -1
- data/test/unit/pool_manager_test.rb +29 -1
- data/test/unit/read_test.rb +15 -15
- data/test/unit/safe_test.rb +4 -4
- data/test/unit/write_concern_test.rb +4 -4
- metadata +134 -143
- data/examples/admin.rb +0 -43
- data/examples/capped.rb +0 -22
- data/examples/cursor.rb +0 -48
- data/examples/gridfs.rb +0 -44
- data/examples/index_test.rb +0 -126
- data/examples/info.rb +0 -31
- data/examples/queries.rb +0 -74
- data/examples/replica_set.rb +0 -26
- data/examples/simple.rb +0 -25
- data/examples/strict.rb +0 -35
- data/examples/types.rb +0 -36
- data/examples/web/thin/load.rb +0 -23
- data/examples/web/unicorn/load.rb +0 -25
- data/test/support/hash_with_indifferent_access.rb +0 -186
- data/test/support/keys.rb +0 -45
- data/test/threading/threading_with_large_pool_test.rb +0 -90
@@ -9,11 +9,12 @@ module Mongo
|
|
9
9
|
# mirroring Ruby's TCPSocket, vis., TCPSocket#send and TCPSocket#read.
|
10
10
|
class SSLSocket
|
11
11
|
|
12
|
-
attr_accessor :pool
|
12
|
+
attr_accessor :pool, :pid
|
13
13
|
|
14
14
|
def initialize(host, port, op_timeout=nil, connect_timeout=nil)
|
15
15
|
@op_timeout = op_timeout
|
16
16
|
@connect_timeout = connect_timeout
|
17
|
+
@pid = Process.pid
|
17
18
|
|
18
19
|
@socket = ::TCPSocket.new(host, port)
|
19
20
|
@socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
data/lib/mongo/util/support.rb
CHANGED
@@ -24,14 +24,6 @@ module Mongo
|
|
24
24
|
include Mongo::Conversions
|
25
25
|
extend self
|
26
26
|
|
27
|
-
READ_PREFERENCES = [
|
28
|
-
:primary,
|
29
|
-
:primary_preferred,
|
30
|
-
:secondary,
|
31
|
-
:secondary_preferred,
|
32
|
-
:nearest
|
33
|
-
]
|
34
|
-
|
35
27
|
# Commands that may be sent to replica-set secondaries, depending on
|
36
28
|
# read preference and tags. All other commands are always run on the primary.
|
37
29
|
SECONDARY_OK_COMMANDS = [
|
@@ -43,7 +35,10 @@ module Mongo
|
|
43
35
|
'distinct',
|
44
36
|
'geonear',
|
45
37
|
'geosearch',
|
46
|
-
'geowalk'
|
38
|
+
'geowalk',
|
39
|
+
'mapreduce',
|
40
|
+
'replsetgetstatus',
|
41
|
+
'ismaster',
|
47
42
|
]
|
48
43
|
|
49
44
|
# Generate an MD5 for authentication.
|
@@ -94,15 +89,6 @@ module Mongo
|
|
94
89
|
end
|
95
90
|
end
|
96
91
|
|
97
|
-
def validate_read_preference(value)
|
98
|
-
if READ_PREFERENCES.include?(value)
|
99
|
-
return true
|
100
|
-
else
|
101
|
-
raise MongoArgumentError, "#{value} is not a valid read preference. " +
|
102
|
-
"Please specify one of the following read preferences as a symbol: #{READ_PREFERENCES}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
92
|
def format_order_clause(order)
|
107
93
|
case order
|
108
94
|
when Hash, BSON::OrderedHash then hash_as_sort_parameters(order)
|
@@ -114,6 +100,10 @@ module Mongo
|
|
114
100
|
end
|
115
101
|
end
|
116
102
|
|
103
|
+
def is_i?(value)
|
104
|
+
return !!(value =~ /^\d+$/)
|
105
|
+
end
|
106
|
+
|
117
107
|
# Determine if a database command has succeeded by
|
118
108
|
# checking the document response.
|
119
109
|
#
|
@@ -8,17 +8,18 @@ module Mongo
|
|
8
8
|
# sans Timeout::timeout
|
9
9
|
#
|
10
10
|
class TCPSocket
|
11
|
-
attr_accessor :pool
|
11
|
+
attr_accessor :pool, :pid
|
12
12
|
|
13
13
|
def initialize(host, port, op_timeout=nil, connect_timeout=nil)
|
14
|
-
@op_timeout = op_timeout
|
14
|
+
@op_timeout = op_timeout
|
15
15
|
@connect_timeout = connect_timeout
|
16
|
+
@pid = Process.pid
|
16
17
|
|
17
18
|
# TODO: Prefer ipv6 if server is ipv6 enabled
|
18
|
-
@
|
19
|
+
@address = Socket.getaddrinfo(host, nil, Socket::AF_INET).first[3]
|
19
20
|
@port = port
|
20
21
|
|
21
|
-
@socket_address = Socket.pack_sockaddr_in(@port, @
|
22
|
+
@socket_address = Socket.pack_sockaddr_in(@port, @address)
|
22
23
|
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
23
24
|
@socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
24
25
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# --
|
4
|
+
# Copyright (C) 2008-2012 10gen Inc.
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
# ++
|
18
|
+
|
19
|
+
#:nodoc:
|
20
|
+
module Mongo
|
21
|
+
module ThreadLocalVariableManager
|
22
|
+
def thread_local
|
23
|
+
Thread.current[:mongo_thread_locals] ||= Hash.new do |hash, key|
|
24
|
+
hash[key] = Hash.new unless hash.key? key
|
25
|
+
hash[key]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Mongo
|
4
|
+
# Wrapper class for Socket
|
5
|
+
#
|
6
|
+
# Emulates UNIXSocket with operation and connection timeout
|
7
|
+
# sans Timeout::timeout
|
8
|
+
#
|
9
|
+
class UNIXSocket < TCPSocket
|
10
|
+
def initialize(socket_path, port=:socket, op_timeout=nil, connect_timeout=nil)
|
11
|
+
@op_timeout = op_timeout
|
12
|
+
@connect_timeout = connect_timeout
|
13
|
+
|
14
|
+
@address = socket_path
|
15
|
+
@port = :socket # purposely override input
|
16
|
+
|
17
|
+
@socket_address = Socket.pack_sockaddr_un(@address)
|
18
|
+
@socket = Socket.new(Socket::AF_UNIX, Socket::SOCK_STREAM, 0)
|
19
|
+
connect
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -40,6 +40,7 @@ module Mongo
|
|
40
40
|
:connect,
|
41
41
|
:replicaset,
|
42
42
|
:slaveok,
|
43
|
+
:ssl,
|
43
44
|
:safe,
|
44
45
|
:w,
|
45
46
|
:wtimeout,
|
@@ -47,52 +48,61 @@ module Mongo
|
|
47
48
|
:journal,
|
48
49
|
:connecttimeoutms,
|
49
50
|
:sockettimeoutms,
|
50
|
-
:wtimeoutms
|
51
|
+
:wtimeoutms,
|
52
|
+
:pool_size
|
51
53
|
]
|
52
54
|
|
53
55
|
OPT_VALID = {:connect => lambda {|arg| ['direct', 'replicaset', 'true', 'false', true, false].include?(arg)},
|
54
56
|
:replicaset => lambda {|arg| arg.length > 0},
|
55
57
|
:slaveok => lambda {|arg| ['true', 'false'].include?(arg)},
|
58
|
+
:ssl => lambda {|arg| ['true', 'false'].include?(arg)},
|
56
59
|
:safe => lambda {|arg| ['true', 'false'].include?(arg)},
|
57
|
-
:w => lambda {|arg| arg =~ /^\
|
60
|
+
:w => lambda {|arg| arg =~ /^\w+$/ },
|
58
61
|
:wtimeout => lambda {|arg| arg =~ /^\d+$/ },
|
59
62
|
:fsync => lambda {|arg| ['true', 'false'].include?(arg)},
|
60
63
|
:journal => lambda {|arg| ['true', 'false'].include?(arg)},
|
61
64
|
:connecttimeoutms => lambda {|arg| arg =~ /^\d+$/ },
|
62
65
|
:sockettimeoutms => lambda {|arg| arg =~ /^\d+$/ },
|
63
|
-
:wtimeoutms => lambda {|arg| arg =~ /^\d+$/ }
|
66
|
+
:wtimeoutms => lambda {|arg| arg =~ /^\d+$/ },
|
67
|
+
:pool_size => lambda {|arg| arg.to_i > 0 }
|
64
68
|
}
|
65
69
|
|
66
70
|
OPT_ERR = {:connect => "must be 'direct', 'replicaset', 'true', or 'false'",
|
67
71
|
:replicaset => "must be a string containing the name of the replica set to connect to",
|
68
72
|
:slaveok => "must be 'true' or 'false'",
|
73
|
+
:ssl => "must be 'true' or 'false'",
|
69
74
|
:safe => "must be 'true' or 'false'",
|
70
|
-
:w => "must be an integer
|
75
|
+
:w => "must be an integer indicating number of nodes to replicate to or a string specifying
|
76
|
+
that replication is required to the majority or nodes with a particilar getLastErrorMode.",
|
71
77
|
:wtimeout => "must be an integer specifying milliseconds",
|
72
78
|
:fsync => "must be 'true' or 'false'",
|
73
79
|
:journal => "must be 'true' or 'false'",
|
74
80
|
:connecttimeoutms => "must be an integer specifying milliseconds",
|
75
81
|
:sockettimeoutms => "must be an integer specifying milliseconds",
|
76
|
-
:wtimeoutms => "must be an integer specifying milliseconds"
|
82
|
+
:wtimeoutms => "must be an integer specifying milliseconds",
|
83
|
+
:pool_size => "must be an integer greater than zero"
|
77
84
|
}
|
78
85
|
|
79
86
|
OPT_CONV = {:connect => lambda {|arg| arg == 'false' ? false : arg}, # be sure to convert 'false' to FalseClass
|
80
87
|
:replicaset => lambda {|arg| arg},
|
81
88
|
:slaveok => lambda {|arg| arg == 'true' ? true : false},
|
89
|
+
:ssl => lambda {|arg| arg == 'true' ? true : false},
|
82
90
|
:safe => lambda {|arg| arg == 'true' ? true : false},
|
83
|
-
:w => lambda {|arg| arg.to_i},
|
91
|
+
:w => lambda {|arg| Mongo::Support.is_i?(arg) ? arg.to_i : arg.to_sym },
|
84
92
|
:wtimeout => lambda {|arg| arg.to_i},
|
85
93
|
:fsync => lambda {|arg| arg == 'true' ? true : false},
|
86
94
|
:journal => lambda {|arg| arg == 'true' ? true : false},
|
87
95
|
:connecttimeoutms => lambda {|arg| arg.to_f / 1000 }, # stored as seconds
|
88
96
|
:sockettimeoutms => lambda {|arg| arg.to_f / 1000 }, # stored as seconds
|
89
|
-
:wtimeoutms => lambda {|arg| arg.to_i }
|
97
|
+
:wtimeoutms => lambda {|arg| arg.to_i },
|
98
|
+
:pool_size => lambda {|arg| arg.to_i }
|
90
99
|
}
|
91
100
|
|
92
101
|
attr_reader :auths,
|
93
102
|
:connect,
|
94
103
|
:replicaset,
|
95
104
|
:slaveok,
|
105
|
+
:ssl,
|
96
106
|
:safe,
|
97
107
|
:w,
|
98
108
|
:wtimeout,
|
@@ -100,7 +110,9 @@ module Mongo
|
|
100
110
|
:journal,
|
101
111
|
:connecttimeoutms,
|
102
112
|
:sockettimeoutms,
|
103
|
-
:wtimeoutms
|
113
|
+
:wtimeoutms,
|
114
|
+
:pool_size,
|
115
|
+
:nodes
|
104
116
|
|
105
117
|
# Parse a MongoDB URI. This method is used by MongoClient.from_uri.
|
106
118
|
# Returns an array of nodes and an array of db authorizations, if applicable.
|
@@ -133,13 +145,13 @@ module Mongo
|
|
133
145
|
opts = connection_options.merge! extra_opts
|
134
146
|
if(legacy)
|
135
147
|
if replicaset?
|
136
|
-
ReplSetConnection.new(
|
148
|
+
ReplSetConnection.new(node_strings, opts)
|
137
149
|
else
|
138
150
|
Connection.new(host, port, opts)
|
139
151
|
end
|
140
152
|
else
|
141
153
|
if replicaset?
|
142
|
-
MongoReplicaSetClient.new(
|
154
|
+
MongoReplicaSetClient.new(node_strings, opts)
|
143
155
|
else
|
144
156
|
MongoClient.new(host, port, opts)
|
145
157
|
end
|
@@ -203,14 +215,20 @@ module Mongo
|
|
203
215
|
opts[:op_timeout] = @sockettimeoutms
|
204
216
|
end
|
205
217
|
|
218
|
+
if @pool_size
|
219
|
+
opts[:pool_size] = @pool_size
|
220
|
+
end
|
221
|
+
|
206
222
|
if @slaveok
|
207
223
|
if direct?
|
208
224
|
opts[:slave_ok] = true
|
209
225
|
else
|
210
|
-
opts[:read] = :
|
226
|
+
opts[:read] = :secondary_preferred
|
211
227
|
end
|
212
228
|
end
|
213
229
|
|
230
|
+
opts[:ssl] = @ssl
|
231
|
+
|
214
232
|
if direct?
|
215
233
|
opts[:auths] = auths
|
216
234
|
end
|
@@ -224,12 +242,8 @@ module Mongo
|
|
224
242
|
opts
|
225
243
|
end
|
226
244
|
|
227
|
-
def
|
228
|
-
|
229
|
-
@nodes
|
230
|
-
else
|
231
|
-
@nodes.collect {|node| "#{node[0]}:#{node[1]}"}
|
232
|
-
end
|
245
|
+
def node_strings
|
246
|
+
nodes.map { |node| node.join(':') }
|
233
247
|
end
|
234
248
|
|
235
249
|
private
|
@@ -258,7 +272,6 @@ module Mongo
|
|
258
272
|
end
|
259
273
|
|
260
274
|
port = port.to_i
|
261
|
-
|
262
275
|
@nodes << [host, port]
|
263
276
|
end
|
264
277
|
|
@@ -52,7 +52,7 @@ module Mongo
|
|
52
52
|
:w => 1,
|
53
53
|
:j => false,
|
54
54
|
:fsync => false,
|
55
|
-
:wtimeout =>
|
55
|
+
:wtimeout => nil
|
56
56
|
}
|
57
57
|
write_concern.merge!(parent.write_concern) if parent
|
58
58
|
write_concern.merge!(opts.reject {|k,v| !write_concern.keys.include?(k)})
|
@@ -60,7 +60,12 @@ module Mongo
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def self.gle?(write_concern)
|
63
|
-
write_concern[:w]
|
63
|
+
(write_concern[:w].is_a? Symbol) ||
|
64
|
+
(write_concern[:w].is_a? String) ||
|
65
|
+
write_concern[:w] > 0 ||
|
66
|
+
write_concern[:j] ||
|
67
|
+
write_concern[:fsync] ||
|
68
|
+
write_concern[:wtimeout]
|
64
69
|
end
|
65
70
|
|
66
71
|
end
|
data/mongo.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
|
13
13
|
s.files = ['mongo.gemspec', 'LICENSE', 'VERSION']
|
14
14
|
s.files += ['README.md', 'Rakefile', 'bin/mongo_console']
|
15
|
-
s.files += ['lib/mongo.rb'] + Dir['lib/mongo/**/*.rb']
|
15
|
+
s.files += ['lib/mongo.rb'] + Dir['lib/mongo/**/*.rb']
|
16
16
|
|
17
17
|
s.test_files = Dir['test/**/*.rb']
|
18
18
|
s.executables = ['mongo_console']
|
@@ -21,14 +21,14 @@ class AuthTest < Test::Unit::TestCase
|
|
21
21
|
|
22
22
|
# Ensure that insert fails
|
23
23
|
assert_raise_error Mongo::OperationFailure, "unauthorized" do
|
24
|
-
@client['foo']['stuff'].insert({:a => 2}, {:w =>
|
24
|
+
@client['foo']['stuff'].insert({:a => 2}, {:w => 2})
|
25
25
|
end
|
26
26
|
|
27
27
|
# Then authenticate
|
28
28
|
assert @client['admin'].authenticate("me", "secret")
|
29
29
|
|
30
30
|
# Insert should succeed now
|
31
|
-
assert @client['foo']['stuff'].insert({:a => 2}, {:w =>
|
31
|
+
assert @client['foo']['stuff'].insert({:a => 2}, {:w => 2})
|
32
32
|
|
33
33
|
# So should a query
|
34
34
|
assert @client['foo']['stuff'].find_one
|
data/test/bson/bson_test.rb
CHANGED
@@ -349,7 +349,7 @@ class BSONTest < Test::Unit::TestCase
|
|
349
349
|
doc2 = @encoder.deserialize(bson)
|
350
350
|
|
351
351
|
# Java doesn't deserialize to DBRefs
|
352
|
-
if RUBY_PLATFORM =~ /java/
|
352
|
+
if RUBY_PLATFORM =~ /java/ && BSON.extension?
|
353
353
|
assert_equal 'namespace', doc2['dbref']['$ns']
|
354
354
|
assert_equal oid, doc2['dbref']['$id']
|
355
355
|
else
|
@@ -45,10 +45,6 @@ class ByteBufferTest < Test::Unit::TestCase
|
|
45
45
|
assert_equal 4, @buf.length
|
46
46
|
end
|
47
47
|
|
48
|
-
def test_default_order
|
49
|
-
assert_equal :little_endian, @buf.order
|
50
|
-
end
|
51
|
-
|
52
48
|
def test_long_length
|
53
49
|
@buf.put_long 1027
|
54
50
|
assert_equal 8, @buf.length
|
@@ -66,29 +62,31 @@ class ByteBufferTest < Test::Unit::TestCase
|
|
66
62
|
assert_equal 41.2, @buf.get_double
|
67
63
|
end
|
68
64
|
|
69
|
-
if
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def test_serialize_cstr_validates_data_as_utf8
|
78
|
-
assert_raises(Encoding::UndefinedConversionError) do
|
79
|
-
ByteBuffer.serialize_cstr(@buf, "hello \xFF")
|
65
|
+
if BSON_CODER == BSON::BSON_RUBY
|
66
|
+
if defined?(Encoding)
|
67
|
+
def test_serialize_cstr_throws_error_for_bad_utf8
|
68
|
+
bad = "hello \xC8".force_encoding("ISO-8859-7")
|
69
|
+
assert_raises(BSON::InvalidStringEncoding) do
|
70
|
+
BSON_CODER::serialize_cstr(@buf, bad)
|
71
|
+
end
|
80
72
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
73
|
+
|
74
|
+
def test_serialize_cstr_does_not_validate_data_as_utf8
|
75
|
+
assert_raises(BSON::InvalidStringEncoding) do
|
76
|
+
BSON_CODER::serialize_cstr(@buf, "hello \xFF")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
else
|
80
|
+
def test_serialize_cstr_forces_encoding_to_utf8
|
81
|
+
# Unicode snowman (\u2603)
|
82
|
+
BSON_CODER::serialize_cstr(@buf, "hello \342\230\203")
|
83
|
+
assert_equal "hello \342\230\203\0", @buf.to_s
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_serialize_cstr_validates_data_as_utf8
|
87
|
+
assert_raises(BSON::InvalidStringEncoding) do
|
88
|
+
BSON_CODER::serialize_cstr(@buf, "hello \xFF")
|
89
|
+
end
|
92
90
|
end
|
93
91
|
end
|
94
92
|
end
|
@@ -1,6 +1,16 @@
|
|
1
1
|
# encoding:utf-8
|
2
2
|
require 'test_helper'
|
3
|
-
|
3
|
+
|
4
|
+
# Note: HashWithIndifferentAccess is so commonly used
|
5
|
+
# that we always need to make sure that the driver works
|
6
|
+
# with it. However, the bson gem should never need to
|
7
|
+
# depend on it.
|
8
|
+
|
9
|
+
# As a result, ActiveSupport is no longer a gem dependency and it should remain
|
10
|
+
# that way. It must be required by the application code or
|
11
|
+
# via bundler for developmet.
|
12
|
+
|
13
|
+
require 'bson/support/hash_with_indifferent_access'
|
4
14
|
|
5
15
|
class HashWithIndifferentAccessTest < Test::Unit::TestCase
|
6
16
|
include BSON
|
@@ -231,8 +231,8 @@ class TestCollection < Test::Unit::TestCase
|
|
231
231
|
docs << {:bar => 1}
|
232
232
|
invalid_docs = []
|
233
233
|
invalid_docs << {"\223\372\226}" => 1} # non utf8 encoding
|
234
|
-
docs += invalid_docs
|
235
|
-
|
234
|
+
docs += invalid_docs
|
235
|
+
|
236
236
|
assert_raise BSON::InvalidStringEncoding do
|
237
237
|
@@test.insert(docs, :collect_on_error => false)
|
238
238
|
end
|
@@ -295,7 +295,7 @@ class TestCollection < Test::Unit::TestCase
|
|
295
295
|
@@test.update({"x" => 1}, {"$set" => {"a.b" => 2}})
|
296
296
|
assert_equal 2, @@test.find_one("x" => 1)["a"]["b"]
|
297
297
|
|
298
|
-
assert_raise_error BSON::InvalidKeyName
|
298
|
+
assert_raise_error BSON::InvalidKeyName do
|
299
299
|
@@test.update({"x" => 1}, {"a.b" => 3})
|
300
300
|
end
|
301
301
|
end
|
@@ -535,7 +535,7 @@ class TestCollection < Test::Unit::TestCase
|
|
535
535
|
end
|
536
536
|
assert c.closed?
|
537
537
|
end
|
538
|
-
|
538
|
+
|
539
539
|
def setup_aggregate_data
|
540
540
|
# save some data
|
541
541
|
@@test.save( {
|
@@ -551,7 +551,7 @@ class TestCollection < Test::Unit::TestCase
|
|
551
551
|
],
|
552
552
|
"other" => { "foo" => 5 }
|
553
553
|
} )
|
554
|
-
|
554
|
+
|
555
555
|
@@test.save( {
|
556
556
|
"_id" => 2,
|
557
557
|
"title" => "this is your title",
|
@@ -565,7 +565,7 @@ class TestCollection < Test::Unit::TestCase
|
|
565
565
|
],
|
566
566
|
"other" => { "bar" => 14 }
|
567
567
|
})
|
568
|
-
|
568
|
+
|
569
569
|
@@test.save( {
|
570
570
|
"_id" => 3,
|
571
571
|
"title" => "this is some other title",
|
@@ -579,9 +579,9 @@ class TestCollection < Test::Unit::TestCase
|
|
579
579
|
],
|
580
580
|
"other" => { "bar" => 14 }
|
581
581
|
})
|
582
|
-
|
582
|
+
|
583
583
|
end
|
584
|
-
|
584
|
+
|
585
585
|
if @@version > '2.1.1'
|
586
586
|
def test_reponds_to_aggregate
|
587
587
|
assert_respond_to @@test, :aggregate
|
@@ -629,7 +629,7 @@ class TestCollection < Test::Unit::TestCase
|
|
629
629
|
assert_equal 1, results.length
|
630
630
|
end
|
631
631
|
|
632
|
-
def test_aggregate_pipeline_unwind
|
632
|
+
def test_aggregate_pipeline_unwind
|
633
633
|
setup_aggregate_data
|
634
634
|
desired_results = [ {"_id"=>1, "title"=>"this is my title", "author"=>"bob", "posted"=>Time.utc(2000),
|
635
635
|
"pageViews"=>5, "tags"=>"fun", "comments"=>[{"author"=>"joe", "text"=>"this is cool"},
|
@@ -742,11 +742,11 @@ class TestCollection < Test::Unit::TestCase
|
|
742
742
|
@@test.map_reduce(m, r, :raw => true, :out => {:inline => 1})
|
743
743
|
assert res["results"]
|
744
744
|
end
|
745
|
-
|
745
|
+
|
746
746
|
def test_map_reduce_with_collection_output_to_other_db
|
747
747
|
@@test << {:user_id => 1}
|
748
748
|
@@test << {:user_id => 2}
|
749
|
-
|
749
|
+
|
750
750
|
m = Code.new("function() { emit(this.user_id, 1); }")
|
751
751
|
r = Code.new("function(k,vals) { return 1; }")
|
752
752
|
oh = BSON::OrderedHash.new
|
@@ -866,7 +866,7 @@ class TestCollection < Test::Unit::TestCase
|
|
866
866
|
cursor = @@test.find({}, :transformer => transformer)
|
867
867
|
assert_equal(transformer, cursor.transformer)
|
868
868
|
end
|
869
|
-
|
869
|
+
|
870
870
|
def test_find_one_with_transformer
|
871
871
|
klass = Struct.new(:id, :a)
|
872
872
|
transformer = Proc.new { |doc| klass.new(doc['_id'], doc['a']) }
|
@@ -1048,7 +1048,7 @@ class TestCollection < Test::Unit::TestCase
|
|
1048
1048
|
assert_equal 1, @collection.size
|
1049
1049
|
end
|
1050
1050
|
end
|
1051
|
-
|
1051
|
+
|
1052
1052
|
context "Drop index " do
|
1053
1053
|
setup do
|
1054
1054
|
@@db.drop_collection('test-collection')
|
@@ -1061,21 +1061,21 @@ class TestCollection < Test::Unit::TestCase
|
|
1061
1061
|
@collection.drop_index([['a', Mongo::ASCENDING]])
|
1062
1062
|
assert_nil @collection.index_information['a_1']
|
1063
1063
|
end
|
1064
|
-
|
1064
|
+
|
1065
1065
|
should "drop an index which was given a specific name" do
|
1066
1066
|
@collection.create_index([['a', Mongo::DESCENDING]], {:name => 'i_will_not_fear'})
|
1067
1067
|
assert @collection.index_information['i_will_not_fear']
|
1068
1068
|
@collection.drop_index([['a', Mongo::DESCENDING]])
|
1069
1069
|
assert_nil @collection.index_information['i_will_not_fear']
|
1070
1070
|
end
|
1071
|
-
|
1071
|
+
|
1072
1072
|
should "drops an composite index" do
|
1073
1073
|
@collection.create_index([['a', Mongo::DESCENDING], ['b', Mongo::ASCENDING]])
|
1074
1074
|
assert @collection.index_information['a_-1_b_1']
|
1075
1075
|
@collection.drop_index([['a', Mongo::DESCENDING], ['b', Mongo::ASCENDING]])
|
1076
1076
|
assert_nil @collection.index_information['a_-1_b_1']
|
1077
1077
|
end
|
1078
|
-
|
1078
|
+
|
1079
1079
|
should "drops an index with symbols" do
|
1080
1080
|
@collection.create_index([['a', Mongo::DESCENDING], [:b, Mongo::ASCENDING]])
|
1081
1081
|
assert @collection.index_information['a_-1_b_1']
|