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 5from __future__ import annotations 6 7import datetime as dt 8 9import os 10from typing import List, Optional 11 12from crossbench.path import AnyPath 13from crossbench.probes.probe import Probe, ProbeConfigParser 14from crossbench.probes.probe_context import ProbeContext 15from crossbench.probes.result_location import ResultLocation 16from crossbench.probes.results import EmptyProbeResult, ProbeResult 17from crossbench.runner.groups.browsers import BrowsersRunGroup 18from crossbench.runner.groups.repetitions import RepetitionsRunGroup 19from crossbench.runner.run import Run 20 21 22class DumpHtmlProbe(Probe): 23 """ 24 General-purpose Probe that collects HTML dumps. 25 """ 26 NAME = "dump_html" 27 RESULT_LOCATION = ResultLocation.LOCAL 28 29 @classmethod 30 def config_parser(cls) -> ProbeConfigParser: 31 parser = super().config_parser() 32 # TODO: support stop dumps 33 return parser 34 35 def get_context(self, run: Run) -> DumpHtmlProbeContext: 36 return DumpHtmlProbeContext(self, run) 37 38 def merge_repetitions(self, group: RepetitionsRunGroup) -> ProbeResult: 39 # TODO: implement 40 return EmptyProbeResult() 41 42 def merge_browsers(self, group: BrowsersRunGroup) -> ProbeResult: 43 # TODO: implement 44 return EmptyProbeResult() 45 46 47class DumpHtmlProbeContext(ProbeContext[DumpHtmlProbe]): 48 49 def __init__(self, probe: DumpHtmlProbe, run: Run) -> None: 50 super().__init__(probe, run) 51 self._results: List[AnyPath] = [] 52 53 def get_default_result_path(self) -> AnyPath: 54 dump_dir = super().get_default_result_path() 55 os.mkdir(dump_dir) 56 return dump_dir 57 58 def start(self) -> None: 59 pass 60 61 def stop(self) -> None: 62 pass 63 64 def dump_html(self, label: Optional[str] = None) -> None: 65 if not label: 66 label = str(dt.datetime.now().strftime("%Y-%m-%d_%H%M%S")) 67 path = self.result_path / f"{label}.html" 68 html = self.browser.js("return document.children[0].outerHTML", 69 dt.timedelta(seconds=10)) 70 with open(path, "w", encoding="utf-8") as dump_file: 71 dump_file.write(html) 72 self._results.append(path) 73 74 def teardown(self) -> ProbeResult: 75 if not self.browser_platform.is_dir(self.result_path): 76 return EmptyProbeResult() 77 return self.browser_result(file=tuple(self._results)) 78