amd-debug-tools 0.2.1__py3-none-any.whl → 0.2.3__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.

Potentially problematic release.


This version of amd-debug-tools might be problematic. Click here for more details.

test_s2idle.py CHANGED
@@ -381,6 +381,7 @@ class TestTestFunction(unittest.TestCase):
381
381
  "2023-02-01",
382
382
  "report.html",
383
383
  "html",
384
+ True,
384
385
  )
385
386
 
386
387
  mock_sleep_validator_instance = mock_sleep_validator.return_value
@@ -454,12 +455,18 @@ class TestTestFunction(unittest.TestCase):
454
455
 
455
456
  @patch("amd_debug.s2idle.Installer")
456
457
  @patch("amd_debug.s2idle.PrerequisiteValidator")
457
- @patch("amd_debug.prerequisites.SleepDatabase")
458
- @patch("amd_debug.validator.SleepDatabase")
458
+ @patch("amd_debug.s2idle.SleepValidator")
459
+ @patch("amd_debug.s2idle.SleepReport")
460
+ @patch("amd_debug.s2idle.prompt_test_arguments")
461
+ @patch("amd_debug.s2idle.prompt_report_arguments")
462
+ @patch("amd_debug.s2idle.display_report_file")
459
463
  def test_test_prerequisite_failure(
460
464
  self,
461
- _mock_sleep_db,
462
- _mock_sleep_db_prerequisite,
465
+ mock_display_report_file,
466
+ mock_prompt_report_arguments,
467
+ mock_prompt_test_arguments,
468
+ mock_sleep_report,
469
+ mock_sleep_validator,
463
470
  mock_prerequisite_validator,
464
471
  mock_installer,
465
472
  ):
@@ -470,6 +477,17 @@ class TestTestFunction(unittest.TestCase):
470
477
  mock_prerequisite_instance = mock_prerequisite_validator.return_value
471
478
  mock_prerequisite_instance.run.return_value = False
472
479
 
480
+ mock_prompt_test_arguments.return_value = (10, 5, 3)
481
+ mock_prompt_report_arguments.return_value = (
482
+ "2023-01-01",
483
+ "2023-02-01",
484
+ "report.html",
485
+ "html",
486
+ True,
487
+ )
488
+ mock_sleep_validator_instance = mock_sleep_validator.return_value
489
+ mock_sleep_report_instance = mock_sleep_report.return_value
490
+
473
491
  result = run_test_cycle(
474
492
  duration=None,
475
493
  wait=None,
@@ -491,7 +509,20 @@ class TestTestFunction(unittest.TestCase):
491
509
  mock_prerequisite_validator.assert_called_once_with(True)
492
510
  mock_prerequisite_instance.run.assert_called_once()
493
511
  mock_prerequisite_instance.report.assert_called_once()
494
- self.assertFalse(result)
512
+ mock_prompt_test_arguments.assert_called_once_with(None, None, None, False)
513
+ mock_prompt_report_arguments.assert_called_once()
514
+ mock_sleep_validator_instance.assert_not_called()
515
+ mock_sleep_report.assert_called_once_with(
516
+ since=None,
517
+ until=None,
518
+ fname="report.html",
519
+ fmt="html",
520
+ tool_debug=True,
521
+ report_debug=True,
522
+ )
523
+ mock_sleep_report_instance.run.assert_called_once()
524
+ mock_display_report_file.assert_called_once_with("report.html", "html")
525
+ self.assertTrue(result)
495
526
 
496
527
  @patch("amd_debug.s2idle.Installer")
497
528
  @patch("amd_debug.s2idle.PrerequisiteValidator")
@@ -532,9 +563,9 @@ class TestTestFunction(unittest.TestCase):
532
563
  "iasl", "ethtool", "edid-decode"
533
564
  )
534
565
  mock_installer_instance.install_dependencies.assert_called_once()
535
- mock_prerequisite_validator.assert_called_once_with(True)
536
- mock_prerequisite_instance.run.assert_called_once()
537
- mock_prerequisite_instance.report.assert_called_once()
566
+ mock_prerequisite_validator.assert_not_called()
567
+ mock_prerequisite_instance.run.assert_not_called()
568
+ mock_prerequisite_instance.report.assert_not_called()
538
569
  mock_prompt_test_arguments.assert_called_once_with(None, None, None, False)
539
570
 
540
571
 
@@ -605,6 +636,7 @@ class TestReportFunction(unittest.TestCase):
605
636
  "2023-02-01",
606
637
  "report.html",
607
638
  "html",
639
+ True,
608
640
  )
609
641
  mock_sleep_report_instance = mock_sleep_report.return_value
610
642
 
@@ -614,10 +646,12 @@ class TestReportFunction(unittest.TestCase):
614
646
  fname=None,
615
647
  fmt=None,
616
648
  tool_debug=True,
617
- report_debug=True,
649
+ report_debug=None,
618
650
  )
619
651
 
620
- mock_prompt_report_arguments.assert_called_once_with(None, None, None, None)
652
+ mock_prompt_report_arguments.assert_called_once_with(
653
+ None, None, None, None, None
654
+ )
621
655
  mock_sleep_report.assert_called_once_with(
622
656
  since="2023-01-01",
623
657
  until="2023-02-01",
@@ -640,10 +674,12 @@ class TestReportFunction(unittest.TestCase):
640
674
  fname=None,
641
675
  fmt=None,
642
676
  tool_debug=True,
643
- report_debug=True,
677
+ report_debug=None,
644
678
  )
645
679
 
646
- mock_prompt_report_arguments.assert_called_once_with(None, None, None, None)
680
+ mock_prompt_report_arguments.assert_called_once_with(
681
+ None, None, None, None, None
682
+ )
647
683
 
648
684
  @patch("amd_debug.s2idle.prompt_report_arguments")
649
685
  @patch(
@@ -659,6 +695,7 @@ class TestReportFunction(unittest.TestCase):
659
695
  "2023-02-01",
660
696
  "report.html",
661
697
  "html",
698
+ True,
662
699
  )
663
700
 
664
701
  result = report(
@@ -667,10 +704,12 @@ class TestReportFunction(unittest.TestCase):
667
704
  fname=None,
668
705
  fmt=None,
669
706
  tool_debug=True,
670
- report_debug=True,
707
+ report_debug=None,
671
708
  )
672
709
 
673
- mock_prompt_report_arguments.assert_called_once_with(None, None, None, None)
710
+ mock_prompt_report_arguments.assert_called_once_with(
711
+ None, None, None, None, None
712
+ )
674
713
  mock_sleep_report.assert_called_once_with(
675
714
  since="2023-01-01",
676
715
  until="2023-02-01",
@@ -695,6 +734,7 @@ class TestReportFunction(unittest.TestCase):
695
734
  "2023-02-01",
696
735
  "report.html",
697
736
  "html",
737
+ True,
698
738
  )
699
739
 
700
740
  result = report(
@@ -703,10 +743,12 @@ class TestReportFunction(unittest.TestCase):
703
743
  fname=None,
704
744
  fmt=None,
705
745
  tool_debug=True,
706
- report_debug=True,
746
+ report_debug=None,
707
747
  )
708
748
 
709
- mock_prompt_report_arguments.assert_called_once_with(None, None, None, None)
749
+ mock_prompt_report_arguments.assert_called_once_with(
750
+ None, None, None, None, None
751
+ )
710
752
  mock_sleep_report.assert_called_once_with(
711
753
  since="2023-01-01",
712
754
  until="2023-02-01",
@@ -729,6 +771,7 @@ class TestReportFunction(unittest.TestCase):
729
771
  "2023-02-01",
730
772
  "report.html",
731
773
  "html",
774
+ True,
732
775
  )
733
776
  mock_sleep_report_instance = mock_sleep_report.return_value
734
777
  mock_sleep_report_instance.run.side_effect = ValueError("Invalid value")
@@ -739,10 +782,12 @@ class TestReportFunction(unittest.TestCase):
739
782
  fname=None,
740
783
  fmt=None,
741
784
  tool_debug=True,
742
- report_debug=True,
785
+ report_debug=None,
743
786
  )
744
787
 
745
- mock_prompt_report_arguments.assert_called_once_with(None, None, None, None)
788
+ mock_prompt_report_arguments.assert_called_once_with(
789
+ None, None, None, None, None
790
+ )
746
791
  mock_sleep_report.assert_called_once_with(
747
792
  since="2023-01-01",
748
793
  until="2023-02-01",
@@ -758,14 +803,14 @@ class TestReportFunction(unittest.TestCase):
758
803
  class TestPromptReportArguments(unittest.TestCase):
759
804
  """Test prompt_report_arguments function"""
760
805
 
761
- @patch("builtins.input", side_effect=["2023-01-01", "2023-02-01", "html"])
806
+ @patch("builtins.input", side_effect=["2023-01-01", "2023-02-01", "html", "true"])
762
807
  @patch("amd_debug.s2idle.get_report_file", return_value="report.html")
763
808
  @patch("amd_debug.s2idle.get_report_format", return_value="html")
764
809
  def test_prompt_report_arguments_success(
765
810
  self, mock_get_report_format, mock_get_report_file, _mock_input
766
811
  ):
767
812
  """Test prompt_report_arguments with valid inputs"""
768
- result = prompt_report_arguments(None, None, None, None)
813
+ result = prompt_report_arguments(None, None, None, None, None)
769
814
  self.assertEqual(result[0], datetime(2023, 1, 1))
770
815
  self.assertEqual(result[1], datetime(2023, 2, 1))
771
816
  self.assertEqual(result[2], "report.html")
@@ -775,33 +820,36 @@ class TestPromptReportArguments(unittest.TestCase):
775
820
 
776
821
  @patch(
777
822
  "builtins.input",
778
- side_effect=["invalid-date", "2023-01-01", "2023-02-01", "html"],
823
+ side_effect=["invalid-date", "2023-01-01", "2023-02-01", "html", "true"],
779
824
  )
780
825
  @patch("sys.exit")
781
826
  def test_prompt_report_arguments_invalid_since_date(self, mock_exit, mock_input):
782
827
  """Test prompt_report_arguments with invalid 'since' date"""
783
828
  mock_exit.side_effect = SystemExit
784
829
  with self.assertRaises(SystemExit):
785
- prompt_report_arguments(None, None, None, None)
830
+ prompt_report_arguments(None, None, None, None, None)
786
831
  mock_exit.assert_called_once_with(
787
832
  "Invalid date, use YYYY-MM-DD: Invalid isoformat string: 'invalid-date'"
788
833
  )
789
834
 
790
835
  @patch(
791
836
  "builtins.input",
792
- side_effect=["2023-01-01", "invalid-date", "2023-02-01", "html"],
837
+ side_effect=["2023-01-01", "invalid-date", "2023-02-01", "html", "true"],
793
838
  )
794
839
  @patch("sys.exit")
795
840
  def test_prompt_report_arguments_invalid_until_date(self, mock_exit, mock_input):
796
841
  """Test prompt_report_arguments with invalid 'until' date"""
797
842
  mock_exit.side_effect = SystemExit
798
843
  with self.assertRaises(SystemExit):
799
- prompt_report_arguments(None, None, None, None)
844
+ prompt_report_arguments(None, None, None, None, None)
800
845
  mock_exit.assert_called_once_with(
801
846
  "Invalid date, use YYYY-MM-DD: Invalid isoformat string: 'invalid-date'"
802
847
  )
803
848
 
804
- @patch("builtins.input", side_effect=["2023-01-01", "2023-02-01", "invalid-format"])
849
+ @patch(
850
+ "builtins.input",
851
+ side_effect=["2023-01-01", "2023-02-01", "invalid-format", "true"],
852
+ )
805
853
  @patch("amd_debug.s2idle.get_report_format", return_value="html")
806
854
  @patch("sys.exit")
807
855
  def test_prompt_report_arguments_invalid_format(
@@ -810,11 +858,27 @@ class TestPromptReportArguments(unittest.TestCase):
810
858
  """Test prompt_report_arguments with invalid format"""
811
859
  mock_exit.side_effect = SystemExit
812
860
  with self.assertRaises(SystemExit):
813
- prompt_report_arguments(None, None, None, None)
861
+ prompt_report_arguments(None, None, None, None, None)
814
862
  mock_exit.assert_called_once_with("Invalid format: invalid-format")
815
863
  mock_get_report_format.assert_called_once()
816
864
 
817
- @patch("builtins.input", side_effect=["", "", ""])
865
+ @patch(
866
+ "builtins.input",
867
+ side_effect=["2023-01-01", "2023-02-01", "html", "foo_the_bar"],
868
+ )
869
+ @patch("amd_debug.s2idle.get_report_format", return_value="html")
870
+ @patch("sys.exit")
871
+ def test_prompt_report_arguments_invalid_report(
872
+ self, mock_exit, mock_get_report_format, mock_input
873
+ ):
874
+ """Test prompt_report_arguments with invalid format"""
875
+ mock_exit.side_effect = SystemExit
876
+ with self.assertRaises(SystemExit):
877
+ prompt_report_arguments(None, None, None, None, None)
878
+ mock_exit.assert_called_once_with("Invalid entry: Foo_the_bar")
879
+ mock_get_report_format.assert_called_once()
880
+
881
+ @patch("builtins.input", side_effect=["", "", "", ""])
818
882
  @patch(
819
883
  "amd_debug.s2idle.get_report_file",
820
884
  return_value="amd-s2idle-report-2023-01-01.html",
@@ -824,10 +888,11 @@ class TestPromptReportArguments(unittest.TestCase):
824
888
  self, mock_get_report_format, mock_get_report_file, mock_input
825
889
  ):
826
890
  """Test prompt_report_arguments with default values"""
827
- result = prompt_report_arguments(None, None, None, None)
891
+ result = prompt_report_arguments(None, None, None, None, None)
828
892
  self.assertEqual(datetime.date(result[0]), Defaults.since)
829
893
  self.assertEqual(datetime.date(result[1]), Defaults.until)
830
894
  self.assertEqual(result[2], "amd-s2idle-report-2023-01-01.html")
831
895
  self.assertEqual(result[3], "html")
896
+ self.assertEqual(result[4], True)
832
897
  mock_get_report_file.assert_called_once_with(None, "html")
833
898
  mock_get_report_format.assert_called()
test_sleep_report.py CHANGED
@@ -5,6 +5,7 @@
5
5
  This module contains unit tests for the s2idle tool in the amd-debug-tools package.
6
6
  """
7
7
 
8
+ import math
8
9
  import unittest
9
10
  from datetime import datetime
10
11
  from unittest.mock import patch
@@ -165,3 +166,31 @@ class TestSleepReport(unittest.TestCase):
165
166
  self.report.build_hw_sleep_chart()
166
167
  self.assertIsNotNone(self.report.hwsleep_svg)
167
168
  mock_savefig.assert_called_once()
169
+
170
+ def test_pre_process_dataframe_zero_duration(self):
171
+ """Test the pre_process_dataframe method when t0 and t1 are the same."""
172
+ # Mock the dataframe with t0 and t1 being the same
173
+ self.report.df = pd.DataFrame(
174
+ {
175
+ "t0": [datetime(2023, 10, 10, 12, 0, 0).strftime("%Y%m%d%H%M%S")],
176
+ "t1": [datetime(2023, 10, 10, 12, 0, 0).strftime("%Y%m%d%H%M%S")],
177
+ "hw": [50],
178
+ "requested": [1],
179
+ "gpio": ["1, 2"],
180
+ "wake_irq": ["1"],
181
+ "b0": [90],
182
+ "b1": [85],
183
+ "full": [100],
184
+ }
185
+ )
186
+
187
+ # Call the method
188
+ self.report.pre_process_dataframe()
189
+
190
+ # Verify the dataframe was processed correctly
191
+ self.assertTrue(
192
+ self.report.df["Duration"].isna().iloc[0]
193
+ ) # Duration should be NaN
194
+ self.assertTrue(
195
+ math.isnan(self.report.df["Hardware Sleep"].iloc[0])
196
+ ) # Hardware Sleep should be NaN
test_validator.py CHANGED
@@ -5,8 +5,9 @@
5
5
  This module contains unit tests for the validator functions in the amd-debug-tools package.
6
6
  """
7
7
 
8
- from unittest.mock import patch, mock_open
8
+ from unittest.mock import patch, mock_open, Mock
9
9
 
10
+ import os
10
11
  import logging
11
12
  import unittest
12
13
  import math
@@ -157,9 +158,8 @@ class TestValidator(unittest.TestCase):
157
158
  self.validator.capture_wake_sources()
158
159
 
159
160
  # Validate debug messages
160
- mock_record_debug.assert_any_call("Possible wakeup sources:")
161
161
  mock_record_debug.assert_any_call(
162
- "└─ [/sys/devices/pci0000:00/0000:00:14.0]: enabled"
162
+ "Wakeup Source|Linux Device|Status\n|/sys/devices/pci0000:00/0000:00:14.0|enabled\n"
163
163
  )
164
164
 
165
165
  # Stop patches
@@ -321,13 +321,11 @@ class TestValidator(unittest.TestCase):
321
321
  self.validator.lockdown = False
322
322
  with patch("os.path.exists", return_value=False), patch(
323
323
  "amd_debug.validator.read_file", side_effect=FileNotFoundError
324
- ), patch.object(
325
- self.validator.db, "record_cycle_data"
326
- ) as mock_record_cycle_data:
324
+ ), patch.object(self.validator.db, "record_debug") as mock_record:
327
325
  result = self.validator.capture_hw_sleep()
328
326
  self.assertFalse(result)
329
- mock_record_cycle_data.assert_called_once_with(
330
- "HW sleep statistics file missing", "❌"
327
+ mock_record.assert_called_once_with(
328
+ "HW sleep statistics file /sys/kernel/debug/amd_pmc/smu_fw_info is missing"
331
329
  )
332
330
 
333
331
  def test_capture_amdgpu_ips_status(self):
@@ -696,7 +694,7 @@ class TestValidator(unittest.TestCase):
696
694
  # Test case 3: Randomized test
697
695
  mock_randint.side_effect = [7, 3] # Random duration and wait
698
696
  self.validator.run(duration=10, count=1, wait=5, rand=True, logind=False)
699
- mock_randint.assert_any_call(1, 10)
697
+ mock_randint.assert_any_call(4, 10)
700
698
  mock_randint.assert_any_call(1, 5)
701
699
  mock_run_countdown.assert_any_call("Suspending system", math.ceil(3 / 2))
702
700
  mock_run_countdown.assert_any_call("Collecting data", math.ceil(3 / 2))
@@ -707,19 +705,128 @@ class TestValidator(unittest.TestCase):
707
705
  mock_report_cycle.assert_called()
708
706
  mock_unlock_session.assert_called()
709
707
 
710
- # Test case 4: Multiple cycles
708
+ # Test case 4: Randomized test, but too short of a duration
709
+ result = self.validator.run(
710
+ duration=4, count=1, wait=5, rand=True, logind=False
711
+ )
712
+ self.assertFalse(result)
713
+ mock_report_cycle.assert_called()
714
+
715
+ # Test case 5: Multiple cycles
711
716
  self.validator.run(duration=10, count=2, wait=5, rand=False, logind=False)
712
717
  self.assertEqual(mock_prep.call_count, 4) # Includes previous calls
713
718
  self.assertEqual(mock_program_wakealarm.call_count, 4)
714
719
  self.assertEqual(mock_suspend_system.call_count, 4)
715
720
  self.assertEqual(mock_post.call_count, 4)
716
- self.assertEqual(mock_report_cycle.call_count, 4)
721
+ self.assertEqual(mock_report_cycle.call_count, 5)
717
722
  self.assertEqual(mock_unlock_session.call_count, 3)
718
723
 
719
- # Test case 5: suspend_system fails
724
+ # Test case 6: suspend_system fails
720
725
  mock_suspend_system.return_value = False
721
726
  result = self.validator.run(
722
727
  duration=10, count=1, wait=5, rand=False, logind=False
723
728
  )
724
729
  self.assertFalse(result)
725
730
  mock_report_cycle.assert_called()
731
+
732
+ @patch("os.path.exists")
733
+ @patch("builtins.open", new_callable=mock_open, read_data="3")
734
+ @patch("os.write")
735
+ @patch("os.open")
736
+ @patch("os.close")
737
+ def test_suspend_system_sysfs_success(
738
+ self,
739
+ mock_os_close,
740
+ mock_os_open,
741
+ mock_os_write,
742
+ _mock_open_file,
743
+ mock_path_exists,
744
+ ):
745
+ """Test suspend_system method using sysfs interface with success"""
746
+ # Mock wakeup_count file existence
747
+ mock_path_exists.side_effect = lambda path: "wakeup_count" in path
748
+
749
+ # Mock os.open and os.write
750
+ mock_os_open.return_value = 3
751
+ mock_os_write.return_value = None
752
+
753
+ # Call the method
754
+ result = self.validator.suspend_system()
755
+
756
+ # Assert the method returned True
757
+ self.assertTrue(result)
758
+
759
+ # Assert os.open and os.write were called
760
+ mock_os_open.assert_called_once_with(
761
+ "/sys/power/state", os.O_WRONLY | os.O_SYNC
762
+ )
763
+ mock_os_write.assert_called_once_with(3, b"mem")
764
+ mock_os_close.assert_called_once_with(3)
765
+
766
+ @patch("os.path.exists")
767
+ @patch("builtins.open", new_callable=mock_open, read_data="3")
768
+ @patch("os.write")
769
+ @patch("os.open")
770
+ @patch("os.close")
771
+ def test_suspend_system_sysfs_failure(
772
+ self,
773
+ mock_os_close,
774
+ mock_os_open,
775
+ mock_os_write,
776
+ _mock_open_file,
777
+ mock_path_exists,
778
+ ):
779
+ """Test suspend_system method using sysfs interface with failure"""
780
+ # Mock wakeup_count file existence
781
+ mock_path_exists.side_effect = lambda path: "wakeup_count" in path
782
+
783
+ # Mock os.open to raise OSError
784
+ mock_os_open.return_value = 3
785
+ mock_os_write.side_effect = OSError("Failed to write to state")
786
+
787
+ # Call the method
788
+ result = self.validator.suspend_system()
789
+
790
+ # Assert the method returned False
791
+ self.assertFalse(result)
792
+
793
+ # Assert os.open and os.write were called
794
+ mock_os_open.assert_called_once_with(
795
+ "/sys/power/state", os.O_WRONLY | os.O_SYNC
796
+ )
797
+ mock_os_write.assert_called_once_with(3, b"mem")
798
+ mock_os_close.assert_called_once_with(3)
799
+
800
+ @patch("os.path.exists")
801
+ @patch("builtins.open", new_callable=mock_open)
802
+ @patch("os.write")
803
+ @patch("os.open")
804
+ @patch("os.close")
805
+ def test_suspend_system_sysfs_no_wakeup_count(
806
+ self,
807
+ mock_os_close,
808
+ mock_os_open,
809
+ mock_os_write,
810
+ _mock_open_file,
811
+ mock_path_exists,
812
+ ):
813
+ """Test suspend_system method using sysfs interface with no wakeup_count file"""
814
+ # Mock wakeup_count file does not exist
815
+ mock_path_exists.return_value = False
816
+
817
+ # Mock os.open and os.write
818
+ mock_os_open.return_value = 3
819
+ mock_os_write.return_value = None
820
+
821
+ # Call the method
822
+ result = self.validator.suspend_system()
823
+
824
+ # Assert the method returned True
825
+ self.assertTrue(result)
826
+
827
+ # Assert os.open and os.write were called
828
+ mock_os_open.assert_called_once_with(
829
+ "/sys/power/state", os.O_WRONLY | os.O_SYNC
830
+ )
831
+ mock_os_write.assert_called_once_with(3, b"mem")
832
+ mock_os_close.assert_called_once_with(3)