1# Copyright 2023 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 7from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple 8 9from crossbench import helper 10from crossbench.runner.groups.base import RunGroup 11 12if TYPE_CHECKING: 13 from crossbench import exception 14 from crossbench.browsers.browser import Browser 15 from crossbench.probes.probe import Probe 16 from crossbench.probes.results import ProbeResult 17 from crossbench.runner.run import Run 18 from crossbench.runner.runner import Runner 19 from crossbench.stories.story import Story 20 from crossbench.types import JsonDict 21 22 23class CacheTemperaturesRunGroup(RunGroup): 24 """ 25 A group of Run objects with different cache temperatures for the same Story 26 with same browser and same repetition. 27 """ 28 29 @classmethod 30 def groups(cls, 31 runs: Iterable[Run], 32 throw: bool = False) -> Tuple[CacheTemperaturesRunGroup, ...]: 33 return tuple( 34 helper.group_by( 35 runs, 36 key=lambda run: (run.story, run.browser, run.repetition), 37 group=lambda _: cls(throw), 38 sort_key=None).values()) 39 40 def __init__(self, throw: bool = False): 41 super().__init__(throw) 42 self._runs: List[Run] = [] 43 self._story: Optional[Story] = None 44 self._browser: Optional[Browser] = None 45 self._repetition = -1 46 self._cache_temperature = "" 47 48 def append(self, run: Run) -> None: 49 if self._path is None: 50 self._set_path(run.group_dir) 51 self._story = run.story 52 self._browser = run.browser 53 self._repetition = run.repetition 54 assert self._story == run.story 55 assert self._path == run.group_dir 56 assert self._browser == run.browser 57 assert self._repetition == run.repetition 58 self._runs.append(run) 59 60 @property 61 def runs(self) -> Iterable[Run]: 62 return iter(self._runs) 63 64 @property 65 def repetition(self) -> int: 66 return self._repetition 67 68 @property 69 def story(self) -> Story: 70 assert self._story 71 return self._story 72 73 @property 74 def browser(self) -> Browser: 75 assert self._browser 76 return self._browser 77 78 @property 79 def info_stack(self) -> exception.TInfoStack: 80 return ( 81 "Merging results from multiple cache temperatures", 82 f"browser={self.browser.unique_name}", 83 f"story={self.story}", 84 f"repetition={self.repetition}", 85 ) 86 87 @property 88 def info(self) -> JsonDict: 89 info = { 90 "story": str(self.story), 91 "repetition": self.repetition, 92 } 93 info.update(super().info) 94 return info 95 96 def _merge_probe_results(self, probe: Probe) -> ProbeResult: 97 return probe.merge_cache_temperatures(self) 98