From: Ben Darnell Date: Fri, 23 Mar 2018 22:10:53 +0000 (-0400) Subject: gen_test: Port some tests to non-deprecated interfaces X-Git-Tag: v5.1.0b1~36^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F2319%2Fhead;p=thirdparty%2Ftornado.git gen_test: Port some tests to non-deprecated interfaces This temporarily duplicates the tests, but the versions using the deprecated interfaces will be gone in 6.0 --- diff --git a/tornado/test/gen_test.py b/tornado/test/gen_test.py index 373fae79a..8b2f62b97 100644 --- a/tornado/test/gen_test.py +++ b/tornado/test/gen_test.py @@ -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,