Skip to content

Commit

Permalink
tests: drop CiTestCase and convert to pytest
Browse files Browse the repository at this point in the history
Prevent disable_sysfs_net fixture from impacting TestSysDevPath
and TestReadSysNet in order to avoid shared mocks of /sys/class/net.
This avoid test artifact pollution for TestReadSysNet.

Adapt the following tests, dropping CiTestCase to use pytest:
 TestDHCPDiscoveryClean, TestSysDevPath, TestReadSysNet,
 TestGenerateFallbackConfig, TestNetFailOver, TestConvertNetJson

Fixes GH-4973
  • Loading branch information
blackboxsw committed Mar 6, 2024
1 parent 463d36c commit 9baf31c
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 247 deletions.
127 changes: 46 additions & 81 deletions tests/unittests/net/test_dhcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,15 +374,13 @@ def test_redhat_format_with_a_space_too_much_after_comma(self):
)


class TestDHCPDiscoveryClean(CiTestCase):
with_logs = True

class TestDHCPDiscoveryClean:
@mock.patch("cloudinit.distros.net.find_fallback_nic", return_value="eth9")
@mock.patch("cloudinit.net.dhcp.os.remove")
@mock.patch("cloudinit.net.dhcp.subp.subp")
@mock.patch("cloudinit.net.dhcp.subp.which")
def test_dhcpcd_exits_with_error(
self, m_which, m_subp, m_remove, m_fallback
self, m_which, m_subp, m_remove, m_fallback, caplog
):
"""Log and do nothing when nic is absent and no fallback is found."""
m_subp.side_effect = [
Expand All @@ -393,16 +391,15 @@ def test_dhcpcd_exits_with_error(
with pytest.raises(NoDHCPLeaseError):
maybe_perform_dhcp_discovery(Distro("fake but not", {}, None))

self.assertIn(
"DHCP client selected: dhcpcd",
self.logs.getvalue(),
)
assert "DHCP client selected: dhcpcd" in caplog.text

@mock.patch("cloudinit.distros.net.find_fallback_nic", return_value="eth9")
@mock.patch("cloudinit.net.dhcp.os.remove")
@mock.patch("cloudinit.net.dhcp.subp.subp")
@mock.patch("cloudinit.net.dhcp.subp.which")
def test_dhcp_client_failover(self, m_which, m_subp, m_remove, m_fallback):
def test_dhcp_client_failover(
self, m_which, m_subp, m_remove, m_fallback, caplog
):
"""Log and do nothing when nic is absent and no fallback client is
found."""
m_subp.side_effect = [
Expand All @@ -414,40 +411,22 @@ def test_dhcp_client_failover(self, m_which, m_subp, m_remove, m_fallback):
with pytest.raises(NoDHCPLeaseError):
maybe_perform_dhcp_discovery(Distro("somename", {}, None))

self.assertIn(
"DHCP client not found: dhclient",
self.logs.getvalue(),
)
self.assertIn(
"DHCP client not found: dhcpcd",
self.logs.getvalue(),
)
self.assertIn(
"DHCP client not found: udhcpc",
self.logs.getvalue(),
)
assert "DHCP client not found: dhclient" in caplog.text
assert "DHCP client not found: dhcpcd" in caplog.text
assert "DHCP client not found: udhcpc" in caplog.text

@mock.patch("cloudinit.net.dhcp.subp.which")
@mock.patch("cloudinit.distros.net.find_fallback_nic")
def test_absent_dhclient_command(self, m_fallback, m_which):
def test_absent_dhclient_command(self, m_fallback, m_which, caplog):
"""When dhclient doesn't exist in the OS, log the issue and no-op."""
m_fallback.return_value = "eth9"
m_which.return_value = None # dhclient isn't found
with pytest.raises(NoDHCPLeaseMissingDhclientError):
maybe_perform_dhcp_discovery(Distro("whoa", {}, None))

self.assertIn(
"DHCP client not found: dhclient",
self.logs.getvalue(),
)
self.assertIn(
"DHCP client not found: dhcpcd",
self.logs.getvalue(),
)
self.assertIn(
"DHCP client not found: udhcpc",
self.logs.getvalue(),
)
assert "DHCP client not found: dhclient" in caplog.text
assert "DHCP client not found: dhcpcd" in caplog.text
assert "DHCP client not found: udhcpc" in caplog.text

@mock.patch("cloudinit.net.dhcp.os.remove")
@mock.patch("time.sleep", mock.MagicMock())
Expand All @@ -456,7 +435,7 @@ def test_absent_dhclient_command(self, m_fallback, m_which):
@mock.patch("cloudinit.net.dhcp.subp.which", return_value="/sbin/dhclient")
@mock.patch("cloudinit.net.dhcp.util.wait_for_files", return_value=False)
def test_dhcp_discovery_warns_invalid_pid(
self, m_wait, m_which, m_subp, m_kill, m_remove
self, m_wait, m_which, m_subp, m_kill, m_remove, caplog
):
"""dhcp_discovery logs a warning when pidfile contains invalid content.
Expand All @@ -478,22 +457,18 @@ def test_dhcp_discovery_warns_invalid_pid(
with mock.patch(
"cloudinit.util.load_text_file", return_value=lease_content
):
self.assertCountEqual(
{
"interface": "eth9",
"fixed-address": "192.168.2.74",
"subnet-mask": "255.255.255.0",
"routers": "192.168.2.1",
},
IscDhclient().get_newest_lease("eth0"),
)
with self.assertRaises(InvalidDHCPLeaseFileError):
assert {
"interface": "eth9",
"fixed-address": "192.168.2.74",
"subnet-mask": "255.255.255.0",
"routers": "192.168.2.1",
} == IscDhclient().get_newest_lease("eth0")
with pytest.raises(InvalidDHCPLeaseFileError):
with mock.patch("cloudinit.util.load_text_file", return_value=""):
IscDhclient().dhcp_discovery("eth9", distro=MockDistro())
self.assertIn(
"dhclient(pid=, parentpid=unknown) failed "
"to daemonize after 10.0 seconds",
self.logs.getvalue(),
assert (
"dhclient(pid=, parentpid=unknown) failed to daemonize after"
" 10.0 seconds" in caplog.text
)
m_kill.assert_not_called()

Expand All @@ -503,23 +478,20 @@ def test_dhcp_discovery_warns_invalid_pid(
@mock.patch("cloudinit.net.dhcp.subp.which", return_value="/sbin/dhclient")
@mock.patch("cloudinit.net.dhcp.subp.subp")
def test_dhcp_discovery_waits_on_lease_and_pid(
self, m_subp, m_which, m_wait, m_kill, m_remove
self, m_subp, m_which, m_wait, m_kill, m_remove, caplog
):
"""dhcp_discovery waits for the presence of pidfile and dhcp.leases."""
m_subp.return_value = ("", "")

# Don't create pid or leases file
m_wait.return_value = [PID_F] # Return the missing pidfile wait for
self.assertEqual(
{}, IscDhclient().dhcp_discovery("eth9", distro=MockDistro())
)
self.assertEqual(
mock.call([PID_F, LEASE_F], maxwait=5, naplen=0.01),
m_wait.call_args_list[0],
assert {} == IscDhclient().dhcp_discovery("eth9", distro=MockDistro())
m_wait.assert_called_once_with(
[PID_F, LEASE_F], maxwait=5, naplen=0.01
)
self.assertIn(
"WARNING: dhclient did not produce expected files: dhclient.pid",
self.logs.getvalue(),
assert (
"dhclient did not produce expected files: dhclient.pid"
in caplog.text
)
m_kill.assert_not_called()

Expand Down Expand Up @@ -557,15 +529,12 @@ def test_dhcp_discovery(
with mock.patch(
"cloudinit.util.load_text_file", side_effect=["1", lease_content]
):
self.assertCountEqual(
{
"interface": "eth9",
"fixed-address": "192.168.2.74",
"subnet-mask": "255.255.255.0",
"routers": "192.168.2.1",
},
IscDhclient().dhcp_discovery("eth9", distro=MockDistro()),
)
assert {
"interface": "eth9",
"fixed-address": "192.168.2.74",
"subnet-mask": "255.255.255.0",
"routers": "192.168.2.1",
} == IscDhclient().dhcp_discovery("eth9", distro=MockDistro())
# Interface was brought up before dhclient called
m_subp.assert_has_calls(
[
Expand Down Expand Up @@ -633,15 +602,12 @@ def test_dhcp_discovery_ib(
with mock.patch(
"cloudinit.util.load_text_file", side_effect=["1", lease_content]
):
self.assertCountEqual(
{
"interface": "ib0",
"fixed-address": "192.168.2.74",
"subnet-mask": "255.255.255.0",
"routers": "192.168.2.1",
},
IscDhclient().dhcp_discovery("ib0", distro=MockDistro()),
)
assert {
"interface": "ib0",
"fixed-address": "192.168.2.74",
"subnet-mask": "255.255.255.0",
"routers": "192.168.2.1",
} == IscDhclient().dhcp_discovery("ib0", distro=MockDistro())
# Interface was brought up before dhclient called
m_subp.assert_has_calls(
[
Expand Down Expand Up @@ -682,14 +648,13 @@ def test_dhcp_discovery_ib(
@mock.patch("cloudinit.net.dhcp.subp.which", return_value="/sbin/dhclient")
@mock.patch("cloudinit.util.wait_for_files")
def test_dhcp_output_error_stream(
self, m_wait, m_which, m_subp, m_kill, m_remove
self, m_wait, m_which, m_subp, m_kill, m_remove, tmpdir
):
""" "dhcp_log_func is called with the output and error streams of
dhclient when the callable is passed."""
dhclient_err = "FAKE DHCLIENT ERROR"
dhclient_out = "FAKE DHCLIENT OUT"
m_subp.return_value = (dhclient_out, dhclient_err)
tmpdir = self.tmp_dir()
lease_content = dedent(
"""
lease {
Expand All @@ -707,8 +672,8 @@ def test_dhcp_output_error_stream(
write_file(pid_file, "%d\n" % my_pid)

def dhcp_log_func(out, err):
self.assertEqual(out, dhclient_out)
self.assertEqual(err, dhclient_err)
assert out == dhclient_out
assert err == dhclient_err

IscDhclient().dhcp_discovery(
"eth9", dhcp_log_func=dhcp_log_func, distro=MockDistro()
Expand Down
Loading

0 comments on commit 9baf31c

Please sign in to comment.