Option C Tools
Loading...
Searching...
No Matches
test_secret_scanner_standalone.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# tests/tests_tools/test_secret_scanner_standalone.py
4
5"""
6Purpose
7-------
8OI-514 regression coverage — :func:`check_no_hardcoded_secrets` and the
9name-pattern helpers live in :mod:`oct.tools.secret_scanner`; the linter
10re-exports them purely for back-compat. The scanner must be reachable
11*without* importing :mod:`oct.linter.oct_lint`.
12
13Responsibilities
14----------------
15- Verify ``oct.tools.secret_scanner`` is importable without loading the
16 linter.
17- Verify the linter re-export is the same object (identity check).
18- Verify the scanner flags secret-shaped name patterns in AST snippets.
19
20Diagnostics
21-----------
22Domain: TOOLS-TESTS
23Levels:
24 L2 — test lifecycle
25 L3 — assertion details
26 L4 — deep tracing
27
28Contracts
29---------
30- ``oct.tools.secret_scanner.check_no_hardcoded_secrets`` is the canonical
31 symbol; :mod:`oct.linter.oct_lint.check_no_hardcoded_secrets` is the
32 same object (identity, not just equality).
33- The scanner flags direct assignments, dict keys, and default args that
34 bind secret-shaped names to string literals.
35- The scanner does not import the linter (no circular dependency).
36"""
37
38from __future__ import annotations
39
40import importlib
41import sys
42
43
45 """OI-514: the scanner module resolves without importing the linter."""
46 # The linter re-exports these symbols for back-compat, but the scanner
47 # itself must not depend on the linter being loaded. Popping only the
48 # scanner (not the linter) would orphan the linter's cached re-export
49 # and break identity checks in ``test_linter_reexport_is_same_object``,
50 # so we accept the already-loaded scanner here — the behaviour we care
51 # about is simply that ``import_module`` succeeds.
52 scanner = importlib.import_module("oct.tools.secret_scanner")
53 assert hasattr(scanner, "check_no_hardcoded_secrets")
54 assert hasattr(scanner, "_name_matches_secret")
55 assert hasattr(scanner, "_SECRET_NAME_PATTERNS")
56 # Independence: the scanner module must not pull the linter in.
57 # (It's fine if the linter is already loaded for unrelated reasons;
58 # the guarantee is that the scanner doesn't cause it.)
59 assert "oct.tools.secret_scanner" in sys.modules
60
61
63 """OI-514: linter re-export preserves object identity."""
64 from oct.linter import oct_lint
65 from oct.tools import secret_scanner
66 assert oct_lint.check_no_hardcoded_secrets is secret_scanner.check_no_hardcoded_secrets
67 assert oct_lint._name_matches_secret is secret_scanner._name_matches_secret
68 assert oct_lint._SECRET_NAME_PATTERNS is secret_scanner._SECRET_NAME_PATTERNS
69
70
72 """OI-514: ``password = "literal"`` flagged with line number."""
73 from oct.tools.secret_scanner import check_no_hardcoded_secrets
74 passed, msg = check_no_hardcoded_secrets('password = "hunter2"\n')
75 assert passed is False
76 assert "password" in msg
77 assert "L1" in msg
78
79
81 """OI-514: calls and subscripts are safe — env lookups never flagged."""
82 from oct.tools.secret_scanner import check_no_hardcoded_secrets
83 src = (
84 "import os\n"
85 "password = os.environ['PASSWORD']\n"
86 "token = os.getenv('TOKEN')\n"
87 )
88 passed, msg = check_no_hardcoded_secrets(src)
89 assert passed is True, msg