|
25 | 25 | from google.cloud.ndb import _retry |
26 | 26 | from google.cloud.ndb import tasklets |
27 | 27 |
|
| 28 | +from . import utils |
| 29 | + |
28 | 30 |
|
29 | 31 | class Test_retry: |
30 | 32 | @staticmethod |
@@ -79,6 +81,40 @@ def test_transient_error(core_retry, sleep): |
79 | 81 |
|
80 | 82 | sleep.assert_called_once_with(0) |
81 | 83 |
|
| 84 | + @staticmethod |
| 85 | + @pytest.mark.usefixtures("in_context") |
| 86 | + @mock.patch("google.cloud.ndb.tasklets.sleep") |
| 87 | + @mock.patch("google.cloud.ndb._retry.core_retry") |
| 88 | + def test_transient_error_callback_is_tasklet(core_retry, sleep): |
| 89 | + """Regression test for #519 |
| 90 | +
|
| 91 | + https://github.com/googleapis/python-ndb/issues/519 |
| 92 | + """ |
| 93 | + core_retry.exponential_sleep_generator.return_value = itertools.count() |
| 94 | + core_retry.if_transient_error.return_value = True |
| 95 | + |
| 96 | + sleep_future = tasklets.Future("sleep") |
| 97 | + sleep.return_value = sleep_future |
| 98 | + |
| 99 | + callback = mock.Mock( |
| 100 | + side_effect=[ |
| 101 | + utils.future_exception(Exception("Spurious error.")), |
| 102 | + utils.future_result("foo"), |
| 103 | + ] |
| 104 | + ) |
| 105 | + retry = _retry.retry_async(callback) |
| 106 | + future = retry() |
| 107 | + |
| 108 | + # This is the important check for the bug in #519. We need to make sure |
| 109 | + # that we're waiting for the sleep future to complete before moving on. |
| 110 | + assert future.running() |
| 111 | + |
| 112 | + # Finish sleeping |
| 113 | + sleep_future.set_result(None) |
| 114 | + assert future.result() == "foo" |
| 115 | + |
| 116 | + sleep.assert_called_once_with(0) |
| 117 | + |
82 | 118 | @staticmethod |
83 | 119 | @pytest.mark.usefixtures("in_context") |
84 | 120 | @mock.patch("google.cloud.ndb.tasklets.sleep") |
|
0 commit comments