Exemple #1
0
    def test_update_ok_feed_3(self, mock_session, mock_request):
        """Test updating feed is ok."""
        mock_session.return_value.__enter__.return_value.send\
            .return_value.ok = True
        mock_session.return_value.__enter__.return_value.send\
            .return_value.text = load_fixture('generic_feed_3.xml')

        feed = MockGeoRssFeed(HOME_COORDINATES_1, None)
        status, entries = feed.update()
        assert status == UPDATE_OK
        self.assertIsNotNone(entries)
        assert len(entries) == 3

        feed_entry = entries[0]
        assert feed_entry.external_id == "1234"
        assert feed_entry.coordinates == (-34.93728111547821,
                                          148.59710883878262)
        self.assertAlmostEqual(feed_entry.distance_to_home, 491.7, 1)

        feed_entry = entries[1]
        assert feed_entry.external_id == "2345"
        assert feed_entry.coordinates == (-34.937170989, 148.597182317)
        self.assertAlmostEqual(feed_entry.distance_to_home, 491.8, 1)

        feed_entry = entries[2]
        assert feed_entry.external_id == "3456"
        assert feed_entry.coordinates == (-29.962746645660683,
                                          152.43090880416074)
        self.assertAlmostEqual(feed_entry.distance_to_home, 176.5, 1)
Exemple #2
0
    def test_update_error(self, mock_session, mock_request):
        """Test updating feed results in error."""
        mock_session.return_value.__enter__.return_value.send.return_value.ok = False

        feed = MockGeoRssFeed(HOME_COORDINATES_1, None)
        status, entries = feed.update()
        assert status == UPDATE_ERROR
Exemple #3
0
    def test_update_bom(self, mock_session, mock_request):
        """Test updating feed with BOM (byte order mark) is ok."""
        mock_session.return_value.__enter__.return_value.send.return_value.ok = True
        mock_session.return_value.__enter__.return_value.send.return_value.text = (
            load_fixture("xml_parser_bom_1.xml"))

        feed = MockGeoRssFeed(HOME_COORDINATES_1, None)
        assert (repr(feed) == "<MockGeoRssFeed(home=(-31.0, 151.0), "
                "url=None, radius=None, categories=None)>")
        status, entries = feed.update()
        assert status == UPDATE_OK
        self.assertIsNotNone(entries)
        assert len(entries) == 0
Exemple #4
0
    def test_update_ok_with_radius_filtering(self, mock_session, mock_request):
        """Test updating feed is ok."""
        mock_session.return_value.__enter__.return_value.send.return_value.ok = True
        mock_session.return_value.__enter__.return_value.send.return_value.text = (
            load_fixture("generic_feed_1.xml"))

        feed = MockGeoRssFeed(HOME_COORDINATES_2, None, filter_radius=90.0)
        status, entries = feed.update()
        assert status == UPDATE_OK
        self.assertIsNotNone(entries)
        assert len(entries) == 4
        self.assertAlmostEqual(entries[0].distance_to_home, 82.0, 1)
        self.assertAlmostEqual(entries[1].distance_to_home, 77.0, 1)
        self.assertAlmostEqual(entries[2].distance_to_home, 84.6, 1)
async def test_update_ok_feed_2(aresponses, event_loop):
    """Test updating feed is ok."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_2.xml"), status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:

        feed = MockGeoRssFeed(
            websession, HOME_COORDINATES_1, "http://test.url/testpath"
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 1

        feed_entry = entries[0]
        assert feed_entry.title == "Title 1"
        assert feed_entry.external_id == "1234"
        assert feed_entry.category == "Category 1"
        assert feed_entry.coordinates == (-37.2345, 149.1234)
        assert round(abs(feed_entry.distance_to_home - 714.4), 1) == 0
async def test_update_bom(aresponses, event_loop):
    """Test updating feed with BOM (byte order mark) is ok."""
    xml = (
        "\xef\xbb\xbf<?xml version='1.0' encoding='utf-8'?>"
        "<rss version='2.0'><channel><item><title>Title 1</title>"
        "</item></channel></rss>"
    )
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=xml, charset="iso-8859-1", status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:
        feed = MockGeoRssFeed(
            websession, HOME_COORDINATES_1, "http://test.url/testpath"
        )
        assert (
            repr(feed) == "<MockGeoRssFeed(home=(-31.0, 151.0), "
            "url=http://test.url/testpath, radius=None, "
            "categories=None)>"
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 0
async def test_update_ok_then_error(aresponses, event_loop):
    """Test updating feed goes fine, followed by an error."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_1.xml"), status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:

        feed = MockGeoRssFeed(
            websession, HOME_COORDINATES_1, "http://test.url/testpath"
        )
        assert (
            repr(feed) == "<MockGeoRssFeed(home=(-31.0, 151.0), "
            "url=http://test.url/testpath, radius=None, "
            "categories=None)>"
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 5
        assert feed.last_timestamp is not None

        aresponses.add("test.url", "/testpath", "get", aresponses.Response(status=404))

        status, entries = await feed.update()
        assert status == UPDATE_ERROR
        assert feed.last_timestamp is None
async def test_update_error(aresponses, event_loop):
    """Test updating feed results in error."""
    aresponses.add("test.url", "/badpath", "get", aresponses.Response(status=404))

    async with aiohttp.ClientSession(loop=event_loop) as websession:
        feed = MockGeoRssFeed(websession, HOME_COORDINATES_1, "http://test.url/badpath")
        status, entries = await feed.update()
        assert status == UPDATE_ERROR
        assert feed.last_timestamp is None
Exemple #9
0
    def test_update_ok_feed_2(self, mock_session, mock_request):
        """Test updating feed is ok."""
        mock_session.return_value.__enter__.return_value.send.return_value.ok = True
        mock_session.return_value.__enter__.return_value.send.return_value.text = (
            load_fixture("generic_feed_2.xml"))

        feed = MockGeoRssFeed(HOME_COORDINATES_1, None)
        status, entries = feed.update()
        assert status == UPDATE_OK
        self.assertIsNotNone(entries)
        assert len(entries) == 1

        feed_entry = entries[0]
        assert feed_entry.title == "Title 1"
        assert feed_entry.external_id == "1234"
        assert feed_entry.category == "Category 1"
        assert feed_entry.coordinates == (-37.2345, 149.1234)
        self.assertAlmostEqual(feed_entry.distance_to_home, 714.4, 1)
async def test_update_ok_feed_3(aresponses, event_loop):
    """Test updating feed is ok."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_3.xml"), status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:
        feed = MockGeoRssFeed(
            websession, HOME_COORDINATES_1, "http://test.url/testpath"
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 5

        feed_entry = entries[0]
        assert feed_entry.external_id == "1234"
        assert len(feed_entry.geometries) == 1
        assert isinstance(feed_entry.geometries[0], Polygon)
        assert feed_entry.coordinates == (-34.93728111547821, 148.59710883878262)
        assert round(abs(feed_entry.distance_to_home - 491.7), 1) == 0

        feed_entry = entries[1]
        assert feed_entry.external_id == "2345"
        assert len(feed_entry.geometries) == 2
        assert isinstance(feed_entry.geometries[0], Point)
        assert isinstance(feed_entry.geometries[1], Polygon)
        assert feed_entry.coordinates == (-34.937170989, 148.597182317)
        assert round(abs(feed_entry.distance_to_home - 491.7), 1) == 0

        feed_entry = entries[2]
        assert feed_entry.external_id == "3456"
        assert len(feed_entry.geometries) == 2
        assert isinstance(feed_entry.geometries[0], Polygon)
        assert isinstance(feed_entry.geometries[1], Polygon)
        assert feed_entry.coordinates == (-29.962746645660683, 152.43090880416074)
        assert round(abs(feed_entry.distance_to_home - 176.5), 1) == 0

        feed_entry = entries[3]
        assert feed_entry.external_id == "4567"
        assert len(feed_entry.geometries) == 2
        assert isinstance(feed_entry.geometries[0], Point)
        assert isinstance(feed_entry.geometries[1], Point)
        assert feed_entry.coordinates == (-33.2345, 154.789)
        assert round(abs(feed_entry.distance_to_home - 172.3), 1) == 0

        feed_entry = entries[4]
        assert feed_entry.external_id == "5678"
        assert len(feed_entry.geometries) == 2
        assert isinstance(feed_entry.geometries[0], Point)
        assert isinstance(feed_entry.geometries[1], Polygon)
        assert feed_entry.coordinates == (-31.2345, 152.789)
        assert round(abs(feed_entry.distance_to_home - 172.3), 1) == 0
async def test_update_ok_with_radius_and_category_filtering(aresponses, event_loop):
    """Test updating feed is ok."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_1.xml"), status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:
        feed = MockGeoRssFeed(
            websession,
            HOME_COORDINATES_2,
            "http://test.url/testpath",
            filter_radius=90.0,
            filter_categories=["Category 2"],
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 1
        assert round(abs(entries[0].distance_to_home - 77.0), 1) == 0

        aresponses.add(
            "test.url",
            "/testpath",
            "get",
            aresponses.Response(text=load_fixture("generic_feed_1.xml"), status=200),
        )

        feed = MockGeoRssFeed(
            websession,
            HOME_COORDINATES_2,
            "http://test.url/testpath",
            filter_radius=90.0,
            filter_categories=["Category 4"],
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 0
Exemple #12
0
    def test_update_ok(self, mock_session, mock_request):
        """Test updating feed is ok."""
        mock_session.return_value.__enter__.return_value.send\
            .return_value.ok = True
        mock_session.return_value.__enter__.return_value.send\
            .return_value.text = load_fixture('generic_feed_1.xml')

        feed = MockGeoRssFeed(HOME_COORDINATES_1, None)
        assert repr(feed) == "<MockGeoRssFeed(home=(-31.0, 151.0), " \
                             "url=None, radius=None, categories=None)>"
        status, entries = feed.update()
        assert status == UPDATE_OK
        self.assertIsNotNone(entries)
        assert len(entries) == 5

        feed_entry = entries[0]
        assert feed_entry.title == "Title 1"
        assert feed_entry.external_id == "1234"
        assert feed_entry.category == "Category 1"
        assert feed_entry.published == datetime.datetime(2018, 9, 23, 8, 30)
        assert feed_entry.updated == datetime.datetime(2018, 9, 23, 8, 35)
        assert feed_entry.coordinates == (-37.2345, 149.1234)
        self.assertAlmostEqual(feed_entry.distance_to_home, 714.4, 1)

        feed_entry = entries[1]
        assert feed_entry.title == "Title 2"
        assert feed_entry.external_id == "2345"
        self.assertIsNone(feed_entry.attribution)
        assert repr(feed_entry) == "<FeedEntry(id=2345)>"

        feed_entry = entries[2]
        assert feed_entry.title == "Title 3"
        assert feed_entry.external_id == "Title 3"

        feed_entry = entries[3]
        self.assertIsNone(feed_entry.title)
        assert feed_entry.external_id == -7266545992534134585

        feed_entry = entries[4]
        assert feed_entry.title == "Title 5"
        assert feed_entry.external_id == "5678"
Exemple #13
0
    def test_update_ok_with_radius_and_category_filtering(
            self, mock_session, mock_request):
        """Test updating feed is ok."""
        mock_session.return_value.__enter__.return_value.send\
            .return_value.ok = True
        mock_session.return_value.__enter__.return_value.send\
            .return_value.text = load_fixture('generic_feed_1.xml')

        feed = MockGeoRssFeed(HOME_COORDINATES_2,
                              None,
                              filter_radius=90.0,
                              filter_categories=['Category 2'])
        status, entries = feed.update()
        assert status == UPDATE_OK
        self.assertIsNotNone(entries)
        assert len(entries) == 1
        self.assertAlmostEqual(entries[0].distance_to_home, 77.0, 1)

        feed = MockGeoRssFeed(HOME_COORDINATES_2,
                              None,
                              filter_radius=90.0,
                              filter_categories=['Category 4'])
        status, entries = feed.update()
        assert status == UPDATE_OK
        self.assertIsNotNone(entries)
        assert len(entries) == 0
async def test_update_ok(aresponses, event_loop):
    """Test updating feed is ok."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_1.xml"), status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:

        feed = MockGeoRssFeed(
            websession, HOME_COORDINATES_1, "http://test.url/testpath"
        )
        assert (
            repr(feed) == "<MockGeoRssFeed(home=(-31.0, 151.0), "
            "url=http://test.url/testpath, radius=None, "
            "categories=None)>"
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 5

        feed_entry = entries[0]
        assert feed_entry.title == "Title 1"
        assert feed_entry.external_id == "1234"
        assert feed_entry.category == "Category 1"
        assert feed_entry.published == datetime.datetime(2018, 9, 23, 8, 30)
        assert feed_entry.updated == datetime.datetime(2018, 9, 23, 8, 35)
        assert feed_entry.coordinates == (-37.2345, 149.1234)
        assert round(abs(feed_entry.distance_to_home - 714.4), 1) == 0
        assert repr(feed_entry) == "<MockFeedEntry(id=1234)>"

        feed_entry = entries[1]
        assert feed_entry.title == "Title 2"
        assert feed_entry.external_id == "2345"
        assert feed_entry.attribution is None
        assert repr(feed_entry) == "<MockFeedEntry(id=2345)>"

        feed_entry = entries[2]
        assert feed_entry.title == "Title 3"
        assert feed_entry.external_id == "Title 3"

        feed_entry = entries[3]
        assert feed_entry.title is None
        assert feed_entry.external_id == hash(feed_entry.coordinates)

        feed_entry = entries[4]
        assert feed_entry.title == "Title 5"
        assert feed_entry.external_id == "5678"
async def test_update_duplicate_geometries(aresponses, event_loop):
    """Test updating feed is ok."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_7.xml"), status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:

        feed = MockGeoRssFeed(
            websession, HOME_COORDINATES_1, "http://test.url/testpath"
        )
        assert (
            repr(feed) == "<MockGeoRssFeed(home=(-31.0, 151.0), "
            "url=http://test.url/testpath, radius=None, "
            "categories=None)>"
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 4

        feed_entry = entries[0]
        assert feed_entry.external_id == "1234"
        assert len(feed_entry.geometries) == 1
        assert isinstance(feed_entry.geometries[0], Point)

        feed_entry = entries[1]
        assert feed_entry.external_id == "2345"
        assert len(feed_entry.geometries) == 1
        assert isinstance(feed_entry.geometries[0], Point)

        feed_entry = entries[2]
        assert feed_entry.external_id == "3456"
        assert len(feed_entry.geometries) == 2
        assert isinstance(feed_entry.geometries[0], Point)
        assert isinstance(feed_entry.geometries[1], Polygon)

        feed_entry = entries[3]
        assert feed_entry.external_id == "4567"
        assert len(feed_entry.geometries) == 2
        assert isinstance(feed_entry.geometries[0], Point)
        assert isinstance(feed_entry.geometries[1], BoundingBox)
async def test_feed_manager_no_timestamp(aresponses, event_loop):
    """Test updating feed is ok."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_5.xml"),
                            status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:

        feed = MockGeoRssFeed(websession, HOME_COORDINATES_1,
                              "http://test.url/testpath")

        # This will just record calls and keep track of external ids.
        generated_entity_external_ids = []
        updated_entity_external_ids = []
        removed_entity_external_ids = []

        async def _generate_entity(external_id: str) -> None:
            """Generate new entity."""
            generated_entity_external_ids.append(external_id)

        async def _update_entity(external_id: str) -> None:
            """Update entity."""
            updated_entity_external_ids.append(external_id)

        async def _remove_entity(external_id: str) -> None:
            """Remove entity."""
            removed_entity_external_ids.append(external_id)

        feed_manager = FeedManagerBase(feed, _generate_entity, _update_entity,
                                       _remove_entity)
        assert (repr(feed_manager) == "<FeedManagerBase("
                "feed=<MockGeoRssFeed(home="
                "(-31.0, 151.0), "
                "url=http://test.url/testpath, "
                "radius=None, categories=None)>)>")
        await feed_manager.update()
        entries = feed_manager.feed_entries
        assert entries is not None
        assert len(entries) == 1
        assert feed_manager.last_timestamp is None
    def test_feed_manager_no_timestamp(self, mock_session, mock_request):
        """Test updating feed is ok."""
        mock_session.return_value.__enter__.return_value.send\
            .return_value.ok = True
        mock_session.return_value.__enter__.return_value.send\
            .return_value.text = load_fixture('generic_feed_5.xml')

        feed = MockGeoRssFeed(HOME_COORDINATES_1, None)

        # This will just record calls and keep track of external ids.
        generated_entity_external_ids = []
        updated_entity_external_ids = []
        removed_entity_external_ids = []

        def _generate_entity(external_id):
            """Generate new entity."""
            generated_entity_external_ids.append(external_id)

        def _update_entity(external_id):
            """Update entity."""
            updated_entity_external_ids.append(external_id)

        def _remove_entity(external_id):
            """Remove entity."""
            removed_entity_external_ids.append(external_id)

        feed_manager = FeedManagerBase(feed, _generate_entity, _update_entity,
                                       _remove_entity)
        assert repr(feed_manager) == "<FeedManagerBase(" \
                                     "feed=<MockGeoRssFeed(home=" \
                                     "(-31.0, 151.0), url=None, " \
                                     "radius=None, categories=None)>)>"
        feed_manager.update()
        entries = feed_manager.feed_entries
        self.assertIsNotNone(entries)
        assert len(entries) == 1
        self.assertIsNone(feed_manager.last_timestamp)
async def test_update_ok_feed_6(aresponses, event_loop):
    """Test updating feed is ok."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_6.xml"), status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:
        feed = MockGeoRssFeed(
            websession, HOME_COORDINATES_1, "http://test.url/testpath"
        )
        status, entries = await feed.update()
        assert status == UPDATE_OK
        assert entries is not None
        assert len(entries) == 1

        feed_entry = entries[0]
        assert feed_entry.external_id == "1234"
        assert len(feed_entry.geometries) == 1
        assert isinstance(feed_entry.geometries[0], BoundingBox)
        assert feed_entry.coordinates == (-20.9041, 168.5652)
        assert round(abs(feed_entry.distance_to_home - 1493.3), 1) == 0
async def test_feed_manager(aresponses, event_loop):
    """Test the feed manager."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_1.xml"),
                            status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:

        feed = MockGeoRssFeed(websession, HOME_COORDINATES_1,
                              "http://test.url/testpath")

        # This will just record calls and keep track of external ids.
        generated_entity_external_ids = []
        updated_entity_external_ids = []
        removed_entity_external_ids = []

        async def _generate_entity(entity_external_id: str) -> None:
            """Generate new entity."""
            generated_entity_external_ids.append(entity_external_id)

        async def _update_entity(entity_external_id: str) -> None:
            """Update entity."""
            updated_entity_external_ids.append(entity_external_id)

        async def _remove_entity(entity_external_id: str) -> None:
            """Remove entity."""
            removed_entity_external_ids.append(entity_external_id)

        feed_manager = FeedManagerBase(feed, _generate_entity, _update_entity,
                                       _remove_entity)
        assert (repr(feed_manager) == "<FeedManagerBase("
                "feed=<MockGeoRssFeed(home="
                "(-31.0, 151.0), "
                "url=http://test.url/testpath, "
                "radius=None, categories=None)>)>")
        await feed_manager.update()
        entries = feed_manager.feed_entries
        assert entries is not None
        assert len(entries) == 5
        assert feed_manager.last_update is not None
        assert feed_manager.last_timestamp == datetime.datetime(
            2018, 9, 23, 9, 10)

        assert len(generated_entity_external_ids) == 5
        assert len(updated_entity_external_ids) == 0
        assert len(removed_entity_external_ids) == 0

        feed_entry = entries.get("1234")
        assert feed_entry.title == "Title 1"
        assert feed_entry.external_id == "1234"
        assert feed_entry.coordinates == (-37.2345, 149.1234)
        assert round(abs(feed_entry.distance_to_home - 714.4), 1) == 0
        assert repr(feed_entry) == "<MockFeedEntry(id=1234)>"

        feed_entry = entries.get("2345")
        assert feed_entry.title == "Title 2"
        assert feed_entry.external_id == "2345"

        feed_entry = entries.get("Title 3")
        assert feed_entry.title == "Title 3"
        assert feed_entry.external_id == "Title 3"

        external_id = hash((-37.8901, 149.7890))
        feed_entry = entries.get(external_id)
        assert feed_entry.title is None
        assert feed_entry.external_id == external_id

        feed_entry = entries.get("5678")
        assert feed_entry.title == "Title 5"
        assert feed_entry.external_id == "5678"

        # Simulate an update with several changes.
        generated_entity_external_ids.clear()
        updated_entity_external_ids.clear()
        removed_entity_external_ids.clear()

        aresponses.add(
            "test.url",
            "/testpath",
            "get",
            aresponses.Response(text=load_fixture("generic_feed_4.xml"),
                                status=200),
        )

        await feed_manager.update()
        entries = feed_manager.feed_entries
        assert entries is not None
        assert len(entries) == 3
        assert len(generated_entity_external_ids) == 1
        assert len(updated_entity_external_ids) == 2
        assert len(removed_entity_external_ids) == 3

        feed_entry = entries.get("1234")
        assert feed_entry.title == "Title 1 UPDATED"

        feed_entry = entries.get("2345")
        assert feed_entry.title == "Title 2"

        feed_entry = entries.get("6789")
        assert feed_entry.title == "Title 6"

        # Simulate an update with no data.
        generated_entity_external_ids.clear()
        updated_entity_external_ids.clear()
        removed_entity_external_ids.clear()

        with patch("aio_georss_client.feed.GeoRssFeed._fetch",
                   new_callable=CoroutineMock) as mock_fetch:
            mock_fetch.return_value = (UPDATE_OK_NO_DATA, None)

            await feed_manager.update()
            entries = feed_manager.feed_entries

            assert len(entries) == 3
            assert len(generated_entity_external_ids) == 0
            assert len(updated_entity_external_ids) == 0
            assert len(removed_entity_external_ids) == 0

        # Simulate an update producing an error.
        generated_entity_external_ids.clear()
        updated_entity_external_ids.clear()
        removed_entity_external_ids.clear()

        aresponses.add(
            "test.url",
            "/testpath",
            "get",
            aresponses.Response(status=500),
        )

        await feed_manager.update()
        entries = feed_manager.feed_entries

        assert len(entries) == 0
        assert len(generated_entity_external_ids) == 0
        assert len(updated_entity_external_ids) == 0
        assert len(removed_entity_external_ids) == 3
    def test_feed_manager(self, mock_session, mock_request):
        """Test the feed manager."""
        mock_session.return_value.__enter__.return_value.send\
            .return_value.ok = True
        mock_session.return_value.__enter__.return_value.send\
            .return_value.text = load_fixture('generic_feed_1.xml')

        feed = MockGeoRssFeed(HOME_COORDINATES_1, None)

        # This will just record calls and keep track of external ids.
        generated_entity_external_ids = []
        updated_entity_external_ids = []
        removed_entity_external_ids = []

        def _generate_entity(external_id):
            """Generate new entity."""
            generated_entity_external_ids.append(external_id)

        def _update_entity(external_id):
            """Update entity."""
            updated_entity_external_ids.append(external_id)

        def _remove_entity(external_id):
            """Remove entity."""
            removed_entity_external_ids.append(external_id)

        feed_manager = FeedManagerBase(feed, _generate_entity, _update_entity,
                                       _remove_entity)
        assert repr(feed_manager) == "<FeedManagerBase(" \
                                     "feed=<MockGeoRssFeed(home=" \
                                     "(-31.0, 151.0), url=None, " \
                                     "radius=None, categories=None)>)>"
        feed_manager.update()
        entries = feed_manager.feed_entries
        self.assertIsNotNone(entries)
        assert len(entries) == 5
        self.assertIsNotNone(feed_manager.last_update)
        assert feed_manager.last_timestamp \
            == datetime.datetime(2018, 9, 23, 9, 10)
        assert len(generated_entity_external_ids) == 5
        assert len(updated_entity_external_ids) == 0
        assert len(removed_entity_external_ids) == 0

        feed_entry = entries.get("1234")
        assert feed_entry.title == "Title 1"
        assert feed_entry.external_id == "1234"
        assert feed_entry.coordinates == (-37.2345, 149.1234)
        self.assertAlmostEqual(feed_entry.distance_to_home, 714.4, 1)
        assert repr(feed_entry) == "<FeedEntry(id=1234)>"

        feed_entry = entries.get("2345")
        assert feed_entry.title == "Title 2"
        assert feed_entry.external_id == "2345"

        feed_entry = entries.get("Title 3")
        assert feed_entry.title == "Title 3"
        assert feed_entry.external_id == "Title 3"

        feed_entry = entries.get(-7266545992534134585)
        self.assertIsNone(feed_entry.title)
        assert feed_entry.external_id == -7266545992534134585

        feed_entry = entries.get("5678")
        assert feed_entry.title == "Title 5"
        assert feed_entry.external_id == "5678"

        # Simulate an update with several changes.
        generated_entity_external_ids.clear()
        updated_entity_external_ids.clear()
        removed_entity_external_ids.clear()

        mock_session.return_value.__enter__.return_value.send\
            .return_value.text = load_fixture('generic_feed_4.xml')

        feed_manager.update()
        entries = feed_manager.feed_entries
        self.assertIsNotNone(entries)
        assert len(entries) == 3
        assert len(generated_entity_external_ids) == 1
        assert len(updated_entity_external_ids) == 2
        assert len(removed_entity_external_ids) == 3

        feed_entry = entries.get("1234")
        assert feed_entry.title == "Title 1 UPDATED"

        feed_entry = entries.get("2345")
        assert feed_entry.title == "Title 2"

        feed_entry = entries.get("6789")
        assert feed_entry.title == "Title 6"

        # Simulate an update with no data.
        generated_entity_external_ids.clear()
        updated_entity_external_ids.clear()
        removed_entity_external_ids.clear()

        mock_session.return_value.__enter__.return_value.send\
            .return_value.ok = False

        feed_manager.update()
        entries = feed_manager.feed_entries

        assert len(entries) == 0
        assert len(generated_entity_external_ids) == 0
        assert len(updated_entity_external_ids) == 0
        assert len(removed_entity_external_ids) == 3
async def test_feed_manager_with_status_callback(aresponses, event_loop):
    """Test the feed manager."""
    aresponses.add(
        "test.url",
        "/testpath",
        "get",
        aresponses.Response(text=load_fixture("generic_feed_1.xml"),
                            status=200),
    )

    async with aiohttp.ClientSession(loop=event_loop) as websession:

        feed = MockGeoRssFeed(websession, HOME_COORDINATES_1,
                              "http://test.url/testpath")

        # This will just record calls and keep track of external ids.
        generated_entity_external_ids = []
        updated_entity_external_ids = []
        removed_entity_external_ids = []
        status_update = []

        async def _generate_entity(external_id: str) -> None:
            """Generate new entity."""
            generated_entity_external_ids.append(external_id)

        async def _update_entity(external_id: str) -> None:
            """Update entity."""
            updated_entity_external_ids.append(external_id)

        async def _remove_entity(external_id: str) -> None:
            """Remove entity."""
            removed_entity_external_ids.append(external_id)

        async def _status(status_details: StatusUpdate) -> None:
            """Capture status update details."""
            status_update.append(status_details)

        feed_manager = FeedManagerBase(feed, _generate_entity, _update_entity,
                                       _remove_entity, _status)
        assert (repr(feed_manager) == "<FeedManagerBase(feed=<"
                "MockGeoRssFeed(home=(-31.0, 151.0), "
                "url=http://test.url/testpath, "
                "radius=None, categories=None)>)>")
        await feed_manager.update()
        entries = feed_manager.feed_entries
        assert entries is not None
        assert len(entries) == 5
        assert feed_manager.last_update is not None
        assert feed_manager.last_timestamp == datetime.datetime(
            2018, 9, 23, 9, 10)

        assert len(generated_entity_external_ids) == 5
        assert len(updated_entity_external_ids) == 0
        assert len(removed_entity_external_ids) == 0

        assert status_update[0].status == "OK"
        assert status_update[0].last_update is not None
        last_update_successful = status_update[0].last_update_successful
        assert status_update[0].last_update == last_update_successful
        assert status_update[0].last_timestamp == datetime.datetime(
            2018, 9, 23, 9, 10)
        assert status_update[0].total == 5
        assert status_update[0].created == 5
        assert status_update[0].updated == 0
        assert status_update[0].removed == 0
        assert (repr(status_update[0]) == f"<StatusUpdate("
                f"OK@{status_update[0].last_update})>")

        # Simulate an update with no data.
        generated_entity_external_ids.clear()
        updated_entity_external_ids.clear()
        removed_entity_external_ids.clear()
        status_update.clear()

        aresponses.add(
            "test.url",
            "/testpath",
            "get",
            aresponses.Response(status=500),
        )

        await feed_manager.update()
        entries = feed_manager.feed_entries

        assert len(entries) == 0
        assert len(generated_entity_external_ids) == 0
        assert len(updated_entity_external_ids) == 0
        assert len(removed_entity_external_ids) == 5

        assert status_update[0].status == "ERROR"
        assert status_update[0].last_update is not None
        assert status_update[0].last_update_successful is not None
        assert status_update[
            0].last_update_successful == last_update_successful
        assert status_update[0].total == 0