Skip to content

Commit

Permalink
improve dnsmasq fixture & handling of timeouts in dhcp client tests
Browse files Browse the repository at this point in the history
  • Loading branch information
etene committed Jan 16, 2025
1 parent b6b752a commit e0566b0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 16 deletions.
8 changes: 4 additions & 4 deletions tests/test_linux/fixtures/dnsmasq.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ class DnsmasqFixture:

def __init__(self, options: DnsmasqOptions) -> None:
self.options = options
self.stdout: list[bytes] = []
self.stderr: list[bytes] = []
self.stdout: list[str] = []
self.stderr: list[str] = []
self.process: Optional[asyncio.subprocess.Process] = None
self.output_poller: Optional[asyncio.Task] = None

Expand All @@ -45,7 +45,7 @@ async def _read_output(self, name: Literal['stdout', 'stderr']):
stream = getattr(self.process, name)
output = getattr(self, name)
while line := await stream.readline():
output.append(line)
output.append(line.decode().strip())

async def _read_outputs(self):
'''Read stdout & stderr until the process exits.'''
Expand Down Expand Up @@ -147,7 +147,7 @@ async def main():
while True:
if len(dnsm.stderr) > read_lines:
read_lines += len(lines := dnsm.stderr[read_lines:])
print(*(i.decode().strip() for i in lines), sep='\n')
print(*lines, sep='\n')
else:
await asyncio.sleep(0.2)

Expand Down
33 changes: 21 additions & 12 deletions tests/test_linux/test_raw/test_dhcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,35 @@ async def test_get_lease(
tmpdir: str,
monkeypatch: pytest.MonkeyPatch,
):
"""The client can get a lease and write it to a file."""
'''The client can get a lease and write it to a file.'''
work_dir = Path(tmpdir)
# Patch JSONFileLease so leases get written to the temp dir
# instead of whatever the working directory is
monkeypatch.setattr(JSONFileLease, "_get_lease_dir", lambda: work_dir)
monkeypatch.setattr(JSONFileLease, '_get_lease_dir', lambda: work_dir)

# boot up the dhcp client and wait for a lease
async with client.AsyncDHCPClient(veth_pair.client) as cli:
await cli.bootstrap()
await asyncio.wait_for(cli.bound.wait(), timeout=5)
try:
await asyncio.wait_for(cli.bound.wait(), timeout=5)
except TimeoutError:
raise AssertionError(
f'Timed out. dnsmasq output: {dnsmasq.stderr}'
)
assert cli.state == fsm.State.BOUND
lease = cli.lease
assert lease.ack["xid"] == cli.xid
assert lease.ack['xid'] == cli.xid

# check the obtained lease
assert lease.interface == veth_pair.client
assert lease.ack["op"] == bootp.MessageType.BOOTREPLY
assert lease.ack["options"]["message_type"] == dhcp.MessageType.ACK
assert lease.ack['op'] == bootp.MessageType.BOOTREPLY
assert lease.ack['options']['message_type'] == dhcp.MessageType.ACK
assert (
dnsmasq.options.range_start
<= IPv4Address(lease.ip)
<= dnsmasq.options.range_end
)
assert lease.ack["chaddr"]
assert lease.ack['chaddr']
# TODO: check chaddr matches veth_pair.client's MAC

# check the lease was written to disk and can be loaded
Expand All @@ -58,22 +63,26 @@ async def test_get_lease(

@pytest.mark.asyncio
async def test_client_console(dnsmasq: DnsmasqFixture, veth_pair: VethPair):
"""The commandline client can get a lease, print it to stdout and exit."""
'''The commandline client can get a lease, print it to stdout and exit.'''
process = await asyncio.create_subprocess_exec(
'pyroute2-dhcp-client',
veth_pair.client,
'--lease-type',
'pyroute2.dhcp.leases.JSONStdoutLease',
'--exit-on-lease',
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE,
# stderr=asyncio.subprocess.PIPE,
)
stdout, _ = await asyncio.wait_for(process.communicate(), timeout=5)
try:
stdout, _ = await asyncio.wait_for(process.communicate(), timeout=5)
except TimeoutError:
raise AssertionError(f'Timed out. dnsmasq output: {dnsmasq.stderr}')
assert process.returncode == 0
assert stdout
json_lease = json.loads(stdout)
assert json_lease["interface"] == veth_pair.client
assert json_lease['interface'] == veth_pair.client
assert (
dnsmasq.options.range_start
<= IPv4Address(json_lease["ack"]["yiaddr"])
<= IPv4Address(json_lease['ack']['yiaddr'])
<= dnsmasq.options.range_end
)

0 comments on commit e0566b0

Please sign in to comment.