Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #34 from ajdavis/master

Some more unittest improvements
  • Loading branch information...
commit fac2c392c0df5446d5ffccabe8471c04605b7670 2 parents 7fb9bd5 + e7f8429
@jehiah jehiah authored
View
0  test/__init__.py
No changes.
View
65 test/test_command.py
@@ -0,0 +1,65 @@
+import tornado.ioloop
+
+import test_shunt
+import asyncmongo
+
+
+class CommandTest(
+ test_shunt.MongoTest,
+ test_shunt.SynchronousMongoTest,
+):
+ mongod_options = [('--port', '27017')]
+
+ def setUp(self):
+ super(CommandTest, self).setUp()
+ self.pymongo_conn.test.foo.insert({'_id': 1})
+
+ def test_find_and_modify(self):
+ db = asyncmongo.Client(pool_id='test_query', host='127.0.0.1', port=int(self.mongod_options[0][1]), dbname='test', mincached=3)
+
+ results = []
+
+ def callback(response, error):
+ tornado.ioloop.IOLoop.instance().stop()
+ self.assert_(error is None)
+ results.append(response['value'])
+
+ before = self.get_open_cursors()
+
+ # First findAndModify creates doc with i: 2 and s: 'a'
+ db.command('findAndModify', 'foo',
+ callback=callback,
+ query={'_id': 2},
+ update={'$set': {'s': 'a'}},
+ upsert=True,
+ new=True,
+ )
+
+ tornado.ioloop.IOLoop.instance().start()
+ self.assertEqual(
+ {'_id': 2, 's': 'a'},
+ results[0]
+ )
+
+ # Second findAndModify updates doc with i: 2, sets s to 'b'
+ db.command('findAndModify', 'foo',
+ callback=callback,
+ query={'_id': 2},
+ update={'$set': {'s': 'b'}},
+ upsert=True,
+ new=True,
+ )
+
+ tornado.ioloop.IOLoop.instance().start()
+ self.assertEqual(
+ {'_id': 2, 's': 'b'},
+ results[1]
+ )
+
+ # check cursors
+ after = self.get_open_cursors()
+ assert before == after, "%d cursors left open (should be 0)" % (after - before)
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
View
24 test/test_connection.py
@@ -4,10 +4,34 @@
import test_shunt
import asyncmongo
+from asyncmongo.errors import DataError
TEST_TIMESTAMP = int(time.time())
class ConnectionTest(test_shunt.MongoTest):
+ def test_getitem(self):
+ db = asyncmongo.Client(pool_id='test_query', host='127.0.0.1', port=27017, dbname='test', mincached=3)
+ self.assert_(
+ repr(db['foo']) == repr(db.foo),
+ "dict-style access of a collection should be same as property access"
+ )
+
+ def test_connection(self):
+ db = asyncmongo.Client(pool_id='test_query', host='127.0.0.1', port=27017, dbname='test', mincached=3)
+ for connection_name in [
+ '.',
+ '..',
+ '.foo',
+ 'foo.',
+ '.foo.',
+ 'foo\x00'
+ '\x00foo'
+ ]:
+ self.assertRaises(
+ DataError,
+ lambda: db.connection(connection_name)
+ )
+
def test_query(self):
logging.info('in test_query')
test_shunt.setup()
View
19 test/test_pooled_db.py
@@ -1,6 +1,7 @@
import tornado.ioloop
import logging
import time
+from asyncmongo.errors import TooManyConnections
import test_shunt
import asyncmongo
@@ -47,3 +48,21 @@ def pool_callback2(response, error):
tornado.ioloop.IOLoop.instance().start()
test_shunt.assert_called('pool1')
test_shunt.assert_called('pool2')
+
+ def too_many_connections(self):
+ clients = [
+ asyncmongo.Client('id2', maxconnections=2, host='127.0.0.1', port=27017, dbname='test')
+ for i in range(3)
+ ]
+
+ def callback(response, error):
+ pass
+
+ for client in clients[:2]:
+ client.connection('foo').find({}, callback=callback)
+
+ self.assertRaises(
+ TooManyConnections,
+ lambda: clients[2].connection('foo').find({}, callback=callback)
+ )
+
View
13 test/test_query.py
@@ -4,22 +4,11 @@
import test_shunt
import asyncmongo
-import pymongo
-class QueryTest(test_shunt.MongoTest):
+class QueryTest(test_shunt.MongoTest, test_shunt.SynchronousMongoTest):
mongod_options = [('--port', '27017')]
- @property
- def pymongo_conn(self):
- if not hasattr(self, '_pymongo_conn'):
- self._pymongo_conn = pymongo.Connection(port=int(self.mongod_options[0][1]))
- return self._pymongo_conn
-
- def get_open_cursors(self):
- output = self.pymongo_conn.admin.command('serverStatus')
- return output.get('cursors', {}).get('totalOpen')
-
def setUp(self):
super(QueryTest, self).setUp()
self.pymongo_conn.test.foo.insert([{'i': i} for i in xrange(200)])
View
48 test/test_shunt.py
@@ -6,6 +6,9 @@
import signal
import time
+import tornado.ioloop
+import pymongo
+
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG,
format='%(asctime)s %(process)d %(filename)s %(lineno)d %(levelname)s #| %(message)s',
datefmt='%H:%M:%S')
@@ -22,11 +25,35 @@
# make sure we get the local asyncmongo
assert asyncmongo.__file__.startswith(app_dir)
+class PuritanicalIOLoop(tornado.ioloop.IOLoop):
+ """
+ A loop that quits when it encounters an Exception -- makes errors in
+ callbacks easier to debug and prevents them from hanging the unittest
+ suite.
+ """
+ def handle_callback_exception(self, callback):
+ exc_type, exc_value, tb = sys.exc_info()
+ raise exc_value
class MongoTest(unittest.TestCase):
+ """
+ Starts and stops a mongod
+ """
mongod_options = [('--port', str(27017))]
def setUp(self):
"""setup method that starts up mongod instances using `self.mongo_options`"""
+ # So any function that calls IOLoop.instance() gets the
+ # PuritanicalIOLoop instead of a default loop.
+ if not tornado.ioloop.IOLoop.initialized():
+ self.loop = PuritanicalIOLoop()
+ self.loop.install()
+ else:
+ self.loop = tornado.ioloop.IOLoop.instance()
+ self.assert_(
+ isinstance(self.loop, PuritanicalIOLoop),
+ "Couldn't install IOLoop"
+ )
+
self.temp_dirs = []
self.mongods = []
for options in self.mongod_options:
@@ -42,11 +69,11 @@ def setUp(self):
sleep_time = 1 + (len(self.mongods) * 2)
logging.info('waiting for mongod to start (sleeping %d seconds)' % sleep_time)
time.sleep(sleep_time)
- asyncmongo.pool.ConnectionPools.close_idle_connections()
-
+
def tearDown(self):
"""teardown method that cleans up child mongod instances, and removes their temporary data files"""
logging.debug('teardown')
+ asyncmongo.pool.ConnectionPools.close_idle_connections()
for mongod in self.mongods:
logging.debug('killing mongod %s' % mongod.pid)
os.kill(mongod.pid, signal.SIGKILL)
@@ -56,6 +83,23 @@ def tearDown(self):
pipe = subprocess.Popen(['rm', '-rf', dirname])
pipe.wait()
+
+class SynchronousMongoTest(unittest.TestCase):
+ """
+ Convenience class: a test case that can make synchronous calls to the
+ official pymongo to ease setup code, via the pymongo_conn property.
+ """
+ mongod_options = [('--port', str(27017))]
+ @property
+ def pymongo_conn(self):
+ if not hasattr(self, '_pymongo_conn'):
+ self._pymongo_conn = pymongo.Connection(port=int(self.mongod_options[0][1]))
+ return self._pymongo_conn
+
+ def get_open_cursors(self):
+ output = self.pymongo_conn.admin.command('serverStatus')
+ return output.get('cursors', {}).get('totalOpen')
+
results = {}
def setup():
Please sign in to comment.
Something went wrong with that request. Please try again.