code-abyss 1.6.15 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/install.js +25 -4
- package/package.json +2 -2
- package/skills/SKILL.md +24 -16
- package/skills/domains/ai/SKILL.md +2 -2
- package/skills/domains/ai/prompt-and-eval.md +279 -0
- package/skills/domains/architecture/SKILL.md +2 -3
- package/skills/domains/architecture/security-arch.md +87 -0
- package/skills/domains/data-engineering/SKILL.md +188 -26
- package/skills/domains/development/SKILL.md +1 -4
- package/skills/domains/devops/SKILL.md +3 -5
- package/skills/domains/devops/performance.md +63 -0
- package/skills/domains/devops/testing.md +97 -0
- package/skills/domains/frontend-design/SKILL.md +12 -3
- package/skills/domains/frontend-design/claymorphism/SKILL.md +117 -0
- package/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
- package/skills/domains/frontend-design/engineering.md +287 -0
- package/skills/domains/frontend-design/glassmorphism/SKILL.md +138 -0
- package/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
- package/skills/domains/frontend-design/liquid-glass/SKILL.md +135 -0
- package/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
- package/skills/domains/frontend-design/neubrutalism/SKILL.md +141 -0
- package/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
- package/skills/domains/infrastructure/SKILL.md +174 -34
- package/skills/domains/mobile/SKILL.md +211 -21
- package/skills/domains/orchestration/SKILL.md +1 -0
- package/skills/domains/security/SKILL.md +4 -6
- package/skills/domains/security/blue-team.md +57 -0
- package/skills/domains/security/red-team.md +54 -0
- package/skills/domains/security/threat-intel.md +50 -0
- package/skills/orchestration/multi-agent/SKILL.md +195 -46
- package/skills/run_skill.js +134 -0
- package/skills/tools/gen-docs/SKILL.md +6 -4
- package/skills/tools/gen-docs/scripts/doc_generator.js +349 -0
- package/skills/tools/verify-change/SKILL.md +8 -6
- package/skills/tools/verify-change/scripts/change_analyzer.js +270 -0
- package/skills/tools/verify-module/SKILL.md +6 -4
- package/skills/tools/verify-module/scripts/module_scanner.js +145 -0
- package/skills/tools/verify-quality/SKILL.md +5 -3
- package/skills/tools/verify-quality/scripts/quality_checker.js +276 -0
- package/skills/tools/verify-security/SKILL.md +7 -5
- package/skills/tools/verify-security/scripts/security_scanner.js +133 -0
- package/skills/domains/COVERAGE_PLAN.md +0 -232
- package/skills/domains/ai/model-evaluation.md +0 -790
- package/skills/domains/ai/prompt-engineering.md +0 -703
- package/skills/domains/architecture/compliance.md +0 -299
- package/skills/domains/architecture/data-security.md +0 -184
- package/skills/domains/data-engineering/data-pipeline.md +0 -762
- package/skills/domains/data-engineering/data-quality.md +0 -894
- package/skills/domains/data-engineering/stream-processing.md +0 -791
- package/skills/domains/development/dart.md +0 -963
- package/skills/domains/development/kotlin.md +0 -834
- package/skills/domains/development/php.md +0 -659
- package/skills/domains/development/swift.md +0 -755
- package/skills/domains/devops/e2e-testing.md +0 -914
- package/skills/domains/devops/performance-testing.md +0 -734
- package/skills/domains/devops/testing-strategy.md +0 -667
- package/skills/domains/frontend-design/build-tools.md +0 -743
- package/skills/domains/frontend-design/performance.md +0 -734
- package/skills/domains/frontend-design/testing.md +0 -699
- package/skills/domains/infrastructure/gitops.md +0 -735
- package/skills/domains/infrastructure/iac.md +0 -855
- package/skills/domains/infrastructure/kubernetes.md +0 -1018
- package/skills/domains/mobile/android-dev.md +0 -979
- package/skills/domains/mobile/cross-platform.md +0 -795
- package/skills/domains/mobile/ios-dev.md +0 -931
- package/skills/domains/security/secrets-management.md +0 -834
- package/skills/domains/security/supply-chain.md +0 -931
- package/skills/domains/security/threat-modeling.md +0 -828
- package/skills/run_skill.py +0 -88
- package/skills/tests/README.md +0 -225
- package/skills/tests/SUMMARY.md +0 -362
- package/skills/tests/__init__.py +0 -3
- package/skills/tests/test_change_analyzer.py +0 -558
- package/skills/tests/test_doc_generator.py +0 -538
- package/skills/tests/test_module_scanner.py +0 -376
- package/skills/tests/test_quality_checker.py +0 -516
- package/skills/tests/test_security_scanner.py +0 -426
- package/skills/tools/gen-docs/scripts/doc_generator.py +0 -491
- package/skills/tools/verify-change/scripts/change_analyzer.py +0 -529
- package/skills/tools/verify-module/scripts/module_scanner.py +0 -321
- package/skills/tools/verify-quality/scripts/quality_checker.py +0 -481
- package/skills/tools/verify-security/scripts/security_scanner.py +0 -368
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
verify-security 单元测试
|
|
4
|
-
测试代码安全扫描器功能
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import unittest
|
|
8
|
-
import tempfile
|
|
9
|
-
import sys
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
from unittest.mock import patch, MagicMock
|
|
12
|
-
|
|
13
|
-
# 添加 skills 目录到 Python 路径
|
|
14
|
-
sys.path.insert(0, str(Path(__file__).parent.parent / "tools" / "verify-security" / "scripts"))
|
|
15
|
-
|
|
16
|
-
from security_scanner import (
|
|
17
|
-
Severity, Finding, ScanResult, scan_file, scan_directory,
|
|
18
|
-
format_report, SECURITY_RULES
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class TestSecurityScanner(unittest.TestCase):
|
|
23
|
-
"""安全扫描器测试"""
|
|
24
|
-
|
|
25
|
-
def setUp(self):
|
|
26
|
-
"""测试前准备"""
|
|
27
|
-
self.temp_dir = tempfile.TemporaryDirectory()
|
|
28
|
-
self.temp_path = Path(self.temp_dir.name)
|
|
29
|
-
|
|
30
|
-
def tearDown(self):
|
|
31
|
-
"""测试后清理"""
|
|
32
|
-
self.temp_dir.cleanup()
|
|
33
|
-
|
|
34
|
-
def test_scan_file_with_sql_injection(self):
|
|
35
|
-
"""测试 SQL 注入检测"""
|
|
36
|
-
test_file = self.temp_path / "test.py"
|
|
37
|
-
test_file.write_text('cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")')
|
|
38
|
-
|
|
39
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
40
|
-
|
|
41
|
-
self.assertTrue(len(findings) > 0)
|
|
42
|
-
self.assertTrue(any(f.severity == Severity.CRITICAL for f in findings))
|
|
43
|
-
self.assertTrue(any("SQL" in f.message for f in findings))
|
|
44
|
-
|
|
45
|
-
def test_scan_file_without_sql_context_not_flagged(self):
|
|
46
|
-
"""测试非 SQL 场景不应误报 SQL 注入"""
|
|
47
|
-
test_file = self.temp_path / "non_sql.py"
|
|
48
|
-
test_file.write_text('long_line = "x = \"" + "a" * 10000 + "\""')
|
|
49
|
-
|
|
50
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
51
|
-
|
|
52
|
-
self.assertFalse(any("SQL" in f.message for f in findings))
|
|
53
|
-
|
|
54
|
-
def test_scan_file_with_hardcoded_secret(self):
|
|
55
|
-
"""测试硬编码密钥检测"""
|
|
56
|
-
test_file = self.temp_path / "config.py"
|
|
57
|
-
test_file.write_text('password = "super_secret_password_12345"')
|
|
58
|
-
|
|
59
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
60
|
-
|
|
61
|
-
self.assertTrue(len(findings) > 0)
|
|
62
|
-
self.assertTrue(any(f.severity == Severity.HIGH for f in findings))
|
|
63
|
-
|
|
64
|
-
def test_scan_file_with_command_injection(self):
|
|
65
|
-
"""测试命令注入检测"""
|
|
66
|
-
test_file = self.temp_path / "shell.py"
|
|
67
|
-
test_file.write_text('os.system(cmd, shell=True)')
|
|
68
|
-
|
|
69
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
70
|
-
|
|
71
|
-
self.assertTrue(len(findings) > 0)
|
|
72
|
-
self.assertTrue(any("shell=True" in f.message for f in findings))
|
|
73
|
-
|
|
74
|
-
def test_scan_file_with_xss_vulnerability(self):
|
|
75
|
-
"""测试 XSS 漏洞检测"""
|
|
76
|
-
test_file = self.temp_path / "app.js"
|
|
77
|
-
test_file.write_text('element.innerHTML = userInput;')
|
|
78
|
-
|
|
79
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
80
|
-
|
|
81
|
-
self.assertTrue(len(findings) > 0)
|
|
82
|
-
self.assertTrue(any("innerHTML" in f.message for f in findings))
|
|
83
|
-
|
|
84
|
-
def test_scan_file_with_unsafe_pickle(self):
|
|
85
|
-
"""测试不安全反序列化检测"""
|
|
86
|
-
test_file = self.temp_path / "data.py"
|
|
87
|
-
test_file.write_text('data = pickle.loads(user_data)')
|
|
88
|
-
|
|
89
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
90
|
-
|
|
91
|
-
self.assertTrue(len(findings) > 0)
|
|
92
|
-
self.assertTrue(any("反序列化" in f.message for f in findings))
|
|
93
|
-
|
|
94
|
-
def test_scan_file_with_weak_crypto(self):
|
|
95
|
-
"""测试弱加密算法检测"""
|
|
96
|
-
test_file = self.temp_path / "crypto.py"
|
|
97
|
-
test_file.write_text('hash_obj = hashlib.md5(password)')
|
|
98
|
-
|
|
99
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
100
|
-
|
|
101
|
-
self.assertTrue(len(findings) > 0)
|
|
102
|
-
self.assertTrue(any("MD5" in f.message for f in findings))
|
|
103
|
-
|
|
104
|
-
def test_scan_file_with_debug_code(self):
|
|
105
|
-
"""测试调试代码检测"""
|
|
106
|
-
test_file = self.temp_path / "main.py"
|
|
107
|
-
test_file.write_text('print("debug info")\npdb.set_trace()')
|
|
108
|
-
|
|
109
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
110
|
-
|
|
111
|
-
self.assertTrue(len(findings) > 0)
|
|
112
|
-
self.assertTrue(any("调试" in f.message for f in findings))
|
|
113
|
-
|
|
114
|
-
def test_scan_file_print_not_marked_debug(self):
|
|
115
|
-
"""测试普通 print 不应被判定调试代码"""
|
|
116
|
-
test_file = self.temp_path / "main.py"
|
|
117
|
-
test_file.write_text('print("normal output")')
|
|
118
|
-
|
|
119
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
120
|
-
|
|
121
|
-
self.assertFalse(any("调试" in f.message for f in findings))
|
|
122
|
-
|
|
123
|
-
def test_scan_file_ignores_comments(self):
|
|
124
|
-
"""测试注释行被忽略"""
|
|
125
|
-
test_file = self.temp_path / "test.py"
|
|
126
|
-
test_file.write_text('# cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")')
|
|
127
|
-
|
|
128
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
129
|
-
|
|
130
|
-
# 注释行应该被忽略
|
|
131
|
-
self.assertEqual(len(findings), 0)
|
|
132
|
-
|
|
133
|
-
def test_scan_file_empty_file(self):
|
|
134
|
-
"""测试空文件扫描"""
|
|
135
|
-
test_file = self.temp_path / "empty.py"
|
|
136
|
-
test_file.write_text('')
|
|
137
|
-
|
|
138
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
139
|
-
|
|
140
|
-
self.assertEqual(len(findings), 0)
|
|
141
|
-
|
|
142
|
-
def test_scan_file_nonexistent(self):
|
|
143
|
-
"""测试不存在的文件"""
|
|
144
|
-
nonexistent = self.temp_path / "nonexistent.py"
|
|
145
|
-
|
|
146
|
-
findings = scan_file(nonexistent, SECURITY_RULES)
|
|
147
|
-
|
|
148
|
-
self.assertEqual(len(findings), 0)
|
|
149
|
-
|
|
150
|
-
def test_scan_directory_basic(self):
|
|
151
|
-
"""测试目录扫描基本功能"""
|
|
152
|
-
# 创建测试文件
|
|
153
|
-
(self.temp_path / "safe.py").write_text('x = 1')
|
|
154
|
-
(self.temp_path / "unsafe.py").write_text('password = "secret123456"')
|
|
155
|
-
|
|
156
|
-
result = scan_directory(str(self.temp_path))
|
|
157
|
-
|
|
158
|
-
self.assertIsInstance(result, ScanResult)
|
|
159
|
-
self.assertEqual(result.files_scanned, 2)
|
|
160
|
-
self.assertTrue(len(result.findings) > 0)
|
|
161
|
-
|
|
162
|
-
def test_scan_directory_empty(self):
|
|
163
|
-
"""测试空目录扫描"""
|
|
164
|
-
result = scan_directory(str(self.temp_path))
|
|
165
|
-
|
|
166
|
-
self.assertEqual(result.files_scanned, 0)
|
|
167
|
-
self.assertEqual(len(result.findings), 0)
|
|
168
|
-
|
|
169
|
-
def test_scan_directory_nonexistent(self):
|
|
170
|
-
"""测试不存在的目录"""
|
|
171
|
-
nonexistent = self.temp_path / "nonexistent"
|
|
172
|
-
|
|
173
|
-
result = scan_directory(str(nonexistent))
|
|
174
|
-
|
|
175
|
-
self.assertEqual(result.files_scanned, 0)
|
|
176
|
-
|
|
177
|
-
def test_scan_directory_excludes_dirs(self):
|
|
178
|
-
"""测试目录排除功能"""
|
|
179
|
-
# 创建被排除的目录
|
|
180
|
-
node_modules = self.temp_path / "node_modules"
|
|
181
|
-
node_modules.mkdir()
|
|
182
|
-
(node_modules / "unsafe.py").write_text('password = "secret123456"')
|
|
183
|
-
|
|
184
|
-
# 创建不被排除的文件
|
|
185
|
-
(self.temp_path / "safe.py").write_text('x = 1')
|
|
186
|
-
|
|
187
|
-
result = scan_directory(str(self.temp_path), exclude_dirs=['node_modules'])
|
|
188
|
-
|
|
189
|
-
self.assertEqual(result.files_scanned, 1)
|
|
190
|
-
|
|
191
|
-
def test_scan_directory_default_excludes_tests(self):
|
|
192
|
-
"""测试默认排除测试目录"""
|
|
193
|
-
tests_dir = self.temp_path / "tests"
|
|
194
|
-
tests_dir.mkdir()
|
|
195
|
-
(tests_dir / "test_unsafe.py").write_text('password = "secret123456"')
|
|
196
|
-
(self.temp_path / "app.py").write_text('x = 1')
|
|
197
|
-
|
|
198
|
-
result = scan_directory(str(self.temp_path))
|
|
199
|
-
|
|
200
|
-
self.assertEqual(result.files_scanned, 1)
|
|
201
|
-
self.assertFalse(any("test_unsafe.py" in f.file_path for f in result.findings))
|
|
202
|
-
|
|
203
|
-
def test_scan_result_passed_property(self):
|
|
204
|
-
"""测试 ScanResult.passed 属性"""
|
|
205
|
-
result = ScanResult(scan_path="/test")
|
|
206
|
-
|
|
207
|
-
# 没有发现时应该通过
|
|
208
|
-
self.assertTrue(result.passed)
|
|
209
|
-
|
|
210
|
-
# 添加低危发现
|
|
211
|
-
result.findings.append(Finding(
|
|
212
|
-
severity=Severity.LOW,
|
|
213
|
-
category="test",
|
|
214
|
-
message="test",
|
|
215
|
-
file_path="test.py",
|
|
216
|
-
line_number=1,
|
|
217
|
-
line_content="test",
|
|
218
|
-
recommendation="test"
|
|
219
|
-
))
|
|
220
|
-
self.assertTrue(result.passed)
|
|
221
|
-
|
|
222
|
-
# 添加高危发现
|
|
223
|
-
result.findings.append(Finding(
|
|
224
|
-
severity=Severity.HIGH,
|
|
225
|
-
category="test",
|
|
226
|
-
message="test",
|
|
227
|
-
file_path="test.py",
|
|
228
|
-
line_number=2,
|
|
229
|
-
line_content="test",
|
|
230
|
-
recommendation="test"
|
|
231
|
-
))
|
|
232
|
-
self.assertFalse(result.passed)
|
|
233
|
-
|
|
234
|
-
def test_scan_result_count_by_severity(self):
|
|
235
|
-
"""测试按严重程度计数"""
|
|
236
|
-
result = ScanResult(scan_path="/test")
|
|
237
|
-
|
|
238
|
-
result.findings.append(Finding(
|
|
239
|
-
severity=Severity.CRITICAL,
|
|
240
|
-
category="test",
|
|
241
|
-
message="test",
|
|
242
|
-
file_path="test.py",
|
|
243
|
-
line_number=1,
|
|
244
|
-
line_content="test",
|
|
245
|
-
recommendation="test"
|
|
246
|
-
))
|
|
247
|
-
result.findings.append(Finding(
|
|
248
|
-
severity=Severity.HIGH,
|
|
249
|
-
category="test",
|
|
250
|
-
message="test",
|
|
251
|
-
file_path="test.py",
|
|
252
|
-
line_number=2,
|
|
253
|
-
line_content="test",
|
|
254
|
-
recommendation="test"
|
|
255
|
-
))
|
|
256
|
-
|
|
257
|
-
counts = result.count_by_severity()
|
|
258
|
-
|
|
259
|
-
self.assertEqual(counts['critical'], 1)
|
|
260
|
-
self.assertEqual(counts['high'], 1)
|
|
261
|
-
self.assertEqual(counts['medium'], 0)
|
|
262
|
-
|
|
263
|
-
def test_format_report_basic(self):
|
|
264
|
-
"""测试报告格式化"""
|
|
265
|
-
result = ScanResult(scan_path="/test", files_scanned=5)
|
|
266
|
-
|
|
267
|
-
report = format_report(result)
|
|
268
|
-
|
|
269
|
-
self.assertIn("代码安全扫描报告", report)
|
|
270
|
-
self.assertIn("/test", report)
|
|
271
|
-
self.assertIn("5", report)
|
|
272
|
-
|
|
273
|
-
def test_format_report_with_findings(self):
|
|
274
|
-
"""测试包含发现的报告格式化"""
|
|
275
|
-
result = ScanResult(scan_path="/test", files_scanned=1)
|
|
276
|
-
result.findings.append(Finding(
|
|
277
|
-
severity=Severity.CRITICAL,
|
|
278
|
-
category="注入",
|
|
279
|
-
message="SQL 注入风险",
|
|
280
|
-
file_path="test.py",
|
|
281
|
-
line_number=10,
|
|
282
|
-
line_content="cursor.execute(f'...')",
|
|
283
|
-
recommendation="使用参数化查询"
|
|
284
|
-
))
|
|
285
|
-
|
|
286
|
-
report = format_report(result, verbose=True)
|
|
287
|
-
|
|
288
|
-
self.assertIn("SQL 注入风险", report)
|
|
289
|
-
self.assertIn("test.py:10", report)
|
|
290
|
-
self.assertIn("使用参数化查询", report)
|
|
291
|
-
|
|
292
|
-
def test_finding_dataclass(self):
|
|
293
|
-
"""测试 Finding 数据类"""
|
|
294
|
-
finding = Finding(
|
|
295
|
-
severity=Severity.HIGH,
|
|
296
|
-
category="敏感信息",
|
|
297
|
-
message="硬编码密钥",
|
|
298
|
-
file_path="config.py",
|
|
299
|
-
line_number=5,
|
|
300
|
-
line_content='password = "secret"',
|
|
301
|
-
recommendation="使用环境变量"
|
|
302
|
-
)
|
|
303
|
-
|
|
304
|
-
self.assertEqual(finding.severity, Severity.HIGH)
|
|
305
|
-
self.assertEqual(finding.category, "敏感信息")
|
|
306
|
-
self.assertEqual(finding.line_number, 5)
|
|
307
|
-
|
|
308
|
-
def test_severity_enum(self):
|
|
309
|
-
"""测试 Severity 枚举"""
|
|
310
|
-
self.assertEqual(Severity.CRITICAL.value, "critical")
|
|
311
|
-
self.assertEqual(Severity.HIGH.value, "high")
|
|
312
|
-
self.assertEqual(Severity.MEDIUM.value, "medium")
|
|
313
|
-
self.assertEqual(Severity.LOW.value, "low")
|
|
314
|
-
self.assertEqual(Severity.INFO.value, "info")
|
|
315
|
-
|
|
316
|
-
def test_scan_file_with_multiple_issues(self):
|
|
317
|
-
"""测试单个文件中的多个问题"""
|
|
318
|
-
test_file = self.temp_path / "multi.py"
|
|
319
|
-
test_file.write_text('''
|
|
320
|
-
password = "secret123456"
|
|
321
|
-
cursor.execute(f"SELECT * FROM users WHERE id = {user_id}")
|
|
322
|
-
os.system(cmd, shell=True)
|
|
323
|
-
''')
|
|
324
|
-
|
|
325
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
326
|
-
|
|
327
|
-
self.assertTrue(len(findings) >= 3)
|
|
328
|
-
|
|
329
|
-
def test_scan_directory_with_multiple_extensions(self):
|
|
330
|
-
"""测试多种文件类型扫描"""
|
|
331
|
-
(self.temp_path / "test.py").write_text('password = "secret123456"')
|
|
332
|
-
(self.temp_path / "test.js").write_text('element.innerHTML = userInput;')
|
|
333
|
-
(self.temp_path / "test.go").write_text('password := "secret123456"')
|
|
334
|
-
|
|
335
|
-
result = scan_directory(str(self.temp_path))
|
|
336
|
-
|
|
337
|
-
self.assertEqual(result.files_scanned, 3)
|
|
338
|
-
self.assertTrue(len(result.findings) > 0)
|
|
339
|
-
|
|
340
|
-
def test_scan_file_with_encoding_error(self):
|
|
341
|
-
"""测试处理编码错误的文件"""
|
|
342
|
-
test_file = self.temp_path / "binary.bin"
|
|
343
|
-
# 写入二进制数据
|
|
344
|
-
test_file.write_bytes(b'\x80\x81\x82\x83')
|
|
345
|
-
|
|
346
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
347
|
-
|
|
348
|
-
# 应该优雅地处理编码错误
|
|
349
|
-
self.assertIsInstance(findings, list)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
class TestSecurityScannerEdgeCases(unittest.TestCase):
|
|
353
|
-
"""安全扫描器边界条件测试"""
|
|
354
|
-
|
|
355
|
-
def setUp(self):
|
|
356
|
-
"""测试前准备"""
|
|
357
|
-
self.temp_dir = tempfile.TemporaryDirectory()
|
|
358
|
-
self.temp_path = Path(self.temp_dir.name)
|
|
359
|
-
|
|
360
|
-
def tearDown(self):
|
|
361
|
-
"""测试后清理"""
|
|
362
|
-
self.temp_dir.cleanup()
|
|
363
|
-
|
|
364
|
-
def test_scan_deeply_nested_directories(self):
|
|
365
|
-
"""测试深层嵌套目录"""
|
|
366
|
-
deep_path = self.temp_path / "a" / "b" / "c" / "d" / "e"
|
|
367
|
-
deep_path.mkdir(parents=True)
|
|
368
|
-
(deep_path / "test.py").write_text('password = "secret123456"')
|
|
369
|
-
|
|
370
|
-
result = scan_directory(str(self.temp_path))
|
|
371
|
-
|
|
372
|
-
self.assertEqual(result.files_scanned, 1)
|
|
373
|
-
self.assertTrue(len(result.findings) > 0)
|
|
374
|
-
|
|
375
|
-
def test_scan_file_with_very_long_line(self):
|
|
376
|
-
"""测试包含超长行的文件"""
|
|
377
|
-
test_file = self.temp_path / "long.py"
|
|
378
|
-
long_line = 'x = "' + 'a' * 10000 + '"'
|
|
379
|
-
test_file.write_text(long_line)
|
|
380
|
-
|
|
381
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
382
|
-
|
|
383
|
-
# 应该能处理超长行
|
|
384
|
-
self.assertIsInstance(findings, list)
|
|
385
|
-
|
|
386
|
-
def test_scan_file_with_special_characters(self):
|
|
387
|
-
"""测试包含特殊字符的文件"""
|
|
388
|
-
test_file = self.temp_path / "special.py"
|
|
389
|
-
test_file.write_text('# 中文注释\npassword = "secret123456" # 密码')
|
|
390
|
-
|
|
391
|
-
findings = scan_file(test_file, SECURITY_RULES)
|
|
392
|
-
|
|
393
|
-
self.assertTrue(len(findings) > 0)
|
|
394
|
-
|
|
395
|
-
def test_scan_result_sorting(self):
|
|
396
|
-
"""测试发现按严重程度排序"""
|
|
397
|
-
result = ScanResult(scan_path="/test")
|
|
398
|
-
|
|
399
|
-
# 添加不同严重程度的发现
|
|
400
|
-
result.findings.append(Finding(
|
|
401
|
-
severity=Severity.LOW,
|
|
402
|
-
category="test",
|
|
403
|
-
message="low",
|
|
404
|
-
file_path="test.py",
|
|
405
|
-
line_number=1,
|
|
406
|
-
line_content="test",
|
|
407
|
-
recommendation="test"
|
|
408
|
-
))
|
|
409
|
-
result.findings.append(Finding(
|
|
410
|
-
severity=Severity.CRITICAL,
|
|
411
|
-
category="test",
|
|
412
|
-
message="critical",
|
|
413
|
-
file_path="test.py",
|
|
414
|
-
line_number=2,
|
|
415
|
-
line_content="test",
|
|
416
|
-
recommendation="test"
|
|
417
|
-
))
|
|
418
|
-
|
|
419
|
-
# 扫描会自动排序
|
|
420
|
-
result2 = scan_directory(str(self.temp_path))
|
|
421
|
-
# 验证排序逻辑存在
|
|
422
|
-
self.assertIsInstance(result2, ScanResult)
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
if __name__ == '__main__':
|
|
426
|
-
unittest.main()
|