|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +"""#2305: :file:`examples/legacy_smoke/test_perf.py` benchmarks every engine it does not skip. |
| 3 | +
|
| 4 | +The demo walks :data:`_engine_support.ENGINES` and hands each engine that passes |
| 5 | +``preflight`` to ``pyperf``. Looking the benchmark up in a hand-written table that |
| 6 | +covers only some of those engines raises a :exc:`KeyError` for the first other |
| 7 | +engine to pass ``preflight``, ending the run, so one ``bench`` takes the engine |
| 8 | +name instead. Run here with ``pyperf`` and the engine checks stubbed, and with |
| 9 | +:func:`pcapkit.extract` recorded rather than run: |
| 10 | +
|
| 11 | +* :class:`TestEveryEngineIsBenchmarked`: with every engine available, each one in |
| 12 | + ``ENGINES`` is benchmarked, under its own name, extracting into |
| 13 | + :file:`../captures/engines/<engine>.txt`; |
| 14 | +* :class:`TestASkippedEngineIsReported`: an engine ``preflight`` refuses is reported |
| 15 | + with the reason and not benchmarked. |
| 16 | +
|
| 17 | +""" |
| 18 | + |
| 19 | +from __future__ import annotations |
| 20 | + |
| 21 | +import importlib.util |
| 22 | +import pathlib |
| 23 | +import runpy |
| 24 | +import sys |
| 25 | +import types |
| 26 | +import unittest |
| 27 | +from typing import TYPE_CHECKING |
| 28 | +from unittest import mock |
| 29 | + |
| 30 | +if TYPE_CHECKING: |
| 31 | + from typing import Any, Callable, Optional |
| 32 | + |
| 33 | +#: Test tier (#1958): runs an example script with its harness stubbed. |
| 34 | +__tier__ = 'LATEST' |
| 35 | + |
| 36 | +ROOT = pathlib.Path(__file__).resolve().parents[2] |
| 37 | +DEMOS = ROOT / 'examples' / 'legacy_smoke' |
| 38 | +SCRIPT = DEMOS / 'test_perf.py' |
| 39 | + |
| 40 | + |
| 41 | +def real_engines() -> 'tuple[str, ...]': |
| 42 | + """``ENGINES`` as :file:`examples/legacy_smoke/_engine_support.py` declares it.""" |
| 43 | + spec = importlib.util.spec_from_file_location('_pcapkit_2305_engine_support', DEMOS / '_engine_support.py') |
| 44 | + assert spec is not None and spec.loader is not None |
| 45 | + module = importlib.util.module_from_spec(spec) |
| 46 | + spec.loader.exec_module(module) |
| 47 | + return tuple(module.ENGINES) |
| 48 | + |
| 49 | + |
| 50 | +ENGINES = real_engines() |
| 51 | + |
| 52 | + |
| 53 | +class _Demo(unittest.TestCase): |
| 54 | + |
| 55 | + def setUp(self) -> None: |
| 56 | + self.benched = [] # type: list[tuple[str, Callable[..., Any], tuple[Any, ...]]] |
| 57 | + self.reports = [] # type: list[tuple[str, str]] |
| 58 | + |
| 59 | + def run_demo(self, preflight: 'Callable[[str, str], Optional[str]]') -> 'mock.Mock': |
| 60 | + """Run the demo; return the stand-in :func:`pcapkit.extract`.""" |
| 61 | + |
| 62 | + class Runner: |
| 63 | + def bench_func(runner, name: 'str', func: 'Callable[..., Any]', *args: 'Any') -> 'None': # pylint: disable=no-self-argument |
| 64 | + self.benched.append((name, func, args)) |
| 65 | + |
| 66 | + pyperf = types.ModuleType('pyperf') |
| 67 | + pyperf.Runner = Runner # type: ignore[attr-defined] |
| 68 | + support = types.ModuleType('_engine_support') |
| 69 | + support.ENGINES = ENGINES # type: ignore[attr-defined] |
| 70 | + support.preflight = preflight # type: ignore[attr-defined] |
| 71 | + support.report = lambda engine, detail: self.reports.append((engine, detail)) # type: ignore[attr-defined] |
| 72 | + extract = mock.Mock(name='extract') |
| 73 | + with mock.patch.dict(sys.modules, {'pyperf': pyperf, '_engine_support': support}), \ |
| 74 | + mock.patch('pcapkit.extract', extract): |
| 75 | + runpy.run_path(str(SCRIPT), run_name='__main__') |
| 76 | + return extract |
| 77 | + |
| 78 | + |
| 79 | +class TestEveryEngineIsBenchmarked(_Demo): |
| 80 | + |
| 81 | + def test_each_engine_is_benchmarked_into_its_own_report(self) -> None: |
| 82 | + extract = self.run_demo(lambda engine, fin: None) |
| 83 | + self.assertEqual([name for name, _, _ in self.benched], list(ENGINES)) |
| 84 | + self.assertEqual(self.reports, []) |
| 85 | + for name, func, args in self.benched: |
| 86 | + with self.subTest(engine=name): |
| 87 | + extract.reset_mock() |
| 88 | + func(*args) |
| 89 | + extract.assert_called_once_with(fin='../captures/in.pcap', fout=f'../captures/engines/{name}.txt', |
| 90 | + format='tree', engine=name) |
| 91 | + |
| 92 | + |
| 93 | +class TestASkippedEngineIsReported(_Demo): |
| 94 | + |
| 95 | + def test_a_refused_engine_is_reported_and_not_benchmarked(self) -> None: |
| 96 | + refused = ENGINES[-1] |
| 97 | + self.run_demo(lambda engine, fin: 'not here' if engine == refused else None) |
| 98 | + self.assertEqual([name for name, _, _ in self.benched], list(ENGINES[:-1])) |
| 99 | + self.assertEqual(self.reports, [(refused, 'skipped -- not here')]) |
| 100 | + |
| 101 | + |
| 102 | +if __name__ == '__main__': |
| 103 | + unittest.main() |
0 commit comments