Beispiel #1
0
    def test_timeout_retry_fail(self, mock_requests, mock_time):
        mock_requests.side_effect = [
            Timeout(), Timeout(), Timeout(),
            Timeout()
        ]

        with self.assertRaises(Timeout):
            self.cache.load_key("jku1", "key-id-1")
        self.assertEqual(4, mock_requests.call_count)
Beispiel #2
0
    def test_timeout_retry_max(self, mock_requests, mock_time):
        mock_requests.side_effect = [
            Timeout(), Timeout(), Timeout(), self.mock
        ]
        self.mock.json.return_value = HTTP_SUCCESS

        key = self.cache.load_key("jku1", "key-id-1")

        self.assert_key_equal(KEY_ID_1, key)
        self.assertEqual(4, mock_requests.call_count)
def test_timeout(get_response):
    def error(msg, *args, **kwargs):
        global error_msg
        error_msg = msg % args

    exc = Timeout('Request timed out')
    exc.request = Request(method='GET', url='http://www.google.com')
    get_response.side_effect = exc
    ret = main(['--ignore-stdin', 'www.google.com'], custom_log_error=error)
    assert ret == ExitStatus.ERROR_TIMEOUT
    assert error_msg == 'Request timed out (30s).'
Beispiel #4
0
def test_timeout(get_response):
    def error(msg, *args, **kwargs):
        global error_msg
        error_msg = msg % args

    exc = Timeout('Request timed out')
    exc.request = Request(method='GET', url='http://www.google.com')
    get_response.side_effect = exc
    ret = main(['--ignore-stdin', 'www.google.com'], custom_log_error=error)
    assert ret == ExitStatus.ERROR_TIMEOUT
    assert error_msg == 'Request timed out (30s).'
Beispiel #5
0
def get_random_fact(category=None):
    ''' Gets a random fact. If category is definided, it will return a
        random fact under 'category'

        Args:
            category ('str'): Optional. Desired category
        Returns:
            dictionary: Json structured response data
    '''
    if category:
        url='https://api.chucknorris.io/jokes/random?category={}'\
            .format(category)
    else:
        url='https://api.chucknorris.io/jokes/random'

    try:
        response = requests.get(url)
        response.raise_for_status()
    except ConnectionError:
        raise ConnectionError('It seems there is not network connection')
    except Timeout:
        raise Timeout('Could not send request to the server')
    except HTTPError:
        raise HTTPError('Category is not valid!')

    return response.json()
        def request(method, url, timeout=None):
            self.assertEquals(method, 'GET', 'Incorrect HTTP method')
            self.assertEquals(url, 'http://localhost:8080/swagger',
                              'Monitored URL is incorrect')
            self.assertEquals(timeout, 0.010)

            raise Timeout()
Beispiel #7
0
    def _invoke_handler(self, handler, params, timeout):
        # Handle synchronously if there's no timeout.
        if not timeout:
            return handler(**params)

        # As there is a timeout, we'll execute it in a separate thread.

        # We store the result at index 0, and the current thread will signal to the
        # spawned thread if it has cancelled its request at index 1.
        result = [None, False]

        def invoke_request():
            try:
                result[0] = handler(**params)
            except Exception as e:  # pragma: no cover
                result[0] = e
            else:
                # This prevents the webtest linter from generating a warning about the iterable
                # response not being closed properly.
                if result[1]:  # Request has been cancelled.
                    iter_close(result[0]._app_iter)  # Tidy up the request.

        thread = threading.Thread(target=invoke_request)
        thread.start()
        thread.join(timeout=timeout)
        if thread.is_alive():
            result[1] = True  # tell the thread we don't want the result
            raise Timeout()
        if isinstance(result[0], Exception):  # pragma: no cover
            raise result[0]  # pylint: disable=raising-bad-type
        return result[0]
class TestContainerManager(CodeBoxCleanupTestMixin, TestCase):
    def setUp(self):
        self.container_manager = ContainerManager()

    def test_codebox_runner_creates_docker_container(self):
        runtime_name = LATEST_PYTHON_RUNTIME
        container_data = self.container_manager.get_container(runtime_name)
        self.assertIn('id', container_data)

    @mock.patch('apps.codeboxes.container_manager.logger')
    def test_raises_error_when_cannot_remove_container(self, logger_mock):
        self.container_manager._remove_container({
            'id': 'nonexisting',
            'tmp_dir': '',
            'source_dir': ''
        })
        self.assertTrue(logger_mock.warning.called)

    @mock.patch('apps.codeboxes.container_manager.logger', mock.Mock())
    @mock.patch(
        'apps.codeboxes.container_manager.docker_client.api.create_container',
        mock.MagicMock(side_effect=Timeout()))
    def test_raises_error_when_cannot_prepare_container(self):
        self.assertRaises(CannotCreateContainer,
                          self.container_manager.prepare_container,
                          LATEST_PYTHON_RUNTIME)
Beispiel #9
0
def get_url_content(get: Callable, url_address: str):
    request_timeout = 5

    try:
        response = get(url_address,
                       params=(('format', 'j1'), ),
                       timeout=request_timeout)
        response.raise_for_status()

        if response.text:  # check response text is empty or not
            return response.text
        else:
            raise Exception("Response contains no data")
    except Timeout:
        raise Timeout(f"URL request timeout more than {request_timeout} sec")
    except URLRequired:
        raise URLRequired(f"{url_address} is an invalid URL")
    except ConnectionError:
        raise ConnectionError(
            "Refused connection or DNS failure etc. occurred")
    except HTTPError as http_err:
        raise HTTPError(f"HTTP error: {http_err}  occurred")
    except RequestException as e:
        raise RequestException(f"There was an ambiguous exception that "
                               f"occurred while handling request. Error: {e} ")
    except KeyboardInterrupt:
        raise KeyboardInterrupt("Script was interrupted by user")
Beispiel #10
0
def download_dsyms(session: Session, credentials: AppConnectCredentials,
                   url: str, path: pathlib.Path) -> None:
    """Downloads dSYMs at `url` into `path` which must be a filename."""
    headers = _get_authorization_header(credentials)

    with session.get(url, headers=headers, stream=True, timeout=15) as res:
        status = res.status_code
        if status == HTTPStatus.UNAUTHORIZED:
            raise UnauthorizedError
        elif status == HTTPStatus.FORBIDDEN:
            raise ForbiddenError
        elif status != HTTPStatus.OK:
            raise RequestError(f"Bad status code downloading dSYM: {status}")

        start = time.time()
        bytes_count = 0
        with open(path, "wb") as fp:
            for chunk in res.iter_content(chunk_size=io.DEFAULT_BUFFER_SIZE):
                # The 315s is just above how long it would take a 4MB/s connection to download
                # 2GB.
                if (time.time() - start) > 315:
                    with sdk.configure_scope() as scope:
                        scope.set_extra("dSYM.bytes_fetched", bytes_count)
                    raise Timeout("Timeout during dSYM download")
                bytes_count += len(chunk)
                fp.write(chunk)
Beispiel #11
0
def get_proxy_list() -> Dict[str, List[str]]:
    """Get proxy list using Webshare API
    The result is in the following format: country code → list of proxies
    """

    headers = {'Authorization': f'Token {AppConfig.WEBSHARE_API_TOKEN}'}

    for _ in range(3):
        try:
            r = get('https://proxy.webshare.io/api/proxy/list',
                    headers=headers,
                    timeout=3)
            r.raise_for_status()
        except Timeout:
            pass
        else:
            break
    else:
        raise Timeout('While getting proxy list')

    proxies = {}
    for proxy in r.json()['results']:
        username = proxy['username']
        password = proxy['password']
        ip = proxy['proxy_address']
        port = proxy['ports']['http']

        country_code = proxy['country_code']
        proxy_url = f'http://{username}:{password}@{ip}:{port}'

        country_proxy_list = proxies.setdefault(country_code, [])
        country_proxy_list.append(proxy_url)

    return proxies
Beispiel #12
0
 def __init__(self, status_code):
     """
     Build a fake error response
     """
     self.error = Timeout(response=Response())
     self.error.response = Response()
     self.error.response.status_code = status_code
class TestDownloadedJSON:
    @pytest.fixture()
    def json_content(self):
        return """
{
    "ResultInfo": {
        "Count": 1,
        "Total": 1,
        "Start": 1,
        "Status": 200,
        "Description": "",
        "Copyright": "",
        "Latency": 0.017
    },
    "Feature": [
        {
            "Id": "20130710667",
            "Gid": "",
            "Name": "\u5e02\u7acb\u65ed\u5ddd\u75c5\u9662",
            "Geometry": {
                "Type": "point",
                "Coordinates": "142.365976388889,43.778422777778"
            },
            "Category": []
        }
    ]
}
        """

    def test_content(self, json_content, mocker):
        responce_mock = mocker.Mock()
        responce_mock.status_code = 200
        responce_mock.content = json_content
        responce_mock.headers = {"content-type": "application/json"}
        mocker.patch.object(requests, "get", return_value=responce_mock)
        json_file = DownloadedJSON("http://dummy.local")
        assert json_file.content == json.loads(json_content)

    def test_not_found_error(self, mocker):
        responce_mock = mocker.Mock()
        responce_mock.status_code = 404
        mocker.patch.object(requests, "get", return_value=responce_mock)
        with pytest.raises(HTTPDownloadError,
                           match="cannot get JSON contents."):
            DownloadedJSON("http://dummy.local")

    @pytest.mark.parametrize(
        "exception,expected",
        [
            (Timeout("Dummy Error."), "cannot connect to web server."),
            (HTTPError("Dummy Error."), "cannot connect to web server."),
            (ConnectionError("Dummy Error."), "cannot connect to web server."),
        ],
    )
    def test_network_error(self, exception, expected, mocker):
        mocker.patch.object(requests, "get", side_effect=exception)
        with pytest.raises(HTTPDownloadError, match=expected):
            DownloadedJSON("http://dummy.local")
Beispiel #14
0
 def test_connection_timeouts_are_retried(self):
     # If a connection times out, we get a Timout exception
     # from requests.  We should be retrying those.
     handler = retryhandler.create_retry_handler(
         self.retry_config, operation_name='OperationBar')
     sleep_time = handler(response=None,
                          attempts=1,
                          caught_exception=Timeout())
     self.assertEqual(sleep_time, 1)
def test_fetch_app_source_request_timed_out(mock_git):
    url = 'https://github.com/release-engineering/retrodep.git'
    ref = 'c50b93a32df1c9d700e3e80996845bc2e13be848'
    mock_git.return_value.fetch_source.side_effect = Timeout(
        'The request timed out')
    with pytest.raises(
            CachitoError,
            match='The connection timed out while downloading the source'):
        tasks.fetch_app_source(url, ref)
Beispiel #16
0
 def test_should_return_exception_timeout_when_api_takes_too_long_to_respond(  # noqa
         self,
         url,
         product_id,
         mock_data_not_found_api,
 ):
     responses.add(responses.GET, url, body=Timeout())
     with pytest.raises(ChallengeProductTimeoutException):
         get_product(product_id)
Beispiel #17
0
def test_fetch_app_source_request_timed_out(mock_git, mock_set_request_state,
                                            gitsubmodule):
    url = "https://github.com/release-engineering/retrodep.git"
    ref = "c50b93a32df1c9d700e3e80996845bc2e13be848"
    mock_git.return_value.fetch_source.side_effect = Timeout(
        "The request timed out")
    with pytest.raises(
            CachitoError,
            match="The connection timed out while downloading the source"):
        tasks.fetch_app_source(url, ref, 1, gitsubmodule)
Beispiel #18
0
    def test_reauth_when_signon_really_slow(
            self, session_delete_sessions_for_user_patch, oauth_get_patch,
            reauth_patch):
        # Set up the Mock for calling Signon
        oauth_get_patch.side_effect = Timeout()
        self.expected_unused(session_delete_sessions_for_user_patch)
        self.expected_unused(reauth_patch)

        response = self.do_reauth_post()
        self.assertEqual(500, response.status_code, response.data)
Beispiel #19
0
 def test_api_exception(self):
     """ If an exception is raised when communicating with the Commerce API, an ERROR message should be logged. """
     error = 'time out error'
     with mock.patch('requests.put', side_effect=Timeout(error)):
         with LogCapture(LOGGER_NAME) as l:
             actual = self.publisher.publish(self.course)
             l.check((
                 LOGGER_NAME, 'ERROR',
                 'Failed to publish commerce data for [{course_id}] to LMS.'
                 .format(course_id=self.course.id)))
             self.assertEqual(actual, self.error_message)
Beispiel #20
0
    def test_lists(self, mock_requests):
        csv_content = ("地区,連番,設置事業所名,郵便番号,住所,電話番号,利用可能時間,AED設置場所," +
                       "地図の緯度,地図の経度" + "\r\n" +
                       "一条通〜十条通,1,旭川市教育委員会,070-0036," +
                       "北海道旭川市6条通8丁目セントラル旭川ビル6階,0166-25-7534,,6階教育政策課," +
                       "43.7703945,142.3631408" + "\r\n" +
                       "一条通〜十条通,9,フィール旭川,070-0031,北海道旭川市1条通8丁目," +
                       "0166-25-5443," +
                       "※平日午前8時45分から午後7時30分まで土日祝午前10時から午後7時30分まで," +
                       "7階国際交流スペース内,43.76572279,142.3597048")
        mock_requests.get.return_value = Mock(
            status_code=200, content=csv_content.encode("cp932"))
        expect = [
            {
                "area": "一条通~十条通",
                "location_id": 1,
                "location_name": "旭川市教育委員会",
                "postal_code": "070-0036",
                "address": "北海道旭川市6条通8丁目セントラル旭川ビル6階",
                "phone_number": "0166-25-7534",
                "available_time": "",
                "installation_floor": "6階教育政策課",
                "latitude": 43.7703945,
                "longitude": 142.3631408,
            },
            {
                "area": "一条通~十条通",
                "location_id": 9,
                "location_name": "フィール旭川",
                "postal_code": "070-0031",
                "address": "北海道旭川市1条通8丁目",
                "phone_number": "0166-25-5443",
                "available_time": "※平日午前8時45分から午後7時30分まで土日祝午前10時から午後7時30分まで",
                "installation_floor": "7階国際交流スペース内",
                "latitude": 43.76572279,
                "longitude": 142.3597048,
            },
        ]
        open_data = OpenData()
        self.assertEqual(open_data.lists, expect)

        mock_requests.get.side_effect = Timeout("Dummy Error.")
        with self.assertRaises(ScrapeError):
            OpenData()

        mock_requests.get.side_effect = HTTPError("Dummy Error.")
        with self.assertRaises(ScrapeError):
            OpenData()

        mock_requests.get.side_effect = ConnectionError("Dummy Error.")
        with self.assertRaises(ScrapeError):
            OpenData()
Beispiel #21
0
def test_send_message_error_timeout_no_exception(mock_request):
    """Should return None given if issues on request."""
    svc = OnapService()
    mock_request.side_effect = Timeout()
    response = svc.send_message("GET", 'test get', 'http://my.url/')
    expect_headers = {
        "Content-Type": "application/json",
        "Accept": "application/json",
    }
    mock_request.assert_called_once_with('GET',
                                         'http://my.url/',
                                         headers=expect_headers,
                                         verify=False,
                                         proxies=None)
    assert response == None
Beispiel #22
0
def get_available_categories():
    ''' Returns available categories on API

        Returns:
            list: Json structured response data
    '''

    url = 'https://api.chucknorris.io/jokes/categories'

    try:
        response = requests.get(url)
    except ConnectionError:
        raise ConnectionError('It seems there is not network connection')
    except Timeout:
        raise Timeout('Could not send request to the server')

    return response.json()
Beispiel #23
0
    def test_refunded_entitlement_order_connection_timeout(self):
        """
        Test the case that we get an error trying to get the entitlement from LMS
        """
        responses.add(
            responses.GET,
            get_lms_entitlement_api_url() + 'entitlements/' +
            self.course_entitlement_uuid + '/',
            status=200,
            body=Timeout(),
            content_type='application/json',
        )

        self.assertFalse(
            UserAlreadyPlacedOrder.user_already_placed_order(
                user=self.user,
                product=self.course_entitlement,
                site=self.site))
Beispiel #24
0
def search_facts(query):
    ''' Returns all the facts that matchs 'query'
        Args:
            query ('str'): Search query
        Returns:
            dict: Json structured response data containing result of search
    '''
    url = 'https://api.chucknorris.io/jokes/search?query={}'.format(query)

    try:
        response = requests.get(url)
        response.raise_for_status()
    except ConnectionError:
        raise ConnectionError('It seems there is not network connection')
    except Timeout:
        raise Timeout('Could not send request to the server')
    except HTTPError:
        raise HTTPError('Query is not valid!')

    return response.json()
class TestDownloadedPDF:
    def test_not_found_error(self, mocker):
        responce_mock = mocker.Mock()
        responce_mock.status_code = 404
        mocker.patch.object(requests, "get", return_value=responce_mock)
        with pytest.raises(HTTPDownloadError,
                           match="cannot get PDF contents."):
            DownloadedPDF("http://dummy.local")

    @pytest.mark.parametrize(
        "exception,expected",
        [
            (Timeout("Dummy Error."), "cannot connect to web server."),
            (HTTPError("Dummy Error."), "cannot connect to web server."),
            (ConnectionError("Dummy Error."), "cannot connect to web server."),
        ],
    )
    def test_network_error(self, exception, expected, mocker):
        mocker.patch.object(requests, "get", side_effect=exception)
        with pytest.raises(HTTPDownloadError, match=expected):
            DownloadedPDF("http://dummy.local")
class TestDownloadedCSV:
    @pytest.fixture()
    def csv_content(self):
        csv_content = """
No,全国地方公共団体コード,都道府県名,市区町村名,公表_年月日,発症_年月日,患者_居住地,患者_年代,患者_性別,患者_職業,患者_状態,患者_症状,患者_渡航歴の有無フラグ,患者_再陽性フラグ,患者_退院済フラグ,備考
1,10006,北海道,,2020-01-28,2020-01-21,中国武漢市,40代,女性,−,−,発熱,1,0,,海外渡航先:中国武漢
2,10006,北海道,,2020-02-14,2020-01-31,石狩振興局管内,50代,男性,自営業,−,発熱;咳;倦怠感,0,0,,
3,10006,北海道,,2020-02-19,2020-02-08,石狩振興局管内,40代,男性,会社員,−,倦怠感;筋肉痛;関節痛;発熱;咳,0,0,,
    """
        return csv_content.encode("cp932")

    def test_content(self, csv_content, mocker):
        responce_mock = mocker.Mock()
        responce_mock.status_code = 200
        responce_mock.content = csv_content
        responce_mock.headers = {"content-type": "text/csv"}
        mocker.patch.object(requests, "get", return_value=responce_mock)
        csv_file = DownloadedCSV(url="http://dummy.local", encoding="cp932")
        assert csv_file.content.getvalue() == csv_content.decode("cp932")

    def test_not_found_error(self, mocker):
        responce_mock = mocker.Mock()
        responce_mock.status_code = 404
        mocker.patch.object(requests, "get", return_value=responce_mock)
        with pytest.raises(HTTPDownloadError,
                           match="cannot get CSV contents."):
            DownloadedCSV("http://dummy.local")

    @pytest.mark.parametrize(
        "exception,expected",
        [
            (Timeout("Dummy Error."), "cannot connect to web server."),
            (HTTPError("Dummy Error."), "cannot connect to web server."),
            (ConnectionError("Dummy Error."), "cannot connect to web server."),
        ],
    )
    def test_network_error(self, exception, expected, mocker):
        mocker.patch.object(requests, "get", side_effect=exception)
        with pytest.raises(HTTPDownloadError, match=expected):
            DownloadedCSV("http://dummy.local")
Beispiel #27
0
 def consume_units_with_timeout(self, units, timeout_ms, always_consume):
     CheckValue.check_int_ge_zero(timeout_ms, 'timeout_ms')
     # call internal logic, get the time we need to sleep to complete the
     # consume.
     ms_to_sleep = self._consume(
         units, timeout_ms, always_consume,
         int(round(time() * SimpleRateLimiter.NANOS)))
     if ms_to_sleep == 0:
         return 0
     """
     If the time required to consume is greater than our timeout, sleep up to
     the timeout then throw a timeout exception. Note the units may have
     already been consumed if always_consume is True.
     """
     if 0 < timeout_ms <= ms_to_sleep:
         sleep(float(timeout_ms) / 1000)
         raise Timeout('Timed out waiting ' + str(timeout_ms) + 'ms for ' +
                       str(units) + ' units in rate limiter.')
     # Sleep for the requested time.
     sleep(float(ms_to_sleep) / 1000)
     # Return the amount of time slept.
     return ms_to_sleep
Beispiel #28
0
 def request_callback(request):
     raise Timeout()
Beispiel #29
0
def mock_oauth_response(*args, **kwargs):  #pylint: disable=E0211
    """Provide mocking for an oauth request

    Read more about this technique for mocking HTTP requests here:
    https://stackoverflow.com/questions/15753390/python-mock-requests-and-the-response/28507806#28507806
    """
    class MockOAuthResponse:
        """Mocking class for OAuth response

            Args:
                json_data (dict): JSON data returned by the mocked API.
                status_code (int): The HTTP status code returned by the mocked API.
        """
        def __init__(self, json_data, status_code):

            self.json_data = json_data
            self.status_code = status_code
            self.text = '{"test_key": "test_value"}'

        def json(self):
            """Return our mock JSON data"""

            return self.json_data

        def raise_for_status(self):
            """Raise HTTP exception if status code >= 400."""

            if 400 <= self.status_code <= 500:
                raise HTTPError(
                    u'%s Client Error: %s for url: %s' % \
                        (
                            self.status_code,
                            'Unauthorized',
                            'https://api.planningcenteronline.com/oauth/token'
                        ),
                    response=self
                )

    # If we have this attrib, we're getting an access token
    if 'code' in kwargs.get('data'):
        if args[0] != "https://api.planningcenteronline.com/oauth/token":
            return MockOAuthResponse(None, 404)

        if kwargs.get('data')['code'] == 'good':
            return MockOAuthResponse(
                {
                    'access_token':
                    '863300f2f093e8be25fdd7f40f218f4276ecf0b5814a558d899730fcee81e898',  #pylint: disable=C0301
                    'token_type': 'bearer',
                    'expires_in': 7200,
                    'refresh_token':
                    '63d68cb3d8a46eea1c842f5ba469b2940a88a657992f915206be1253a175b6ad',  #pylint: disable=C0301
                    'scope': 'people',
                    'created_at': 1516054388
                },
                200)

        if kwargs.get('data')['code'] == 'bad':
            return MockOAuthResponse(
                {
                    'error':
                    'invalid_client',
                    'error_description':
                    'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'  #pylint: disable=C0301
                },
                401)

        if kwargs.get('data')['code'] == 'server_error':
            return MockOAuthResponse({}, 500)

        if kwargs.get('data')['code'] == 'timeout':
            raise Timeout()

        if kwargs.get('data')['code'] == 'connection':
            raise RequestsConnectionError()

    # If we have this attrib, we're attempting a refresh
    if 'refresh_token' in kwargs.get('data'):
        if kwargs.get('data')['refresh_token'] == 'refresh_good':
            return MockOAuthResponse(
                {
                    'access_token':
                    '863300f2f093e8be25fdd7f40f218f4276ecf0b5814a558d899730fcee81e898',  #pylint: disable=C0301
                    'token_type': 'bearer',
                    'expires_in': 7200,
                    'refresh_token':
                    '63d68cb3d8a46eea1c842f5ba469b2940a88a657992f915206be1253a175b6ad',  #pylint: disable=C0301
                    'created_at': 1516054388
                },
                200)

        if kwargs.get('data')['refresh_token'] == 'refresh_bad':
            return MockOAuthResponse(
                {
                    'error': 'invalid_request',
                    'error_description': 'The refresh token is no longer valid'
                }, 401)

    return MockOAuthResponse(None, 400)
def test_retry_timeout(azure):
    __test_retry_error(azure, 200, 2, body=Timeout())
class TestDownloadedHTML:
    @pytest.fixture()
    def html_content(self):
        return """
<table cellspacing="1" cellpadding="1" style="width: 660px;">
    <caption>新型コロナウイルス感染症の市内発生状況</caption>
    <tbody>
        <tr>
            <th nowrap="nowrap">NO.</th>
            <th nowrap="nowrap">
            <p>北海道発表</p>
            <p>NO.</p>
            </th>
            <th nowrap="nowrap">判明日</th>
            <th nowrap="nowrap">年代</th>
            <th nowrap="nowrap">性別 </th>
            <th nowrap="nowrap">居住地</th>
            <th>周囲の患者の発生</th>
            <th>
            <p>濃厚接触者の状況</p>
            </th>
        </tr>
        <tr>
            <td nowrap="nowrap">1121</td>
            <td>19080</td>
            <td nowrap="nowrap">2月27日</td>
            <td nowrap="nowrap">30代</td>
            <td nowrap="nowrap">男性</td>
            <td>旭川市</td>
            <td>
            <p>No.1072</p>
            <p>No.1094</p>
            <p>No.1107</p>
            <p>No.1108</p>
            </td>
            <td>0人</td>
        </tr>
        <tr>
            <td nowrap="nowrap">1120</td>
            <td>19050</td>
            <td nowrap="nowrap">2 月26日</td>
            <td nowrap="nowrap">50代</td>
            <td nowrap="nowrap">女性</td>
            <td>旭川市</td>
            <td>調査中</td>
            <td>2人</td>
        </tr>
        <tr>
            <td nowrap="nowrap">1119</td>
            <td>19004</td>
            <td nowrap="nowrap">2月25日</td>
            <td nowrap="nowrap">非公表</td>
            <td nowrap="nowrap">非公表</td>
            <td>旭川市</td>
            <td>
            <p>No.1092</p>
            No.1093</td>
            <td>1人</td>
        </tr>
        <tr>
            <td nowrap="nowrap">1112</td>
            <td>18891</td>
            <td nowrap="nowrap">2月22日</td>
            <td nowrap="nowrap">10代未満</td>
            <td nowrap="nowrap">女性</td>
            <td>旭川市</td>
            <td>No.1074</td>
            <td>0人</td>
        </tr>
        <tr>
            <td nowrap="nowrap">1032</td>
            <td>17511</td>
            <td nowrap="nowrap">1月31日</td>
            <td nowrap="nowrap">90代</td>
            <td nowrap="nowrap">男性</td>
            <td>
            <p>旭川市</p>
            </td>
            <td>調査中</td>
            <td>8人</td>
        </tr>
        <tr>
            <th nowrap="nowrap">NO.</th>
            <th nowrap="nowrap">
            <p>北海道発表</p>
            <p>NO.</p>
            </th>
            <th nowrap="nowrap">判明日</th>
            <th nowrap="nowrap">年代</th>
            <th nowrap="nowrap">性別 </th>
            <th nowrap="nowrap">居住地</th>
            <th>周囲の患者の発生</th>
            <th>
            <p>濃厚接触者の状況</p>
            </th>
        </tr>
        <tr>
            <td nowrap="nowrap">715</td>
            <td>10716</td>
            <td nowrap="nowrap">12月9日</td>
            <td nowrap="nowrap">100代</td>
            <td nowrap="nowrap">女性</td>
            <td>旭川市</td>
            <td>あり</td>
            <td>調査中</td>
        </tr>
    </tbody>
</table>
<p><a href="test.html">新型コロナウイルス感染症の発生状況(令和3年8月19日発表分)(PDF形式90キロバイト)</a></p>
"""

    def test_content(self, html_content, mocker):
        responce_mock = mocker.Mock()
        responce_mock.status_code = 200
        responce_mock.content = html_content
        mocker.patch.object(requests, "get", return_value=responce_mock)
        html_file = DownloadedHTML("http://dummy.local")
        assert html_file.content == html_content

    def test_not_found_error(self, mocker):
        responce_mock = mocker.Mock()
        responce_mock.status_code = 404
        mocker.patch.object(requests, "get", return_value=responce_mock)
        with pytest.raises(HTTPDownloadError,
                           match="cannot get HTML contents."):
            DownloadedHTML("http://dummy.local")

    @pytest.mark.parametrize(
        "exception,expected",
        [
            (Timeout("Dummy Error."), "cannot connect to web server."),
            (HTTPError("Dummy Error."), "cannot connect to web server."),
            (ConnectionError("Dummy Error."), "cannot connect to web server."),
        ],
    )
    def test_network_error(self, exception, expected, mocker):
        mocker.patch.object(requests, "get", side_effect=exception)
        with pytest.raises(HTTPDownloadError, match=expected):
            DownloadedHTML("http://dummy.local")