Skip to content
This repository

Some more unittest improvements #34

Merged
merged 5 commits into from about 2 years ago

2 participants

A. Jesse Jiryu Davis Jehiah Czebotar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
0  test/__init__.py
No changes.
65  test/test_command.py
... ...
@@ -0,0 +1,65 @@
  1
+import tornado.ioloop
  2
+
  3
+import test_shunt
  4
+import asyncmongo
  5
+
  6
+
  7
+class CommandTest(
  8
+    test_shunt.MongoTest,
  9
+    test_shunt.SynchronousMongoTest,
  10
+):
  11
+    mongod_options = [('--port', '27017')]
  12
+
  13
+    def setUp(self):
  14
+        super(CommandTest, self).setUp()
  15
+        self.pymongo_conn.test.foo.insert({'_id': 1})
  16
+
  17
+    def test_find_and_modify(self):
  18
+        db = asyncmongo.Client(pool_id='test_query', host='127.0.0.1', port=int(self.mongod_options[0][1]), dbname='test', mincached=3)
  19
+
  20
+        results = []
  21
+
  22
+        def callback(response, error):
  23
+            tornado.ioloop.IOLoop.instance().stop()
  24
+            self.assert_(error is None)
  25
+            results.append(response['value'])
  26
+
  27
+        before = self.get_open_cursors()
  28
+
  29
+        # First findAndModify creates doc with i: 2 and s: 'a'
  30
+        db.command('findAndModify', 'foo',
  31
+            callback=callback,
  32
+            query={'_id': 2},
  33
+            update={'$set': {'s': 'a'}},
  34
+            upsert=True,
  35
+            new=True,
  36
+        )
  37
+
  38
+        tornado.ioloop.IOLoop.instance().start()
  39
+        self.assertEqual(
  40
+            {'_id': 2, 's': 'a'},
  41
+            results[0]
  42
+        )
  43
+
  44
+        # Second findAndModify updates doc with i: 2, sets s to 'b'
  45
+        db.command('findAndModify', 'foo',
  46
+            callback=callback,
  47
+            query={'_id': 2},
  48
+            update={'$set': {'s': 'b'}},
  49
+            upsert=True,
  50
+            new=True,
  51
+        )
  52
+
  53
+        tornado.ioloop.IOLoop.instance().start()
  54
+        self.assertEqual(
  55
+            {'_id': 2, 's': 'b'},
  56
+            results[1]
  57
+        )
  58
+
  59
+        # check cursors
  60
+        after = self.get_open_cursors()
  61
+        assert before == after, "%d cursors left open (should be 0)" % (after - before)
  62
+
  63
+if __name__ == '__main__':
  64
+    import unittest
  65
+    unittest.main()
24  test/test_connection.py
@@ -4,10 +4,34 @@
4 4
 
5 5
 import test_shunt
6 6
 import asyncmongo
  7
+from asyncmongo.errors import DataError
7 8
 
8 9
 TEST_TIMESTAMP = int(time.time())
9 10
 
10 11
 class ConnectionTest(test_shunt.MongoTest):
  12
+    def test_getitem(self):
  13
+        db = asyncmongo.Client(pool_id='test_query', host='127.0.0.1', port=27017, dbname='test', mincached=3)
  14
+        self.assert_(
  15
+            repr(db['foo']) == repr(db.foo),
  16
+            "dict-style access of a collection should be same as property access"
  17
+        )
  18
+
  19
+    def test_connection(self):
  20
+        db = asyncmongo.Client(pool_id='test_query', host='127.0.0.1', port=27017, dbname='test', mincached=3)
  21
+        for connection_name in [
  22
+            '.',
  23
+            '..',
  24
+            '.foo',
  25
+            'foo.',
  26
+            '.foo.',
  27
+            'foo\x00'
  28
+            '\x00foo'
  29
+        ]:
  30
+            self.assertRaises(
  31
+                DataError,
  32
+                lambda: db.connection(connection_name)
  33
+            )
  34
+
11 35
     def test_query(self):
12 36
         logging.info('in test_query')
13 37
         test_shunt.setup()
19  test/test_pooled_db.py
... ...
@@ -1,6 +1,7 @@
1 1
 import tornado.ioloop
2 2
 import logging
3 3
 import time
  4
+from asyncmongo.errors import TooManyConnections
4 5
 
5 6
 import test_shunt
6 7
 import asyncmongo
@@ -47,3 +48,21 @@ def pool_callback2(response, error):
47 48
         tornado.ioloop.IOLoop.instance().start()
48 49
         test_shunt.assert_called('pool1')
49 50
         test_shunt.assert_called('pool2')
  51
+
  52
+    def too_many_connections(self):
  53
+        clients = [
  54
+            asyncmongo.Client('id2', maxconnections=2, host='127.0.0.1', port=27017, dbname='test')
  55
+            for i in range(3)
  56
+        ]
  57
+
  58
+        def callback(response, error):
  59
+            pass
  60
+
  61
+        for client in clients[:2]:
  62
+            client.connection('foo').find({}, callback=callback)
  63
+
  64
+        self.assertRaises(
  65
+            TooManyConnections,
  66
+            lambda: clients[2].connection('foo').find({}, callback=callback)
  67
+        )
  68
+
13  test/test_query.py
@@ -4,22 +4,11 @@
4 4
 
5 5
 import test_shunt
6 6
 import asyncmongo
7  
-import pymongo
8 7
 
9 8
 
10  
-class QueryTest(test_shunt.MongoTest):
  9
+class QueryTest(test_shunt.MongoTest, test_shunt.SynchronousMongoTest):
11 10
     mongod_options = [('--port', '27017')]
12 11
 
13  
-    @property
14  
-    def pymongo_conn(self):
15  
-        if not hasattr(self, '_pymongo_conn'):
16  
-            self._pymongo_conn = pymongo.Connection(port=int(self.mongod_options[0][1]))
17  
-        return self._pymongo_conn
18  
-
19  
-    def get_open_cursors(self):
20  
-        output = self.pymongo_conn.admin.command('serverStatus')
21  
-        return output.get('cursors', {}).get('totalOpen')
22  
-
23 12
     def setUp(self):
24 13
         super(QueryTest, self).setUp()
25 14
         self.pymongo_conn.test.foo.insert([{'i': i} for i in xrange(200)])
48  test/test_shunt.py
@@ -6,6 +6,9 @@
6 6
 import signal
7 7
 import time
8 8
 
  9
+import tornado.ioloop
  10
+import pymongo
  11
+
9 12
 logging.basicConfig(stream=sys.stdout, level=logging.DEBUG,
10 13
    format='%(asctime)s %(process)d %(filename)s %(lineno)d %(levelname)s #| %(message)s',
11 14
    datefmt='%H:%M:%S')
@@ -22,11 +25,35 @@
22 25
 # make sure we get the local asyncmongo
23 26
 assert asyncmongo.__file__.startswith(app_dir)
24 27
 
  28
+class PuritanicalIOLoop(tornado.ioloop.IOLoop):
  29
+    """
  30
+    A loop that quits when it encounters an Exception -- makes errors in
  31
+    callbacks easier to debug and prevents them from hanging the unittest
  32
+    suite.
  33
+    """
  34
+    def handle_callback_exception(self, callback):
  35
+        exc_type, exc_value, tb = sys.exc_info()
  36
+        raise exc_value
25 37
 
26 38
 class MongoTest(unittest.TestCase):
  39
+    """
  40
+    Starts and stops a mongod
  41
+    """
27 42
     mongod_options = [('--port', str(27017))]
28 43
     def setUp(self):
29 44
         """setup method that starts up mongod instances using `self.mongo_options`"""
  45
+        # So any function that calls IOLoop.instance() gets the
  46
+        # PuritanicalIOLoop instead of a default loop.
  47
+        if not tornado.ioloop.IOLoop.initialized():
  48
+            self.loop = PuritanicalIOLoop()
  49
+            self.loop.install()
  50
+        else:
  51
+            self.loop = tornado.ioloop.IOLoop.instance()
  52
+            self.assert_(
  53
+                isinstance(self.loop, PuritanicalIOLoop),
  54
+                "Couldn't install IOLoop"
  55
+            )
  56
+            
30 57
         self.temp_dirs = []
31 58
         self.mongods = []
32 59
         for options in self.mongod_options:
@@ -42,11 +69,11 @@ def setUp(self):
42 69
         sleep_time = 1 + (len(self.mongods) * 2)
43 70
         logging.info('waiting for mongod to start (sleeping %d seconds)' % sleep_time)
44 71
         time.sleep(sleep_time)
45  
-        asyncmongo.pool.ConnectionPools.close_idle_connections()
46  
-    
  72
+
47 73
     def tearDown(self):
48 74
         """teardown method that cleans up child mongod instances, and removes their temporary data files"""
49 75
         logging.debug('teardown')
  76
+        asyncmongo.pool.ConnectionPools.close_idle_connections()
50 77
         for mongod in self.mongods:
51 78
             logging.debug('killing mongod %s' % mongod.pid)
52 79
             os.kill(mongod.pid, signal.SIGKILL)
@@ -56,6 +83,23 @@ def tearDown(self):
56 83
             pipe = subprocess.Popen(['rm', '-rf', dirname])
57 84
             pipe.wait()
58 85
 
  86
+
  87
+class SynchronousMongoTest(unittest.TestCase):
  88
+    """
  89
+    Convenience class: a test case that can make synchronous calls to the
  90
+    official pymongo to ease setup code, via the pymongo_conn property.
  91
+    """
  92
+    mongod_options = [('--port', str(27017))]
  93
+    @property
  94
+    def pymongo_conn(self):
  95
+        if not hasattr(self, '_pymongo_conn'):
  96
+            self._pymongo_conn = pymongo.Connection(port=int(self.mongod_options[0][1]))
  97
+        return self._pymongo_conn
  98
+
  99
+    def get_open_cursors(self):
  100
+        output = self.pymongo_conn.admin.command('serverStatus')
  101
+        return output.get('cursors', {}).get('totalOpen')
  102
+
59 103
 results = {}
60 104
 
61 105
 def setup():
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.