async def test_watch_timeout_with_resource_version(self):
        fake_resp = CoroutineMock()
        fake_resp.content.readline = CoroutineMock()
        fake_resp.release = Mock()

        fake_resp.content.readline.side_effect = [asyncio.TimeoutError(), b""]

        fake_api = Mock()
        fake_api.get_namespaces = CoroutineMock(return_value=fake_resp)
        fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList'

        watch = kubernetes_asyncio.watch.Watch()
        async with watch.stream(fake_api.get_namespaces,
                                resource_version='10') as stream:
            async for e in stream:  # noqa
                pass

        # all calls use the passed resource version
        fake_api.get_namespaces.assert_has_calls([
            call(_preload_content=False, watch=True, resource_version='10'),
            call(_preload_content=False, watch=True, resource_version='10')
        ])

        fake_resp.release.assert_called_once_with()
        self.assertEqual(watch.resource_version, '10')
    async def test_watch_for_follow(self):
        fake_resp = CoroutineMock()
        fake_resp.content.readline = CoroutineMock()
        fake_resp.release = Mock()
        side_effects = ['log_line_1', 'log_line_2']
        side_effects = [_.encode('utf8') for _ in side_effects]
        side_effects.extend([AssertionError('Should not have been called')])
        fake_resp.content.readline.side_effect = side_effects

        fake_api = Mock()
        fake_api.read_namespaced_pod_log = CoroutineMock(
            return_value=fake_resp)
        fake_api.read_namespaced_pod_log.__doc__ = ':param bool follow:\n:return: str'

        watch = kubernetes_asyncio.watch.Watch()
        count = 1
        async with watch:
            async for e in watch.stream(fake_api.read_namespaced_pod_log):
                self.assertEqual("log_line_1", e)
                # Stop the watch. This must not return the next event which would
                # be an AssertionError exception.
                count += 1
                if count == len(side_effects) - 1:
                    watch.stop()

        fake_api.read_namespaced_pod_log.assert_called_once_with(
            _preload_content=False, follow=True)
        fake_resp.release.assert_called_once_with()
    async def test_watch_with_decode(self):
        fake_resp = CoroutineMock()
        fake_resp.content.readline = CoroutineMock()
        fake_resp.release = Mock()
        side_effects = [{
            "type": "ADDED",
            "object": {
                "metadata": {
                    "name": "test{}".format(uid),
                    "resourceVersion": str(uid)
                },
                "spec": {},
                "status": {}
            }
        } for uid in range(3)]
        side_effects = [json.dumps(_).encode('utf8') for _ in side_effects]
        side_effects.extend([AssertionError('Should not have been called')])
        fake_resp.content.readline.side_effect = side_effects

        fake_api = Mock()
        fake_api.get_namespaces = CoroutineMock(return_value=fake_resp)
        fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList'

        watch = kubernetes_asyncio.watch.Watch()
        count = 0
        async with watch:
            async for e in watch.stream(fake_api.get_namespaces,
                                        resource_version='123'):
                self.assertEqual("ADDED", e['type'])
                # make sure decoder worked and we got a model with the right name
                self.assertEqual("test%d" % count, e['object'].metadata.name)
                # make sure decoder worked and updated Watch.resource_version
                self.assertEqual(e['object'].metadata.resource_version,
                                 str(count))
                self.assertEqual(watch.resource_version, str(count))

                # Stop the watch. This must not return the next event which would
                # be an AssertionError exception.
                count += 1
                if count == len(side_effects) - 1:
                    watch.stop()

        fake_api.get_namespaces.assert_called_once_with(_preload_content=False,
                                                        watch=True,
                                                        resource_version='123')
        fake_resp.release.assert_called_once_with()

        # last resource_version has to be stored in the object
        self.assertEqual(watch.resource_version, '2')
    async def test_watch_timeout(self):
        fake_resp = CoroutineMock()
        fake_resp.content.readline = CoroutineMock()
        fake_resp.release = Mock()

        mock_event = {
            "type": "ADDED",
            "object": {
                "metadata": {
                    "name": "test1555",
                    "resourceVersion": "1555"
                },
                "spec": {},
                "status": {}
            }
        }

        fake_resp.content.readline.side_effect = [
            json.dumps(mock_event).encode('utf8'),
            asyncio.TimeoutError(), b""
        ]

        fake_api = Mock()
        fake_api.get_namespaces = CoroutineMock(return_value=fake_resp)
        fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList'

        watch = kubernetes_asyncio.watch.Watch()
        async with watch.stream(fake_api.get_namespaces) as stream:
            async for e in stream:  # noqa
                pass

        fake_api.get_namespaces.assert_has_calls([
            call(_preload_content=False, watch=True),
            call(_preload_content=False, watch=True, resource_version='1555')
        ])
        fake_resp.release.assert_called_once_with()