Skip to content

Commit ec2ab33

Browse files
committed
PYTHON-2680 Add DBRef spec prose tests
1 parent f822569 commit ec2ab33

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

test/test_dbref.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import sys
1919
sys.path[0:0] = [""]
2020

21+
from bson import encode, decode
2122
from bson.dbref import DBRef
2223
from bson.objectid import ObjectId
2324
from test import unittest
@@ -131,5 +132,108 @@ def test_dbref_hash(self):
131132

132133
self.assertNotEqual(hash(dbref_1a), hash(dbref_2a))
133134

135+
136+
# https://github.com/mongodb/specifications/blob/master/source/dbref.rst#test-plan
137+
class TestDBRefSpec(unittest.TestCase):
138+
def test_decoding_1_2_3(self):
139+
for doc in [
140+
# 1, Valid documents MUST be decoded to a DBRef:
141+
{"$ref": "coll0", "$id": ObjectId("60a6fe9a54f4180c86309efa")},
142+
{"$ref": "coll0", "$id": 1},
143+
{"$ref": "coll0", "$id": None},
144+
{"$ref": "coll0", "$id": 1, "$db": "db0"},
145+
# 2, Valid documents with extra fields:
146+
{"$ref": "coll0", "$id": 1, "$db": "db0", "foo": "bar"},
147+
{"$ref": "coll0", "$id": 1, "foo": True, "bar": False},
148+
{"$ref": "coll0", "$id": 1, "meta": {"foo": 1, "bar": 2}},
149+
{"$ref": "coll0", "$id": 1, "$foo": "bar"},
150+
{"$ref": "coll0", "$id": 1, "foo.bar": 0},
151+
# 3, Valid documents with out of order fields:
152+
{"$id": 1, "$ref": "coll0"},
153+
{"$db": "db0", "$ref": "coll0", "$id": 1},
154+
{"foo": 1, "$id": 1, "$ref": "coll0"},
155+
{"foo": 1, "$ref": "coll0", "$id": 1, "$db": "db0"},
156+
{"foo": 1, "$ref": "coll0", "$id": 1, "$db": "db0", "bar": 1},
157+
]:
158+
with self.subTest(doc=doc):
159+
decoded = decode(encode({'dbref': doc}))
160+
dbref = decoded['dbref']
161+
self.assertIsInstance(dbref, DBRef)
162+
self.assertEqual(dbref.collection, doc['$ref'])
163+
self.assertEqual(dbref.id, doc['$id'])
164+
self.assertEqual(dbref.database, doc.get('$db'))
165+
for extra in set(doc.keys()) - {"$ref", "$id", "$db"}:
166+
self.assertEqual(getattr(dbref, extra), doc[extra])
167+
168+
def test_decoding_4_5(self):
169+
for doc in [
170+
# 4, Documents missing required fields MUST NOT be decoded to a
171+
# DBRef:
172+
{"$ref": "coll0"},
173+
{"$id": ObjectId("60a6fe9a54f4180c86309efa")},
174+
{"$db": "db0"},
175+
# 5, Documents with invalid types for $ref or $db MUST NOT be
176+
# decoded to a DBRef
177+
{"$ref": True, "$id": 1},
178+
{"$ref": "coll0", "$id": 1, "$db": 1},
179+
]:
180+
with self.subTest(doc=doc):
181+
decoded = decode(encode({'dbref': doc}))
182+
dbref = decoded['dbref']
183+
self.assertIsInstance(dbref, dict)
184+
185+
def test_encoding_1_2(self):
186+
for doc in [
187+
# 1, Encoding DBRefs with basic fields:
188+
{"$ref": "coll0", "$id": ObjectId("60a6fe9a54f4180c86309efa")},
189+
{"$ref": "coll0", "$id": 1},
190+
{"$ref": "coll0", "$id": None},
191+
{"$ref": "coll0", "$id": 1, "$db": "db0"},
192+
# 2, Encoding DBRefs with extra, optional fields:
193+
{"$ref": "coll0", "$id": 1, "$db": "db0", "foo": "bar"},
194+
{"$ref": "coll0", "$id": 1, "foo": True, "bar": False},
195+
{"$ref": "coll0", "$id": 1, "meta": {"foo": 1, "bar": 2}},
196+
{"$ref": "coll0", "$id": 1, "$foo": "bar"},
197+
{"$ref": "coll0", "$id": 1, "foo.bar": 0},
198+
]:
199+
with self.subTest(doc=doc):
200+
# Decode the test input to a DBRef via a BSON roundtrip.
201+
encoded_doc = encode({'dbref': doc})
202+
decoded = decode(encoded_doc)
203+
dbref = decoded['dbref']
204+
self.assertIsInstance(dbref, DBRef)
205+
# Encode the DBRef.
206+
encoded_dbref = encode(decoded)
207+
self.assertEqual(encoded_dbref, encoded_doc)
208+
# Ensure extra fields are present.
209+
for extra in set(doc.keys()) - {"$ref", "$id", "$db"}:
210+
self.assertEqual(getattr(dbref, extra), doc[extra])
211+
212+
def test_encoding_3(self):
213+
for doc in [
214+
# 3, Encoding DBRefs re-orders any out of order fields during
215+
# decoding:
216+
{"$id": 1, "$ref": "coll0"},
217+
{"$db": "db0", "$ref": "coll0", "$id": 1},
218+
{"foo": 1, "$id": 1, "$ref": "coll0"},
219+
{"foo": 1, "$ref": "coll0", "$id": 1, "$db": "db0"},
220+
{"foo": 1, "$ref": "coll0", "$id": 1, "$db": "db0", "bar": 1},
221+
]:
222+
with self.subTest(doc=doc):
223+
# Decode the test input to a DBRef via a BSON roundtrip.
224+
encoded_doc = encode({'dbref': doc})
225+
decoded = decode(encoded_doc)
226+
dbref = decoded['dbref']
227+
self.assertIsInstance(dbref, DBRef)
228+
# Encode the DBRef.
229+
encoded_dbref = encode(decoded)
230+
# BSON does not match because DBRef fields are reordered.
231+
self.assertNotEqual(encoded_dbref, encoded_doc)
232+
self.assertEqual(decode(encoded_dbref), decode(encoded_doc))
233+
# Ensure extra fields are present.
234+
for extra in set(doc.keys()) - {"$ref", "$id", "$db"}:
235+
self.assertEqual(getattr(dbref, extra), doc[extra])
236+
237+
134238
if __name__ == "__main__":
135239
unittest.main()

0 commit comments

Comments
 (0)