Merge branch 'master' of github.com:mongodb/mongo-ruby-driver

This commit is contained in:
Mike Dirolf 2009-12-17 09:47:29 -05:00
commit f9fb823c53
29 changed files with 193 additions and 200 deletions

View File

@ -47,11 +47,13 @@ Les Hill, leshill on github
* OrderedHash#each returns self
Sean Cribbs, seancribbs on github
* Modify standard_benchmark to allow profiling
* Modified standard_benchmark to allow profiling
* c ext for faster ObjectID creation
Sunny Hirai
* Suggested hashcode fix for Mongo::ObjectID
* Noted index ordering bug.
* GridFS performance boost
Christos Trochalakis
* Added map/reduce helper

View File

@ -8,7 +8,7 @@
0.18 2009-11-25
* Connections now support connection pooling. See http://api.mongodb.org/ruby/0.18/classes/Mongo/Connection.html#M000158
* Deprecated :auto_reconnect option on connection; if the driver fails to
connect, it will automatically try to reconnect on the subsequent operation.
connect, it will automatically try to reconnect on the subsequent operation.
See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
* Added Collection#map_reduce helper (Christos Trochalakis)
* Deprecated DB#db_command in favor of DB#command.

View File

@ -13,7 +13,7 @@ Here is a quick code sample. See the MongoDB Ruby Tutorial
@coll = db.collection('test')
@coll.remove
3.times do |i|
3.times do |i|
@coll.insert({'a' => i+1})
end
puts "There are #{@coll.count()} records. Here they are:"
@ -254,7 +254,7 @@ Random cursor fun facts:
= Testing
If you have the source code, you can run the tests. There's a separate rake task for testing with
If you have the source code, you can run the tests. There's a separate rake task for testing with
the mongo_ext c extension enabled.
$ rake test:c

View File

@ -1,26 +0,0 @@
$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
require 'mongo'
db = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil, :auto_reconnect => true).db("ruby_test")
db['test'].clear
10.times do |i|
db['test'].save("x" => i)
end
while true do
begin
exit() if not db['test'].count() == 10
x = 0
db['test'].find().each do |doc|
x += doc['x']
end
exit() if not x == 45
print "."
STDOUT.flush
sleep 1
rescue
sleep 1
end
end

View File

@ -2,7 +2,7 @@
require 'rubygems'
require 'mongo'
require 'mongo/gridfs'
require 'benchmark'
#require 'ruby-prof'
include Mongo
include GridFS
@ -15,10 +15,15 @@ length = sample_data.length
mb = length / 1048576.0
t1 = Time.now
#RubyProf.start
GridStore.open(db, 'mongodb.pdf', 'w') do |f|
f.write(sample_data)
end
#result = RubyProf.stop
puts "Write: #{mb / (Time.now - t1)} mb/s"
#printer = RubyProf::FlatPrinter.new(result)
#printer.print(STDOUT, 0)
t1 = Time.now
GridStore.open(db, 'mongodb.pdf', 'r') do |f|

View File

@ -33,14 +33,14 @@ array = cursor.to_a
cursor.each { |row| pp row }
# You can get the next object
first_object = coll.find().next_object
first_object = coll.find().next_document
# next_object returns nil if there are no more objects that match
# next_document returns nil if there are no more objects that match
cursor = coll.find()
obj = cursor.next_object
obj = cursor.next_document
while obj
pp obj
obj = cursor.next_object
obj = cursor.next_document
end
# Destroy the collection

View File

@ -30,6 +30,6 @@ coll.insert('array' => [1, 2, 3],
'null' => nil,
'symbol' => :zildjian)
pp coll.find().next_object
pp coll.find().next_document
coll.clear

View File

@ -459,6 +459,7 @@ static void write_doc(buffer_t buffer, VALUE hash, VALUE check_keys) {
// make sure that length doesn't exceed 4MB
if (length > 4 * 1024 * 1024) {
buffer_free(buffer);
rb_raise(InvalidDocument, "Document too large: BSON documents are limited to 4MB.");
return;
}

View File

@ -21,7 +21,7 @@ begin
warn " You can install the extension as follows:\n gem install mongo_ext\n"
warn " If you continue to receive this message after installing, make sure that the"
warn " mongo_ext gem is in your load path and that the mongo_ext and mongo gems are of the same version.\n"
end
end
require 'mongo/types/binary'
require 'mongo/types/code'

View File

@ -59,8 +59,7 @@ module Mongo
raise "Error with profile command: #{doc.inspect}" unless @db.ok?(doc)
end
# Return an array contining current profiling information from the
# database.
# Returns an array containing current profiling information.
def profiling_info
Cursor.new(Collection.new(@db, DB::SYSTEM_PROFILE_COLLECTION), :selector => {}).to_a
end

View File

@ -158,7 +158,7 @@ module Mongo
else
raise TypeError, "spec_or_object_id must be an instance of ObjectID or Hash, or nil"
end
find(spec, options.merge(:limit => -1)).next_object
find(spec, options.merge(:limit => -1)).next_document
end
# Save a document in this collection.
@ -497,7 +497,7 @@ EOS
# 'create' will be the collection name. For the other possible keys
# and values, see DB#create_collection.
def options
@db.collections_info(@name).next_object()['options']
@db.collections_info(@name).next_document['options']
end
# Get the number of documents in this collection.
@ -526,7 +526,7 @@ EOS
private
# Sends an Mongo::Constants::OP_INSERT message to the database.
# Sends a Mongo::Constants::OP_INSERT message to the database.
# Takes an array of +documents+, an optional +collection_name+, and a
# +check_keys+ setting.
def insert_documents(documents, collection_name=@name, check_keys=true, safe=false)

View File

@ -33,10 +33,10 @@ module Mongo
attr_reader :logger, :size, :host, :port, :nodes, :sockets, :checked_out, :reserved_connections
def slave_ok?
def slave_ok?
@slave_ok
end
# Counter for generating unique request ids.
@@current_request_id = 0
@ -45,7 +45,7 @@ module Mongo
#
# == Connecting
# If connecting to just one server, you may specify whether connection to slave is permitted.
#
#
# In all cases, the default host is "localhost" and the default port, is 27017.
#
# When specifying a pair, pair_or_host, is a hash with two keys: :left and :right. Each key maps to either
@ -69,13 +69,13 @@ module Mongo
# :timeout :: When all of the connections to the pool are checked out,
# this is the number of seconds to wait for a new connection
# to be released before throwing an exception.
#
#
#
# === Examples:
#
# # localhost, 27017
# Connection.new
#
#
# # localhost, 27017
# Connection.new("localhost")
#
@ -85,9 +85,9 @@ module Mongo
# # localhost, 3000, where this node may be a slave
# Connection.new("localhost", 3000, :slave_ok => true)
#
# # A pair of servers. The driver will always talk to master.
# # A pair of servers. The driver will always talk to master.
# # On connection errors, Mongo::ConnectionFailure will be raised.
# # See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
# # See http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby
# Connection.new({:left => ["db1.example.com", 27017],
# :right => ["db2.example.com", 27017]})
#
@ -100,7 +100,7 @@ module Mongo
# Host and port of current master.
@host = @port = nil
# Lock for request ids.
@id_lock = Mutex.new
@ -123,7 +123,7 @@ module Mongo
if options[:auto_reconnect]
warn(":auto_reconnect is deprecated. see http://www.mongodb.org/display/DOCS/Replica+Pairs+in+Ruby")
end
# Slave ok can be true only if one node is specified
@slave_ok = options[:slave_ok] && @nodes.length == 1
@logger = options[:logger] || nil
@ -177,7 +177,7 @@ module Mongo
# Increments and returns the next available request id.
def get_request_id
request_id = ''
@id_lock.synchronize do
@id_lock.synchronize do
request_id = @@current_request_id += 1
end
request_id
@ -196,7 +196,7 @@ module Mongo
## Connections and pooling ##
# Sends a message to MongoDB.
#
# Takes a MongoDB opcode, +operation+, a message of class ByteBuffer,
@ -234,7 +234,7 @@ module Mongo
# Sends a message to the database and waits for the response.
#
# Takes a MongoDB opcode, +operation+, a message of class ByteBuffer,
# +message+, and an optional formatted +log_message+. This method
# +message+, and an optional formatted +log_message+. This method
# also takes an options socket for internal use with #connect_to_master.
def receive_message(operation, message, log_message=nil, socket=nil)
packed_message = add_message_headers(operation, message).to_s
@ -275,7 +275,7 @@ module Mongo
socket.close if socket
false
end
end
end
raise ConnectionFailure, "failed to connect to any given host:port" unless socket
end
@ -291,7 +291,7 @@ module Mongo
sock.close
end
@host = @port = nil
@sockets.clear
@sockets.clear
@checked_out.clear
@reserved_connections.clear
end
@ -312,7 +312,7 @@ module Mongo
# Return a socket to the pool.
def checkin(socket)
@connection_mutex.synchronize do
@connection_mutex.synchronize do
@reserved_connections.delete Thread.current.object_id
@checked_out.delete(socket)
@queue.signal
@ -328,7 +328,7 @@ module Mongo
Thread.list.each do |thread|
keys.delete(thread.object_id) if thread.alive?
end
keys.each do |key|
next unless @reserved_connections.has_key?(key)
checkin(@reserved_connections[key])
@ -366,10 +366,10 @@ module Mongo
# pool size has not been exceeded. Otherwise, wait for the next
# available socket.
def obtain_socket
@connection_mutex.synchronize do
@connection_mutex.synchronize do
connect_to_master if !connected?
loop do
loop do
socket = if @checked_out.size < @sockets.size
checkout_existing_socket
elsif @sockets.size < @size
@ -401,9 +401,9 @@ module Mongo
if RUBY_VERSION >= '1.9'
# Ruby 1.9's Condition Variables don't support timeouts yet;
# until they do, we'll make do with this hack.
# until they do, we'll make do with this hack.
def wait
Timeout.timeout(@timeout) do
Timeout.timeout(@timeout) do
@queue.wait
end
end
@ -424,7 +424,7 @@ module Mongo
header.put_array(receive_message_on_socket(16, sock).unpack("C*"))
unless header.size == STANDARD_HEADER_SIZE
raise "Short read for DB response header: " +
"expected #{STANDARD_HEADER_SIZE} bytes, saw #{header.size}"
"expected #{STANDARD_HEADER_SIZE} bytes, saw #{header.size}"
end
header.rewind
size = header.get_int
@ -473,7 +473,7 @@ module Mongo
message.put_array(BSON.serialize({:getlasterror => 1}, false).unpack("C*"))
add_message_headers(Mongo::Constants::OP_QUERY, message)
end
# Prepares a message for transmission to MongoDB by
# constructing a valid message header.
def add_message_headers(operation, message)
@ -494,7 +494,7 @@ module Mongo
end
# Low-level method for sending a message on a socket.
# Requires a packed message and an available socket,
# Requires a packed message and an available socket,
def send_message_on_socket(packed_message, socket)
begin
socket.send(packed_message, 0)
@ -537,7 +537,7 @@ module Mongo
[['localhost', DEFAULT_PORT]]
end
end
# Turns an array containing a host name string and a
# port number integer into a [host, port] pair array.
def pair_val_to_connection(a)

View File

@ -1,8 +1,8 @@
module Mongo
module Constants
OP_REPLY = 1
OP_MSG = 1000
OP_UPDATE = 2001
OP_REPLY = 1
OP_MSG = 1000
OP_UPDATE = 2001
OP_INSERT = 2002
OP_QUERY = 2004
OP_GET_MORE = 2005

View File

@ -19,7 +19,7 @@ module Mongo
include Mongo::Conversions
include Enumerable
attr_reader :collection, :selector, :admin, :fields,
attr_reader :collection, :selector, :admin, :fields,
:order, :hint, :snapshot, :timeout,
:full_collection_name
@ -49,19 +49,17 @@ module Mongo
@query_run = false
end
# Return the next object or nil if there are no more. Raises an error
# if necessary.
def next_object
# Return the next document or nil if there are no more.
def next_document
refill_via_get_more if num_remaining == 0
o = @cache.shift
doc = @cache.shift
if o && o['$err']
err = o['$err']
if doc && doc['$err']
err = doc['$err']
# If the server has stopped being the master (e.g., it's one of a
# pair but it has died or something like that) then we close that
# connection. If the db has auto connect option and a pair of
# servers, next request will re-open on master server.
# connection. The next request will re-open on master server.
if err == "not master"
raise ConnectionFailure, err
@connection.close
@ -70,12 +68,17 @@ module Mongo
raise OperationFailure, err
end
o
doc
end
# Get the size of the results set for this query.
def next_object
warn "Cursor#next_object is deprecated; please use Cursor#next_document instead."
next_document
end
# Get the size of the result set for this query.
#
# Returns the number of objects in the results set for this query. Does
# Returns the number of objects in the result set for this query. Does
# not take limit and skip into account. Raises OperationFailure on a
# database error.
def count
@ -88,17 +91,17 @@ module Mongo
raise OperationFailure, "Count failed: #{response['errmsg']}"
end
# Sort this cursor's result
# Sort this cursor's results.
#
# Takes either a single key and a direction, or an array of [key,
# direction] pairs. Directions should be specified as Mongo::ASCENDING
# or Mongo::DESCENDING (or :ascending or :descending) (or :asc or :desc).
# direction] pairs. Directions should be specified as Mongo::ASCENDING / Mongo::DESCENDING
# (or :ascending / :descending, :asc / :desc).
#
# Raises InvalidOperation if this cursor has already been used. Raises
# InvalidSortValueError if specified order is invalid.
# InvalidSortValueError if the specified order is invalid.
#
# This method overrides any sort order specified in the Collection#find
# method, and only the last sort applied has an effect
# method, and only the last sort applied has an effect.
def sort(key_or_list, direction=nil)
check_modifiable
@ -130,7 +133,7 @@ module Mongo
# Skips the first +number_to_skip+ results of this cursor.
# Returns the current number_to_skip if no parameter is given.
#
#
# Raises InvalidOperation if this cursor has already been used.
#
# This method overrides any skip specified in the Collection#find method,
@ -151,15 +154,15 @@ module Mongo
def each
num_returned = 0
while more? && (@limit <= 0 || num_returned < @limit)
yield next_object()
yield next_document
num_returned += 1
end
end
# Return all of the documents in this cursor as an array of hashes.
#
# Raises InvalidOperation if this cursor has already been used (including
# any previous calls to this method).
# Raises InvalidOperation if this cursor has already been used or if
# this methods has already been called on the cursor.
#
# Use of this method is discouraged - iterating over a cursor is much
# more efficient in most cases.
@ -168,22 +171,22 @@ module Mongo
rows = []
num_returned = 0
while more? && (@limit <= 0 || num_returned < @limit)
rows << next_object()
rows << next_document
num_returned += 1
end
rows
end
# Returns an explain plan record for this cursor.
# Returns an explain plan document for this cursor.
def explain
c = Cursor.new(@collection, query_options_hash.merge(:limit => -@limit.abs, :explain => true))
explanation = c.next_object
explanation = c.next_document
c.close
explanation
end
# Close the cursor.
# Closes the cursor.
#
# Note: if a cursor is read until exhausted (read until Mongo::Constants::OP_QUERY or
# Mongo::Constants::OP_GETMORE returns zero for the cursor id), there is no need to
@ -211,20 +214,20 @@ module Mongo
# See http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol#MongoWireProtocol-Mongo::Constants::OPQUERY
def query_opts
timeout = @timeout ? 0 : Mongo::Constants::OP_QUERY_NO_CURSOR_TIMEOUT
slave_ok = @connection.slave_ok? ? Mongo::Constants::OP_QUERY_SLAVE_OK : 0
slave_ok = @connection.slave_ok? ? Mongo::Constants::OP_QUERY_SLAVE_OK : 0
slave_ok + timeout
end
# Returns the query options set on this Cursor.
# Returns the query options for this Cursor.
def query_options_hash
{ :selector => @selector,
:fields => @fields,
:admin => @admin,
:skip => @skip_num,
:limit => @limit_num,
:order => @order,
:hint => @hint,
:snapshot => @snapshot,
:fields => @fields,
:admin => @admin,
:skip => @skip_num,
:limit => @limit_num,
:order => @order,
:hint => @hint,
:snapshot => @snapshot,
:timeout => @timeout }
end
@ -245,7 +248,7 @@ module Mongo
end
end
# Set query selector hash. If the selector is a Code or String object,
# Set the query selector hash. If the selector is a Code or String object,
# the selector will be used in a $where clause.
# See http://www.mongodb.org/display/DOCS/Server-side+Code+Execution
def convert_selector_for_query(selector)
@ -266,20 +269,21 @@ module Mongo
@order || @explain || @hint || @snapshot
end
# Return a number of documents remaining for this cursor.
def num_remaining
refill_via_get_more if @cache.length == 0
@cache.length
end
# Internal method, not for general use. Return +true+ if there are
# more records to retrieve. This methods does not check @limit;
# #each is responsible for doing that.
# more records to retrieve. This method does not check @limit;
# Cursor#each is responsible for doing that.
def more?
num_remaining > 0
end
def refill_via_get_more
return if send_query_if_needed || @cursor_id.zero?
return if send_initial_query || @cursor_id.zero?
message = ByteBuffer.new
# Reserved.
message.put_int(0)
@ -290,7 +294,7 @@ module Mongo
# Number of results to return; db decides for now.
message.put_int(0)
# Cursor id.
message.put_long(@cursor_id)
results, @n_received, @cursor_id = @connection.receive_message(Mongo::Constants::OP_GET_MORE, message, "cursor.get_more()", @socket)
@ -299,13 +303,13 @@ module Mongo
end
# Run query the first time we request an object from the wire
def send_query_if_needed
def send_initial_query
if @query_run
false
else
message = construct_query_message
results, @n_received, @cursor_id = @connection.receive_message(Mongo::Constants::OP_QUERY, message,
(query_log_message if @connection.logger), @socket)
results, @n_received, @cursor_id = @connection.receive_message(Mongo::Constants::OP_QUERY, message,
(query_log_message if @connection.logger), @socket)
@cache += results
@query_run = true
close_cursor_if_query_complete
@ -331,7 +335,7 @@ module Mongo
def query_log_message
"#{@admin ? 'admin' : @db.name}.#{@collection.name}.find(#{@selector.inspect}, #{@fields ? @fields.inspect : '{}'})" +
"#{@skip != 0 ? ('.skip(' + @skip.to_s + ')') : ''}#{@limit != 0 ? ('.limit(' + @limit.to_s + ')') : ''}"
"#{@skip != 0 ? ('.skip(' + @skip.to_s + ')') : ''}#{@limit != 0 ? ('.limit(' + @limit.to_s + ')') : ''}"
end
def selector_with_special_query_fields
@ -349,7 +353,7 @@ module Mongo
when String, Symbol then string_as_sort_parameters(@order)
when Array then array_as_sort_parameters(@order)
else
raise InvalidSortValueError, "Illegal sort clause, '#{@order.class.name}'; must be of the form " +
raise InvalidSortValueError, "Illegal sort clause, '#{@order.class.name}'; must be of the form " +
"[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]"
end
end

View File

@ -48,7 +48,7 @@ module Mongo
# The Mongo::Connection instance connecting to the MongoDB server.
attr_reader :connection
# An array of [host, port] pairs.
attr_reader :nodes
@ -316,7 +316,7 @@ module Mongo
def create_index(collection_name, field_or_spec, unique=false)
self.collection(collection_name).create_index(field_or_spec, unique)
end
# Return +true+ if +doc+ contains an 'ok' field with the value 1.
def ok?(doc)
ok = doc['ok']
@ -334,9 +334,9 @@ module Mongo
end
cursor = Cursor.new(Collection.new(self, SYSTEM_COMMAND_COLLECTION), :admin => use_admin_db, :limit => -1, :selector => selector, :socket => sock)
cursor.next_object
cursor.next_document
end
# Sends a command to the database.
#
# :selector (required) :: An OrderedHash, or a standard Hash with just one
@ -352,12 +352,12 @@ module Mongo
# any selector containing more than one key must be an OrderedHash.
def command(selector, admin=false, check_response=false, sock=nil)
raise MongoArgumentError, "command must be given a selector" unless selector.is_a?(Hash) && !selector.empty?
if selector.class.eql?(Hash) && selector.keys.length > 1
if selector.class.eql?(Hash) && selector.keys.length > 1
raise MongoArgumentError, "DB#command requires an OrderedHash when hash contains multiple keys"
end
result = Cursor.new(system_command_collection, :admin => admin,
:limit => -1, :selector => selector, :socket => sock).next_object
result = Cursor.new(system_command_collection, :admin => admin,
:limit => -1, :selector => selector, :socket => sock).next_document
if check_response && !ok?(result)
raise OperationFailure, "Database command '#{selector.keys.first}' failed."

View File

@ -73,7 +73,7 @@ module GridFS
class << self
def exist?(db, name, root_collection=DEFAULT_ROOT_COLLECTION)
db.collection("#{root_collection}.files").find({'filename' => name}).next_object != nil
db.collection("#{root_collection}.files").find({'filename' => name}).next_document != nil
end
def open(db, name, mode, options={})
@ -94,12 +94,12 @@ module GridFS
}
end
# List the contains of all GridFS files stored in the given db and
# List the contents of all GridFS files stored in the given db and
# root collection.
#
# :db :: the database to use
#
# :root_collection :: the root collection to use
# :root_collection :: the root collection to use. If not specified, will use default root collection.
def list(db, root_collection=DEFAULT_ROOT_COLLECTION)
db.collection("#{root_collection}.files").find().map { |f|
f['filename']
@ -148,7 +148,7 @@ module GridFS
@db, @filename, @mode = db, name, mode
@root = options[:root] || DEFAULT_ROOT_COLLECTION
doc = collection.find({'filename' => @filename}).next_object
doc = collection.find({'filename' => @filename}).next_document
if doc
@files_id = doc['_id']
@content_type = doc['contentType']
@ -495,7 +495,7 @@ module GridFS
end
def nth_chunk(n)
mongo_chunk = chunk_collection.find({'files_id' => @files_id, 'n' => n}).next_object
mongo_chunk = chunk_collection.find({'files_id' => @files_id, 'n' => n}).next_document
Chunk.new(self, mongo_chunk || {})
end

View File

@ -18,6 +18,7 @@ module Mongo
# JavaScript code to be evaluated by MongoDB
class Code < String
# Hash mapping identifiers to their values
attr_accessor :scope

View File

@ -25,7 +25,7 @@ module Mongo
# Implements comparable.
def <=>(new)
local, new = self.to_a, to_array(new)
for n in 0...local.size do
for n in 0...local.size do
break if elements_include_mods?(local[n], new[n])
if local[n] < new[n].to_i
result = -1
@ -52,10 +52,10 @@ module Mongo
# Returns true if any elements include mod symbols (-, +)
def elements_include_mods?(*elements)
elements.any? { |n| n =~ /[\-\+]/ }
elements.any? { |n| n =~ /[\-\+]/ }
end
# Converts argument to an array of integers,
# Converts argument to an array of integers,
# appending any mods as the final element.
def to_array(version)
array = version.split(".").map {|n| (n =~ /^\d+$/) ? n.to_i : n }

View File

@ -1,5 +1,5 @@
require 'lib/mongo'
VERSION_HEADER = File.open(File.join(File.dirname(__FILE__), 'ext', 'cbson', 'version.h'), "r")
VERSION_HEADER = File.open(File.join(File.dirname(__FILE__), 'ext', 'cbson', 'version.h'), "r")
VERSION = VERSION_HEADER.read.scan(/VERSION\s+"(\d+\.\d+(\.\d+)?)\"/)[0][0]
Gem::Specification.new do |s|
s.name = 'mongo_ext'

View File

@ -6,8 +6,8 @@ require 'test/test_helper'
# NOTE: this test should be run only if a replica pair is running.
class ReplicaPairCountTest < Test::Unit::TestCase
include Mongo
def setup
def setup
@conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
@db = @conn.db('mongo-ruby-test')
@db.drop_collection("test-pairs")
@ -24,7 +24,7 @@ class ReplicaPairCountTest < Test::Unit::TestCase
puts "Please disconnect the current master."
gets
rescue_connection_failure do
rescue_connection_failure do
@coll.insert({:a => 30}, :safe => true)
end
@coll.insert({:a => 40}, :safe => true)

View File

@ -6,8 +6,8 @@ require 'test/test_helper'
# NOTE: this test should be run only if a replica pair is running.
class ReplicaPairInsertTest < Test::Unit::TestCase
include Mongo
def setup
def setup
@conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
@db = @conn.db('mongo-ruby-test')
@db.drop_collection("test-pairs")
@ -19,7 +19,7 @@ class ReplicaPairInsertTest < Test::Unit::TestCase
puts "Please disconnect the current master."
gets
rescue_connection_failure do
rescue_connection_failure do
@coll.save({:a => 30}, :safe => true)
end
@ -28,12 +28,12 @@ class ReplicaPairInsertTest < Test::Unit::TestCase
@coll.save({:a => 60}, :safe => true)
@coll.save({:a => 70}, :safe => true)
puts "Please reconnect the old master to make sure that the new master " +
puts "Please reconnect the old master to make sure that the new master " +
"has synced with the previous master. Note: this may have happened already."
gets
results = []
rescue_connection_failure do
rescue_connection_failure do
@coll.find.each {|r| results << r}
[20, 30, 40, 50, 60, 70].each do |a|
assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"

View File

@ -6,8 +6,8 @@ require 'test/test_helper'
# NOTE: this test should be run only if a replica pair is running.
class ReplicaPairPooledInsertTest < Test::Unit::TestCase
include Mongo
def setup
def setup
@conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil, :pool_size => 10, :timeout => 5)
@db = @conn.db('mongo-ruby-test')
@db.drop_collection("test-pairs")
@ -22,22 +22,22 @@ class ReplicaPairPooledInsertTest < Test::Unit::TestCase
threads = []
10.times do |i|
threads[i] = Thread.new do
rescue_connection_failure do
threads[i] = Thread.new do
rescue_connection_failure do
@coll.save({:a => i}, :safe => true)
end
end
end
puts "Please reconnect the old master to make sure that the new master " +
"has synced with the previous master. Note: this may have happened already." +
puts "Please reconnect the old master to make sure that the new master " +
"has synced with the previous master. Note: this may have happened already." +
"Note also that when connection with multiple threads, you may need to wait a few seconds" +
"after restarting the old master so that all the data has had a chance to sync." +
"This is a case of eventual consistency."
gets
results = []
rescue_connection_failure do
rescue_connection_failure do
@coll.find.each {|r| results << r}
expected_results.each do |a|
assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"

View File

@ -6,8 +6,8 @@ require 'test/test_helper'
# NOTE: this test should be run only if a replica pair is running.
class ReplicaPairQueryTest < Test::Unit::TestCase
include Mongo
def setup
def setup
@conn = Mongo::Connection.new({:left => ["localhost", 27017], :right => ["localhost", 27018]}, nil)
@db = @conn.db('mongo-ruby-test')
@db.drop_collection("test-pairs")
@ -28,7 +28,7 @@ class ReplicaPairQueryTest < Test::Unit::TestCase
gets
results = []
rescue_connection_failure do
rescue_connection_failure do
@coll.find.each {|r| results << r}
[20, 30, 40].each do |a|
assert results.any? {|r| r['a'] == a}, "Could not find record for a => #{a}"

View File

@ -359,12 +359,12 @@ class TestCollection < Test::Unit::TestCase
@@test.save(:foo => i)
end
assert_equal 5, @@test.find({}, :skip => 5).next_object()["foo"]
assert_equal nil, @@test.find({}, :skip => 10).next_object()
assert_equal 5, @@test.find({}, :skip => 5).next_document()["foo"]
assert_equal nil, @@test.find({}, :skip => 10).next_document()
assert_equal 5, @@test.find({}, :limit => 5).to_a.length
assert_equal 3, @@test.find({}, :skip => 3, :limit => 5).next_object()["foo"]
assert_equal 3, @@test.find({}, :skip => 3, :limit => 5).next_document()["foo"]
assert_equal 5, @@test.find({}, :skip => 3, :limit => 5).to_a.length
end

View File

@ -54,8 +54,8 @@ class TestConnection < Test::Unit::TestCase
def test_copy_database
@mongo.db('old').collection('copy-test').insert('a' => 1)
@mongo.copy_database('old', 'new')
old_object = @mongo.db('old').collection('copy-test').find.next_object
new_object = @mongo.db('new').collection('copy-test').find.next_object
old_object = @mongo.db('old').collection('copy-test').find.next_document
new_object = @mongo.db('new').collection('copy-test').find.next_document
assert_equal old_object, new_object
end

View File

@ -58,33 +58,40 @@ class CursorTest < Test::Unit::TestCase
assert_equal 0, @@db['acollectionthatdoesn'].count()
end
def test_next_object_deprecation
@@coll.remove
@@coll.insert({"a" => 1})
assert_equal 1, @@coll.find().next_object["a"]
end
def test_sort
@@coll.remove
5.times{|x| @@coll.insert({"a" => x}) }
assert_kind_of Cursor, @@coll.find().sort(:a, 1)
assert_equal 0, @@coll.find().sort(:a, 1).next_object["a"]
assert_equal 4, @@coll.find().sort(:a, -1).next_object["a"]
assert_equal 0, @@coll.find().sort([["a", :asc]]).next_object["a"]
assert_equal 0, @@coll.find().sort(:a, 1).next_document["a"]
assert_equal 4, @@coll.find().sort(:a, -1).next_document["a"]
assert_equal 0, @@coll.find().sort([["a", :asc]]).next_document["a"]
assert_kind_of Cursor, @@coll.find().sort([[:a, -1], [:b, 1]])
assert_equal 4, @@coll.find().sort(:a, 1).sort(:a, -1).next_object["a"]
assert_equal 0, @@coll.find().sort(:a, -1).sort(:a, 1).next_object["a"]
assert_equal 4, @@coll.find().sort(:a, 1).sort(:a, -1).next_document["a"]
assert_equal 0, @@coll.find().sort(:a, -1).sort(:a, 1).next_document["a"]
cursor = @@coll.find()
cursor.next_object()
cursor.next_document
assert_raise InvalidOperation do
cursor.sort(["a"])
end
assert_raise InvalidSortValueError do
@@coll.find().sort(:a, 25).next_object
@@coll.find().sort(:a, 25).next_document
end
assert_raise InvalidSortValueError do
@@coll.find().sort(25).next_object
@@coll.find().sort(25).next_document
end
end
@ -106,7 +113,7 @@ class CursorTest < Test::Unit::TestCase
end
cursor = @@coll.find()
firstResult = cursor.next_object()
firstResult = cursor.next_document
assert_raise InvalidOperation, "Cannot modify the query once it has been run or closed." do
cursor.limit(1)
end
@ -140,7 +147,7 @@ class CursorTest < Test::Unit::TestCase
end
cursor = @@coll.find()
firstResult = cursor.next_object()
firstResult = cursor.next_document
assert_raise InvalidOperation, "Cannot modify the query once it has been run or closed." do
cursor.skip(1)
end
@ -233,7 +240,7 @@ class CursorTest < Test::Unit::TestCase
def test_close_after_query_sent
begin
cursor = @@coll.find('a' => 1)
cursor.next_object
cursor.next_document
cursor.close
assert cursor.closed?
rescue => ex
@ -267,7 +274,7 @@ class CursorTest < Test::Unit::TestCase
10.times do |i|
a = @@coll.find()
a.next_object()
a.next_document
a.close()
end
@ -277,7 +284,7 @@ class CursorTest < Test::Unit::TestCase
@@db.command("cursorInfo" => 1)["byLocation_size"])
a = @@coll.find()
a.next_object()
a.next_document
assert_not_equal(client_cursors,
@@db.command("cursorInfo" => 1)["clientCursors_size"])
@ -291,7 +298,7 @@ class CursorTest < Test::Unit::TestCase
assert_equal(by_location,
@@db.command("cursorInfo" => 1)["byLocation_size"])
a = @@coll.find({}, :limit => 10).next_object()
a = @@coll.find({}, :limit => 10).next_document
assert_equal(client_cursors,
@@db.command("cursorInfo" => 1)["clientCursors_size"])
@ -299,7 +306,7 @@ class CursorTest < Test::Unit::TestCase
@@db.command("cursorInfo" => 1)["byLocation_size"])
@@coll.find() do |cursor|
cursor.next_object()
cursor.next_document
end
assert_equal(client_cursors,
@ -308,7 +315,7 @@ class CursorTest < Test::Unit::TestCase
@@db.command("cursorInfo" => 1)["byLocation_size"])
@@coll.find() { |cursor|
cursor.next_object()
cursor.next_document
}
assert_equal(client_cursors,

View File

@ -2,26 +2,26 @@ require 'test/test_helper'
class ConnectionTest < Test::Unit::TestCase
context "Basic operations: " do
setup do
context "Basic operations: " do
setup do
@logger = mock()
end
should "send update message" do
should "send update message" do
@conn = Connection.new('localhost', 27017, :logger => @logger, :connect => false)
@db = @conn['testing']
@coll = @db.collection('books')
@conn.expects(:send_message).with do |op, msg, log|
@conn.expects(:send_message).with do |op, msg, log|
op == 2001 && log.include?("db.books.update")
end
@coll.update({}, {:title => 'Moby Dick'})
end
should "send insert message" do
should "send insert message" do
@conn = Connection.new('localhost', 27017, :logger => @logger, :connect => false)
@db = @conn['testing']
@coll = @db.collection('books')
@conn.expects(:send_message).with do |op, msg, log|
@conn.expects(:send_message).with do |op, msg, log|
op == 2002 && log.include?("db.books.insert")
end
@coll.insert({:title => 'Moby Dick'})
@ -49,4 +49,4 @@ class ConnectionTest < Test::Unit::TestCase
end
end

View File

@ -2,15 +2,15 @@ require 'test/test_helper'
class TestCursor < Test::Unit::TestCase
context "Cursor options" do
setup do
context "Cursor options" do
setup do
@connection = stub(:class => Connection)
@db = stub(:name => "testing", :slave_ok? => false, :connection => @connection)
@db = stub(:name => "testing", :slave_ok? => false, :connection => @connection)
@collection = stub(:db => @db, :name => "items")
@cursor = Cursor.new(@collection)
end
should "set admin to false" do
should "set admin to false" do
assert_equal false, @cursor.admin
@cursor = Cursor.new(@collection, :admin => true)
@ -60,35 +60,35 @@ class TestCursor < Test::Unit::TestCase
assert_equal "name", @cursor.hint
end
should "cache full collection name" do
should "cache full collection name" do
assert_equal "testing.items", @cursor.full_collection_name
end
end
context "Query fields" do
setup do
context "Query fields" do
setup do
@connection = stub(:class => Collection)
@db = stub(:slave_ok? => true, :name => "testing", :connection => @connection)
@collection = stub(:db => @db, :name => "items")
end
should "when an array should return a hash with each key" do
should "when an array should return a hash with each key" do
@cursor = Cursor.new(@collection, :fields => [:name, :age])
result = @cursor.fields
assert_equal result.keys.sort{|a,b| a.to_s <=> b.to_s}, [:age, :name].sort{|a,b| a.to_s <=> b.to_s}
assert result.values.all? {|v| v == 1}
end
should "when a string, return a hash with just the key" do
should "when a string, return a hash with just the key" do
@cursor = Cursor.new(@collection, :fields => "name")
result = @cursor.fields
result = @cursor.fields
assert_equal result.keys.sort, ["name"]
assert result.values.all? {|v| v == 1}
end
should "return nil when neither hash nor string nor symbol" do
should "return nil when neither hash nor string nor symbol" do
@cursor = Cursor.new(@collection, :fields => 1234567)
assert_nil @cursor.fields
assert_nil @cursor.fields
end
end
end

View File

@ -11,8 +11,8 @@ class DBTest < Test::Unit::TestCase
message = db.add_message_headers(Mongo::Constants::OP_INSERT, message)
end
context "DB commands" do
setup do
context "DB commands" do
setup do
@conn = stub()
@db = DB.new("testing", @conn)
@collection = mock()
@ -20,30 +20,30 @@ class DBTest < Test::Unit::TestCase
end
should "raise an error if given a hash with more than one key" do
assert_raise MongoArgumentError do
assert_raise MongoArgumentError do
@db.command(:buildinfo => 1, :somekey => 1)
end
end
should "raise an error if the selector is omitted" do
assert_raise MongoArgumentError do
should "raise an error if the selector is omitted" do
assert_raise MongoArgumentError do
@db.command({}, true)
end
end
should "create the proper cursor" do
@cursor = mock(:next_object => {"ok" => 1})
should "create the proper cursor" do
@cursor = mock(:next_document => {"ok" => 1})
Cursor.expects(:new).with(@collection, :admin => true,
:limit => -1, :selector => {:buildinfo => 1}, :socket => nil).returns(@cursor)
command = {:buildinfo => 1}
@db.command(command, true)
end
should "raise an error when the command fails" do
@cursor = mock(:next_object => {"ok" => 0})
should "raise an error when the command fails" do
@cursor = mock(:next_document => {"ok" => 0})
Cursor.expects(:new).with(@collection, :admin => true,
:limit => -1, :selector => {:buildinfo => 1}, :socket => nil).returns(@cursor)
assert_raise OperationFailure do
assert_raise OperationFailure do
command = {:buildinfo => 1}
@db.command(command, true, true)
end
@ -51,4 +51,4 @@ class DBTest < Test::Unit::TestCase
end
end