import importlib.util import json import os import tempfile import unittest from pathlib import Path from unittest.mock import patch MODULE_PATH = Path(__file__).resolve().parents[1] / 'scripts' / 'siteforge_v817_audit.py' spec = importlib.util.spec_from_file_location('siteforge_audit', MODULE_PATH) a = importlib.util.module_from_spec(spec) import sys sys.modules[spec.name] = a spec.loader.exec_module(a) class DummyArgs: pass class AuditTests(unittest.TestCase): def setUp(self): self.r = a.Report(DummyArgs()) self.temp = tempfile.TemporaryDirectory() self.root = Path(self.temp.name) def tearDown(self): self.temp.cleanup() def statuses(self): return {c.code: c.status for c in self.r.checks} def test_loopback_url(self): self.assertTrue(a._local_host('http://127.0.0.1:8787')) self.assertTrue(a._local_host('http://[::1]:8787')) self.assertTrue(a._local_host('https://localhost')) def test_remote_is_not_loopback(self): for host in ('example.com', '192.168.1.1', '169.254.169.254', '10.0.0.3'): self.assertFalse(a._local_host('http://' + host)) def test_credentials_in_url_forbidden(self): self.assertFalse(a._local_host('http://admin:secret@localhost:8787')) def test_http_remote_refused_without_consent(self): with patch.object(a, '_probe', side_effect=AssertionError('should not send a request')): a.audit_http(self.r, 'https://example.com', False) self.assertEqual(self.statuses()['http.scope'], 'fail') def test_http_health_pass(self): with patch.object(a, '_probe', side_effect=[(200, '{"status":"ok"}', ''), (200, '{"status":"ok"}', ''), (200, 'OK', '')]): a.audit_http(self.r, 'http://127.0.0.1:8787', False) self.assertEqual(self.statuses()['http.ready'], 'pass') def test_http_not_ready_fails(self): with patch.object(a, '_probe', side_effect=[(200, '{"status":"ok"}', ''), (503, '', 'bad'), (200, 'OK', '')]): a.audit_http(self.r, 'http://127.0.0.1:8787', False) self.assertEqual(self.statuses()['http.ready'], 'fail') def test_http_unavailable_status_fails(self): with patch.object(a, '_probe', side_effect=[(200, '{"status":"ok"}', ''), (200, '{"status":"unavailable"}', ''), (200, 'OK', '')]): a.audit_http(self.r, 'http://127.0.0.1:8787', False) self.assertEqual(self.statuses()['http.ready'], 'fail') def test_route_with_path_traversal_rejected(self): self.assertIsNone(a.normalized_route('/../private')) self.assertIsNone(a.normalized_route('/%2e%2e/secret')) self.assertIsNone(a.normalized_route('/bad\\path')) self.assertIsNone(a.normalized_route('/a//b')) def test_route_query_disallowed(self): self.assertIsNone(a.normalized_route('/foo/?hello=1')) self.assertIsNone(a.normalized_route('https://example.com/')) self.assertEqual(a.normalized_route('/product/'), '/product/') def test_static_html_pass(self): (self.root / 'index.html').write_text('Home') (self.root / 'sitemap.xml').write_text('ok') (self.root / 'robots.txt').write_text('ok') a.audit_build(self.r, self.root, None) self.assertEqual(self.statuses()['build.internal_links'], 'pass') self.assertEqual(self.statuses()['build.canonical_scheme'], 'pass') def test_broken_internal_link_fails(self): (self.root / 'index.html').write_text('Missing') a.audit_build(self.r, self.root, None) self.assertEqual(self.statuses()['build.internal_links'], 'fail') def test_duplicate_canonicals_fail(self): (self.root / 'index.html').write_text('') a.audit_build(self.r, self.root, None) self.assertEqual(self.statuses()['build.canonical_duplicate'], 'fail') def test_url_baseline_coverage(self): (self.root / 'index.html').write_text('') b = self.root / 'urls.txt' b.write_text('/\n/product/\n') a.audit_build(self.r, self.root, b) self.assertEqual(self.statuses()['build.url_baseline'], 'fail') (self.root / 'product').mkdir() (self.root / 'product' / 'index.html').write_text('') r2 = a.Report(DummyArgs()) a.audit_build(r2, self.root, b) self.assertEqual({x.code:x.status for x in r2.checks}['build.url_baseline'], 'pass') def test_invalid_baseline_route_fails(self): (self.root / 'index.html').write_text('') b = self.root / 'urls.txt' b.write_text('/\n/../secret\n') a.audit_build(self.r, self.root, b) self.assertEqual(self.statuses()['build.url_baseline'], 'fail') def test_html_reports_escape_untrusted_text(self): self.r.add('test', 'http', 'warn', '', '') x = a.html_report(self.r.data()) self.assertNotIn('', x) self.assertNotIn('', x) self.assertIn('<script>', x) def test_report_ready_requires_all_pass(self): self.r.add('test', 'http', 'pass', 'ok') self.assertTrue(self.r.data()['selected_checks_clear']) self.assertFalse(self.r.data()['production_ready']) self.r.add('skip', 'release', 'skip', 'not done') self.assertFalse(self.r.data()['selected_checks_clear']) def test_release_evidence_requires_proof_fields(self): f = self.root/'evidence.json' f.write_text('{"isolated_pg":{"status":"passed","operator":"team"}}') a.release_gate(self.r, f) self.assertEqual(self.statuses()['release.isolated_pg'], 'warn') self.assertEqual(len(self.r.checks), 10) def test_release_no_evidence_not_passed(self): a.release_gate(self.r, None) self.assertEqual(self.statuses()['release.evidence'], 'skip') def test_repo_minimal_fails_softly(self): (self.root/'app').mkdir() (self.root/'app'/'test.py').write_text('x = 1') a.audit_repo(self.r, self.root) self.assertEqual(self.statuses()['repo.python_syntax'], 'pass') self.assertEqual(self.statuses()['repo.app.builder.py'], 'warn') def test_repo_python_syntax_fail(self): (self.root/'app').mkdir() (self.root/'app'/'bad.py').write_text('def oops(\n') a.audit_repo(self.r, self.root) self.assertEqual(self.statuses()['repo.python_syntax'], 'fail') def test_reports_generated_cli(self): out = self.root/'audit' f = self.root/'build' f.mkdir() (f/'index.html').write_text('') code = a.main(['--build-dir', str(f), '--output', str(out)]) self.assertEqual(code, 0) for ext in ('.json', '.md', '.html'): self.assertTrue(out.with_suffix(ext).exists()) self.assertEqual(json.loads(out.with_suffix('.json').read_text())['live_production_verified'], False) def test_no_redis_settings_skipped(self): with patch.dict(os.environ, {'SITEFORGE_REDIS_URL':''}): a.audit_redis(self.r) self.assertEqual(self.statuses()['redis.config'], 'skip') def test_no_pg_settings_skipped(self): with patch.dict(os.environ, {'SITEFORGE_DATABASE_URL':''}): a.audit_postgres(self.r) self.assertEqual(self.statuses()['postgres.config'], 'skip') if __name__ == '__main__': unittest.main()