def setUp(self):
     self.fetcher_instance = BaseFetcher()
class BaseFetcherTest(TestCase):
    def setUp(self):
        self.fetcher_instance = BaseFetcher()

    def test_set_callback(self):
        """
        Test all callback setter
        :return:
        """

        def callback(response):
            pass

        try:
            self.fetcher_instance.set_error_callback(callback)

        except:
            self.fail("Error callback set failed")

        try:
            self.fetcher_instance.set_chunk_callback(callback)

        except:
            self.fail("Chunk callback set failed")

        # pass a non function
        false_callbacks = [
            1,
            'string',
        ]

        for callback in false_callbacks:
            with self.assertRaises(TypeError):
                self.fetcher_instance.set_error_callback(callback)
                self.fetcher_instance.set_chunk_callback(callback)

    def test_set_data(self):
        correct_data = {
            'Field': 'Key'
        }

        try:
            self.fetcher_instance.set_data(correct_data)
        except:
            self.fail("failed to set data")

        false_data = [
            1,
            '{"key":"field"}',
            [1, 2]
        ]

        for _false_data in false_data:
            with self.assertRaises(TypeError):
                self.fetcher_instance.set_data(_false_data)

    def test_set_interval(self):

        # Reset instance
        self.setUp()



        # Test set class property (correct)
        interval_values = (0, 1, 2, 10000,
                           0.1, 0.2, 1.0,
                           )
        self.fetcher_instance.use_class_properties = True

        for interval_value in interval_values:
            self.fetcher_instance.set_interval(interval_value)
            self.assertEqual(math.ceil(interval_value), self.fetcher_instance.class_interval)

        # class property (wrong type)
        interval_values = ('1100')

        for interval_value in interval_values:
            with self.assertRaises(TypeError):
                self.fetcher_instance.set_interval(interval_value)

        # class property (wrong value)
        interval_values = (-1, -1.0, -0.1)

        for interval_value in interval_values:
            with self.assertRaises(ValueError):
                self.fetcher_instance.set_interval(interval_value)

        # Test set instance property (correct)
        interval_values = (0, 1, 2, 10000,
                           0.1, 0.2, 1.0,
                           )
        self.fetcher_instance.use_class_properties = False

        for interval_value in interval_values:
            self.fetcher_instance.set_interval(interval_value)
            self.assertEqual(math.ceil(interval_value), self.fetcher_instance.instance_interval)

        # instance property (wrong type)
        interval_values = ('1100')

        for interval_value in interval_values:
            with self.assertRaises(TypeError):
                self.fetcher_instance.set_interval(interval_value)

        # instance property (wrong value)
        interval_values = (-1, -1.0, -0.1)

        for interval_value in interval_values:
            with self.assertRaises(ValueError):
                self.fetcher_instance.set_interval(interval_value)

    def test_get_time_to_run(self):
        self.setUp()
        # first run should be allowed
        self.assertLessEqual(self.fetcher_instance.get_time_to_run(), 0)

        # Not ready should return time greater than 0
        self.fetcher_instance.set_interval(1000)
        self.fetcher_instance.record_time()
        self.assertGreater(self.fetcher_instance.get_time_to_run(), 0)

        # Allow ready
        self.fetcher_instance.set_interval(1000)
        from datetime import datetime, timedelta
        happened_at = datetime.now() - timedelta(seconds=5)
        self.fetcher_instance.record_time(happened_at)
        self.assertLessEqual(self.fetcher_instance.get_time_to_run(), 0)

    def test_fetch(self):

        url = r"http://testme.notexist.m"
        url_scheme = r"(.*\.)?testme\.notexist\.m$"
        content = r"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"
        data = {
            "headers": {
                "panda": "goose"
            }
        }
        # Define mock request function
        @urlmatch(netloc=url_scheme)
        def http_mock(url, request):
            # header consistency assert
            self.assertEqual(request.headers.get("panda"), data["headers"]["panda"])
            resp = response(200, content, {"content-length": len(content)})
            return resp

        def begin(_url):
            self.assertEqual(url, _url)

        def error(res):
            pass

        def end(req):
            pass

        self.setUp()

        self.fetcher_instance.urls = [url]
        self.fetcher_instance.set_data(data)
        self.fetcher_instance.chunk_size = 0
        self.fetcher_instance.RequestStarted.connect(begin)
        self.fetcher_instance.RequestFinished.connect(end)
        self.fetcher_instance.RequestFailed.connect(error)

        # Non chunk content assert
        with HTTMock(http_mock):
            self.fetcher_instance.fetch()
            self.fetcher_instance.wait()
            self.assertEqual(content, self.fetcher_instance.stream[0].getvalue())

        # Chunk content assert
        def chunk_ready(chunk, rate, progress):
            pass

        self.fetcher_instance.RequestChunkFinished.connect(chunk_ready)
        self.fetcher_instance.chunk_size = 50

        with HTTMock(http_mock):
            self.fetcher_instance.fetch()
            self.fetcher_instance.wait()
            self.assertEqual(content, self.fetcher_instance.stream[0].getvalue())