Files

89 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Тест задачи 08: сравнение вывода solution.sh с эталоном на фикстуре и большом логе."""
import os
import random
import subprocess
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
SCRIPT = os.path.join(HERE, "solution.sh")
failures = 0
def check(cond, name, extra=""):
global failures
if cond:
print(f"ok {name}")
else:
print(f"FAIL {name} {extra}")
failures += 1
def run(path):
r = subprocess.run(["bash", SCRIPT, path], capture_output=True, text=True, timeout=120)
return r.returncode, r.stdout, r.stderr
def expected(lines):
from collections import Counter
ips = [l.split()[0] for l in lines if l.strip()]
total = len(lines)
cnt = Counter(ips)
top = sorted(cnt.items(), key=lambda kv: (-kv[1], kv[0]))[:3]
five = 0
for l in lines:
parts = l.split('"')
if len(parts) >= 3:
codes = parts[2].split()
if codes and codes[0].isdigit() and 500 <= int(codes[0]) <= 599:
five += 1
out = [f"TOTAL {total}"]
for ip, c in top:
out.append(f"TOP {ip} {c}")
out.append(f"5XX {five}")
return "\n".join(out)
def compare(path, lines, label):
rc, out, err = run(path)
exp = expected(lines)
got = out.strip("\n")
if got != exp:
print(f"--- ожидалось ({label}) ---\n{exp}\n--- получено ---\n{got}")
check(rc == 0, f"{label}: код возврата 0 (получен {rc})", err[:300])
check(got == exp, f"{label}: вывод совпадает с эталоном")
def main():
fixture = os.path.join(HERE, "access.log")
with open(fixture, encoding="utf-8") as f:
lines = f.read().splitlines()
compare(fixture, lines, "фикстура")
# пустой файл
empty = os.path.join(HERE, "empty.log")
open(empty, "w").close()
compare(empty, [], "пустой файл")
# большой лог: 200k строк, часть 5xx, один лидер, ничья между двумя IP
rng = random.Random(7)
big = os.path.join(HERE, "big.log")
ips = ["10.0.0.1"] * 50000 + ["10.0.0.2"] * 30000 + ["10.0.0.3"] * 30000
ips += [f"192.168.1.{i}" for i in range(1, 61)] * 10
ips += [f"172.16.0.{i}" for i in range(1, 21)] * 5
rng.shuffle(ips)
big_lines = []
for ip in ips:
code = rng.choice([200, 200, 200, 301, 404, 500, 502, 503])
big_lines.append(f'{ip} - - [23/Sep/2026:11:00:00 +0700] "GET /p HTTP/1.1" {code} 100')
with open(big, "w", encoding="utf-8") as f:
f.write("\n".join(big_lines) + "\n")
compare(big, big_lines, "большой лог 110k строк")
print(f"\n{'FAILURES: %d' % failures if failures else 'ALL PASS'}")
sys.exit(1 if failures else 0)
if __name__ == "__main__":
main()