Ejemplo n.º 1
0
def test_client_lifecycle(client, requests_mocker):
    """Client is usable in with statement"""

    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/repositories/search/",
        json=[{
            "id": "repo1"
        }],
    )

    client = Client("https://pulp.example.com")
    with client:
        # This should work OK
        assert client.search_repository().result()

    # But after end of 'with' statement, it should be shut down
    with pytest.raises(RuntimeError) as excinfo:
        client.search_repository()

    assert "cannot schedule new futures after shutdown" in str(excinfo.value)
def test_search_stops_paginate(requests_mocker):
    """Paginated search will stop issuing requests if pages are no longer referenced."""

    client = Client("https://pulp.example.com/")
    client._PAGE_SIZE = 10

    responses = []
    current_response = []
    for i in range(0, 997):
        repo_id = "repo-%s" % i
        current_response.append({"id": repo_id})
        if len(current_response) == client._PAGE_SIZE:
            responses.append({"json": current_response})
            current_response = []

    responses.append({"json": current_response})

    # Inject a failing response for stable behavior from test:
    #
    # The expected behavior is that, after the first two requests,
    # pagination is cancelled since we no longer hold onto a page.
    # But that cancellation is racing with the scheduling of the
    # request, and there is generally no way to ensure our cancel
    # happens before the request thread starts the request, so we
    # can't be sure about how many requests we'd do.
    #
    # However, if we insert a failure after the first two pages,
    # then the client will need to retry a request (with some delay).
    # It should always be possible to cancel the request during that
    # retry delay, making the test stable.
    responses.insert(2, {"status_code": 500})

    requests_mocker.post(
        "https://pulp.example.com/pulp/api/v2/repositories/search/", responses)

    # Imagine we have some function which processes two pages of results and
    # then stops
    def do_something_first_two_pages(repos_f):
        page = repos_f.result()
        return len(page.data) + len(page.next.result().data)

    two_pages_len = do_something_first_two_pages(client.search_repository())

    # It should have seen the first two pages
    assert two_pages_len == 20

    # Now wait a bit to ensure any futures under the hood have time to finish up
    time.sleep(2.0)

    # It should have done only two or three requests
    # (2 vs 3 depends on scheduling). Because we threw away all references to
    # the search result, it stopped searching rather than continuing through
    # all pages.
    assert requests_mocker.call_count in (2, 3)