diff --git a/tests/data/empty.bson b/tests/data/empty.bson
new file mode 100644
index 0000000..a536906
Binary files /dev/null and b/tests/data/empty.bson differ
diff --git a/tests/data/empty.xml b/tests/data/empty.xml
new file mode 100644
index 0000000..fee7568
--- /dev/null
+++ b/tests/data/empty.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/tests/data/smorgasbord.bson b/tests/data/smorgasbord.bson
new file mode 100644
index 0000000..bbd7700
Binary files /dev/null and b/tests/data/smorgasbord.bson differ
diff --git a/tests/data/smorgasbord.xml b/tests/data/smorgasbord.xml
new file mode 100644
index 0000000..b543c2d
--- /dev/null
+++ b/tests/data/smorgasbord.xml
@@ -0,0 +1,29 @@
+
+
+
+ 4ea067497065180748000000
+ 42
+ foo
+ true
+ 42.12345
+
+ x
+ y
+ z
+
+ yup
+
+
+ 1231515664416
+ [
+ namespace
+ 4ea067497065180748010000
+ ]
+
+ foobar
+
+
+
+ this is code
+
+
diff --git a/tests/test_round_trip.rb b/tests/test_round_trip.rb
new file mode 100644
index 0000000..0670222
--- /dev/null
+++ b/tests/test_round_trip.rb
@@ -0,0 +1,137 @@
+HERE = File.dirname(__FILE__)
+$LOAD_PATH[0,0] = File.join(HERE, '..', 'lib')
+require 'mongo'
+require 'rexml/document'
+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.
+class RoundTripTest < Test::Unit::TestCase
+
+ include XGen::Mongo::Driver
+
+ @@ruby = nil
+
+ def setup
+ unless @@ruby
+ names = Dir[File.join(HERE, 'data', '*.xml')].collect {|f| File.basename(f).sub(/\.xml$/, '') }
+ @@ruby = {}
+ names.each { |name| @@ruby[name] = xml_to_ruby(name) }
+ end
+ end
+
+ def xml_to_ruby(name)
+ File.open(File.join(HERE, 'data', "#{name}.xml")) { |f|
+ doc = REXML::Document.new(f)
+ doc_to_ruby(doc.root.elements['doc'])
+ }
+ end
+
+ def element_to_ruby(e)
+ type = e.name
+ child = e.elements[1]
+ case type
+ when 'oid'
+ ObjectID.from_string(e.text)
+ when 'ref'
+ dbref_to_ruby(e.elements)
+ when 'int'
+ e.text.to_i
+ when 'number'
+ e.text.to_f
+ when 'string', 'code'
+ e.text.to_s
+ when 'boolean'
+ e.text.to_s == 'true'
+ when 'array'
+ array_to_ruby(e.elements)
+ when 'date'
+ Time.at(e.text.to_f / 1000.0)
+ when 'regex'
+ regex_to_ruby(e.elements)
+ when 'null'
+ nil
+ when 'doc'
+ doc_to_ruby(e)
+ else
+ raise "Unknown type #{type} in element with name #{e.attributes['name']}"
+ end
+ end
+
+ def doc_to_ruby(element)
+ oh = OrderedHash.new
+ element.elements.each { |e| oh[e.attributes['name']] = element_to_ruby(e) }
+ oh
+ end
+
+ def array_to_ruby(elements)
+ a = []
+ elements.each { |e|
+ index_str = e.attributes['name']
+ a[index_str.to_i] = element_to_ruby(e)
+ }
+ a
+ end
+
+ def regex_to_ruby(elements)
+ pattern = elements['pattern'].text
+ options_str = elements['options'].text || ''
+
+ 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')
+ Regexp.new(pattern, options)
+ end
+
+ def dbref_to_ruby(elements)
+ ns = elements['ns'].text
+ oid_str = elements['oid'].text
+ DBRef.new(nil, nil, nil, ns, ObjectID.from_string(oid_str))
+ end
+
+# DEBUG
+# def test_foo
+# $stderr.puts "#{@@ruby['smorgasbord'].class.name}" # DEBUG
+# $stderr.puts "@@ruby['smorgasbord'] = #{@@ruby['smorgasbord'].inspect.gsub(/, /, ",\n")}" # DEBUG
+# end
+
+ # Round-trip comparisons of Ruby-to-BSON and back.
+ # * Take the objects that were read from XML
+ # * Turn them into BSON bytes
+ # * Compare that with the BSON files we have
+ # * Turn those BSON bytes back in to Ruby objects
+ # * Turn them back into BSON bytes
+ # * Compare that with the BSON files we have (or the bytes that were already
+ # generated)
+ def test_round_trip
+ @@ruby.each { |name, obj|
+ File.open(File.join(HERE, 'data', "#{name}.bson"), 'r') { |f|
+ # Read the BSON from the file
+ bson = f.read
+ bson = if RUBY_VERSION >= '1.9'
+ bson.bytes
+ else
+ bson.split(//).collect { |c| c[0] }
+ end
+
+ # Turn the Ruby object into BSON bytes and compare with the BSON bytes
+ # from the file.
+ bson_from_ruby = BSON.new.serialize(obj).to_a
+ assert_equal bson.length, bson_from_ruby.length
+ assert_equal bson, bson_from_ruby
+
+ # Turn those BSON bytes back into a Ruby object
+ obj_from_bson = BSON.new.deserialize(ByteBuffer.new(bson_from_ruby))
+ assert_kind_of OrderedHash, obj_from_bson
+
+ # Turn that Ruby object into BSON and compare it to the original BSON
+ # bytes.
+ bson_from_ruby = BSON.new.serialize(obj_from_bson).to_a
+ assert_equal bson.length, bson_from_ruby.length
+ assert_equal bson, bson_from_ruby
+ }
+ }
+ end
+
+end