]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
gen_test: Port some tests to non-deprecated interfaces 2319/head
authorBen Darnell <ben@bendarnell.com>
Fri, 23 Mar 2018 22:10:53 +0000 (18:10 -0400)
committerBen Darnell <ben@bendarnell.com>
Fri, 23 Mar 2018 22:10:53 +0000 (18:10 -0400)
This temporarily duplicates the tests, but the versions using the
deprecated interfaces will be gone in 6.0

tornado/test/gen_test.py

index 373fae79a63994c8acadd3513686f6ad5c2f1601..8b2f62b9728acbc9254f535689de56a2585d6db1 100644 (file)
@@ -667,6 +667,236 @@ class GenEngineTest(AsyncTestCase):
         self.assertIs(self.task_ref(), None)
 
 
+# GenBasicTest duplicates the non-deprecated portions of GenEngineTest
+# with gen.coroutine to ensure we don't lose coverage when gen.engine
+# goes away.
+class GenBasicTest(AsyncTestCase):
+    @gen.coroutine
+    def delay(self, iterations, arg):
+        """Returns arg after a number of IOLoop iterations."""
+        for i in range(iterations):
+            yield gen.moment
+        raise gen.Return(arg)
+
+    @return_future
+    def async_future(self, result, callback):
+        self.io_loop.add_callback(callback, result)
+
+    @gen.coroutine
+    def async_exception(self, e):
+        yield gen.moment
+        raise e
+
+    @gen.coroutine
+    def add_one_async(self, x):
+        yield gen.moment
+        raise gen.Return(x + 1)
+
+    def test_no_yield(self):
+        @gen.coroutine
+        def f():
+            pass
+        self.io_loop.run_sync(f)
+
+    def test_exception_phase1(self):
+        @gen.coroutine
+        def f():
+            1 / 0
+        self.assertRaises(ZeroDivisionError, self.io_loop.run_sync, f)
+
+    def test_exception_phase2(self):
+        @gen.coroutine
+        def f():
+            yield gen.moment
+            1 / 0
+        self.assertRaises(ZeroDivisionError, self.io_loop.run_sync, f)
+
+    def test_bogus_yield(self):
+        @gen.coroutine
+        def f():
+            yield 42
+        self.assertRaises(gen.BadYieldError, self.io_loop.run_sync, f)
+
+    def test_bogus_yield_tuple(self):
+        @gen.coroutine
+        def f():
+            yield (1, 2)
+        self.assertRaises(gen.BadYieldError, self.io_loop.run_sync, f)
+
+    def test_reuse(self):
+        @gen.coroutine
+        def f():
+            yield gen.moment
+        self.io_loop.run_sync(f)
+        self.io_loop.run_sync(f)
+
+    def test_none(self):
+        @gen.coroutine
+        def f():
+            yield None
+        self.io_loop.run_sync(f)
+
+    def test_multi(self):
+        @gen.coroutine
+        def f():
+            results = yield [self.add_one_async(1), self.add_one_async(2)]
+            self.assertEqual(results, [2, 3])
+        self.io_loop.run_sync(f)
+
+    def test_multi_dict(self):
+        @gen.coroutine
+        def f():
+            results = yield dict(foo=self.add_one_async(1), bar=self.add_one_async(2))
+            self.assertEqual(results, dict(foo=2, bar=3))
+        self.io_loop.run_sync(f)
+
+    def test_multi_delayed(self):
+        @gen.coroutine
+        def f():
+            # callbacks run at different times
+            responses = yield gen.multi_future([
+                self.delay(3, "v1"),
+                self.delay(1, "v2"),
+            ])
+            self.assertEqual(responses, ["v1", "v2"])
+        self.io_loop.run_sync(f)
+
+    def test_multi_dict_delayed(self):
+        @gen.coroutine
+        def f():
+            # callbacks run at different times
+            responses = yield gen.multi_future(dict(
+                foo=self.delay(3, "v1"),
+                bar=self.delay(1, "v2"),
+            ))
+            self.assertEqual(responses, dict(foo="v1", bar="v2"))
+        self.io_loop.run_sync(f)
+
+    @skipOnTravis
+    @gen_test
+    def test_multi_performance(self):
+        # Yielding a list used to have quadratic performance; make
+        # sure a large list stays reasonable.  On my laptop a list of
+        # 2000 used to take 1.8s, now it takes 0.12.
+        start = time.time()
+        yield [gen.moment for i in range(2000)]
+        end = time.time()
+        self.assertLess(end - start, 1.0)
+
+    @gen_test
+    def test_multi_empty(self):
+        # Empty lists or dicts should return the same type.
+        x = yield []
+        self.assertTrue(isinstance(x, list))
+        y = yield {}
+        self.assertTrue(isinstance(y, dict))
+
+    @gen_test
+    def test_future(self):
+        result = yield self.async_future(1)
+        self.assertEqual(result, 1)
+
+    @gen_test
+    def test_multi_future(self):
+        results = yield [self.async_future(1), self.async_future(2)]
+        self.assertEqual(results, [1, 2])
+
+    @gen_test
+    def test_multi_future_duplicate(self):
+        f = self.async_future(2)
+        results = yield [self.async_future(1), f, self.async_future(3), f]
+        self.assertEqual(results, [1, 2, 3, 2])
+
+    @gen_test
+    def test_multi_dict_future(self):
+        results = yield dict(foo=self.async_future(1), bar=self.async_future(2))
+        self.assertEqual(results, dict(foo=1, bar=2))
+
+    @gen_test
+    def test_multi_exceptions(self):
+        with ExpectLog(app_log, "Multiple exceptions in yield list"):
+            with self.assertRaises(RuntimeError) as cm:
+                yield gen.Multi([self.async_exception(RuntimeError("error 1")),
+                                 self.async_exception(RuntimeError("error 2"))])
+        self.assertEqual(str(cm.exception), "error 1")
+
+        # With only one exception, no error is logged.
+        with self.assertRaises(RuntimeError):
+            yield gen.Multi([self.async_exception(RuntimeError("error 1")),
+                             self.async_future(2)])
+
+        # Exception logging may be explicitly quieted.
+        with self.assertRaises(RuntimeError):
+            yield gen.Multi([self.async_exception(RuntimeError("error 1")),
+                             self.async_exception(RuntimeError("error 2"))],
+                            quiet_exceptions=RuntimeError)
+
+    @gen_test
+    def test_multi_future_exceptions(self):
+        with ExpectLog(app_log, "Multiple exceptions in yield list"):
+            with self.assertRaises(RuntimeError) as cm:
+                yield [self.async_exception(RuntimeError("error 1")),
+                       self.async_exception(RuntimeError("error 2"))]
+        self.assertEqual(str(cm.exception), "error 1")
+
+        # With only one exception, no error is logged.
+        with self.assertRaises(RuntimeError):
+            yield [self.async_exception(RuntimeError("error 1")),
+                   self.async_future(2)]
+
+        # Exception logging may be explicitly quieted.
+        with self.assertRaises(RuntimeError):
+            yield gen.multi_future(
+                [self.async_exception(RuntimeError("error 1")),
+                 self.async_exception(RuntimeError("error 2"))],
+                quiet_exceptions=RuntimeError)
+
+    def test_sync_raise_return(self):
+        @gen.coroutine
+        def f():
+            raise gen.Return()
+
+        self.io_loop.run_sync(f)
+
+    def test_async_raise_return(self):
+        @gen.coroutine
+        def f():
+            yield gen.moment
+            raise gen.Return()
+
+        self.io_loop.run_sync(f)
+
+    def test_sync_raise_return_value(self):
+        @gen.coroutine
+        def f():
+            raise gen.Return(42)
+
+        self.assertEqual(42, self.io_loop.run_sync(f))
+
+    def test_sync_raise_return_value_tuple(self):
+        @gen.coroutine
+        def f():
+            raise gen.Return((1, 2))
+
+        self.assertEqual((1, 2), self.io_loop.run_sync(f))
+
+    def test_async_raise_return_value(self):
+        @gen.coroutine
+        def f():
+            yield gen.moment
+            raise gen.Return(42)
+
+        self.assertEqual(42, self.io_loop.run_sync(f))
+
+    def test_async_raise_return_value_tuple(self):
+        @gen.coroutine
+        def f():
+            yield gen.moment
+            raise gen.Return((1, 2))
+
+        self.assertEqual((1, 2), self.io_loop.run_sync(f))
+
+
 class GenCoroutineTest(AsyncTestCase):
     def setUp(self):
         # Stray StopIteration exceptions can lead to tests exiting prematurely,