From 4ff4b3a85ca5f8e00b198b9c0e5ee1308a1375f7 Mon Sep 17 00:00:00 2001 From: Thomas Sileo Date: Sat, 16 Jun 2018 14:19:47 +0200 Subject: [PATCH] More tests --- little_boxes/backend.py | 17 +++++++ little_boxes/collection.py | 27 +++++++---- tests/test_collection.py | 92 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 9 deletions(-) diff --git a/little_boxes/backend.py b/little_boxes/backend.py index eecce14..627b134 100644 --- a/little_boxes/backend.py +++ b/little_boxes/backend.py @@ -1,11 +1,28 @@ import abc import typing +from typing import Any +from typing import Dict + +import requests + +from .__version__ import __version__ if typing.TYPE_CHECKING: from little_boxes import activitypub as ap # noqa: type checking class Backend(abc.ABC): + def user_agent(self) -> str: + return f"Little Boxes {__version__} (+http://github.com/tsileo/little-boxes)" + + def fetch_json(self, url: str) -> Dict[str, Any]: + resp = requests.get( + url, headers={"User-Agent": self.user_agent(), "Accept": "application/json"} + ) + resp.raise_for_status() + + return resp.json() + @abc.abstractmethod def base_url(self) -> str: pass diff --git a/little_boxes/collection.py b/little_boxes/collection.py index 7c20dea..5b6e239 100644 --- a/little_boxes/collection.py +++ b/little_boxes/collection.py @@ -1,4 +1,4 @@ -"""Contains some ActivityPub related utils.""" +"""Collection releated utils.""" from typing import Any from typing import Callable from typing import Dict @@ -9,7 +9,7 @@ from .errors import RecursionLimitExceededError from .errors import UnexpectedActivityTypeError -def parse_collection( +def parse_collection( # noqa: C901 payload: Optional[Dict[str, Any]] = None, url: Optional[str] = None, level: int = 0, @@ -34,13 +34,22 @@ def parse_collection( if "items" in payload: return payload["items"] if "first" in payload: - if "orderedItems" in payload["first"]: - out.extend(payload["first"]["orderedItems"]) - if "items" in payload["first"]: - out.extend(payload["first"]["items"]) - n = payload["first"].get("next") - if n: - out.extend(parse_collection(url=n, level=level + 1, fetcher=fetcher)) + if isinstance(payload["first"], str): + out.extend( + parse_collection( + url=payload["first"], level=level + 1, fetcher=fetcher + ) + ) + else: + if "orderedItems" in payload["first"]: + out.extend(payload["first"]["orderedItems"]) + if "items" in payload["first"]: + out.extend(payload["first"]["items"]) + n = payload["first"].get("next") + if n: + out.extend( + parse_collection(url=n, level=level + 1, fetcher=fetcher) + ) return out while payload: diff --git a/tests/test_collection.py b/tests/test_collection.py index e69de29..9f3dc17 100644 --- a/tests/test_collection.py +++ b/tests/test_collection.py @@ -0,0 +1,92 @@ +import logging + +import pytest + +from little_boxes import activitypub as ap +from little_boxes.collection import parse_collection +from little_boxes.errors import RecursionLimitExceededError +from little_boxes.errors import UnexpectedActivityTypeError +from test_backend import InMemBackend + +logging.basicConfig(level=logging.DEBUG) + + +def test_empty_collection(): + back = InMemBackend() + ap.use_backend(back) + + back.FETCH_MOCK["https://lol.com"] = { + "type": "Collection", + "items": [], + "id": "https://lol.com", + } + + out = parse_collection(url="https://lol.com", fetcher=back.fetch_iri) + assert out == [] + + +def test_recursive_collection_limit(): + back = InMemBackend() + ap.use_backend(back) + + back.FETCH_MOCK["https://lol.com"] = { + "type": "Collection", + "first": "https://lol.com", + "id": "https://lol.com", + } + + with pytest.raises(RecursionLimitExceededError): + parse_collection(url="https://lol.com", fetcher=back.fetch_iri) + + +def test_unexpected_activity_type(): + back = InMemBackend() + ap.use_backend(back) + + back.FETCH_MOCK["https://lol.com"] = {"type": "Actor", "id": "https://lol.com"} + + with pytest.raises(UnexpectedActivityTypeError): + parse_collection(url="https://lol.com", fetcher=back.fetch_iri) + + +def test_collection(): + back = InMemBackend() + ap.use_backend(back) + + back.FETCH_MOCK["https://lol.com"] = { + "type": "Collection", + "first": "https://lol.com/page1", + "id": "https://lol.com", + } + back.FETCH_MOCK["https://lol.com/page1"] = { + "type": "CollectionPage", + "id": "https://lol.com/page1", + "items": [1, 2, 3], + } + + out = parse_collection(url="https://lol.com", fetcher=back.fetch_iri) + assert out == [1, 2, 3] + + +def test_ordered_collection(): + back = InMemBackend() + ap.use_backend(back) + + back.FETCH_MOCK["https://lol.com"] = { + "type": "OrderedCollection", + "first": { + "type": "OrderedCollectionPage", + "id": "https://lol.com/page1", + "orderedItems": [1, 2, 3], + "next": "https://lol.com/page2", + }, + "id": "https://lol.com", + } + back.FETCH_MOCK["https://lol.com/page2"] = { + "type": "OrderedCollectionPage", + "id": "https://lol.com/page2", + "orderedItems": [4, 5, 6], + } + + out = parse_collection(url="https://lol.com", fetcher=back.fetch_iri) + assert out == [1, 2, 3, 4, 5, 6]