1# Copyright 2024 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import inspect 6 7import crossbench.path as pth 8from crossbench.cli.config.probe import ProbeListConfig 9from crossbench.probes.all import GENERAL_PURPOSE_PROBES, INTERNAL_PROBES 10from crossbench.probes.debugger import DebuggerProbe 11from crossbench.probes.frequency import FrequencyProbe 12from crossbench.probes.dtrace import DTraceProbe 13from crossbench.probes.dump_html import DumpHtmlProbe 14from crossbench.probes.perfetto.perfetto import PerfettoProbe 15from crossbench.probes.perfetto.tracing import TracingProbe 16from crossbench.probes.performance_entries import PerformanceEntriesProbe 17from crossbench.probes.polling import ShellPollingProbe 18from crossbench.probes.power_sampler import PowerSamplerProbe 19from crossbench.probes.powermetrics import PowerMetricsProbe 20from crossbench.probes.probe import Probe 21from crossbench.probes.profiling.browser_profiling import BrowserProfilingProbe 22from crossbench.probes.profiling.system_profiling import ProfilingProbe 23from crossbench.probes.screenshot import ScreenshotProbe 24from crossbench.probes.system_stats import SystemStatsProbe 25from crossbench.probes.v8.builtins_pgo import V8BuiltinsPGOProbe 26from crossbench.probes.v8.log import V8LogProbe 27from crossbench.probes.v8.rcs import V8RCSProbe 28from crossbench.probes.v8.turbolizer import V8TurbolizerProbe 29from crossbench.probes.video import VideoProbe 30from crossbench.probes.web_page_replay.recorder import WebPageReplayProbe 31from tests import test_helper 32from tests.crossbench.base import CrossbenchFakeFsTestCase 33 34 35class ProbeListConfigTestCase(CrossbenchFakeFsTestCase): 36 37 def test_invalid_empty(self): 38 with self.assertRaises(ValueError) as cm: 39 ProbeListConfig.parse({"probes": ""}) 40 self.assertIn("str", str(cm.exception).lower()) 41 with self.assertRaises(ValueError) as cm: 42 ProbeListConfig.parse({"browsers": {}}) 43 self.assertIn("probes", str(cm.exception).lower()) 44 45 def test_empty(self): 46 probe_list = ProbeListConfig.parse({"probes": []}) 47 self.assertEqual(probe_list.probes, []) 48 probe_list = ProbeListConfig.parse({"probes": {}}) 49 self.assertEqual(probe_list.probes, []) 50 51 52class ProbeTestCase(CrossbenchFakeFsTestCase): 53 54 def probe_instances(self): 55 yield from self.internal_probe_instances() 56 yield from self.general_purpose_probe_instances() 57 58 def internal_probe_instances(self): 59 for probe_cls in self.internal_probe_classes(): 60 with self.subTest(probe_cls=probe_cls): 61 try: 62 yield probe_cls() 63 except GeneratorExit: 64 break 65 66 def general_purpose_probe_instances(self): 67 yield BrowserProfilingProbe() 68 yield DTraceProbe(pth.LocalPath("script.dtrace")) 69 yield DebuggerProbe(pth.LocalPath("debugger.bin")) 70 yield DumpHtmlProbe() 71 yield FrequencyProbe.from_config({}) 72 yield PerfettoProbe("textproto", pth.LocalPath("perfetto.bin")) 73 yield PerformanceEntriesProbe() 74 yield PowerMetricsProbe() 75 yield PowerSamplerProbe() 76 yield ProfilingProbe() 77 yield ScreenshotProbe() 78 yield ShellPollingProbe(cmd=["ls"]) 79 yield SystemStatsProbe() 80 yield TracingProbe() 81 yield V8BuiltinsPGOProbe() 82 yield V8LogProbe() 83 yield V8RCSProbe() 84 yield V8TurbolizerProbe() 85 yield VideoProbe() 86 yield WebPageReplayProbe(wpr_go_bin=self.create_file("wpr.go")) 87 88 def probe_classes(self): 89 yield from self.internal_probe_classes() 90 yield from self.general_purpose_probe_classes() 91 92 def all_probe_subclasses(self, probe_cls=Probe): 93 for probe_sub_cls in probe_cls.__subclasses__(): 94 if "Mock" in str(probe_sub_cls): 95 continue 96 if not inspect.isabstract(probe_sub_cls): 97 yield probe_sub_cls 98 yield from self.all_probe_subclasses(probe_sub_cls) 99 100 def internal_probe_classes(self): 101 for probe_cls in INTERNAL_PROBES: 102 with self.subTest(probe_cls=probe_cls): 103 try: 104 yield probe_cls 105 except GeneratorExit: 106 break 107 108 def general_purpose_probe_classes(self): 109 for probe_cls in GENERAL_PURPOSE_PROBES: 110 with self.subTest(probe_cls=probe_cls): 111 try: 112 yield probe_cls 113 except GeneratorExit: 114 break 115 116 def test_properties(self): 117 for probe_cls in self.internal_probe_classes(): 118 self.assertFalse(probe_cls.IS_GENERAL_PURPOSE) 119 for probe_cls in self.general_purpose_probe_classes(): 120 self.assertTrue(probe_cls.IS_GENERAL_PURPOSE) 121 for probe_cls in self.probe_classes(): 122 self.assertTrue(probe_cls.NAME) 123 124 def test_default_lists(self): 125 count = 0 126 for probe_cls in self.all_probe_subclasses(): 127 count += 1 128 if probe_cls.IS_GENERAL_PURPOSE: 129 self.assertIn(probe_cls, GENERAL_PURPOSE_PROBES) 130 self.assertGreater(count, 131 len(GENERAL_PURPOSE_PROBES) + len(INTERNAL_PROBES)) 132 133 def test_help(self): 134 for probe_cls in self.probe_classes(): 135 help_text = probe_cls.help_text() 136 self.assertTrue(help) 137 summary = probe_cls.summary_text() 138 self.assertTrue(summary) 139 self.assertIn(summary, help_text) 140 141 def test_config_parser(self): 142 for probe_cls in self.probe_classes(): 143 config_parser = probe_cls.config_parser() 144 self.assertEqual(config_parser.probe_cls, probe_cls) 145 146 def test_basic_probe_instances(self): 147 keys = set() 148 names = set() 149 for probe_instance in self.probe_instances(): 150 _ = hash(probe_instance) 151 key = probe_instance.key 152 self.assertIsInstance(key, tuple) 153 self.assertNotIn(key, keys) 154 keys.add(key) 155 self.assertTrue(probe_instance.name) 156 self.assertNotIn(probe_instance.name, names) 157 names.add(probe_instance.name) 158 159 def test_is_internal(self): 160 for probe_instance in self.internal_probe_instances(): 161 self.assertTrue(probe_instance.is_internal) 162 for probe_instance in self.general_purpose_probe_instances(): 163 self.assertFalse(probe_instance.is_internal) 164 165 def test_is_attached(self): 166 for probe_instance in self.general_purpose_probe_instances(): 167 self.assertFalse(probe_instance.is_attached) 168 169 170if __name__ == "__main__": 171 test_helper.run_pytest(__file__) 172