From 05b5fc576b3cfad714742a31a08c28eccaae0ddb Mon Sep 17 00:00:00 2001 From: Kyle Banker Date: Tue, 1 Dec 2009 13:49:57 -0500 Subject: [PATCH] Cleanup w/r/t loading c ext and testing it --- README.rdoc | 16 +- Rakefile | 25 +- lib/mongo.rb | 38 ++- lib/mongo/admin.rb | 2 - lib/mongo/connection.rb | 2 +- lib/mongo/cursor.rb | 3 - lib/mongo/db.rb | 3 - lib/mongo/gridfs/chunk.rb | 1 - lib/mongo/util/bson.rb | 563 ---------------------------------- lib/mongo/util/byte_buffer.rb | 19 ++ test/test_admin.rb | 4 +- test/test_bson.rb | 133 ++++---- test/test_byte_buffer.rb | 4 +- test/test_chunk.rb | 4 +- test/test_collection.rb | 17 +- test/test_connection.rb | 4 +- test/test_conversions.rb | 3 +- test/test_cursor.rb | 4 +- test/test_db.rb | 4 +- test/test_db_api.rb | 4 +- test/test_db_connection.rb | 4 +- test/test_grid_store.rb | 4 +- test/test_helper.rb | 7 +- test/test_objectid.rb | 4 +- test/test_ordered_hash.rb | 4 +- test/test_round_trip.rb | 3 +- test/test_slave_connection.rb | 4 +- 27 files changed, 159 insertions(+), 724 deletions(-) delete mode 100644 lib/mongo/util/bson.rb diff --git a/README.rdoc b/README.rdoc index cd24a03..3b7c267 100644 --- a/README.rdoc +++ b/README.rdoc @@ -254,16 +254,23 @@ Random cursor fun facts: = Testing -If you have the source code, you can run the tests. +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 + $ rake test:c -This will run both unit and functional tests. If you want to run these -individually: +Or, to test without the extension: + + $ rake test:ruby + +These will run both unit and functional tests. To run these tests alone: $ rake test:unit $ rake test:functional +To run any individual rake tasks with the C extenson enabled, just pass C_EXT=true to the task: + + $ rake test:unit C_EXT=true If you want to test replica pairs, you can run the following tests individually: @@ -276,6 +283,7 @@ It's also possible to test replica pairs with connection pooling: $ rake test:pooled_pair_insert +===Shoulda and Mocha All tests now require shoulda and mocha. You can install these gems as follows: diff --git a/Rakefile b/Rakefile index faf6f31..e526d7c 100644 --- a/Rakefile +++ b/Rakefile @@ -14,15 +14,32 @@ include Config gem_command = "gem" gem_command = "gem1.9" if $0.match(/1\.9$/) # use gem1.9 if we used rake1.9 -# NOTE: the functional tests assume MongoDB is running. desc "Test the MongoDB Ruby driver." task :test do - Rake::Task['test:unit'].invoke - Rake::Task['test:functional'].invoke - Rake::Task['test:pooled_threading'].invoke + puts "\nThis option has changed." + puts "\nTo test the driver with the c-extensions:\nrake test:c\n" + puts "To test the pure ruby driver: \nrake test:ruby" end namespace :test do + + desc "Test the driver with the c extension enabled." + task :c do + ENV['C_EXT'] = 'TRUE' + Rake::Task['test:unit'].invoke + Rake::Task['test:functional'].invoke + Rake::Task['test:pooled_threading'].invoke + ENV['C_EXT'] = nil + end + + desc "Test the driver using pure ruby (no c extension)" + task :ruby do + ENV['C_EXT'] = nil + Rake::Task['test:unit'].invoke + Rake::Task['test:functional'].invoke + Rake::Task['test:pooled_threading'].invoke + end + Rake::TestTask.new(:unit) do |t| t.test_files = FileList['test/unit/*_test.rb'] t.verbose = true diff --git a/lib/mongo.rb b/lib/mongo.rb index 898696a..6f3d702 100644 --- a/lib/mongo.rb +++ b/lib/mongo.rb @@ -1,5 +1,27 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +module Mongo + ASCENDING = 1 + DESCENDING = -1 + + VERSION = "0.18" +end + +begin + require 'mongo_ext/cbson' + require 'mongo/util/bson_c' + BSON = BSON_C + BSON_SERIALIZER = CBson + rescue LoadError + require 'mongo/util/bson_ruby' + BSON = BSON_RUBY + BSON_SERIALIZER = BSON + warn "\n**Notice: C extension not loaded. This is required for optimum MongoDB Ruby driver performance." + 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. This may mean requiring rubygems.\n" +end + require 'mongo/types/binary' require 'mongo/types/code' require 'mongo/types/dbref' @@ -17,19 +39,3 @@ require 'mongo/db' require 'mongo/cursor' require 'mongo/collection' require 'mongo/admin' - -begin - require 'mongo_ext/cbson' - BSON_SERIALIZER = CBson - rescue LoadError - BSON_SERIALIZER = BSON - warn "\n**Notice: C extension not detected. This is required for optimum MongoDB Ruby driver performance." - warn " You can install the extension as follows:\n gem install mongo_ext\n" -end - -module Mongo - ASCENDING = 1 - DESCENDING = -1 - - VERSION = "0.18" -end diff --git a/lib/mongo/admin.rb b/lib/mongo/admin.rb index 66e6f63..7f9fc01 100644 --- a/lib/mongo/admin.rb +++ b/lib/mongo/admin.rb @@ -14,8 +14,6 @@ # limitations under the License. # ++ -require 'mongo/util/ordered_hash' - module Mongo # Provide administrative database methods: those having to do with diff --git a/lib/mongo/connection.rb b/lib/mongo/connection.rb index 4ff11f1..17fbe6e 100644 --- a/lib/mongo/connection.rb +++ b/lib/mongo/connection.rb @@ -459,7 +459,7 @@ module Mongo buf.put_array(receive_message_on_socket(size - 4, sock).unpack("C*"), 4) number_remaining -= 1 buf.rewind - docs << BSON.new.deserialize(buf) + docs << BSON.deserialize(buf) end [docs, number_received, cursor_id] end diff --git a/lib/mongo/cursor.rb b/lib/mongo/cursor.rb index af75a34..bdf916a 100644 --- a/lib/mongo/cursor.rb +++ b/lib/mongo/cursor.rb @@ -12,9 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'mongo/util/byte_buffer' -require 'mongo/util/bson' - module Mongo # A cursor over query results. Returned objects are hashes. diff --git a/lib/mongo/db.rb b/lib/mongo/db.rb index aba526c..b5b3def 100644 --- a/lib/mongo/db.rb +++ b/lib/mongo/db.rb @@ -18,9 +18,6 @@ require 'socket' require 'timeout' require 'digest/md5' require 'thread' -require 'mongo/collection' -require 'mongo/util/ordered_hash.rb' -require 'mongo/admin' module Mongo diff --git a/lib/mongo/gridfs/chunk.rb b/lib/mongo/gridfs/chunk.rb index ddeee7f..71325a9 100644 --- a/lib/mongo/gridfs/chunk.rb +++ b/lib/mongo/gridfs/chunk.rb @@ -18,7 +18,6 @@ require 'mongo/types/objectid' require 'mongo/util/byte_buffer' require 'mongo/util/ordered_hash' - module GridFS # A chunk stores a portion of GridStore data. diff --git a/lib/mongo/util/bson.rb b/lib/mongo/util/bson.rb deleted file mode 100644 index 4a8dfa0..0000000 --- a/lib/mongo/util/bson.rb +++ /dev/null @@ -1,563 +0,0 @@ -# -- -# Copyright (C) 2008-2009 10gen Inc. -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Affero General Public License, version 3, as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License -# for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# ++ - -require 'base64' -require 'mongo/util/byte_buffer' -require 'mongo/util/ordered_hash' -require 'mongo/types/binary' -require 'mongo/types/dbref' -require 'mongo/types/objectid' -require 'mongo/types/regexp_of_holding' - -# A BSON seralizer/deserializer. -class BSON - - include Mongo - - MINKEY = -1 - EOO = 0 - NUMBER = 1 - STRING = 2 - OBJECT = 3 - ARRAY = 4 - BINARY = 5 - UNDEFINED = 6 - OID = 7 - BOOLEAN = 8 - DATE = 9 - NULL = 10 - REGEX = 11 - REF = 12 - CODE = 13 - SYMBOL = 14 - CODE_W_SCOPE = 15 - NUMBER_INT = 16 - TIMESTAMP = 17 - NUMBER_LONG = 18 - MAXKEY = 127 - - if RUBY_VERSION >= '1.9' - def self.to_utf8(str) - str.encode("utf-8") - end - else - def self.to_utf8(str) - begin - str.unpack("U*") - rescue => ex - raise InvalidStringEncoding, "String not valid utf-8: #{str}" - end - str - end - end - - def self.serialize_cstr(buf, val) - buf.put_array(to_utf8(val.to_s).unpack("C*") + [0]) - end - - def initialize() - @buf = ByteBuffer.new - end - - def to_a - @buf.to_a - end - - # Serializes an object. - # Implemented to ensure an API compatible with BSON extension. - def self.serialize(obj, check_keys) - new.serialize(obj, check_keys) - end - - begin - require 'mongo_ext/cbson' - def serialize(obj, check_keys=false) - @buf = ByteBuffer.new(CBson.serialize(obj, check_keys)) - end - rescue LoadError - def serialize(obj, check_keys=false) - raise "Document is null" unless obj - - @buf.rewind - # put in a placeholder for the total size - @buf.put_int(0) - - # Write key/value pairs. Always write _id first if it exists. - if obj.has_key? '_id' - serialize_key_value('_id', obj['_id'], check_keys) - elsif obj.has_key? :_id - serialize_key_value('_id', obj[:_id], check_keys) - end - - obj.each {|k, v| serialize_key_value(k, v, check_keys) unless k == '_id' || k == :_id } - - serialize_eoo_element(@buf) - @buf.put_int(@buf.size, 0) - self - end - end - - # Returns the array stored in the buffer. - # Implemented to ensure an API compatible with BSON extension. - def unpack(arg) - @buf.to_a - end - - def serialize_key_value(k, v, check_keys) - k = k.to_s - if check_keys - if k[0] == ?$ - raise InvalidName.new("key #{k} must not start with '$'") - end - if k.include? ?. - raise InvalidName.new("key #{k} must not contain '.'") - end - end - type = bson_type(v) - case type - when STRING, SYMBOL - serialize_string_element(@buf, k, v, type) - when NUMBER, NUMBER_INT - serialize_number_element(@buf, k, v, type) - when OBJECT - serialize_object_element(@buf, k, v, check_keys) - when OID - serialize_oid_element(@buf, k, v) - when ARRAY - serialize_array_element(@buf, k, v, check_keys) - when REGEX - serialize_regex_element(@buf, k, v) - when BOOLEAN - serialize_boolean_element(@buf, k, v) - when DATE - serialize_date_element(@buf, k, v) - when NULL - serialize_null_element(@buf, k) - when REF - serialize_dbref_element(@buf, k, v) - when BINARY - serialize_binary_element(@buf, k, v) - when UNDEFINED - serialize_null_element(@buf, k) - when CODE_W_SCOPE - serialize_code_w_scope(@buf, k, v) - else - raise "unhandled type #{type}" - end - end - - begin - require 'mongo_ext/cbson' - def deserialize(buf=nil) - if buf.is_a? String - @buf = ByteBuffer.new(buf) if buf - else - @buf = ByteBuffer.new(buf.to_a) if buf - end - @buf.rewind - CBson.deserialize(@buf.to_s) - end - rescue LoadError - def deserialize(buf=nil) - # If buf is nil, use @buf, assumed to contain already-serialized BSON. - # This is only true during testing. - if buf.is_a? String - @buf = ByteBuffer.new(buf) if buf - else - @buf = ByteBuffer.new(buf.to_a) if buf - end - @buf.rewind - @buf.get_int # eat message size - doc = OrderedHash.new - while @buf.more? - type = @buf.get - case type - when STRING, CODE - key = deserialize_cstr(@buf) - doc[key] = deserialize_string_data(@buf) - when SYMBOL - key = deserialize_cstr(@buf) - doc[key] = deserialize_string_data(@buf).intern - when NUMBER - key = deserialize_cstr(@buf) - doc[key] = deserialize_number_data(@buf) - when NUMBER_INT - key = deserialize_cstr(@buf) - doc[key] = deserialize_number_int_data(@buf) - when NUMBER_LONG - key = deserialize_cstr(@buf) - doc[key] = deserialize_number_long_data(@buf) - when OID - key = deserialize_cstr(@buf) - doc[key] = deserialize_oid_data(@buf) - when ARRAY - key = deserialize_cstr(@buf) - doc[key] = deserialize_array_data(@buf) - when REGEX - key = deserialize_cstr(@buf) - doc[key] = deserialize_regex_data(@buf) - when OBJECT - key = deserialize_cstr(@buf) - doc[key] = deserialize_object_data(@buf) - when BOOLEAN - key = deserialize_cstr(@buf) - doc[key] = deserialize_boolean_data(@buf) - when DATE - key = deserialize_cstr(@buf) - doc[key] = deserialize_date_data(@buf) - when NULL - key = deserialize_cstr(@buf) - doc[key] = nil - when UNDEFINED - key = deserialize_cstr(@buf) - doc[key] = nil - when REF - key = deserialize_cstr(@buf) - doc[key] = deserialize_dbref_data(@buf) - when BINARY - key = deserialize_cstr(@buf) - doc[key] = deserialize_binary_data(@buf) - when CODE_W_SCOPE - key = deserialize_cstr(@buf) - doc[key] = deserialize_code_w_scope_data(@buf) - when TIMESTAMP - key = deserialize_cstr(@buf) - doc[key] = [deserialize_number_int_data(@buf), - deserialize_number_int_data(@buf)] - when EOO - break - else - raise "Unknown type #{type}, key = #{key}" - end - end - @buf.rewind - doc - end - end - - # For debugging. - def hex_dump - str = '' - @buf.to_a.each_with_index { |b,i| - if (i % 8) == 0 - str << "\n" if i > 0 - str << '%4d: ' % i - else - str << ' ' - end - str << '%02X' % b - } - str - end - - def deserialize_date_data(buf) - unsigned = buf.get_long() - # see note for deserialize_number_long_data below - milliseconds = unsigned >= 2 ** 64 / 2 ? unsigned - 2**64 : unsigned - Time.at(milliseconds.to_f / 1000.0).utc # at() takes fractional seconds - end - - def deserialize_boolean_data(buf) - buf.get == 1 - end - - def deserialize_number_data(buf) - buf.get_double - end - - def deserialize_number_int_data(buf) - # sometimes ruby makes me angry... why would the same code pack as signed - # but unpack as unsigned - unsigned = buf.get_int - unsigned >= 2**32 / 2 ? unsigned - 2**32 : unsigned - end - - def deserialize_number_long_data(buf) - # same note as above applies here... - unsigned = buf.get_long - unsigned >= 2 ** 64 / 2 ? unsigned - 2**64 : unsigned - end - - def deserialize_object_data(buf) - size = buf.get_int - buf.position -= 4 - object = BSON.new().deserialize(buf.get(size)) - if object.has_key? "$ref" - DBRef.new(object["$ref"], object["$id"]) - else - object - end - end - - def deserialize_array_data(buf) - h = deserialize_object_data(buf) - a = [] - h.each { |k, v| a[k.to_i] = v } - a - end - - def deserialize_regex_data(buf) - str = deserialize_cstr(buf) - options_str = deserialize_cstr(buf) - options = 0 - options |= Regexp::IGNORECASE if options_str.include?('i') - options |= Regexp::MULTILINE if options_str.include?('m') - options |= Regexp::EXTENDED if options_str.include?('x') - options_str.gsub!(/[imx]/, '') # Now remove the three we understand - RegexpOfHolding.new(str, options, options_str) - end - - def deserialize_string_data(buf) - len = buf.get_int - bytes = buf.get(len) - str = bytes[0..-2] - if str.respond_to? "pack" - str = str.pack("C*") - end - if RUBY_VERSION >= '1.9' - str.force_encoding("utf-8") - end - str - end - - def deserialize_code_w_scope_data(buf) - buf.get_int - len = buf.get_int - code = buf.get(len)[0..-2] - if code.respond_to? "pack" - code = code.pack("C*") - end - if RUBY_VERSION >= '1.9' - code.force_encoding("utf-8") - end - - scope_size = buf.get_int - buf.position -= 4 - scope = BSON.new().deserialize(buf.get(scope_size)) - - Code.new(code, scope) - end - - def deserialize_oid_data(buf) - ObjectID.new(buf.get(12)) - end - - def deserialize_dbref_data(buf) - ns = deserialize_string_data(buf) - oid = deserialize_oid_data(buf) - DBRef.new(ns, oid) - end - - def deserialize_binary_data(buf) - len = buf.get_int - type = buf.get - len = buf.get_int if type == Binary::SUBTYPE_BYTES - Binary.new(buf.get(len), type) - end - - def serialize_eoo_element(buf) - buf.put(EOO) - end - - def serialize_null_element(buf, key) - buf.put(NULL) - self.class.serialize_cstr(buf, key) - end - - def serialize_dbref_element(buf, key, val) - oh = OrderedHash.new - oh['$ref'] = val.namespace - oh['$id'] = val.object_id - serialize_object_element(buf, key, oh, false) - end - - def serialize_binary_element(buf, key, val) - buf.put(BINARY) - self.class.serialize_cstr(buf, key) - - bytes = val.to_a - num_bytes = bytes.length - subtype = val.respond_to?(:subtype) ? val.subtype : Binary::SUBTYPE_BYTES - if subtype == Binary::SUBTYPE_BYTES - buf.put_int(num_bytes + 4) - buf.put(subtype) - buf.put_int(num_bytes) - buf.put_array(bytes) - else - buf.put_int(num_bytes) - buf.put(subtype) - buf.put_array(bytes) - end - end - - def serialize_boolean_element(buf, key, val) - buf.put(BOOLEAN) - self.class.serialize_cstr(buf, key) - buf.put(val ? 1 : 0) - end - - def serialize_date_element(buf, key, val) - buf.put(DATE) - self.class.serialize_cstr(buf, key) - millisecs = (val.to_f * 1000).to_i - buf.put_long(millisecs) - end - - def serialize_number_element(buf, key, val, type) - if type == NUMBER - buf.put(type) - self.class.serialize_cstr(buf, key) - buf.put_double(val) - else - if val > 2**64 / 2 - 1 or val < -2**64 / 2 - raise RangeError.new("MongoDB can only handle 8-byte ints") - end - if val > 2**32 / 2 - 1 or val < -2**32 / 2 - buf.put(NUMBER_LONG) - self.class.serialize_cstr(buf, key) - buf.put_long(val) - else - buf.put(type) - self.class.serialize_cstr(buf, key) - buf.put_int(val) - end - end - end - - def serialize_object_element(buf, key, val, check_keys, opcode=OBJECT) - buf.put(opcode) - self.class.serialize_cstr(buf, key) - buf.put_array(BSON.new.serialize(val, check_keys).to_a) - end - - def serialize_array_element(buf, key, val, check_keys) - # Turn array into hash with integer indices as keys - h = OrderedHash.new - i = 0 - val.each { |v| h[i] = v; i += 1 } - serialize_object_element(buf, key, h, check_keys, ARRAY) - end - - def serialize_regex_element(buf, key, val) - buf.put(REGEX) - self.class.serialize_cstr(buf, key) - - str = val.to_s.sub(/.*?:/, '')[0..-2] # Turn "(?xxx:yyy)" into "yyy" - self.class.serialize_cstr(buf, str) - - options = val.options - options_str = '' - options_str << 'i' if ((options & Regexp::IGNORECASE) != 0) - options_str << 'm' if ((options & Regexp::MULTILINE) != 0) - options_str << 'x' if ((options & Regexp::EXTENDED) != 0) - options_str << val.extra_options_str if val.respond_to?(:extra_options_str) - # Must store option chars in alphabetical order - self.class.serialize_cstr(buf, options_str.split(//).sort.uniq.join) - end - - def serialize_oid_element(buf, key, val) - buf.put(OID) - self.class.serialize_cstr(buf, key) - - buf.put_array(val.to_a) - end - - def serialize_string_element(buf, key, val, type) - buf.put(type) - self.class.serialize_cstr(buf, key) - - # Make a hole for the length - len_pos = buf.position - buf.put_int(0) - - # Save the string - start_pos = buf.position - self.class.serialize_cstr(buf, val) - end_pos = buf.position - - # Put the string size in front - buf.put_int(end_pos - start_pos, len_pos) - - # Go back to where we were - buf.position = end_pos - end - - def serialize_code_w_scope(buf, key, val) - buf.put(CODE_W_SCOPE) - self.class.serialize_cstr(buf, key) - - # Make a hole for the length - len_pos = buf.position - buf.put_int(0) - - buf.put_int(val.length + 1) - self.class.serialize_cstr(buf, val) - buf.put_array(BSON.new.serialize(val.scope).to_a) - - end_pos = buf.position - buf.put_int(end_pos - len_pos, len_pos) - buf.position = end_pos - end - - def deserialize_cstr(buf) - chars = "" - while true - b = buf.get - break if b == 0 - chars << b.chr - end - if RUBY_VERSION >= '1.9' - chars.force_encoding("utf-8") # Mongo stores UTF-8 - end - chars - end - - def bson_type(o) - case o - when nil - NULL - when Integer - NUMBER_INT - when Numeric - NUMBER - when ByteBuffer - BINARY - when Code - CODE_W_SCOPE - when String - STRING - when Array - ARRAY - when Regexp - REGEX - when ObjectID - OID - when DBRef - REF - when true, false - BOOLEAN - when Time - DATE - when Hash - OBJECT - when Symbol - SYMBOL - else - raise "Unknown type of object: #{o.class.name}" - end - end - -end diff --git a/lib/mongo/util/byte_buffer.rb b/lib/mongo/util/byte_buffer.rb index b852ba4..d927a9d 100644 --- a/lib/mongo/util/byte_buffer.rb +++ b/lib/mongo/util/byte_buffer.rb @@ -27,6 +27,25 @@ class ByteBuffer @double_pack_order = 'E' end + if RUBY_VERSION >= '1.9' + def self.to_utf8(str) + str.encode("utf-8") + end + else + def self.to_utf8(str) + begin + str.unpack("U*") + rescue => ex + raise InvalidStringEncoding, "String not valid utf-8: #{str}" + end + str + end + end + + def self.serialize_cstr(buf, val) + buf.put_array(to_utf8(val.to_s).unpack("C*") + [0]) + end + # +endianness+ should be :little_endian or :big_endian. Default is :little_endian def order=(endianness) @order = endianness diff --git a/test/test_admin.rb b/test/test_admin.rb index 07e8a9e..f720e18 100644 --- a/test/test_admin.rb +++ b/test/test_admin.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'test/unit' +require 'test/test_helper' # NOTE: assumes Mongo is running class AdminTest < Test::Unit::TestCase diff --git a/test/test_bson.rb b/test/test_bson.rb index 76c3d0d..c243322 100644 --- a/test/test_bson.rb +++ b/test/test_bson.rb @@ -1,9 +1,5 @@ -# -*- coding: utf-8 -*- -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'mongo/util/ordered_hash' +require 'test/test_helper' require 'iconv' -require 'test/unit' class BSONTest < Test::Unit::TestCase @@ -13,58 +9,58 @@ class BSONTest < Test::Unit::TestCase # We don't pass a DB to the constructor, even though we are about to test # deserialization. This means that when we deserialize, any DBRefs will # have nil @db ivars. That's fine for now. - @b = BSON.new + #BSON = BSON.new end def test_string doc = {'doc' => 'hello, world'} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_valid_utf8_string doc = {'doc' => "aéあ"} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_invalid_string string = Iconv.conv('iso-8859-1', 'utf-8', 'aé').first - doc = {'doc' => string} + doc = {'doc' => string} assert_raise InvalidStringEncoding do - @b.serialize(doc) + BSON.serialize(doc) end end def test_code doc = {'$where' => Code.new('this.a.b < this.b')} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_number doc = {'doc' => 41.99} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_int doc = {'doc' => 42} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) doc = {"doc" => -5600} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) doc = {"doc" => 2147483647} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) doc = {"doc" => -2147483648} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_ordered_hash @@ -73,32 +69,32 @@ class BSONTest < Test::Unit::TestCase doc["a"] = 2 doc["c"] = 3 doc["d"] = 4 - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_object doc = {'doc' => {'age' => 42, 'name' => 'Spongebob', 'shoe_size' => 9.5}} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_oid doc = {'doc' => ObjectID.new} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_array doc = {'doc' => [1, 2, 'a', 'b']} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_regex doc = {'doc' => /foobar/i} - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) assert_equal doc, doc2 r = doc2['doc'] @@ -108,11 +104,10 @@ class BSONTest < Test::Unit::TestCase r.extra_options_str << 'zywcab' assert_equal 'zywcab', r.extra_options_str - b = BSON.new doc = {'doc' => r} - b.serialize(doc) + bson_doc = BSON.serialize(doc) doc2 = nil - doc2 = b.deserialize + doc2 = BSON.deserialize(bson_doc) assert_equal doc, doc2 r = doc2['doc'] @@ -122,30 +117,30 @@ class BSONTest < Test::Unit::TestCase def test_boolean doc = {'doc' => true} - @b.serialize(doc) - assert_equal doc, @b.deserialize + bson = BSON.serialize(doc) + assert_equal doc, BSON.deserialize(bson) end def test_date doc = {'date' => Time.now} - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) # Mongo only stores up to the millisecond assert_in_delta doc['date'], doc2['date'], 0.001 end def test_date_returns_as_utc doc = {'date' => Time.now} - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) assert doc2['date'].utc? end def test_date_before_epoch begin doc = {'date' => Time.utc(1600)} - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) # Mongo only stores up to the millisecond assert_in_delta doc['date'], doc2['date'], 0.001 rescue ArgumentError @@ -160,16 +155,16 @@ class BSONTest < Test::Unit::TestCase oid = ObjectID.new doc = {} doc['dbref'] = DBRef.new('namespace', oid) - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) assert_equal 'namespace', doc2['dbref'].namespace assert_equal oid, doc2['dbref'].object_id end def test_symbol doc = {'sym' => :foo} - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) assert_equal :foo, doc2['sym'] end @@ -178,8 +173,8 @@ class BSONTest < Test::Unit::TestCase 'binstring'.each_byte { |b| bin.put(b) } doc = {'bin' => bin} - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) bin2 = doc2['bin'] assert_kind_of Binary, bin2 assert_equal 'binstring', bin2.to_s @@ -190,8 +185,8 @@ class BSONTest < Test::Unit::TestCase bin = Binary.new([1, 2, 3, 4, 5], Binary::SUBTYPE_USER_DEFINED) doc = {'bin' => bin} - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) bin2 = doc2['bin'] assert_kind_of Binary, bin2 assert_equal [1, 2, 3, 4, 5], bin2.to_a @@ -203,8 +198,8 @@ class BSONTest < Test::Unit::TestCase 5.times { |i| bb.put(i + 1) } doc = {'bin' => bb} - @b.serialize(doc) - doc2 = @b.deserialize + bson = BSON.serialize(doc) + doc2 = BSON.deserialize(bson) bin2 = doc2['bin'] assert_kind_of Binary, bin2 assert_equal [1, 2, 3, 4, 5], bin2.to_a @@ -215,24 +210,24 @@ class BSONTest < Test::Unit::TestCase val = OrderedHash.new val['not_id'] = 1 val['_id'] = 2 - roundtrip = @b.deserialize(@b.serialize(val).to_a) + roundtrip = BSON.deserialize(BSON.serialize(val).to_a) assert_kind_of OrderedHash, roundtrip assert_equal '_id', roundtrip.keys.first val = {'a' => 'foo', 'b' => 'bar', :_id => 42, 'z' => 'hello'} - roundtrip = @b.deserialize(@b.serialize(val).to_a) + roundtrip = BSON.deserialize(BSON.serialize(val).to_a) assert_kind_of OrderedHash, roundtrip assert_equal '_id', roundtrip.keys.first end def test_nil_id doc = {"_id" => nil} - assert_equal doc, @b.deserialize(@b.serialize(doc).to_a) + assert_equal doc, BSON.deserialize(bson = BSON.serialize(doc).to_a) end def test_timestamp val = {"test" => [4, 20]} - assert_equal val, @b.deserialize([0x13, 0x00, 0x00, 0x00, + assert_equal val, BSON.deserialize([0x13, 0x00, 0x00, 0x00, 0x11, 0x74, 0x65, 0x73, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14, 0x00, @@ -242,29 +237,29 @@ class BSONTest < Test::Unit::TestCase def test_overflow doc = {"x" => 2**75} assert_raise RangeError do - @b.serialize(doc) + bson = BSON.serialize(doc) end doc = {"x" => 9223372036854775} - assert_equal doc, @b.deserialize(@b.serialize(doc).to_a) + assert_equal doc, BSON.deserialize(BSON.serialize(doc).to_a) doc = {"x" => 9223372036854775807} - assert_equal doc, @b.deserialize(@b.serialize(doc).to_a) + assert_equal doc, BSON.deserialize(BSON.serialize(doc).to_a) doc["x"] = doc["x"] + 1 assert_raise RangeError do - @b.serialize(doc) + bson = BSON.serialize(doc) end doc = {"x" => -9223372036854775} - assert_equal doc, @b.deserialize(@b.serialize(doc).to_a) + assert_equal doc, BSON.deserialize(BSON.serialize(doc).to_a) doc = {"x" => -9223372036854775808} - assert_equal doc, @b.deserialize(@b.serialize(doc).to_a) + assert_equal doc, BSON.deserialize(BSON.serialize(doc).to_a) doc["x"] = doc["x"] - 1 assert_raise RangeError do - @b.serialize(doc) + bson = BSON.serialize(doc) end end @@ -273,12 +268,12 @@ class BSONTest < Test::Unit::TestCase val['not_id'] = 1 val['_id'] = 2 assert val.keys.include?('_id') - @b.serialize(val) + BSON.serialize(val) assert val.keys.include?('_id') val = {'a' => 'foo', 'b' => 'bar', :_id => 42, 'z' => 'hello'} assert val.keys.include?(:_id) - @b.serialize(val) + BSON.serialize(val) assert val.keys.include?(:_id) end @@ -293,7 +288,7 @@ class BSONTest < Test::Unit::TestCase dup = {"_id" => "foo", :_id => "foo"} one = {"_id" => "foo"} - assert_equal @b.serialize(one).to_a, @b.serialize(dup).to_a + assert_equal BSON.serialize(one).to_a, BSON.serialize(dup).to_a end end diff --git a/test/test_byte_buffer.rb b/test/test_byte_buffer.rb index 86da23f..7770a1d 100644 --- a/test/test_byte_buffer.rb +++ b/test/test_byte_buffer.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'test/unit' +require 'test/test_helper' class ByteBufferTest < Test::Unit::TestCase diff --git a/test/test_chunk.rb b/test/test_chunk.rb index 7239c77..f7a0fda 100644 --- a/test/test_chunk.rb +++ b/test/test_chunk.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'test/unit' -require 'mongo' +require 'test/test_helper' require 'mongo/gridfs' class ChunkTest < Test::Unit::TestCase diff --git a/test/test_collection.rb b/test/test_collection.rb index d965fc8..59130ad 100644 --- a/test/test_collection.rb +++ b/test/test_collection.rb @@ -1,20 +1,5 @@ -# -- -# Copyright (C) 2008-2009 10gen Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ++ - require 'test/test_helper' + class TestCollection < Test::Unit::TestCase @@connection = Connection.new(ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost', ENV['MONGO_RUBY_DRIVER_PORT'] || Connection::DEFAULT_PORT) @@db = @@connection.db('ruby-mongo-test') diff --git a/test/test_connection.rb b/test/test_connection.rb index 499de84..536315e 100644 --- a/test/test_connection.rb +++ b/test/test_connection.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'test/unit' +require 'test/test_helper' require 'logger' require 'stringio' diff --git a/test/test_conversions.rb b/test/test_conversions.rb index ab3e28c..cce85a6 100644 --- a/test/test_conversions.rb +++ b/test/test_conversions.rb @@ -1,8 +1,7 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') +require 'test/test_helper' require 'mongo/errors' require 'mongo/util/conversions' require 'mongo/util/ordered_hash' -require 'test/unit' class ConversionsTest < Test::Unit::TestCase include Mongo::Conversions diff --git a/test/test_cursor.rb b/test/test_cursor.rb index 30da2f4..99f42a9 100644 --- a/test/test_cursor.rb +++ b/test/test_cursor.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'test/unit' +require 'test/test_helper' # NOTE: assumes Mongo is running class CursorTest < Test::Unit::TestCase diff --git a/test/test_db.rb b/test/test_db.rb index 0f1c574..a376feb 100644 --- a/test/test_db.rb +++ b/test/test_db.rb @@ -1,7 +1,5 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') +require 'test/test_helper' require 'digest/md5' -require 'mongo' -require 'test/unit' require 'stringio' require 'logger' diff --git a/test/test_db_api.rb b/test/test_db_api.rb index e3848d1..fe5333f 100644 --- a/test/test_db_api.rb +++ b/test/test_db_api.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'test/unit' +require 'test/test_helper' # NOTE: assumes Mongo is running class DBAPITest < Test::Unit::TestCase diff --git a/test/test_db_connection.rb b/test/test_db_connection.rb index 432c477..91f4715 100644 --- a/test/test_db_connection.rb +++ b/test/test_db_connection.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'test/unit' +require 'test/test_helper' # NOTE: assumes Mongo is running class DBConnectionTest < Test::Unit::TestCase diff --git a/test/test_grid_store.rb b/test/test_grid_store.rb index 594b771..d2c5a01 100644 --- a/test/test_grid_store.rb +++ b/test/test_grid_store.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'test/unit' -require 'mongo' +require 'test/test_helper' require 'mongo/gridfs' class GridStoreTest < Test::Unit::TestCase diff --git a/test/test_helper.rb b/test/test_helper.rb index 198206f..d6fe269 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,9 +1,10 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'rubygems' +$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +require 'rubygems' if ENV['C_EXT'] require 'mongo' require 'test/unit' begin + require 'rubygems' require 'shoulda' require 'mocha' rescue LoadError @@ -18,6 +19,8 @@ MSG exit end +require 'mongo_ext/cbson' if ENV['C_EXT'] + # NOTE: most tests assume that MongoDB is running. class Test::Unit::TestCase include Mongo diff --git a/test/test_objectid.rb b/test/test_objectid.rb index bc0d405..e7ecb44 100644 --- a/test/test_objectid.rb +++ b/test/test_objectid.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'test/unit' +require 'test/test_helper' class ObjectIDTest < Test::Unit::TestCase diff --git a/test/test_ordered_hash.rb b/test/test_ordered_hash.rb index 398325b..4fcda98 100644 --- a/test/test_ordered_hash.rb +++ b/test/test_ordered_hash.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo/util/ordered_hash' -require 'test/unit' +require 'test/test_helper' class OrderedHashTest < Test::Unit::TestCase diff --git a/test/test_round_trip.rb b/test/test_round_trip.rb index 4991643..fac9a14 100644 --- a/test/test_round_trip.rb +++ b/test/test_round_trip.rb @@ -1,8 +1,7 @@ HERE = File.dirname(__FILE__) $LOAD_PATH[0,0] = File.join(HERE, '..', 'lib') -require 'mongo' +require 'test/test_helper' require 'mongo/util/xml_to_ruby' -require 'test/unit' # For each xml/bson file in the data subdirectory, we turn the XML into an # OrderedHash and then test both Ruby-to-BSON and BSON-to-Ruby translations. diff --git a/test/test_slave_connection.rb b/test/test_slave_connection.rb index bffb4e7..50fcefc 100644 --- a/test/test_slave_connection.rb +++ b/test/test_slave_connection.rb @@ -1,6 +1,4 @@ -$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib') -require 'mongo' -require 'test/unit' +require 'test/test_helper' # NOTE: these tests are run only if we can connect to a single MongoDB in slave mode. class SlaveConnectionTest < Test::Unit::TestCase