Coverage for mlos_bench/mlos_bench/tests/environments/test_status.py: 100%
40 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-14 00:55 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-14 00:55 +0000
1#
2# Copyright (c) Microsoft Corporation.
3# Licensed under the MIT License.
4#
5"""
6Unit tests for the :py:class:`mlos_bench.environments.status.Status` class.
8Tests the :py:meth:`mlos_bench.environments.status.Status.from_str` static method
9for correct parsing of both numeric and string representations of each Status,
10as well as handling of invalid input.
11"""
13from typing import Any
15import pytest
17from mlos_bench.environments.status import Status
20@pytest.mark.parametrize(
21 ["input_str", "expected_status"],
22 [
23 ("UNKNOWN", Status.UNKNOWN),
24 ("0", Status.UNKNOWN),
25 ("PENDING", Status.PENDING),
26 ("1", Status.PENDING),
27 ("READY", Status.READY),
28 ("2", Status.READY),
29 ("RUNNING", Status.RUNNING),
30 ("3", Status.RUNNING),
31 ("SUCCEEDED", Status.SUCCEEDED),
32 ("4", Status.SUCCEEDED),
33 ("CANCELED", Status.CANCELED),
34 ("5", Status.CANCELED),
35 ("FAILED", Status.FAILED),
36 ("6", Status.FAILED),
37 ("TIMED_OUT", Status.TIMED_OUT),
38 ("7", Status.TIMED_OUT),
39 (" TIMED_OUT ", Status.TIMED_OUT),
40 ],
41)
42def test_status_from_str_valid(input_str: str, expected_status: Status) -> None:
43 """
44 Test :py:meth:`Status.from_str` with valid string and numeric representations.
46 Parameters
47 ----------
48 input_str : str
49 String representation of the status.
50 expected_status : Status
51 Expected Status enum value.
52 """
53 assert (
54 Status.parse(input_str) == expected_status
55 ), f"Expected {expected_status} for input: {input_str}"
56 # Check lowercase representation
57 assert (
58 Status.parse(input_str.lower()) == expected_status
59 ), f"Expected {expected_status} for input: {input_str.lower()}"
60 assert (
61 Status.parse(expected_status) == expected_status
62 ), f"Expected {expected_status} for input: {expected_status}"
63 if input_str.isdigit():
64 # Also test the numeric representation
65 assert (
66 Status.parse(int(input_str)) == expected_status
67 ), f"Expected {expected_status} for input: {int(input_str)}"
70@pytest.mark.parametrize(
71 "invalid_input",
72 [
73 "UNKNOWABLE",
74 "8",
75 "-1",
76 "successful",
77 "",
78 None,
79 123,
80 [],
81 {},
82 ],
83)
84def test_status_from_str_invalid(invalid_input: Any) -> None:
85 """Test :py:meth:`Status.from_str` returns :py:attr:`Status.UNKNOWN` for invalid
86 input.
87 """
88 assert (
89 Status.parse(invalid_input) == Status.UNKNOWN
90 ), f"Expected Status.UNKNOWN for invalid input: {invalid_input}"
93@pytest.mark.parametrize(
94 ["status", "expected_result"],
95 [
96 (Status.UNKNOWN, False),
97 (Status.PENDING, True),
98 (Status.READY, True),
99 (Status.RUNNING, True),
100 (Status.SUCCEEDED, True),
101 (Status.CANCELED, False),
102 (Status.FAILED, False),
103 (Status.TIMED_OUT, False),
104 ],
105)
106def test_status_is_good(status: Status, expected_result: bool) -> None:
107 """
108 Test :py:meth:`Status.is_good` for various statuses.
110 Parameters
111 ----------
112 status : Status
113 The Status enum value to test.
114 expected_result : bool
115 Expected result of the is_good method.
116 """
117 assert status.is_good() == expected_result, f"Expected {expected_result} for status: {status}"
120@pytest.mark.parametrize(
121 ["status", "expected_result"],
122 [
123 (Status.UNKNOWN, False),
124 (Status.PENDING, False),
125 (Status.READY, False),
126 (Status.RUNNING, False),
127 (Status.SUCCEEDED, True),
128 (Status.CANCELED, True),
129 (Status.FAILED, True),
130 (Status.TIMED_OUT, True),
131 ],
132)
133def test_status_is_completed(status: Status, expected_result: bool) -> None:
134 """
135 Test :py:meth:`Status.is_completed` for various statuses.
137 Parameters
138 ----------
139 status : Status
140 The Status enum value to test.
141 expected_result : bool
142 Expected result of the is_completed method.
143 """
144 assert (
145 status.is_completed() == expected_result
146 ), f"Expected {expected_result} for status: {status}"
149@pytest.mark.parametrize(
150 ["status", "expected_result"],
151 [
152 (Status.UNKNOWN, False),
153 (Status.PENDING, True),
154 (Status.READY, False),
155 (Status.RUNNING, False),
156 (Status.SUCCEEDED, False),
157 (Status.CANCELED, False),
158 (Status.FAILED, False),
159 (Status.TIMED_OUT, False),
160 ],
161)
162def test_status_is_pending(status: Status, expected_result: bool) -> None:
163 """
164 Test :py:meth:`Status.is_pending` for various statuses.
166 Parameters
167 ----------
168 status : Status
169 The Status enum value to test.
170 expected_result : bool
171 Expected result of the is_pending method.
172 """
173 assert (
174 status.is_pending() == expected_result
175 ), f"Expected {expected_result} for status: {status}"
178@pytest.mark.parametrize(
179 ["status", "expected_result"],
180 [
181 (Status.UNKNOWN, False),
182 (Status.PENDING, False),
183 (Status.READY, True),
184 (Status.RUNNING, False),
185 (Status.SUCCEEDED, False),
186 (Status.CANCELED, False),
187 (Status.FAILED, False),
188 (Status.TIMED_OUT, False),
189 ],
190)
191def test_status_is_ready(status: Status, expected_result: bool) -> None:
192 """
193 Test :py:meth:`Status.is_ready` for various statuses.
195 Parameters
196 ----------
197 status : Status
198 The Status enum value to test.
199 expected_result : bool
200 Expected result of the is_ready method.
201 """
202 assert status.is_ready() == expected_result, f"Expected {expected_result} for status: {status}"
205@pytest.mark.parametrize(
206 ["status", "expected_result"],
207 [
208 (Status.UNKNOWN, False),
209 (Status.PENDING, False),
210 (Status.READY, False),
211 (Status.RUNNING, True),
212 (Status.SUCCEEDED, False),
213 (Status.CANCELED, False),
214 (Status.FAILED, False),
215 (Status.TIMED_OUT, False),
216 ],
217)
218def test_status_is_running(status: Status, expected_result: bool) -> None:
219 """
220 Test :py:meth:`Status.is_running` for various statuses.
222 Parameters
223 ----------
224 status : Status
225 The Status enum value to test.
226 expected_result : bool
227 Expected result of the is_running method.
228 """
229 assert (
230 status.is_running() == expected_result
231 ), f"Expected {expected_result} for status: {status}"
234@pytest.mark.parametrize(
235 ["status", "expected_result"],
236 [
237 (Status.UNKNOWN, False),
238 (Status.PENDING, False),
239 (Status.READY, False),
240 (Status.RUNNING, False),
241 (Status.SUCCEEDED, True),
242 (Status.CANCELED, False),
243 (Status.FAILED, False),
244 (Status.TIMED_OUT, False),
245 ],
246)
247def test_status_is_succeeded(status: Status, expected_result: bool) -> None:
248 """
249 Test :py:meth:`Status.is_succeeded` for various statuses.
251 Parameters
252 ----------
253 status : Status
254 The Status enum value to test.
255 expected_result : bool
256 Expected result of the is_succeeded method.
257 """
258 assert (
259 status.is_succeeded() == expected_result
260 ), f"Expected {expected_result} for status: {status}"
263@pytest.mark.parametrize(
264 ["status", "expected_result"],
265 [
266 (Status.UNKNOWN, False),
267 (Status.PENDING, False),
268 (Status.READY, False),
269 (Status.RUNNING, False),
270 (Status.SUCCEEDED, False),
271 (Status.CANCELED, True),
272 (Status.FAILED, False),
273 (Status.TIMED_OUT, False),
274 ],
275)
276def test_status_is_canceled(status: Status, expected_result: bool) -> None:
277 """
278 Test :py:meth:`Status.is_canceled` for various statuses.
280 Parameters
281 ----------
282 status : Status
283 The Status enum value to test.
284 expected_result : bool
285 Expected result of the is_canceled method.
286 """
287 assert (
288 status.is_canceled() == expected_result
289 ), f"Expected {expected_result} for status: {status}"
292@pytest.mark.parametrize(
293 ["status", "expected_result"],
294 [
295 (Status.UNKNOWN, False),
296 (Status.PENDING, False),
297 (Status.READY, False),
298 (Status.RUNNING, False),
299 (Status.SUCCEEDED, False),
300 (Status.CANCELED, False),
301 (Status.FAILED, True),
302 (Status.TIMED_OUT, False),
303 ],
304)
305def test_status_is_failed(status: Status, expected_result: bool) -> None:
306 """
307 Test :py:meth:`Status.is_failed` for various statuses.
309 Parameters
310 ----------
311 status : Status
312 The Status enum value to test.
313 expected_result : bool
314 Expected result of the is_failed method.
315 """
316 assert (
317 status.is_failed() == expected_result
318 ), f"Expected {expected_result} for status: {status}"
321@pytest.mark.parametrize(
322 ["status", "expected_result"],
323 [
324 (Status.UNKNOWN, False),
325 (Status.PENDING, False),
326 (Status.READY, False),
327 (Status.RUNNING, False),
328 (Status.SUCCEEDED, False),
329 (Status.CANCELED, False),
330 (Status.FAILED, False),
331 (Status.TIMED_OUT, True),
332 ],
333)
334def test_status_is_timed_out(status: Status, expected_result: bool) -> None:
335 """
336 Test :py:meth:`Status.is_timed_out` for various statuses.
338 Parameters
339 ----------
340 status : Status
341 The Status enum value to test.
342 expected_result : bool
343 Expected result of the is_timed_out method.
344 """
345 assert (
346 status.is_timed_out() == expected_result
347 ), f"Expected {expected_result} for status: {status}"