00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 """Test the connection module."""
00016
00017 import datetime
00018 import os
00019 import sys
00020 import time
00021 import unittest
00022 import warnings
00023 sys.path[0:0] = [""]
00024
00025 from nose.plugins.skip import SkipTest
00026
00027 from bson.son import SON
00028 from bson.tz_util import utc
00029 from pymongo.connection import (Connection,
00030 _parse_uri)
00031 from pymongo.database import Database
00032 from pymongo.errors import (AutoReconnect,
00033 ConfigurationError,
00034 ConnectionFailure,
00035 InvalidName,
00036 InvalidURI,
00037 OperationFailure)
00038 from test import version
00039
00040
00041 def get_connection(*args, **kwargs):
00042 host = os.environ.get("DB_IP", "localhost")
00043 port = int(os.environ.get("DB_PORT", 27017))
00044 return Connection(host, port, *args, **kwargs)
00045
00046
00047 class TestConnection(unittest.TestCase):
00048
00049 def setUp(self):
00050 self.host = os.environ.get("DB_IP", "localhost")
00051 self.port = int(os.environ.get("DB_PORT", 27017))
00052
00053 def test_types(self):
00054 self.assertRaises(TypeError, Connection, 1)
00055 self.assertRaises(TypeError, Connection, 1.14)
00056 self.assertRaises(TypeError, Connection, "localhost", "27017")
00057 self.assertRaises(TypeError, Connection, "localhost", 1.14)
00058 self.assertRaises(TypeError, Connection, "localhost", [])
00059
00060 self.assertRaises(ConfigurationError, Connection, [])
00061
00062 def test_constants(self):
00063 Connection.HOST = self.host
00064 Connection.PORT = self.port
00065 self.assert_(Connection())
00066
00067 Connection.HOST = "somedomainthatdoesntexist.org"
00068 Connection.PORT = 123456789
00069 self.assertRaises(ConnectionFailure, Connection)
00070 self.assert_(Connection(self.host, self.port))
00071
00072 Connection.HOST = self.host
00073 Connection.PORT = self.port
00074 self.assert_(Connection())
00075
00076 def test_connect(self):
00077 self.assertRaises(ConnectionFailure, Connection,
00078 "somedomainthatdoesntexist.org")
00079 self.assertRaises(ConnectionFailure, Connection, self.host, 123456789)
00080
00081 self.assert_(Connection(self.host, self.port))
00082
00083 def test_host_w_port(self):
00084 self.assert_(Connection("%s:%d" % (self.host, self.port)))
00085 self.assertRaises(ConnectionFailure, Connection,
00086 "%s:1234567" % self.host, self.port)
00087
00088 def test_repr(self):
00089 self.assertEqual(repr(Connection(self.host, self.port)),
00090 "Connection('%s', %s)" % (self.host, self.port))
00091
00092 def test_getters(self):
00093 self.assertEqual(Connection(self.host, self.port).host, self.host)
00094 self.assertEqual(Connection(self.host, self.port).port, self.port)
00095 self.assertEqual(set([(self.host, self.port)]), Connection(self.host, self.port).nodes)
00096
00097 def test_get_db(self):
00098 connection = Connection(self.host, self.port)
00099
00100 def make_db(base, name):
00101 return base[name]
00102
00103 self.assertRaises(InvalidName, make_db, connection, "")
00104 self.assertRaises(InvalidName, make_db, connection, "te$t")
00105 self.assertRaises(InvalidName, make_db, connection, "te.t")
00106 self.assertRaises(InvalidName, make_db, connection, "te\\t")
00107 self.assertRaises(InvalidName, make_db, connection, "te/t")
00108 self.assertRaises(InvalidName, make_db, connection, "te st")
00109
00110 self.assert_(isinstance(connection.test, Database))
00111 self.assertEqual(connection.test, connection["test"])
00112 self.assertEqual(connection.test, Database(connection, "test"))
00113
00114 def test_database_names(self):
00115 connection = Connection(self.host, self.port)
00116
00117 connection.pymongo_test.test.save({"dummy": u"object"})
00118 connection.pymongo_test_mike.test.save({"dummy": u"object"})
00119
00120 dbs = connection.database_names()
00121 self.assert_("pymongo_test" in dbs)
00122 self.assert_("pymongo_test_mike" in dbs)
00123
00124 def test_drop_database(self):
00125 connection = Connection(self.host, self.port)
00126
00127 self.assertRaises(TypeError, connection.drop_database, 5)
00128 self.assertRaises(TypeError, connection.drop_database, None)
00129
00130 connection.pymongo_test.test.save({"dummy": u"object"})
00131 dbs = connection.database_names()
00132 self.assert_("pymongo_test" in dbs)
00133 connection.drop_database("pymongo_test")
00134 dbs = connection.database_names()
00135 self.assert_("pymongo_test" not in dbs)
00136
00137 connection.pymongo_test.test.save({"dummy": u"object"})
00138 dbs = connection.database_names()
00139 self.assert_("pymongo_test" in dbs)
00140 connection.drop_database(connection.pymongo_test)
00141 dbs = connection.database_names()
00142 self.assert_("pymongo_test" not in dbs)
00143
00144 def test_copy_db(self):
00145 c = Connection(self.host, self.port)
00146
00147 self.assertRaises(TypeError, c.copy_database, 4, "foo")
00148 self.assertRaises(TypeError, c.copy_database, "foo", 4)
00149
00150 self.assertRaises(InvalidName, c.copy_database, "foo", "$foo")
00151
00152 c.pymongo_test.test.drop()
00153 c.drop_database("pymongo_test1")
00154 c.drop_database("pymongo_test2")
00155
00156 c.pymongo_test.test.insert({"foo": "bar"})
00157
00158 self.assertFalse("pymongo_test1" in c.database_names())
00159 self.assertFalse("pymongo_test2" in c.database_names())
00160
00161 c.copy_database("pymongo_test", "pymongo_test1")
00162
00163 self.assert_("pymongo_test1" in c.database_names())
00164 self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"])
00165
00166 c.copy_database("pymongo_test", "pymongo_test2",
00167 "%s:%s" % (self.host, self.port))
00168
00169 self.assert_("pymongo_test2" in c.database_names())
00170 self.assertEqual("bar", c.pymongo_test2.test.find_one()["foo"])
00171
00172 if version.at_least(c, (1, 3, 3, 1)):
00173 c.drop_database("pymongo_test1")
00174
00175 c.pymongo_test.add_user("mike", "password")
00176
00177 self.assertRaises(OperationFailure, c.copy_database,
00178 "pymongo_test", "pymongo_test1",
00179 username="foo", password="bar")
00180 self.assertFalse("pymongo_test1" in c.database_names())
00181
00182 self.assertRaises(OperationFailure, c.copy_database,
00183 "pymongo_test", "pymongo_test1",
00184 username="mike", password="bar")
00185 self.assertFalse("pymongo_test1" in c.database_names())
00186
00187 c.copy_database("pymongo_test", "pymongo_test1",
00188 username="mike", password="password")
00189 self.assert_("pymongo_test1" in c.database_names())
00190 self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"])
00191
00192 def test_iteration(self):
00193 connection = Connection(self.host, self.port)
00194
00195 def iterate():
00196 [a for a in connection]
00197
00198 self.assertRaises(TypeError, iterate)
00199
00200
00201
00202 def test_low_network_timeout(self):
00203 c = None
00204 i = 0
00205 n = 10
00206 while c is None and i < n:
00207 try:
00208 c = Connection(self.host, self.port, network_timeout=0.0001)
00209 except AutoReconnect:
00210 i += 1
00211 if i == n:
00212 raise SkipTest()
00213
00214 coll = c.pymongo_test.test
00215
00216 for _ in range(1000):
00217 try:
00218 coll.find_one()
00219 except AutoReconnect:
00220 pass
00221 except AssertionError:
00222 self.fail()
00223
00224 def test_disconnect(self):
00225 c = Connection(self.host, self.port)
00226 coll = c.foo.bar
00227
00228 c.disconnect()
00229 c.disconnect()
00230
00231 coll.count()
00232
00233 c.disconnect()
00234 c.disconnect()
00235
00236 coll.count()
00237
00238 def test_parse_uri(self):
00239 self.assertEqual(([("localhost", 27017)], None, None, None, None, {}),
00240 _parse_uri("localhost", 27017))
00241 self.assertEqual(([("localhost", 27018)], None, None, None, None, {}),
00242 _parse_uri("localhost", 27018))
00243 self.assertRaises(InvalidURI, _parse_uri,
00244 "http://foobar.com", 27017)
00245 self.assertRaises(InvalidURI, _parse_uri,
00246 "http://foo@foobar.com", 27017)
00247
00248 self.assertEqual(([("localhost", 27017)], None, None, None, None, {}),
00249 _parse_uri("mongodb://localhost", 27017))
00250 self.assertEqual(([("localhost", 27017)], None, "fred", "foobar", None, {}),
00251 _parse_uri("mongodb://fred:foobar@localhost",
00252 27017))
00253 self.assertEqual(([("localhost", 27017)], "baz", "fred", "foobar", None, {}),
00254 _parse_uri("mongodb://fred:foobar@localhost/baz",
00255 27017))
00256 self.assertEqual(([("example1.com", 27017), ("example2.com", 27017)],
00257 None, None, None, None, {}),
00258 _parse_uri("mongodb://example1.com:27017,example2.com:27017",
00259 27018))
00260 self.assertEqual(([("localhost", 27017),
00261 ("localhost", 27018),
00262 ("localhost", 27019)], None, None, None, None, {}),
00263 _parse_uri("mongodb://localhost,localhost:27018,localhost:27019",
00264 27017))
00265
00266 self.assertEqual(([("localhost", 27018)], None, None, None, None, {}),
00267 _parse_uri("localhost:27018", 27017))
00268 self.assertEqual(([("localhost", 27017)], "foo", None, None, None, {}),
00269 _parse_uri("localhost/foo", 27017))
00270 self.assertEqual(([("localhost", 27017)], None, None, None, None, {}),
00271 _parse_uri("localhost/", 27017))
00272
00273 self.assertEqual(([("localhost", 27017)], "test", None, None, "yield_historical.in", {}),
00274 _parse_uri("mongodb://localhost/test.yield_historical.in", 27017))
00275 self.assertEqual(([("localhost", 27017)], "test", "fred", "foobar", "yield_historical.in", {}),
00276 _parse_uri("mongodb://fred:foobar@localhost/test.yield_historical.in",
00277 27017))
00278 self.assertEqual(([("example1.com", 27017), ("example2.com", 27017)],
00279 "test", None, None, "yield_historical.in", {}),
00280 _parse_uri("mongodb://example1.com:27017,example2.com:27017/test.yield_historical.in",
00281 27017))
00282 self.assertEqual(([("localhost", 27017)], "test", "fred", "foobar", "yield_historical.in", {'slaveok': 'true'}),
00283 _parse_uri("mongodb://fred:foobar@localhost/test.yield_historical.in?slaveok=true",
00284 27017))
00285
00286 def test_from_uri(self):
00287 c = Connection(self.host, self.port)
00288
00289 self.assertRaises(InvalidURI, Connection, "mongodb://localhost/baz")
00290
00291 self.assertEqual(c, Connection("mongodb://%s:%s" %
00292 (self.host, self.port)))
00293
00294 c.admin.system.users.remove({})
00295 c.pymongo_test.system.users.remove({})
00296
00297 c.admin.add_user("admin", "pass")
00298 c.pymongo_test.add_user("user", "pass")
00299
00300 self.assertRaises(ConfigurationError, Connection,
00301 "mongodb://foo:bar@%s:%s" % (self.host, self.port))
00302 self.assertRaises(ConfigurationError, Connection,
00303 "mongodb://admin:bar@%s:%s" % (self.host, self.port))
00304 self.assertRaises(ConfigurationError, Connection,
00305 "mongodb://user:pass@%s:%s" % (self.host, self.port))
00306 Connection("mongodb://admin:pass@%s:%s" % (self.host, self.port))
00307
00308 self.assertRaises(ConfigurationError, Connection,
00309 "mongodb://admin:pass@%s:%s/pymongo_test" %
00310 (self.host, self.port))
00311 self.assertRaises(ConfigurationError, Connection,
00312 "mongodb://user:foo@%s:%s/pymongo_test" %
00313 (self.host, self.port))
00314 Connection("mongodb://user:pass@%s:%s/pymongo_test" %
00315 (self.host, self.port))
00316
00317 self.assert_(Connection("mongodb://%s:%s" %
00318 (self.host, self.port),
00319 slave_okay=True).slave_okay)
00320 self.assert_(Connection("mongodb://%s:%s/?slaveok=true;w=2" %
00321 (self.host, self.port)).slave_okay)
00322
00323 def test_fork(self):
00324 """Test using a connection before and after a fork.
00325 """
00326 if sys.platform == "win32":
00327 raise SkipTest()
00328
00329 try:
00330 from multiprocessing import Process, Pipe
00331 except ImportError:
00332 raise SkipTest()
00333
00334 db = Connection(self.host, self.port).pymongo_test
00335
00336
00337 db.test.find_one()
00338 db.connection.end_request()
00339
00340 def loop(pipe):
00341 while True:
00342 try:
00343 db.test.insert({"a": "b"}, safe=True)
00344 for _ in db.test.find():
00345 pass
00346 except:
00347 pipe.send(True)
00348 os._exit(1)
00349
00350 cp1, cc1 = Pipe()
00351 cp2, cc2 = Pipe()
00352
00353 p1 = Process(target=loop, args=(cc1,))
00354 p2 = Process(target=loop, args=(cc2,))
00355
00356 p1.start()
00357 p2.start()
00358
00359 p1.join(1)
00360 p2.join(1)
00361
00362 p1.terminate()
00363 p2.terminate()
00364
00365 p1.join()
00366 p2.join()
00367
00368 cc1.close()
00369 cc2.close()
00370
00371
00372 try:
00373 cp1.recv()
00374 self.fail()
00375 except EOFError:
00376 pass
00377 try:
00378 cp2.recv()
00379 self.fail()
00380 except EOFError:
00381 pass
00382
00383 def test_document_class(self):
00384 c = Connection(self.host, self.port)
00385 db = c.pymongo_test
00386 db.test.insert({"x": 1})
00387
00388 self.assertEqual(dict, c.document_class)
00389 self.assert_(isinstance(db.test.find_one(), dict))
00390 self.assertFalse(isinstance(db.test.find_one(), SON))
00391
00392 c.document_class = SON
00393
00394 self.assertEqual(SON, c.document_class)
00395 self.assert_(isinstance(db.test.find_one(), SON))
00396 self.assertFalse(isinstance(db.test.find_one(as_class=dict), SON))
00397
00398 c = Connection(self.host, self.port, document_class=SON)
00399 db = c.pymongo_test
00400
00401 self.assertEqual(SON, c.document_class)
00402 self.assert_(isinstance(db.test.find_one(), SON))
00403 self.assertFalse(isinstance(db.test.find_one(as_class=dict), SON))
00404
00405 c.document_class = dict
00406
00407 self.assertEqual(dict, c.document_class)
00408 self.assert_(isinstance(db.test.find_one(), dict))
00409 self.assertFalse(isinstance(db.test.find_one(), SON))
00410
00411 def test_network_timeout(self):
00412 no_timeout = Connection(self.host, self.port)
00413 timeout = Connection(self.host, self.port, network_timeout=0.1)
00414
00415 no_timeout.pymongo_test.drop_collection("test")
00416 no_timeout.pymongo_test.test.insert({"x": 1}, safe=True)
00417
00418 where_func = """function (doc) {
00419 var d = new Date().getTime() + 200;
00420 var x = new Date().getTime();
00421 while (x < d) {
00422 x = new Date().getTime();
00423 }
00424 return true;
00425 }"""
00426
00427 def get_x(db):
00428 return db.test.find().where(where_func).next()["x"]
00429 self.assertEqual(1, get_x(no_timeout.pymongo_test))
00430 self.assertRaises(ConnectionFailure, get_x, timeout.pymongo_test)
00431
00432 def get_x_timeout(db, t):
00433 return db.test.find(network_timeout=t).where(where_func).next()["x"]
00434 self.assertEqual(1, get_x_timeout(timeout.pymongo_test, None))
00435 self.assertRaises(ConnectionFailure, get_x_timeout,
00436 no_timeout.pymongo_test, 0.1)
00437
00438 def test_tz_aware(self):
00439 aware = Connection(self.host, self.port, tz_aware=True)
00440 naive = Connection(self.host, self.port)
00441 aware.pymongo_test.drop_collection("test")
00442
00443 now = datetime.datetime.utcnow()
00444 aware.pymongo_test.test.insert({"x": now}, safe=True)
00445
00446 self.assertEqual(None, naive.pymongo_test.test.find_one()["x"].tzinfo)
00447 self.assertEqual(utc, aware.pymongo_test.test.find_one()["x"].tzinfo)
00448 self.assertEqual(aware.pymongo_test.test.find_one()["x"].replace(tzinfo=None),
00449 naive.pymongo_test.test.find_one()["x"])
00450
00451
00452 if __name__ == "__main__":
00453 unittest.main()