|
1 |
| -# Copyright (c) 2022 - 2022, Oracle and/or its affiliates. All rights reserved. |
| 1 | +# Copyright (c) 2022 - 2024, Oracle and/or its affiliates. All rights reserved. |
2 | 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.
|
3 | 3 |
|
4 | 4 | """
|
5 | 5 | This module test the Util methods
|
6 | 6 | """
|
7 |
| - |
| 7 | +from collections.abc import Callable |
8 | 8 | from unittest import TestCase
|
9 | 9 | from unittest.mock import call, patch
|
10 | 10 |
|
| 11 | +from pytest_httpserver import HTTPServer |
| 12 | +from werkzeug import Request, Response |
| 13 | + |
11 | 14 | from macaron import util
|
| 15 | +from macaron.config.defaults import defaults |
| 16 | +from macaron.util import send_get_http_raw |
12 | 17 |
|
13 | 18 |
|
14 | 19 | class TestUtil(TestCase):
|
@@ -78,3 +83,55 @@ def test_copy_file_bulk(self) -> None:
|
78 | 83 | call("/src/path/foo/file2", "/target/path/foo/file2"),
|
79 | 84 | ]
|
80 | 85 | )
|
| 86 | + |
| 87 | + |
| 88 | +def _response_generator(target_value: int) -> Callable[[Request], Response]: |
| 89 | + """Return a generator with closure so a value can be tracked across multiple invocations.""" |
| 90 | + value = 0 |
| 91 | + |
| 92 | + def generator(request: Request) -> Response: # pylint: disable=unused-argument |
| 93 | + """Add the next value as a header and adjust the status code based on the value.""" |
| 94 | + nonlocal value, target_value |
| 95 | + value += 1 |
| 96 | + response = Response() |
| 97 | + response.status_code = 403 if value <= (target_value + 1) else 200 |
| 98 | + response.headers["X-VALUE"] = str(value) |
| 99 | + return response |
| 100 | + |
| 101 | + return generator |
| 102 | + |
| 103 | + |
| 104 | +def _http_setup(retries: int, httpserver: HTTPServer) -> str: |
| 105 | + """Set up the http server for a GET test.""" |
| 106 | + # Get a localhost URL. |
| 107 | + mocked_url: str = httpserver.url_for("") |
| 108 | + |
| 109 | + # Create and assign the stateful handler. |
| 110 | + handler = _response_generator(retries) |
| 111 | + httpserver.expect_request("").respond_with_handler(handler) |
| 112 | + return mocked_url |
| 113 | + |
| 114 | + |
| 115 | +def test_get_http_partial_failure(httpserver: HTTPServer) -> None: |
| 116 | + """Test the http GET operation when some errors are received before the request succeeds.""" |
| 117 | + # Retrieve the allowed number of retries on a failed request and reduce it by 1. |
| 118 | + target_value = defaults.getint("requests", "error_retries", fallback=5) - 1 |
| 119 | + |
| 120 | + mocked_url = _http_setup(target_value, httpserver) |
| 121 | + |
| 122 | + # Test for a correct response after the expected number of retries. |
| 123 | + response = send_get_http_raw(mocked_url) |
| 124 | + assert response |
| 125 | + assert "X-VALUE" in response.headers |
| 126 | + assert response.headers["X-VALUE"] == str(target_value + 2) |
| 127 | + |
| 128 | + |
| 129 | +def test_get_http_complete_failure(httpserver: HTTPServer) -> None: |
| 130 | + """Test the http GET operation when too many errors are received and the request fails.""" |
| 131 | + # Retrieve the allowed number of retries on a failed request. |
| 132 | + target_value = defaults.getint("requests", "error_retries", fallback=5) |
| 133 | + |
| 134 | + mocked_url = _http_setup(target_value, httpserver) |
| 135 | + |
| 136 | + # Assert the request fails and returns nothing. |
| 137 | + assert send_get_http_raw(mocked_url) is None |
0 commit comments