def test_download_successful(self, fire_download_succeeded, fire_download_failed,
                                 _clear_easy_handle_download):
        """
        Assert correct behavior for a successful download.
        """
        config = DownloaderConfig(max_concurrent=1)
        curl_downloader = HTTPCurlDownloader(config)
        multi_handle = curl_downloader._build_multi_handle()
        easy_handle = multi_handle.handles[0]
        easy_handle.report = DownloadReport('http://fake.com/doesntmatter.html', '/dev/null')
        multi_handle._curls = [easy_handle]
        free_handles = []
        start_time = datetime.now()

        curl_downloader._process_completed_download(easy_handle, multi_handle, free_handles)

        # The easy_handle should have been removed from the multi_handle
        multi_handle.remove_handle.assert_called_once_with(easy_handle)
        # _clear_easy_handle_download should have been handed the easy_handle
        _clear_easy_handle_download.assert_called_once_wth(easy_handle)
        # The free_handles list should have the easy_handle
        self.assertEqual(free_handles, [easy_handle])
        # fire_download_failed should not have been called
        self.assertEqual(fire_download_failed.call_count, 0)

        # fire_download_succeeded should have been called once with the report. Let's assert that, and assert
        # that the report looks good
        self.assertEqual(fire_download_succeeded.call_count, 1)
        report = fire_download_succeeded.mock_calls[0][1][0]
        self.assertTrue(isinstance(report, DownloadReport))
        self.assertTrue(report.state, DOWNLOAD_SUCCEEDED)
        # It's difficult to know what the finish_time on the report will be exactly, so we'll just assert that
        # it's after the start_time we recorded earlier
        self.assertTrue(report.finish_time > start_time)
    def test_pycurl_errors(self, fire_download_succeeded, fire_download_failed, _clear_easy_handle_download):
        """
        Assert correct behavior when error is not None.
        """
        config = DownloaderConfig(max_concurrent=1)
        curl_downloader = HTTPCurlDownloader(config)
        multi_handle = curl_downloader._build_multi_handle()
        easy_handle = multi_handle.handles[0]
        easy_handle.report = DownloadReport('http://fake.com/doesntmatter.html', '/dev/null')
        multi_handle._curls = [easy_handle]

        def return_code(ignored_param):
            """
            This function will allow us to fake the response code when pycurl didn't reach the server, which
            will be 0.
            """
            return 0

        easy_handle.getinfo = return_code
        free_handles = []
        start_time = datetime.now()

        curl_downloader._process_completed_download(
            easy_handle, multi_handle, free_handles,
            {'code': pycurl.E_COULDNT_CONNECT, 'message': "Couldn't Connect"})

        # The easy_handle should have been removed from the multi_handle
        multi_handle.remove_handle.assert_called_once_with(easy_handle)
        # _clear_easy_handle_download should have been handed the easy_handle
        _clear_easy_handle_download.assert_called_once_wth(easy_handle)
        # The free_handles list should have the easy_handle
        self.assertEqual(free_handles, [easy_handle])
        # fire_download_succeeded should not have been called
        self.assertEqual(fire_download_succeeded.call_count, 0)

        # fire_download_failed should have been called once with the report. Let's assert that, and assert
        # that the report looks good
        self.assertEqual(fire_download_failed.call_count, 1)
        report = fire_download_failed.mock_calls[0][1][0]
        self.assertTrue(isinstance(report, DownloadReport))
        self.assertTrue(report.state, DOWNLOAD_FAILED)
        self.assertEqual(report.error_report['response_code'], 0)
        self.assertEqual(report.error_report['error_code'], pycurl.E_COULDNT_CONNECT)
        self.assertEqual(report.error_report['error_message'], "Couldn't Connect")
        # It's difficult to know what the finish_time on the report will be exactly, so we'll just assert that
        # it's after the start_time we recorded earlier
        self.assertTrue(report.finish_time > start_time)