mongo 1.8.0 → 1.8.2
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.
- 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']
|