diff --git a/unittests/conftest.py b/unittests/conftest.py new file mode 100644 index 00000000..b738ee3a --- /dev/null +++ b/unittests/conftest.py @@ -0,0 +1,272 @@ +#!/usr/bin/python3 + +""" +# The Clear BSD License +# +# Copyright (c) 2023 Samsung Electronics Co., Ltd. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted (subject to the limitations in the disclaimer +# below) provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Samsung Electronics Co., Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY +# THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +# NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from faker import Faker +import pytest +import secrets +import json +import os + + +default_mock_ip = '1.x.x.x' +json_path = os.path.dirname(os.path.abspath(__file__)) + "/pytest_config.json" +d = {} +with open(json_path, "r") as json_file: + d = json.load(json_file) +fake = Faker() + + +@pytest.fixture(scope="session") +def get_sample_nvme_devices(): + return d["nvme_devices"] + + +@pytest.fixture(scope="session") +def get_sample_nvme_subsystems(): + return d["nvme_subsystems"] + + +def get_sample_lscpu_output(): + return d["lscpu"] + + +@pytest.fixture(scope="session") +def get_sample_nvme_discover_output(): + return d["nvme_discover"] + + +@pytest.fixture(scope="session") +def get_sample_dict_data(): + sample_dict = {"key " + str(i): secrets.randbelow(100) for i in range(10)} + return sample_dict + + +@pytest.fixture(scope="session") +def get_temp_dir(tmpdir): + return tmpdir + + +@pytest.fixture +def get_sample_ipv4_addr(): + return fake.ipv4() + + +@pytest.fixture +def get_sample_ipv6_addr(): + return fake.ipv6() + + +@pytest.fixture +def get_sample_ipv4_addr_list(): + return [fake.ipv4() for _ in range(4)] + + +@pytest.fixture +def get_sample_ipv6_addr_list(): + return [fake.ipv6() for _ in range(4)] + + +@pytest.fixture +def get_global_var(): + global rdd + rdd = "yes" + return rdd + + +def get_sample_lshw_output(): + return """\ + { + "id" : "network:0", + "class" : "network", + "claimed" : true, + "handle" : "PCI:0000:04:00.0", + "description" : "Ethernet interface", + "product" : "MT27800 Family [ConnectX-5]", + "vendor" : "Mellanox Technologies", + "physid" : "0", + "businfo" : "pci@0000:04:00.0", + "logicalname" : "p6p1", + "version" : "00", + "serial" : "b8:59:9f:2d:18:7e", + "width" : 64, + "clock" : 33000000, + "configuration" : { + "autonegotiation" : "on", + "broadcast" : "yes", + "driver" : "mlx5_core", + "driverversion" : "5.0-0", + "firmware" : "16.33.1048 (MT_0000000012)", + "latency" : "0", + "link" : "no", + "multicast" : "yes", + "port" : "fibre", + "ip": "192.168.1.x" + }, + "capabilities" : { + "pciexpress" : "PCI Express", + "vpd" : "Vital Product Data", + "msix" : "MSI-X", + "pm" : "Power Management", + "bus_master" : "bus mastering", + "cap_list" : "PCI capabilities listing", + "rom" : "extension ROM", + "ethernet" : true, + "physical" : "Physical interface", + "fibre" : "optical fibre", + "autonegotiation" : "Auto-negotiation" + } + } + """ + + +def get_sample_nvme_list_subsys(): + return """\ + { + "Subsystems" : [ + { + "Name" : "nvme-subsys0", + "NQN" : "nqn.2023-12.io:109-tcp-0-kv_data1" + }, + { + "Paths" : [ + { + "Name" : "nvme0", + "Transport" : "rdma", + "Address" : "traddr=192.168.1.x trsvcid=1024", + "State" : "live" + } + ] + } + ] +} + """ + + +def get_ls_pci_bus(cmd): + begin = "/sys/class/pci_bus/0000:17/" +\ + "device/0000:17:00.0/nvme/nvme1/" + if cmd.endswith("firmware_rev"): + return begin + "firmware_rev" + else: + return begin + "serial" + + +def get_cat_sys_class_net(cmd): + if cmd.endswith("mtu"): + return "9000" + else: + return "0" + + +def mock_exec_cmd(cmd): + ls_pci_bus = "ls /sys/class/pci_bus/" + cat_sys_class_net = "cat /sys/class/net/" + nvme_list_subsys = "nvme list-subsys -o json" + lspci_mm_n_D = "lspci -mm -n -D | grep 0108 " + lshw = "lshw -c network -json" + ip_d = "ip -d link show dev" + res = "" + + if cmd == "uname -r": + res = "5.1.0" + elif cmd.startswith(nvme_list_subsys): + res = get_sample_nvme_list_subsys() + elif cmd.startswith("ip -4 addr | grep"): + res = "192.168.1.x/24" + elif cmd.startswith(ls_pci_bus): + res = get_ls_pci_bus(cmd) + elif cmd.startswith(lspci_mm_n_D): + res = "0000:17:00.0" + elif cmd.startswith(cat_sys_class_net): + res = get_cat_sys_class_net(cmd) + elif cmd == "lscpu": + res = get_sample_lscpu_output() + elif cmd == "nproc": + res = "128" + elif cmd == lshw: + res = get_sample_lshw_output() + elif cmd.startswith(ip_d): + res = "vlanid 1234" + + return 0, res, "" + + +def mock_os_dirname_host(name): + return "/usr/dss/nkv-sdk/bin" + + +def mock_exec_cmd_remote(cmd, host, user, pw): + if cmd.startswith("lshw -c network -json"): + return 0, get_sample_lshw_output(), "" + elif cmd.startswith("ip -d link show dev"): + return 0, ["vlanid 1234"], "" + else: + return 0, "", "" + + +def mock_interfaces(): + return ['nic'] + + +def mock_ifaddresses(interface): + return [[{'addr': default_mock_ip}]] + + +class MockArgs(): + + def __init__(self, *args, **kwargs): + self.addrs = [default_mock_ip] + self.ports = [1234] + self.command = "config_host" + self.gen2 = False + self.vlan_ip_map = None + self.rdd_port = None + self.proto = "rdma" + self.memalign = 512 + self.qpair = 32 + self.kvpair = [] + + +class MockArgParser(): + + def __init__(self, *args, **kwargs): + # mock function, do nothing + pass + + def parse_args(self, *args, **kwargs): + return MockArgs() + + def add_argument(self, *args, **kwargs): + # mock function, do nothing + pass diff --git a/unittests/pytest_config.json b/unittests/pytest_config.json new file mode 100644 index 00000000..afa5818e --- /dev/null +++ b/unittests/pytest_config.json @@ -0,0 +1,6 @@ +{ + "lscpu":" Architecture: x86_64\n CPU op-mode(s): 32-bit, 64-bit\n Byte Order: Little Endian\n CPU(s): 88\n On-line CPU(s) list: 0-87\n Thread(s) per core: 2\n Core(s) per socket: 22\n Socket(s): 2\n NUMA node(s): 2\n Vendor ID: GenuineIntel\n CPU family: 6\n Model: 85\n Model name: Intel(R) Xeon(R) Gold 6152 CPU @ 2.10GHz\n Stepping: 4\n CPU MHz: 2543.753\n CPU max MHz: 3700.0000\n CPU min MHz: 1000.0000\n BogoMIPS: 4200.00\n Virtualization: VT-x\n L1d cache: 32K\n L1i cache: 32K\n L2 cache: 1024K\n L3 cache: 30976K\n NUMA node0 CPU(s): 0-21,44-65\n NUMA node1 CPU(s): 22-43,66-87\n Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 x2apic movbe popcnt tsc_deadline_timer aes xsave avx rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l3 cdp_l3 pti intel_ppin ssbd mba ibrs ibpb stibp vnmi ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms rtm cqm mpx rdt_a ", + "nvme_devices":" Node SN Model Namespace Usage Format FW Rev\n ---------------- -------------------- ------------------------------------ ---- --------- -------------------------- ---------------- --------\n /dev/nvme0n1 DSS5066419069 SPDK bdev Controller 1 13.63 MB / 7.65 TB 512 B + 0 B 20.07\n /dev/nvme1n1 DSS2690548027 SPDK bdev Controller 1 13.63 MB / 7.65 TB 512 B + 0 B 20.07\n /dev/nvme2n1 DSS1137172735 SPDK bdev Controller 1 13.63 MB / 7.65 TB 512 B + 0 B 20.07\n /dev/nvme3n1 DSS7754076932 SPDK bdev Controller 1 12.58 MB / 7.65 TB 512 B + 0 B 20.07\n /dev/nvme4n1 DSS5066419069 SPDK bdev Controller 1 13.63 MB / 7.65 TB 512 B + 0 B 20.07\n /dev/nvme5n1 DSS2690548027 SPDK bdev Controller 1 13.63 MB / 7.65 TB 512 B + 0 B 20.07\n /dev/nvme6n1 DSS1137172735 SPDK bdev Controller 1 13.63 MB / 7.65 TB 512 B + 0 B 20.07\n /dev/nvme7n1 DSS7754076932 SPDK bdev Controller 1 12.58 MB / 7.65 TB 512 B + 0 B 20.07\n ", + "nvme_discover":" Discovery Log Number of Records 1, Generation counter 4\n =====Discovery Log Entry 0======\n trtype: rdma\n adrfam: ipv4\n subtype: nvme subsystem\n treq: not required\n portid: 0\n trsvcid: 1024\n subnqn: nqn.2023-06.io:msl-dpe-perf35-kv_data1\n traddr: x.x.x.x\n rdma_prtype: not specified\n rdma_qptype: connected\n rdma_cms: rdma-cm\n rdma_pkey: 0x0000\n ", + "nvme_subsystems":" nvme-subsys0 - NQN=nqn.2023-06.io:msl-ssg-sm1-kv_data1\n +- nvme0 rdma traddr=201.x.x.xxx trsvcid=1024 live\n +- nvme4 rdma traddr=203.x.x.xxx trsvcid=1024 live\n nvme-subsys1 - NQN=nqn.2023-06.io:msl-ssg-sm1-kv_data2\n +- nvme1 rdma traddr=201.x.x.xxx trsvcid=1024 live\n +- nvme5 rdma traddr=203.x.x.xxx trsvcid=1024 live\n nvme-subsys2 - NQN=nqn.2023-06.io:msl-ssg-sm1-kv_data3\n +- nvme2 rdma traddr=201.x.x.xxx trsvcid=1024 live\n +- nvme6 rdma traddr=203.x.x.xxx trsvcid=1024 live\n nvme-subsys3 - NQN=nqn.2023-06.io:msl-ssg-sm1-kv_data4\n +- nvme3 rdma traddr=201.x.x.xxx trsvcid=1024 live\n +- nvme7 rdma traddr=203.x.x.xxx trsvcid=1024 live\n " +} diff --git a/unittests/test_dss_host.py b/unittests/test_dss_host.py new file mode 100644 index 00000000..38cec04f --- /dev/null +++ b/unittests/test_dss_host.py @@ -0,0 +1,148 @@ +#!/usr/bin/python3 + +""" +# The Clear BSD License +# +# Copyright (c) 2023 Samsung Electronics Co., Ltd. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted (subject to the limitations in the disclaimer +# below) provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Samsung Electronics Co., Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY +# THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +# NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from host.scripts.dss_host import ( + is_ipv4, getSubnet, get_ip_port_nqn_info, decode, + build_driver, install_kernel_driver, get_ips_for_vlan, + drive_to_addr_map, mountpt_to_nqn_addr_map, subnet_drive_map, + discover_dist, config_minio_dist, config_minio_sa, dss_host_args +) +import pytest +import secrets +import os +from conftest import ( + mock_exec_cmd, mock_os_dirname_host, + mock_exec_cmd_remote, + MockArgParser +) + + +EXEC = "host.scripts.dss_host.exec_cmd" +DIRNAME = "os.path.dirname" +EXEC_REMOTE = "host.scripts.dss_host.exec_cmd_remote" +ARG_PARSER = "argparse.ArgumentParser" +OPEN = "builtins.open" +CHMOD = "os.chmod" + + +def mock_functions(mocker, *args): + for arg in args: + if arg == EXEC: + mocker.patch(arg, mock_exec_cmd) + elif arg == DIRNAME: + mocker.patch(arg, mock_os_dirname_host) + elif arg == EXEC_REMOTE: + mocker.patch(arg, mock_exec_cmd_remote) + elif arg == ARG_PARSER: + mocker.patch(arg, MockArgParser) + else: + mocker.patch(arg) + + +@pytest.mark.usefixtures( + "get_sample_ipv4_addr", + "get_sample_ipv6_addr", + "get_sample_nvme_discover_output" +) +class TestDSSHost(): + def test_is_ipv4(self, get_sample_ipv4_addr, get_sample_ipv6_addr): + assert bool(is_ipv4(get_sample_ipv4_addr)) + assert not is_ipv4(get_sample_ipv6_addr) + + def test_getSubnet(self, get_sample_ipv4_addr): + addr = get_sample_ipv4_addr + subnet = '.'.join(addr.split('.')[0:3]) + assert subnet == getSubnet(addr) + + def test_get_ip_port_nqn_info(self, get_sample_nvme_discover_output): + data = get_ip_port_nqn_info(get_sample_nvme_discover_output, "rdma") + proto = 'rdma' + port = '1024' + subsystem = 'nqn.2023-06.io:msl-dpe-perf35-kv_data1' + ip = 'x.x.x.x' + assert data == [[proto, port, subsystem, ip]] + + def test_decode(self): + bytes = bytearray(secrets.randbits(8) for _ in range(200)) + assert isinstance(decode(bytes), str) + + def test_build_driver(self, mocker): + mock_functions(mocker, EXEC, DIRNAME) + build_driver() + + def test_install_kernel_driver(self, mocker): + mock_functions(mocker, EXEC, DIRNAME) + install_kernel_driver(512) + + def test_get_ips_for_vlan(self, mocker): + mock_functions(mocker, EXEC_REMOTE) + res = get_ips_for_vlan("1234", "host", ["pw"]) + assert len(res) > 0 + + def test_drive_to_addr_map(self, mocker): + mock_functions(mocker, EXEC) + res = drive_to_addr_map() + assert len(res) == 1 + + def test_mountpt_to_nqn_addr_map(self, mocker): + mock_functions(mocker, EXEC) + res = mountpt_to_nqn_addr_map() + assert len(res) == 1 + for dev in res.keys(): + assert "nqn" in res[dev] + assert "addr" in res[dev] + + def test_subnet_drive_map(self, mocker): + mock_functions(mocker, EXEC) + res = subnet_drive_map() + assert len(res) > 0 + + def test_discover_dist(self, mocker): + mock_functions(mocker, EXEC, EXEC_REMOTE) + res = discover_dist(1234, ["1234"], ["1234"], "pw") + assert len(res) > 0 + + def test_config_minio_dist(self, mocker): + mock_functions(mocker, OPEN, CHMOD) + config_minio_dist(["ip", "port", "dev_start", "dev"], 1) + + def test_config_minio_sa(self, mocker): + mock_functions(mocker, OPEN) + config_minio_sa(["ip", "port", "dev_start", "dev"], 1) + + def test_dss_host_args_config_host(self, mocker): + mock_functions(mocker, ARG_PARSER, EXEC, + EXEC_REMOTE, OPEN, CHMOD, "os.chdir", + "os.path.exists", "json.load", "json.dump") + dss_host_args() diff --git a/unittests/test_dss_target.py b/unittests/test_dss_target.py new file mode 100644 index 00000000..2cbf5181 --- /dev/null +++ b/unittests/test_dss_target.py @@ -0,0 +1,139 @@ +#!/usr/bin/python3 + +""" +# The Clear BSD License +# +# Copyright (c) 2023 Samsung Electronics Co., Ltd. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted (subject to the limitations in the disclaimer +# below) provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# * Neither the name of Samsung Electronics Co., Ltd. nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY +# THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +# NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +""" + +from target.dss_target import ( + random_with_N_digits, generate_core_mask, generate_core_mask_vmmode, + get_pcie_address_firmware_mapping, get_pcie_address_serial_mapping, + get_nvme_list_numa, ip4_addresses, only_mtu9k, get_rdma_ips, + get_numa_boundary, get_numa_ip, create_nvmf_config_file, get_vlan_ips, + setup_hugepage +) +import pytest +from conftest import ( + mock_exec_cmd, default_mock_ip, + mock_interfaces, mock_ifaddresses +) + + +EXEC = "target.dss_target.exec_cmd" +INTERFACE = "target.dss_target.interfaces" +IFADDRESS = "target.dss_target.ifaddresses" +AFINET = "target.dss_target.AF_INET" +OPEN = "builtins.open" +READLINES = "typing.IO.readlines" + + +def mock_functions(mocker, *args): + for arg in args: + if arg == EXEC: + mocker.patch(arg, mock_exec_cmd) + elif arg == INTERFACE: + mocker.patch(arg, mock_interfaces) + elif arg == IFADDRESS: + mocker.patch(arg, mock_ifaddresses) + elif arg == AFINET: + mocker.patch(arg, 0) + else: + mocker.patch(arg) + + +class TestDSSTarget(): + def test_random_with_N_digits(self): + num_digits = 10 + num = random_with_N_digits(10) + assert len(str(num)) == num_digits + + def test_generate_core_mask(self): + core_count = 12 + dedicated_core_percent = 0.6 + return 0 == generate_core_mask(core_count, dedicated_core_percent) + + def test_generate_core_mask_vmmode(self): + core_count = 12 + return 0 == generate_core_mask_vmmode(core_count) + + def test_get_pcie_address_firmware_mapping(self, mocker): + mock_functions(mocker, EXEC, OPEN, READLINES) + r1, r2 = get_pcie_address_firmware_mapping() + + def test_get_pcie_address_serial_mapping(self, mocker): + mock_functions(mocker, EXEC, OPEN, READLINES) + r = get_pcie_address_serial_mapping([]) + assert len(r) > 0 + + def test_get_nvme_list_numa(self, mocker): + mock_functions(mocker, EXEC) + r = get_nvme_list_numa() + assert len(r) > 0 + + def test_ip4_addresses(self, mocker): + r = ip4_addresses() + assert len(r) > 0 + + def test_only_mtu9k(self, mocker): + mock_functions(mocker, EXEC) + r = only_mtu9k({"ip": 100}) + assert len(r) > 0 + + def test_get_rdma_ips(self, mocker): + r = get_rdma_ips({"nic": default_mock_ip}, [default_mock_ip]) + assert len(r) > 0 + + def test_get_numa_boundary(self, mocker): + mock_functions(mocker, EXEC) + r = get_numa_boundary() + assert int(r) == 1 + + def test_get_numa_ip(self, mocker): + mock_functions(mocker, EXEC, INTERFACE, + IFADDRESS, AFINET) + r1, r2 = get_numa_ip([default_mock_ip]) + assert len(r1) > 0 + assert len(r2) == 0 + + def test_create_nvmf_config_file(self, mocker): + mock_functions(mocker, EXEC, INTERFACE, + IFADDRESS, AFINET, OPEN) + r = create_nvmf_config_file("", [default_mock_ip], [], []) + assert r == 0 + + def test_get_vlan_ips(self, mocker): + mock_functions(mocker, EXEC) + r = get_vlan_ips("1234") + assert r + + def test_setup_hugepage(self, mocker): + mock_functions(mocker, EXEC, OPEN) + r = setup_hugepage() + assert r == 0