import subprocess from time import sleep from ward import test, fixture, raises from ports.commands.base import PortInfo from ports.commands.open import OpenCommand @fixture def closed_portinfs_8000_to_8020(): """ can't yield this because `_fill_portinfos` consumes it for every port """ return [PortInfo(is_open=False, port=i) for i in range(8000, 8021)] @fixture def http_server_pid(): p = subprocess.Popen(["python3", "-m", "http.server", "14520"]) sleep(1) # the server may take a bit to be up-n-running yield p.pid p.kill() @fixture def open_command_8000_to_8021(): yield OpenCommand(start_port=7990, end_port=8025) @test("initializing with start port 80 and end port 79 should raise `ValueError`") def _(): with raises(ValueError): OpenCommand(start_port=80, end_port=79) @test( "`closed_portinfos` returns a list with the port 14520 closed by the " "`http.server` process" ) def _(hpd: int = http_server_pid): closed_portinfos = OpenCommand().closed_portinfos portinfo_14520 = [ portinfo for portinfo in closed_portinfos if portinfo.port == 14520 ][0] assert portinfo_14520 assert portinfo_14520.pid == hpd assert portinfo_14520.interface == "localhost" assert portinfo_14520.process_name == "python3" @test("`_fill_portinfos` of [7990..8025] should return [7990..7999],[8022...8025]") def _( cp: list[PortInfo] = closed_portinfs_8000_to_8020, op: OpenCommand = open_command_8000_to_8021, ): filled_portinfos = op._fill_portinfos(cp) assert len(filled_portinfos) == 8025 - 8000 - 20 + 8000 - 7990 for portinfo in filled_portinfos: assert portinfo.port in range(7990, 8000) or portinfo.port in range(8021, 8026)