コード例 #1
0
    def test_memoization_with_default_arguments(self):
        for _ in range(5):
            f1(10)
            f2(10)
        f1(20)
        f2(20)

        self.assertEqual(exec_times['f1'], 2)
        self.assertEqual(exec_times['f2'], 2)

        for info in f1.cache_info(), f2.cache_info():
            self.assertIsNone(info.max_size)
            self.assertEqual(info.algorithm, CachingAlgorithmFlag.LRU)
            self.assertIsNone(info.ttl)
            self.assertTrue(info.thread_safe)

            self.assertEqual(info.hits, 4)
            self.assertEqual(info.misses, 2)
            self.assertEqual(info.current_size, 2)
        for f in f1, f2:
            keys = make_key((10, ), None), make_key((20, ), None)
            for key in keys:
                self.assertIn(key, f._cache)

        f1.cache_clear()
        f2.cache_clear()
        self._check_empty_cache_after_clearing(f1)
        self._check_empty_cache_after_clearing(f2)
コード例 #2
0
ファイル: test.py プロジェクト: meiliqi/python-memoization
    def _general_test(self, tested_function, algorithm, hits, misses, in_cache,
                      not_in_cache):
        # clear
        exec_times[tested_function.__name__] = 0
        tested_function.cache_clear()

        for i in range(20):
            tested_function(i)
        tested_function(99)

        self.assertEqual(exec_times[tested_function.__name__], 21)
        info = tested_function.cache_info()
        self.assertEqual(info.max_size, 5)
        self.assertEqual(info.algorithm, algorithm)
        self.assertIsNone(info.ttl)
        self.assertIsNotNone(info.thread_safe)

        self.assertEqual(info.hits, 0)
        self.assertEqual(info.misses, 21)
        self.assertEqual(info.current_size, 5)

        keys = [make_key((x, ), None) for x in (99, 19, 18, 17, 16)]
        for key in keys:
            self.assertIn(key, tested_function._cache)

        # 10 consecutive calls here
        tested_function(16)
        tested_function(17)
        tested_function(18)
        tested_function(16)
        tested_function(17)
        tested_function(18)

        tested_function(19)
        tested_function(15)
        tested_function(100)
        tested_function(16)

        info = tested_function.cache_info()
        self.assertEqual(info.hits, hits)
        self.assertEqual(info.misses, misses)
        self.assertEqual(info.current_size, 5)

        keys = [make_key((x, ), None) for x in in_cache]
        for key in keys:
            self.assertIn(key, tested_function._cache)
        keys = [
            make_key((x, ), None) for x in chain(not_in_cache, range(0, 15))
        ]
        for key in keys:
            self.assertNotIn(key, tested_function._cache)
コード例 #3
0
    def _general_ttl_test(self, tested_function, arg=1, kwargs=None):
        # clear
        exec_times[tested_function.__name__] = 0
        tested_function.cache_clear()

        def call_tested_function(arg, kwargs):
            if kwargs is None:
                tested_function(arg)
            else:
                tested_function(arg, **kwargs)

        key = make_key((arg, ), kwargs)
        call_tested_function(arg, kwargs)
        time.sleep(0.25)  # wait for a short time

        info = tested_function.cache_info()
        self.assertEqual(info.hits, 0)
        self.assertEqual(info.misses, 1)
        self.assertEqual(info.current_size, 1)
        self.assertIn(key, tested_function._cache)

        call_tested_function(arg,
                             kwargs)  # this WILL NOT call the tested function

        info = tested_function.cache_info()
        self.assertEqual(info.hits, 1)
        self.assertEqual(info.misses, 1)
        self.assertEqual(info.current_size, 1)
        self.assertIn(key, tested_function._cache)
        self.assertEqual(exec_times[tested_function.__name__], 1)

        time.sleep(0.35)  # wait until the cache expires

        info = tested_function.cache_info()
        self.assertEqual(info.current_size, 1)

        call_tested_function(arg, kwargs)  # this WILL call the tested function

        info = tested_function.cache_info()
        self.assertEqual(info.hits, 1)
        self.assertEqual(info.misses, 2)
        self.assertEqual(info.current_size, 1)
        self.assertIn(key, tested_function._cache)
        self.assertEqual(exec_times[tested_function.__name__], 2)

        # The previous call should have been cached, so it must not call the function again
        call_tested_function(
            arg, kwargs)  # this SHOULD NOT call the tested function

        info = tested_function.cache_info()
        self.assertEqual(info.hits, 2)
        self.assertEqual(info.misses, 2)
        self.assertEqual(info.current_size, 1)
        self.assertIn(key, tested_function._cache)
        self.assertEqual(exec_times[tested_function.__name__], 2)
コード例 #4
0
    def _general_unhashable_arguments_test(self, tested_function):
        args = ([1, 2, 3], {
            'this': 'is unhashable'
        }, ['yet', ['another', ['complex', {
            'type, ': 'isn\'t it?'
        }]]])
        for arg in args:
            # clear
            exec_times[tested_function.__name__] = 0
            tested_function.cache_clear()

            key = make_key((arg, ), None)
            tested_function(arg)
            self.assertIn(key, tested_function._cache)

            if isinstance(arg, list):
                arg.append(0)
            elif isinstance(arg, dict):
                arg['foo'] = 'bar'
            else:
                raise TypeError
            key = make_key((arg, ), None)
            tested_function(arg)
            self.assertIn(key, tested_function._cache)

            if isinstance(arg, list):
                arg.pop()
            elif isinstance(arg, dict):
                del arg['foo']
            else:
                raise TypeError
            key = make_key((arg, ), None)
            tested_function(arg)
            self.assertIn(key, tested_function._cache)

            self.assertEqual(exec_times[tested_function.__name__], 2)
            info = tested_function.cache_info()
            self.assertEqual(info.hits, 1)
            self.assertEqual(info.misses, 2)
            self.assertEqual(info.current_size, 2)
コード例 #5
0
        async def _wrapper(*args, **kwargs):
            nonlocal hits, misses
            key = keys_order_dependent.make_key(args, kwargs)

            # Attempt to get value from cache
            try:
                node = cache[key]
            except KeyError:
                pass
            else:
                # Hit. Return cached value if still valid.
                if values_with_ttl.is_cache_value_valid(node):
                    hits += 1
                    return values_with_ttl.retrieve_result_from_cache_value(node)

            # Miss. Get value from function and insert into cache.
            misses += 1
            value = await func(*args, **kwargs)
            cache[key] = values_with_ttl.make_cache_value(value, ttl)
            return value
コード例 #6
0
    def _general_multithreading_test(self, tested_function, algorithm):
        number_of_keys = 30000
        number_of_threads = 4

        # clear
        exec_times[tested_function.__name__] = 0
        tested_function.cache_clear()

        info = tested_function.cache_info()
        self.assertEqual(info.max_size, 5)
        self.assertEqual(info.algorithm, algorithm)
        self.assertIsNone(info.ttl)
        self.assertTrue(info.thread_safe)
        self.assertEqual(info.current_size, 0)

        # Test must-hit
        def run_must_hit():
            keys = list(range(5)) * int(number_of_keys / 5)
            random.shuffle(keys)
            for i in keys:
                tested_function(i)

        threads = [
            Thread(target=run_must_hit) for _ in range(number_of_threads)
        ]
        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()

        self.assertGreaterEqual(exec_times[tested_function.__name__], 5)
        info = tested_function.cache_info()
        self.assertLessEqual(info.hits, number_of_keys * number_of_threads - 5)
        self.assertGreaterEqual(info.misses, 5)
        self.assertEqual(info.current_size, 5)

        for key in [make_key((x, ), None) for x in range(5)]:
            self.assertIn(key, tested_function._cache)

        # Test can-miss
        def run_can_miss():
            keys = list(range(20)) * int(number_of_keys / 20)
            random.shuffle(keys)
            for i in keys:
                tested_function(i)

        threads = [
            Thread(target=run_can_miss) for _ in range(number_of_threads)
        ]
        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()

        executed_times = exec_times[tested_function.__name__]
        self.assertLessEqual(executed_times,
                             number_of_keys * number_of_threads)
        self.assertGreaterEqual(executed_times, 20)
        info = tested_function.cache_info()
        self.assertGreaterEqual(info.hits, 0)
        self.assertLessEqual(info.misses, number_of_keys * number_of_threads)
        self.assertEqual(info.current_size, 5)