mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2026-08-04 14:55:40 +00:00
93 lines
2.7 KiB
Python
93 lines
2.7 KiB
Python
#!/usr/bin/env python
|
|
|
|
"""
|
|
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
|
|
See the file 'LICENSE' for copying permission
|
|
|
|
Function decorators in lib/core/decorators.py: cachedmethod (memoization with a
|
|
hashable fast path and a frozen slow path for unhashable arguments), stackedmethod
|
|
(value-stack realignment) and lockedmethod (reentrant serialization).
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import unittest
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from _testutils import bootstrap
|
|
bootstrap()
|
|
|
|
from lib.core.decorators import cachedmethod, stackedmethod, lockedmethod
|
|
from lib.core.threads import getCurrentThreadData
|
|
|
|
|
|
class TestCachedMethod(unittest.TestCase):
|
|
def test_memoizes_hashable_args(self):
|
|
calls = []
|
|
|
|
@cachedmethod
|
|
def f(x):
|
|
calls.append(x)
|
|
return x * 2
|
|
|
|
self.assertEqual(f(3), 6)
|
|
self.assertEqual(f(3), 6)
|
|
self.assertEqual(len(calls), 1) # second call served from cache
|
|
|
|
def test_memoizes_unhashable_args(self):
|
|
calls = []
|
|
|
|
@cachedmethod
|
|
def g(seq):
|
|
calls.append(1)
|
|
return sum(seq)
|
|
|
|
self.assertEqual(g([1, 2, 3]), 6)
|
|
self.assertEqual(g([1, 2, 3]), 6) # same list content -> cache hit
|
|
self.assertEqual(len(calls), 1)
|
|
self.assertEqual(g([4, 5]), 9) # different content -> recomputed
|
|
self.assertEqual(len(calls), 2)
|
|
|
|
def test_tuple_and_list_args_do_not_collide(self):
|
|
# regression: a list arg ([1,2],) freezes to ((1,2),), the raw fast key of a tuple
|
|
# arg ((1,2),); the two calls must not share a cache slot
|
|
@cachedmethod
|
|
def kind(x):
|
|
return type(x).__name__
|
|
|
|
self.assertEqual(kind((1, 2)), "tuple")
|
|
self.assertEqual(kind([1, 2]), "list")
|
|
|
|
def test_kwargs_are_part_of_the_key(self):
|
|
@cachedmethod
|
|
def h(a, b=0):
|
|
return a + b
|
|
|
|
self.assertEqual(h(1, b=2), 3)
|
|
self.assertEqual(h(1, b=5), 6) # different kwarg -> not a cache hit
|
|
|
|
|
|
class TestStackedMethod(unittest.TestCase):
|
|
def test_realigns_leftover_pushes(self):
|
|
td = getCurrentThreadData()
|
|
base = len(td.valueStack)
|
|
|
|
@stackedmethod
|
|
def leaky(_):
|
|
td.valueStack.append(_) # pushes without popping
|
|
|
|
leaky(1)
|
|
self.assertEqual(len(td.valueStack), base) # stack restored to original level
|
|
|
|
|
|
class TestLockedMethod(unittest.TestCase):
|
|
def test_reentrant(self):
|
|
@lockedmethod
|
|
def recursive_count(n):
|
|
return 0 if n <= 0 else n + recursive_count(n - 1)
|
|
|
|
self.assertEqual(recursive_count(5), 15)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main(verbosity=2)
|