• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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