Skip to content

Commit 16e91eb

Browse files
committed
add tests
1 parent 58a418b commit 16e91eb

3 files changed

Lines changed: 124 additions & 1 deletion

File tree

src/otaclient_common/cmdhelper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def detect_storage_device_type(rootfs_devpath: str) -> str:
9898
)
9999
return "L3"
100100

101-
if rotational is True:
101+
if rotational:
102102
logger.info(f"detected SATA HDD: {parent_devpath}, classified as L3")
103103
return "L3"
104104
logger.info(f"detected SATA SSD: {parent_devpath}, classified as L2")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2022 TIER IV, INC. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# Copyright 2022 TIER IV, INC. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from __future__ import annotations
16+
17+
from subprocess import CalledProcessError
18+
19+
import pytest
20+
from pytest_mock import MockerFixture
21+
22+
from otaclient.configs._cfg_consts import StorageDeviceType
23+
from otaclient_common.cmdhelper import detect_storage_device_type
24+
25+
_CMDHELPER = "otaclient_common.cmdhelper"
26+
27+
28+
class TestDetectStorageDeviceType:
29+
@pytest.mark.parametrize(
30+
"parent_devpath, expected",
31+
[
32+
pytest.param("/dev/nvme0n1", "L1", id="nvme0n1"),
33+
pytest.param("/dev/nvme1n1", "L1", id="nvme1n1"),
34+
],
35+
)
36+
def test_nvme_classified_as_l1(
37+
self, mocker: MockerFixture, parent_devpath: str, expected: str
38+
):
39+
mocker.patch(f"{_CMDHELPER}.get_parent_dev", return_value=parent_devpath)
40+
assert detect_storage_device_type("/dev/nvme0n1p1") == expected
41+
42+
@pytest.mark.parametrize(
43+
"parent_devpath, expected",
44+
[
45+
pytest.param("/dev/mmcblk0", "L3", id="mmcblk0"),
46+
pytest.param("/dev/mmcblk1", "L3", id="mmcblk1"),
47+
],
48+
)
49+
def test_emmc_classified_as_l3(
50+
self, mocker: MockerFixture, parent_devpath: str, expected: str
51+
):
52+
mocker.patch(f"{_CMDHELPER}.get_parent_dev", return_value=parent_devpath)
53+
assert detect_storage_device_type("/dev/mmcblk0p1") == expected
54+
55+
def test_sata_ssd_classified_as_l2(self, mocker: MockerFixture):
56+
mocker.patch(f"{_CMDHELPER}.get_parent_dev", return_value="/dev/sda")
57+
mocker.patch(f"{_CMDHELPER}._read_sysfs_rotational", return_value=False)
58+
assert detect_storage_device_type("/dev/sda1") == "L2"
59+
60+
def test_sata_hdd_classified_as_l3(self, mocker: MockerFixture):
61+
mocker.patch(f"{_CMDHELPER}.get_parent_dev", return_value="/dev/sda")
62+
mocker.patch(f"{_CMDHELPER}._read_sysfs_rotational", return_value=True)
63+
assert detect_storage_device_type("/dev/sda1") == "L3"
64+
65+
def test_sdx_rotational_unreadable_falls_back_to_l3(self, mocker: MockerFixture):
66+
mocker.patch(f"{_CMDHELPER}.get_parent_dev", return_value="/dev/sdb")
67+
mocker.patch(f"{_CMDHELPER}._read_sysfs_rotational", return_value=None)
68+
assert detect_storage_device_type("/dev/sdb1") == "L3"
69+
70+
def test_unknown_device_falls_back_to_l3(self, mocker: MockerFixture):
71+
mocker.patch(f"{_CMDHELPER}.get_parent_dev", return_value="/dev/vda")
72+
assert detect_storage_device_type("/dev/vda1") == "L3"
73+
74+
def test_get_parent_dev_failure_falls_back_to_l3(self, mocker: MockerFixture):
75+
mocker.patch(
76+
f"{_CMDHELPER}.get_parent_dev",
77+
side_effect=CalledProcessError(1, "lsblk"),
78+
)
79+
assert detect_storage_device_type("/dev/sda1") == "L3"
80+
81+
82+
class TestStorageDeviceTypeMapDownloadThreads:
83+
@pytest.mark.parametrize(
84+
"device_type, cpu_count, expected",
85+
[
86+
pytest.param(StorageDeviceType.L1, 8, 32, id="L1_8cpu"),
87+
pytest.param(StorageDeviceType.L1, 4, 24, id="L1_4cpu_clamped_min"),
88+
pytest.param(StorageDeviceType.L1, 16, 32, id="L1_16cpu_clamped_max"),
89+
pytest.param(StorageDeviceType.L2, 8, 24, id="L2_8cpu"),
90+
pytest.param(StorageDeviceType.L2, 4, 16, id="L2_4cpu_clamped_min"),
91+
pytest.param(StorageDeviceType.L2, 16, 24, id="L2_16cpu_clamped_max"),
92+
pytest.param(StorageDeviceType.L3, 8, 12, id="L3_8cpu_clamped_max"),
93+
pytest.param(StorageDeviceType.L3, 4, 8, id="L3_4cpu"),
94+
pytest.param(StorageDeviceType.L3, 16, 12, id="L3_16cpu_clamped_max"),
95+
],
96+
)
97+
def test_thread_calculation(
98+
self,
99+
mocker: MockerFixture,
100+
device_type: StorageDeviceType,
101+
cpu_count: int,
102+
expected: int,
103+
):
104+
mocker.patch("os.cpu_count", return_value=cpu_count)
105+
assert device_type.map_device_rank_to_download_threads() == expected
106+
107+
def test_cpu_count_none_defaults_to_4(self, mocker: MockerFixture):
108+
mocker.patch("os.cpu_count", return_value=None)
109+
# cpu_count defaults to 4, L3: min(12, max(8, 4*2)) = 8
110+
assert StorageDeviceType.L3.map_device_rank_to_download_threads() == 8

0 commit comments

Comments
 (0)