KeyHunter parser v10 + 18 scanners + tests (synthetic fixtures only, no keys/db/tokens)
This commit is contained in:
157
test_wp_svn.py
Normal file
157
test_wp_svn.py
Normal file
@@ -0,0 +1,157 @@
|
||||
"""Offline test for wp_svn_eternal — SVN listing parsing + file scan + DB write + dedup.
|
||||
|
||||
Uses real fixture files (no network). Proves:
|
||||
a) fetch_svn_list parses trunk HTML correctly
|
||||
b) scan_text finds keys in injected sample file
|
||||
c) junk filter drops garbage candidates
|
||||
d) db_add inserts + dedupes
|
||||
"""
|
||||
import hashlib, os, sys, sqlite3, tempfile, unittest
|
||||
|
||||
BASE = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
FIXTURE_TRUNK = os.path.join(BASE, "tests", "wp_svn_trunk_fixture.html")
|
||||
FIXTURE_FILE = os.path.join(BASE, "tests", "wp_svn_file_fixture.txt")
|
||||
|
||||
DB_CONTRACT_SQL = """CREATE TABLE IF NOT EXISTS keys (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
hash TEXT UNIQUE,
|
||||
val TEXT, prov TEXT, status TEXT DEFAULT "NEW",
|
||||
plan TEXT, price TEXT, remaining TEXT,
|
||||
found TEXT, repo TEXT)"""
|
||||
|
||||
|
||||
class TestWpSvn(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.tmp = tempfile.NamedTemporaryFile(suffix=".db", delete=False)
|
||||
self.tmp.close()
|
||||
conn = sqlite3.connect(self.tmp.name)
|
||||
conn.execute(DB_CONTRACT_SQL)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
self.old_kf_db = os.environ.get("KF_DB")
|
||||
os.environ["KF_DB"] = self.tmp.name
|
||||
|
||||
def tearDown(self):
|
||||
if "wp_svn_eternal" in sys.modules:
|
||||
m = sys.modules["wp_svn_eternal"]
|
||||
try:
|
||||
m.conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
if self.old_kf_db:
|
||||
os.environ["KF_DB"] = self.old_kf_db
|
||||
else:
|
||||
os.environ.pop("KF_DB", None)
|
||||
try:
|
||||
os.unlink(self.tmp.name)
|
||||
except PermissionError:
|
||||
pass
|
||||
|
||||
def _import(self):
|
||||
if "wp_svn_eternal" in sys.modules:
|
||||
del sys.modules["wp_svn_eternal"]
|
||||
if BASE not in sys.path:
|
||||
sys.path.insert(0, BASE)
|
||||
import wp_svn_eternal as m
|
||||
m.conn = sqlite3.connect(self.tmp.name, timeout=120,
|
||||
check_same_thread=False, isolation_level=None)
|
||||
m.conn.execute(DB_CONTRACT_SQL)
|
||||
m.conn.commit()
|
||||
return m
|
||||
|
||||
def test_parse_trunk_listing(self):
|
||||
"""(a) Replicate fetch_svn_list parser on real trunk HTML."""
|
||||
m = self._import()
|
||||
with open(FIXTURE_TRUNK, encoding="utf-8") as fh:
|
||||
html = fh.read()
|
||||
|
||||
files, dirs = [], []
|
||||
for li in __import__("re").finditer(
|
||||
r'<li><a\s+href="([^"]+)">([^<]*)</a></li>', html):
|
||||
href = li.group(1)
|
||||
name = li.group(2)
|
||||
if name == ".." or not name:
|
||||
continue
|
||||
if href.endswith("/"):
|
||||
dirs.append(name.rstrip("/"))
|
||||
elif not href.startswith("?"):
|
||||
files.append(name)
|
||||
|
||||
self.assertIn("akismet.php", files)
|
||||
self.assertIn("_inc", dirs)
|
||||
self.assertIn("abilities", dirs)
|
||||
self.assertIn("readme.txt", files)
|
||||
self.assertIn("changelog.txt", files)
|
||||
self.assertGreater(len(files) + len(dirs), 10)
|
||||
|
||||
def test_scan_finds_keys(self):
|
||||
"""(b) scan_text extracts injected keys from fixture file."""
|
||||
m = self._import()
|
||||
with open(FIXTURE_FILE, encoding="utf-8") as fh:
|
||||
text = fh.read()
|
||||
results = m.scan_text(text)
|
||||
found_keys = [k for prov, k in results if isinstance(k, str)]
|
||||
|
||||
self.assertTrue(
|
||||
any("LongKeyBodyAvoidGarbageFilterCheckPassOpenaiTestSkProjValidCharsHereForSixtyPlusMoreNow" in k
|
||||
for k in found_keys),
|
||||
f"Expected injected key in results, got first 5: {found_keys[:5]}"
|
||||
)
|
||||
|
||||
def test_junk_filter(self):
|
||||
"""(c) GARBAGE-filtered keys are dropped by db_add."""
|
||||
m = self._import()
|
||||
with open(FIXTURE_FILE, encoding="utf-8") as fh:
|
||||
text = fh.read()
|
||||
results = m.scan_text(text)
|
||||
self.assertGreater(len(results), 1,
|
||||
"Need at least 2 scan results to test filtering")
|
||||
|
||||
before = m.total
|
||||
for prov, key in results:
|
||||
if isinstance(key, tuple):
|
||||
key = key[0]
|
||||
m.db_add(key, prov, "wp:test-slug")
|
||||
added = m.total - before
|
||||
|
||||
conn = sqlite3.connect(self.tmp.name)
|
||||
rows = conn.execute("SELECT val FROM keys").fetchall()
|
||||
conn.close()
|
||||
vals = [r[0] for r in rows]
|
||||
|
||||
for v in vals:
|
||||
self.assertFalse("xxxxxxxxxxxx" in v,
|
||||
f"Garbage key leaked: {v[:30]}")
|
||||
self.assertGreater(added, 0,
|
||||
"Should have added at least one key")
|
||||
self.assertLess(added, len(results),
|
||||
"Junk filter should have removed garbage entries")
|
||||
|
||||
def test_db_add_dedup(self):
|
||||
"""(d) db_add dedupes on repeat insert."""
|
||||
m = self._import()
|
||||
key = "sk-proj-TestDedupLongKeyBodyPassFilterCheckOpenaiApiTestValidSixtyPlusCharsHereMoreNowXyz"
|
||||
self.assertGreater(len(key), 60)
|
||||
m.db_add(key, "OPENAI", "wp:test-slug")
|
||||
|
||||
h = hashlib.sha1(key.encode()).hexdigest()[:16]
|
||||
conn = sqlite3.connect(self.tmp.name)
|
||||
row = conn.execute(
|
||||
"SELECT COUNT(*) FROM keys WHERE hash=?", (h,)).fetchone()
|
||||
self.assertEqual(row[0], 1,
|
||||
"First insert should create one row")
|
||||
|
||||
# Second insert of same key: ON CONFLICT WHERE status IN ('DEAD','ERR')
|
||||
# won't match (status='NEW'), no duplicate row created
|
||||
m.db_add(key, "OPENAI", "wp:test-slug")
|
||||
row2 = conn.execute(
|
||||
"SELECT COUNT(*) FROM keys WHERE hash=?", (h,)).fetchone()
|
||||
conn.close()
|
||||
self.assertEqual(row2[0], 1,
|
||||
"Dedup failed: duplicate row created")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
Reference in New Issue
Block a user