amd-debug-tools 0.2.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
test_s2idle.py ADDED
@@ -0,0 +1,868 @@
1
+ #!/usr/bin/python3
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ """
5
+ This module contains unit tests for the s2idle tool in the amd-debug-tools package.
6
+ """
7
+ import argparse
8
+ import sys
9
+ import unittest
10
+ import logging
11
+ import sqlite3
12
+ from datetime import datetime
13
+ from unittest.mock import patch
14
+
15
+ from amd_debug.s2idle import (
16
+ parse_args,
17
+ main,
18
+ install,
19
+ uninstall,
20
+ run_test_cycle,
21
+ display_report_file,
22
+ report,
23
+ prompt_report_arguments,
24
+ Defaults,
25
+ )
26
+
27
+
28
+ class TestParseArgs(unittest.TestCase):
29
+ """Test parse_args function"""
30
+
31
+ @classmethod
32
+ def setUpClass(cls):
33
+ logging.basicConfig(filename="/dev/null", level=logging.DEBUG)
34
+
35
+ def setUp(self):
36
+ self.default_sys_argv = sys.argv
37
+
38
+ def tearDown(self):
39
+ sys.argv = self.default_sys_argv
40
+
41
+ @patch("sys.stderr")
42
+ def test_no_arguments(self, _mock_print):
43
+ """Test parse_args with no arguments"""
44
+ sys.argv = ["s2idle.py"]
45
+ with self.assertRaises(SystemExit):
46
+ parse_args()
47
+
48
+ def test_test_command_with_arguments(self):
49
+ """Test parse_args with test command and arguments"""
50
+ sys.argv = [
51
+ "s2idle.py",
52
+ "test",
53
+ "--count",
54
+ "5",
55
+ "--duration",
56
+ "10",
57
+ "--wait",
58
+ "3",
59
+ "--format",
60
+ "txt",
61
+ "--tool-debug",
62
+ ]
63
+ args = parse_args()
64
+ self.assertEqual(args.action, "test")
65
+ self.assertEqual(args.count, "5")
66
+ self.assertEqual(args.duration, "10")
67
+ self.assertEqual(args.wait, "3")
68
+ self.assertEqual(args.format, "txt")
69
+ self.assertTrue(args.tool_debug)
70
+
71
+ def test_report_command_with_arguments(self):
72
+ """Test parse_args with report command and arguments"""
73
+ sys.argv = [
74
+ "s2idle.py",
75
+ "report",
76
+ "--since",
77
+ "2023-01-01",
78
+ "--until",
79
+ "2023-02-01",
80
+ "--format",
81
+ "html",
82
+ "--report-debug",
83
+ ]
84
+ args = parse_args()
85
+ self.assertEqual(args.action, "report")
86
+ self.assertEqual(args.since, "2023-01-01")
87
+ self.assertEqual(args.until, "2023-02-01")
88
+ self.assertEqual(args.format, "html")
89
+ self.assertTrue(args.report_debug)
90
+
91
+ @patch("sys.prefix", "amd_debug.s2idle")
92
+ @patch("sys.base_prefix", "foo")
93
+ def test_install_command(self):
94
+ """Test parse_args with install command"""
95
+ sys.argv = ["s2idle.py", "install", "--tool-debug"]
96
+ args = parse_args()
97
+ self.assertEqual(args.action, "install")
98
+ self.assertTrue(args.tool_debug)
99
+
100
+ @patch("sys.prefix", "amd_debug.s2idle")
101
+ @patch("sys.base_prefix", "foo")
102
+ def test_uninstall_command(self):
103
+ """Test parse_args with uninstall command"""
104
+ sys.argv = ["s2idle.py", "uninstall", "--tool-debug"]
105
+ args = parse_args()
106
+ self.assertEqual(args.action, "uninstall")
107
+ self.assertTrue(args.tool_debug)
108
+
109
+ @patch("sys.prefix", "amd_debug.s2idle")
110
+ @patch("sys.base_prefix", "amd_debug.s2idle")
111
+ @patch("sys.stderr")
112
+ def test_hidden_install_command(self, _mock_print):
113
+ """Test parse_args with install command"""
114
+ sys.argv = ["s2idle.py", "install", "--tool-debug"]
115
+ with self.assertRaises(SystemExit):
116
+ parse_args()
117
+
118
+ def test_version_command(self):
119
+ """Test parse_args with version command"""
120
+ sys.argv = ["s2idle.py", "version"]
121
+ args = parse_args()
122
+ self.assertEqual(args.action, "version")
123
+
124
+
125
+ class TestMainFunction(unittest.TestCase):
126
+ """Test main function"""
127
+
128
+ @classmethod
129
+ def setUpClass(cls):
130
+ logging.basicConfig(filename="/dev/null", level=logging.DEBUG)
131
+
132
+ def setUp(self):
133
+ self.default_sys_argv = sys.argv
134
+
135
+ def tearDown(self):
136
+ sys.argv = self.default_sys_argv
137
+
138
+ @patch("amd_debug.s2idle.relaunch_sudo")
139
+ @patch("amd_debug.s2idle.install")
140
+ def test_main_install(self, mock_install, mock_relaunch_sudo):
141
+ """Test main function with install action"""
142
+ sys.argv = ["s2idle.py", "install", "--tool-debug"]
143
+ with patch("amd_debug.s2idle.parse_args") as mock_parse_args:
144
+ mock_parse_args.return_value = argparse.Namespace(
145
+ action="install", tool_debug=True
146
+ )
147
+ main()
148
+ mock_relaunch_sudo.assert_called_once()
149
+ mock_install.assert_called_once_with(True)
150
+
151
+ @patch("amd_debug.s2idle.relaunch_sudo")
152
+ @patch("amd_debug.s2idle.uninstall")
153
+ def test_main_uninstall(self, mock_uninstall, mock_relaunch_sudo):
154
+ """Test main function with uninstall action"""
155
+ sys.argv = ["s2idle.py", "uninstall", "--tool-debug"]
156
+ with patch("amd_debug.s2idle.parse_args") as mock_parse_args:
157
+ mock_parse_args.return_value = argparse.Namespace(
158
+ action="uninstall", tool_debug=True
159
+ )
160
+ main()
161
+ mock_relaunch_sudo.assert_called_once()
162
+ mock_uninstall.assert_called_once_with(True)
163
+
164
+ @patch("amd_debug.s2idle.report")
165
+ def test_main_report(self, mock_report):
166
+ """Test main function with report action"""
167
+ sys.argv = ["s2idle.py", "report", "--since", "2023-01-01"]
168
+ with patch("amd_debug.s2idle.parse_args") as mock_parse_args:
169
+ mock_parse_args.return_value = argparse.Namespace(
170
+ action="report",
171
+ since="2023-01-01",
172
+ until="2023-02-01",
173
+ report_file=None,
174
+ format="html",
175
+ tool_debug=False,
176
+ report_debug=False,
177
+ )
178
+ mock_report.return_value = True
179
+ result = main()
180
+ mock_report.assert_called_once_with(
181
+ "2023-01-01", "2023-02-01", None, "html", False, False
182
+ )
183
+ self.assertTrue(result)
184
+
185
+ @patch("amd_debug.s2idle.relaunch_sudo")
186
+ @patch("amd_debug.s2idle.run_test_cycle")
187
+ def test_main_run_test_cycle(self, mock_test, mock_relaunch_sudo):
188
+ """Test main function with test action"""
189
+ sys.argv = ["s2idle.py", "test", "--count", "5"]
190
+ with patch("amd_debug.s2idle.parse_args") as mock_parse_args:
191
+ mock_parse_args.return_value = argparse.Namespace(
192
+ action="test",
193
+ duration=None,
194
+ wait=None,
195
+ count="5",
196
+ format="txt",
197
+ report_file=None,
198
+ force=False,
199
+ tool_debug=False,
200
+ random=False,
201
+ logind=False,
202
+ bios_debug=False,
203
+ )
204
+ mock_test.return_value = True
205
+ result = main()
206
+ mock_relaunch_sudo.assert_called_once()
207
+ mock_test.assert_called_once_with(
208
+ None, None, "5", "txt", None, False, False, False, False, False
209
+ )
210
+ self.assertTrue(result)
211
+
212
+ @patch("amd_debug.s2idle.version")
213
+ def test_main_version(self, mock_version):
214
+ """Test main function with version action"""
215
+ sys.argv = ["s2idle.py", "version"]
216
+ with patch("amd_debug.s2idle.parse_args") as mock_parse_args:
217
+ mock_parse_args.return_value = argparse.Namespace(action="version")
218
+ mock_version.return_value = "1.0.0"
219
+ with patch("builtins.print") as mock_print:
220
+ result = main()
221
+ mock_version.assert_called_once()
222
+ mock_print.assert_called_once_with("1.0.0")
223
+ self.assertTrue(result)
224
+
225
+ def test_main_no_action(self):
226
+ """Test main function with no action specified"""
227
+ sys.argv = ["s2idle.py"]
228
+ with patch("amd_debug.s2idle.parse_args") as mock_parse_args:
229
+ mock_parse_args.return_value = argparse.Namespace(action=None)
230
+ with self.assertRaises(SystemExit) as cm:
231
+ main()
232
+ self.assertEqual(cm.exception.code, "no action specified")
233
+
234
+ @patch("amd_debug.s2idle.Installer")
235
+ def test_uninstall_success(self, mock_installer):
236
+ """Test uninstall function when removal is successful"""
237
+ mock_app = mock_installer.return_value
238
+ mock_app.remove.return_value = True
239
+
240
+ uninstall(debug=True)
241
+ mock_installer.assert_called_once_with(tool_debug=True)
242
+ mock_app.remove.assert_called_once()
243
+
244
+
245
+ class TestInstallFunction(unittest.TestCase):
246
+ """Test main function"""
247
+
248
+ @patch("amd_debug.s2idle.Installer")
249
+ @patch("sys.exit")
250
+ def test_uninstall_failure(self, mock_sys_exit, mock_installer):
251
+ """Test uninstall function when removal fails"""
252
+ mock_app = mock_installer.return_value
253
+ mock_app.remove.return_value = False
254
+
255
+ uninstall(debug=True)
256
+ mock_installer.assert_called_once_with(tool_debug=True)
257
+ mock_app.remove.assert_called_once()
258
+ mock_sys_exit.assert_called_once_with("Failed to remove")
259
+
260
+ @patch("amd_debug.s2idle.Installer")
261
+ @patch("amd_debug.s2idle.PrerequisiteValidator")
262
+ @patch("sys.exit")
263
+ def test_install_success(
264
+ self, mock_sys_exit, mock_prerequisite_validator, mock_installer
265
+ ):
266
+ """Test install function when installation is successful"""
267
+ mock_installer_instance = mock_installer.return_value
268
+ mock_installer_instance.install_dependencies.return_value = True
269
+ mock_installer_instance.install.return_value = True
270
+
271
+ mock_prerequisite_instance = mock_prerequisite_validator.return_value
272
+ mock_prerequisite_instance.run.return_value = True
273
+
274
+ install(debug=True)
275
+
276
+ mock_installer.assert_called_once_with(tool_debug=True)
277
+ mock_installer_instance.set_requirements.assert_called_once_with(
278
+ "iasl", "ethtool", "edid-decode"
279
+ )
280
+ mock_installer_instance.install_dependencies.assert_called_once()
281
+ mock_prerequisite_validator.assert_called_once_with(True)
282
+ mock_prerequisite_instance.run.assert_called_once()
283
+ mock_installer_instance.install.assert_called_once()
284
+ mock_sys_exit.assert_not_called()
285
+
286
+ @patch("amd_debug.s2idle.Installer")
287
+ def test_install_dependencies_failure(self, mock_installer):
288
+ """Test install function when dependency installation fails"""
289
+ mock_installer_instance = mock_installer.return_value
290
+ mock_installer_instance.install_dependencies.return_value = False
291
+
292
+ with self.assertRaises(SystemExit):
293
+ install(debug=True)
294
+
295
+ @patch("amd_debug.s2idle.Installer")
296
+ @patch("amd_debug.s2idle.PrerequisiteValidator")
297
+ @patch("sys.exit")
298
+ def test_prerequisite_check_failure(
299
+ self, mock_sys_exit, mock_prerequisite_validator, mock_installer
300
+ ):
301
+ """Test install function when prerequisite check fails"""
302
+ mock_installer_instance = mock_installer.return_value
303
+ mock_installer_instance.install_dependencies.return_value = True
304
+
305
+ mock_prerequisite_instance = mock_prerequisite_validator.return_value
306
+ mock_prerequisite_instance.run.return_value = False
307
+
308
+ install(debug=True)
309
+
310
+ mock_installer.assert_called_once_with(tool_debug=True)
311
+ mock_installer_instance.set_requirements.assert_called_once_with(
312
+ "iasl", "ethtool", "edid-decode"
313
+ )
314
+ mock_installer_instance.install_dependencies.assert_called_once()
315
+ mock_prerequisite_validator.assert_called_once_with(True)
316
+ mock_prerequisite_instance.run.assert_called_once()
317
+ mock_prerequisite_instance.report.assert_called_once()
318
+ mock_sys_exit.assert_called_once_with("Failed to meet prerequisites")
319
+
320
+ @patch("amd_debug.s2idle.Installer")
321
+ @patch("amd_debug.s2idle.PrerequisiteValidator")
322
+ @patch("sys.exit")
323
+ def test_install_failure(
324
+ self, mock_sys_exit, mock_prerequisite_validator, mock_installer
325
+ ):
326
+ """Test install function when installation fails"""
327
+ mock_installer_instance = mock_installer.return_value
328
+ mock_installer_instance.install_dependencies.return_value = True
329
+ mock_installer_instance.install.return_value = False
330
+
331
+ mock_prerequisite_instance = mock_prerequisite_validator.return_value
332
+ mock_prerequisite_instance.run.return_value = True
333
+
334
+ install(debug=True)
335
+
336
+ mock_installer.assert_called_once_with(tool_debug=True)
337
+ mock_installer_instance.set_requirements.assert_called_once_with(
338
+ "iasl", "ethtool", "edid-decode"
339
+ )
340
+ mock_installer_instance.install_dependencies.assert_called_once()
341
+ mock_prerequisite_validator.assert_called_once_with(True)
342
+ mock_prerequisite_instance.run.assert_called_once()
343
+ mock_installer_instance.install.assert_called_once()
344
+ mock_sys_exit.assert_called_once_with("Failed to install")
345
+
346
+
347
+ class TestTestFunction(unittest.TestCase):
348
+ """Test the test function"""
349
+
350
+ @classmethod
351
+ def setUpClass(cls):
352
+ logging.basicConfig(filename="/dev/null", level=logging.DEBUG)
353
+
354
+ @patch("amd_debug.s2idle.Installer")
355
+ @patch("amd_debug.s2idle.PrerequisiteValidator")
356
+ @patch("amd_debug.s2idle.SleepValidator")
357
+ @patch("amd_debug.s2idle.SleepReport")
358
+ @patch("amd_debug.s2idle.prompt_test_arguments")
359
+ @patch("amd_debug.s2idle.prompt_report_arguments")
360
+ @patch("amd_debug.s2idle.display_report_file")
361
+ def test_test_success(
362
+ self,
363
+ mock_display_report_file,
364
+ mock_prompt_report_arguments,
365
+ mock_prompt_test_arguments,
366
+ mock_sleep_report,
367
+ mock_sleep_validator,
368
+ mock_prerequisite_validator,
369
+ mock_installer,
370
+ ):
371
+ """Test the test function when everything succeeds"""
372
+ mock_installer_instance = mock_installer.return_value
373
+ mock_installer_instance.install_dependencies.return_value = True
374
+
375
+ mock_prerequisite_instance = mock_prerequisite_validator.return_value
376
+ mock_prerequisite_instance.run.return_value = True
377
+
378
+ mock_prompt_test_arguments.return_value = (10, 5, 3)
379
+ mock_prompt_report_arguments.return_value = (
380
+ "2023-01-01",
381
+ "2023-02-01",
382
+ "report.html",
383
+ "html",
384
+ True,
385
+ )
386
+
387
+ mock_sleep_validator_instance = mock_sleep_validator.return_value
388
+ mock_sleep_report_instance = mock_sleep_report.return_value
389
+
390
+ result = run_test_cycle(
391
+ duration=None,
392
+ wait=None,
393
+ count=None,
394
+ fmt=None,
395
+ fname=None,
396
+ force=False,
397
+ debug=True,
398
+ rand=False,
399
+ logind=False,
400
+ bios_debug=False,
401
+ )
402
+
403
+ mock_installer.assert_called_once_with(tool_debug=True)
404
+ mock_installer_instance.set_requirements.assert_called_once_with(
405
+ "iasl", "ethtool", "edid-decode"
406
+ )
407
+ mock_installer_instance.install_dependencies.assert_called_once()
408
+ mock_prerequisite_validator.assert_called_once_with(True)
409
+ mock_prerequisite_instance.run.assert_called_once()
410
+ mock_prerequisite_instance.report.assert_called_once()
411
+ mock_prompt_test_arguments.assert_called_once_with(None, None, None, False)
412
+ mock_prompt_report_arguments.assert_called_once()
413
+ mock_sleep_validator.assert_called_once_with(tool_debug=True, bios_debug=False)
414
+ mock_sleep_validator_instance.run.assert_called_once_with(
415
+ duration=10, wait=5, count=3, rand=False, logind=False
416
+ )
417
+ mock_sleep_report.assert_called_once_with(
418
+ since="2023-01-01",
419
+ until="2023-02-01",
420
+ fname="report.html",
421
+ fmt="html",
422
+ tool_debug=True,
423
+ report_debug=True,
424
+ )
425
+ mock_sleep_report_instance.run.assert_called_once()
426
+ mock_display_report_file.assert_called_once_with("report.html", "html")
427
+ self.assertTrue(result)
428
+
429
+ @patch("amd_debug.s2idle.Installer")
430
+ @patch("builtins.print")
431
+ def test_test_install_dependencies_failure(self, _mock_print, mock_installer):
432
+ """Test the test function when dependency installation fails"""
433
+ mock_installer_instance = mock_installer.return_value
434
+ mock_installer_instance.install_dependencies.return_value = False
435
+
436
+ result = run_test_cycle(
437
+ duration=None,
438
+ wait=None,
439
+ count=None,
440
+ fmt=None,
441
+ fname=None,
442
+ force=False,
443
+ debug=True,
444
+ rand=False,
445
+ logind=False,
446
+ bios_debug=False,
447
+ )
448
+
449
+ mock_installer.assert_called_once_with(tool_debug=True)
450
+ mock_installer_instance.set_requirements.assert_called_once_with(
451
+ "iasl", "ethtool", "edid-decode"
452
+ )
453
+ mock_installer_instance.install_dependencies.assert_called_once()
454
+ self.assertFalse(result)
455
+
456
+ @patch("amd_debug.s2idle.Installer")
457
+ @patch("amd_debug.s2idle.PrerequisiteValidator")
458
+ @patch("amd_debug.prerequisites.SleepDatabase")
459
+ @patch("amd_debug.validator.SleepDatabase")
460
+ def test_test_prerequisite_failure(
461
+ self,
462
+ _mock_sleep_db,
463
+ _mock_sleep_db_prerequisite,
464
+ mock_prerequisite_validator,
465
+ mock_installer,
466
+ ):
467
+ """Test the test function when prerequisite check fails"""
468
+ mock_installer_instance = mock_installer.return_value
469
+ mock_installer_instance.install_dependencies.return_value = True
470
+
471
+ mock_prerequisite_instance = mock_prerequisite_validator.return_value
472
+ mock_prerequisite_instance.run.return_value = False
473
+
474
+ result = run_test_cycle(
475
+ duration=None,
476
+ wait=None,
477
+ count=None,
478
+ fmt=None,
479
+ fname=None,
480
+ force=False,
481
+ debug=True,
482
+ rand=False,
483
+ logind=False,
484
+ bios_debug=False,
485
+ )
486
+
487
+ mock_installer.assert_called_once_with(tool_debug=True)
488
+ mock_installer_instance.set_requirements.assert_called_once_with(
489
+ "iasl", "ethtool", "edid-decode"
490
+ )
491
+ mock_installer_instance.install_dependencies.assert_called_once()
492
+ mock_prerequisite_validator.assert_called_once_with(True)
493
+ mock_prerequisite_instance.run.assert_called_once()
494
+ mock_prerequisite_instance.report.assert_called_once()
495
+ self.assertFalse(result)
496
+
497
+ @patch("amd_debug.s2idle.Installer")
498
+ @patch("amd_debug.s2idle.PrerequisiteValidator")
499
+ @patch("amd_debug.s2idle.prompt_test_arguments", side_effect=KeyboardInterrupt)
500
+ @patch("amd_debug.prerequisites.SleepDatabase")
501
+ @patch("amd_debug.validator.SleepDatabase")
502
+ def test_test_keyboard_interrupt(
503
+ self,
504
+ _mock_sleep_db_validator,
505
+ _mock_sleep_db_prerequisite,
506
+ mock_prompt_test_arguments,
507
+ mock_prerequisite_validator,
508
+ mock_installer,
509
+ ):
510
+ """Test the test function when interrupted by the user"""
511
+ mock_installer_instance = mock_installer.return_value
512
+ mock_installer_instance.install_dependencies.return_value = True
513
+
514
+ mock_prerequisite_instance = mock_prerequisite_validator.return_value
515
+ mock_prerequisite_instance.run.return_value = True
516
+
517
+ with self.assertRaises(SystemExit):
518
+ run_test_cycle(
519
+ duration=None,
520
+ wait=None,
521
+ count=None,
522
+ fmt=None,
523
+ fname=None,
524
+ force=False,
525
+ debug=True,
526
+ rand=False,
527
+ logind=False,
528
+ bios_debug=False,
529
+ )
530
+
531
+ mock_installer.assert_called_once_with(tool_debug=True)
532
+ mock_installer_instance.set_requirements.assert_called_once_with(
533
+ "iasl", "ethtool", "edid-decode"
534
+ )
535
+ mock_installer_instance.install_dependencies.assert_called_once()
536
+ mock_prerequisite_validator.assert_called_once_with(True)
537
+ mock_prerequisite_instance.run.assert_called_once()
538
+ mock_prerequisite_instance.report.assert_called_once()
539
+ mock_prompt_test_arguments.assert_called_once_with(None, None, None, False)
540
+
541
+
542
+ class TestDisplayReportFile(unittest.TestCase):
543
+ """Test display_report_file function"""
544
+
545
+ @patch("amd_debug.s2idle.is_root", return_value=False)
546
+ @patch("subprocess.call")
547
+ def test_display_report_file_non_html(self, mock_subprocess_call, mock_is_root):
548
+ """Test display_report_file when format is not html"""
549
+ display_report_file("report.txt", "txt")
550
+ mock_is_root.assert_not_called()
551
+ mock_subprocess_call.assert_not_called()
552
+
553
+ @patch("amd_debug.s2idle.is_root", return_value=False)
554
+ @patch("subprocess.call")
555
+ def test_display_report_file_html_non_root(
556
+ self, mock_subprocess_call, mock_is_root
557
+ ):
558
+ """Test display_report_file when format is html and user is not root"""
559
+ display_report_file("report.html", "html")
560
+ mock_is_root.assert_called_once()
561
+ mock_subprocess_call.assert_called_once_with(["xdg-open", "report.html"])
562
+
563
+ @patch("amd_debug.s2idle.is_root", return_value=True)
564
+ @patch(
565
+ "os.environ.get",
566
+ side_effect=lambda key: "testuser" if key == "SUDO_USER" else "foo",
567
+ )
568
+ @patch("subprocess.call")
569
+ def test_display_report_file_html_root_with_user(
570
+ self, mock_subprocess_call, mock_env_get, mock_is_root
571
+ ):
572
+ """Test display_report_file when format is html, user is root, and SUDO_USER is set"""
573
+ display_report_file("report.html", "html")
574
+ mock_is_root.assert_called_once()
575
+ mock_env_get.assert_any_call("SUDO_USER")
576
+ mock_env_get.assert_any_call("XDG_SESSION_TYPE")
577
+ mock_subprocess_call.assert_called_once_with(
578
+ ["sudo", "-E", "-u", "testuser", "xdg-open", "report.html"]
579
+ )
580
+
581
+ @patch("amd_debug.s2idle.is_root", return_value=True)
582
+ @patch("os.environ.get", side_effect=lambda key: None)
583
+ @patch("builtins.print")
584
+ def test_display_report_file_html_root_without_user(
585
+ self, mock_print, mock_env_get, mock_is_root
586
+ ):
587
+ """Test display_report_file when format is html, user is root, and SUDO_USER is not set"""
588
+ display_report_file("report.html", "html")
589
+ mock_is_root.assert_called_once()
590
+ mock_env_get.assert_any_call("SUDO_USER")
591
+ mock_print.assert_not_called()
592
+
593
+
594
+ class TestReportFunction(unittest.TestCase):
595
+ """Test the report function"""
596
+
597
+ @patch("amd_debug.s2idle.prompt_report_arguments")
598
+ @patch("amd_debug.s2idle.SleepReport")
599
+ @patch("amd_debug.s2idle.display_report_file")
600
+ def test_report_success(
601
+ self, mock_display_report_file, mock_sleep_report, mock_prompt_report_arguments
602
+ ):
603
+ """Test the report function when everything succeeds"""
604
+ mock_prompt_report_arguments.return_value = (
605
+ "2023-01-01",
606
+ "2023-02-01",
607
+ "report.html",
608
+ "html",
609
+ True,
610
+ )
611
+ mock_sleep_report_instance = mock_sleep_report.return_value
612
+
613
+ result = report(
614
+ since=None,
615
+ until=None,
616
+ fname=None,
617
+ fmt=None,
618
+ tool_debug=True,
619
+ report_debug=None,
620
+ )
621
+
622
+ mock_prompt_report_arguments.assert_called_once_with(
623
+ None, None, None, None, None
624
+ )
625
+ mock_sleep_report.assert_called_once_with(
626
+ since="2023-01-01",
627
+ until="2023-02-01",
628
+ fname="report.html",
629
+ fmt="html",
630
+ tool_debug=True,
631
+ report_debug=True,
632
+ )
633
+ mock_sleep_report_instance.run.assert_called_once()
634
+ mock_display_report_file.assert_called_once_with("report.html", "html")
635
+ self.assertTrue(result)
636
+
637
+ @patch("amd_debug.s2idle.prompt_report_arguments", side_effect=KeyboardInterrupt)
638
+ def test_report_keyboard_interrupt(self, mock_prompt_report_arguments):
639
+ """Test the report function when interrupted by the user"""
640
+ with self.assertRaises(SystemExit):
641
+ report(
642
+ since=None,
643
+ until=None,
644
+ fname=None,
645
+ fmt=None,
646
+ tool_debug=True,
647
+ report_debug=None,
648
+ )
649
+
650
+ mock_prompt_report_arguments.assert_called_once_with(
651
+ None, None, None, None, None
652
+ )
653
+
654
+ @patch("amd_debug.s2idle.prompt_report_arguments")
655
+ @patch(
656
+ "amd_debug.s2idle.SleepReport", side_effect=sqlite3.OperationalError("DB error")
657
+ )
658
+ @patch("builtins.print")
659
+ def test_report_sqlite_error(
660
+ self, _mock_print, mock_sleep_report, mock_prompt_report_arguments
661
+ ):
662
+ """Test the report function when a SQLite error occurs"""
663
+ mock_prompt_report_arguments.return_value = (
664
+ "2023-01-01",
665
+ "2023-02-01",
666
+ "report.html",
667
+ "html",
668
+ True,
669
+ )
670
+
671
+ result = report(
672
+ since=None,
673
+ until=None,
674
+ fname=None,
675
+ fmt=None,
676
+ tool_debug=True,
677
+ report_debug=None,
678
+ )
679
+
680
+ mock_prompt_report_arguments.assert_called_once_with(
681
+ None, None, None, None, None
682
+ )
683
+ mock_sleep_report.assert_called_once_with(
684
+ since="2023-01-01",
685
+ until="2023-02-01",
686
+ fname="report.html",
687
+ fmt="html",
688
+ tool_debug=True,
689
+ report_debug=True,
690
+ )
691
+ self.assertFalse(result)
692
+
693
+ @patch("amd_debug.s2idle.prompt_report_arguments")
694
+ @patch(
695
+ "amd_debug.s2idle.SleepReport", side_effect=PermissionError("Permission denied")
696
+ )
697
+ @patch("builtins.print")
698
+ def test_report_permission_error(
699
+ self, _mock_print, mock_sleep_report, mock_prompt_report_arguments
700
+ ):
701
+ """Test the report function when a PermissionError occurs"""
702
+ mock_prompt_report_arguments.return_value = (
703
+ "2023-01-01",
704
+ "2023-02-01",
705
+ "report.html",
706
+ "html",
707
+ True,
708
+ )
709
+
710
+ result = report(
711
+ since=None,
712
+ until=None,
713
+ fname=None,
714
+ fmt=None,
715
+ tool_debug=True,
716
+ report_debug=None,
717
+ )
718
+
719
+ mock_prompt_report_arguments.assert_called_once_with(
720
+ None, None, None, None, None
721
+ )
722
+ mock_sleep_report.assert_called_once_with(
723
+ since="2023-01-01",
724
+ until="2023-02-01",
725
+ fname="report.html",
726
+ fmt="html",
727
+ tool_debug=True,
728
+ report_debug=True,
729
+ )
730
+ self.assertFalse(result)
731
+
732
+ @patch("amd_debug.s2idle.prompt_report_arguments")
733
+ @patch("amd_debug.s2idle.SleepReport")
734
+ @patch("builtins.print")
735
+ def test_report_run_error(
736
+ self, _mock_print, mock_sleep_report, mock_prompt_report_arguments
737
+ ):
738
+ """Test the report function when an error occurs during app.run()"""
739
+ mock_prompt_report_arguments.return_value = (
740
+ "2023-01-01",
741
+ "2023-02-01",
742
+ "report.html",
743
+ "html",
744
+ True,
745
+ )
746
+ mock_sleep_report_instance = mock_sleep_report.return_value
747
+ mock_sleep_report_instance.run.side_effect = ValueError("Invalid value")
748
+
749
+ result = report(
750
+ since=None,
751
+ until=None,
752
+ fname=None,
753
+ fmt=None,
754
+ tool_debug=True,
755
+ report_debug=None,
756
+ )
757
+
758
+ mock_prompt_report_arguments.assert_called_once_with(
759
+ None, None, None, None, None
760
+ )
761
+ mock_sleep_report.assert_called_once_with(
762
+ since="2023-01-01",
763
+ until="2023-02-01",
764
+ fname="report.html",
765
+ fmt="html",
766
+ tool_debug=True,
767
+ report_debug=True,
768
+ )
769
+ mock_sleep_report_instance.run.assert_called_once()
770
+ self.assertFalse(result)
771
+
772
+
773
+ class TestPromptReportArguments(unittest.TestCase):
774
+ """Test prompt_report_arguments function"""
775
+
776
+ @patch("builtins.input", side_effect=["2023-01-01", "2023-02-01", "html", "true"])
777
+ @patch("amd_debug.s2idle.get_report_file", return_value="report.html")
778
+ @patch("amd_debug.s2idle.get_report_format", return_value="html")
779
+ def test_prompt_report_arguments_success(
780
+ self, mock_get_report_format, mock_get_report_file, _mock_input
781
+ ):
782
+ """Test prompt_report_arguments with valid inputs"""
783
+ result = prompt_report_arguments(None, None, None, None, None)
784
+ self.assertEqual(result[0], datetime(2023, 1, 1))
785
+ self.assertEqual(result[1], datetime(2023, 2, 1))
786
+ self.assertEqual(result[2], "report.html")
787
+ self.assertEqual(result[3], "html")
788
+ mock_get_report_file.assert_called_once_with(None, "html")
789
+ mock_get_report_format.assert_called_once()
790
+
791
+ @patch(
792
+ "builtins.input",
793
+ side_effect=["invalid-date", "2023-01-01", "2023-02-01", "html", "true"],
794
+ )
795
+ @patch("sys.exit")
796
+ def test_prompt_report_arguments_invalid_since_date(self, mock_exit, mock_input):
797
+ """Test prompt_report_arguments with invalid 'since' date"""
798
+ mock_exit.side_effect = SystemExit
799
+ with self.assertRaises(SystemExit):
800
+ prompt_report_arguments(None, None, None, None, None)
801
+ mock_exit.assert_called_once_with(
802
+ "Invalid date, use YYYY-MM-DD: Invalid isoformat string: 'invalid-date'"
803
+ )
804
+
805
+ @patch(
806
+ "builtins.input",
807
+ side_effect=["2023-01-01", "invalid-date", "2023-02-01", "html", "true"],
808
+ )
809
+ @patch("sys.exit")
810
+ def test_prompt_report_arguments_invalid_until_date(self, mock_exit, mock_input):
811
+ """Test prompt_report_arguments with invalid 'until' date"""
812
+ mock_exit.side_effect = SystemExit
813
+ with self.assertRaises(SystemExit):
814
+ prompt_report_arguments(None, None, None, None, None)
815
+ mock_exit.assert_called_once_with(
816
+ "Invalid date, use YYYY-MM-DD: Invalid isoformat string: 'invalid-date'"
817
+ )
818
+
819
+ @patch(
820
+ "builtins.input",
821
+ side_effect=["2023-01-01", "2023-02-01", "invalid-format", "true"],
822
+ )
823
+ @patch("amd_debug.s2idle.get_report_format", return_value="html")
824
+ @patch("sys.exit")
825
+ def test_prompt_report_arguments_invalid_format(
826
+ self, mock_exit, mock_get_report_format, mock_input
827
+ ):
828
+ """Test prompt_report_arguments with invalid format"""
829
+ mock_exit.side_effect = SystemExit
830
+ with self.assertRaises(SystemExit):
831
+ prompt_report_arguments(None, None, None, None, None)
832
+ mock_exit.assert_called_once_with("Invalid format: invalid-format")
833
+ mock_get_report_format.assert_called_once()
834
+
835
+ @patch(
836
+ "builtins.input",
837
+ side_effect=["2023-01-01", "2023-02-01", "html", "foo_the_bar"],
838
+ )
839
+ @patch("amd_debug.s2idle.get_report_format", return_value="html")
840
+ @patch("sys.exit")
841
+ def test_prompt_report_arguments_invalid_report(
842
+ self, mock_exit, mock_get_report_format, mock_input
843
+ ):
844
+ """Test prompt_report_arguments with invalid format"""
845
+ mock_exit.side_effect = SystemExit
846
+ with self.assertRaises(SystemExit):
847
+ prompt_report_arguments(None, None, None, None, None)
848
+ mock_exit.assert_called_once_with("Invalid entry: Foo_the_bar")
849
+ mock_get_report_format.assert_called_once()
850
+
851
+ @patch("builtins.input", side_effect=["", "", "", ""])
852
+ @patch(
853
+ "amd_debug.s2idle.get_report_file",
854
+ return_value="amd-s2idle-report-2023-01-01.html",
855
+ )
856
+ @patch("amd_debug.s2idle.get_report_format", return_value="html")
857
+ def test_prompt_report_arguments_defaults(
858
+ self, mock_get_report_format, mock_get_report_file, mock_input
859
+ ):
860
+ """Test prompt_report_arguments with default values"""
861
+ result = prompt_report_arguments(None, None, None, None, None)
862
+ self.assertEqual(datetime.date(result[0]), Defaults.since)
863
+ self.assertEqual(datetime.date(result[1]), Defaults.until)
864
+ self.assertEqual(result[2], "amd-s2idle-report-2023-01-01.html")
865
+ self.assertEqual(result[3], "html")
866
+ self.assertEqual(result[4], True)
867
+ mock_get_report_file.assert_called_once_with(None, "html")
868
+ mock_get_report_format.assert_called()