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 argparse 6import copy 7import csv 8 9from crossbench.benchmarks.loading.page.live import LivePage 10from crossbench.benchmarks.loading.tab_controller import TabController 11from crossbench.benchmarks.memory.memory_benchmark import ( 12 MemoryBenchmark, MemoryBenchmarkStoryFilter, MemoryProbe) 13from crossbench.env import HostEnvironmentConfig, ValidationMode 14from crossbench.runner.runner import Runner 15from tests import test_helper 16from tests.crossbench.benchmarks import helper 17 18 19class MemoryBenchmarkTestCase(helper.BaseBenchmarkTestCase): 20 21 @property 22 def benchmark_cls(self): 23 return MemoryBenchmark 24 25 @property 26 def story_cls(self): 27 return MemoryBenchmarkStoryFilter 28 29 @property 30 def probe_cls(self): 31 return MemoryProbe 32 33 def _create_stories(self, tab_count): 34 args = argparse.Namespace( 35 alloc_count=8, 36 prefill_constant=8, 37 compressibility=50, 38 random_per_page=False, 39 block_size=128, 40 tabs=TabController.repeat(tab_count)) 41 stories = self.story_cls.stories_from_cli_args(args=args) 42 return stories 43 44 def test_story(self): 45 stories = self._create_stories(tab_count=2) 46 self.assertEqual(len(stories), 1) 47 story = stories[0] 48 self.assertIsInstance(story, LivePage) 49 expected_url = ("https://chromium-workloads.web.app/web-tests/main/" 50 "synthetic/memory?alloc=8&blocksize=128&compress=50" 51 "&prefill=8&randomperpage=false") 52 self.assertEqual(story.first_url, expected_url) 53 names = set(story.name for story in stories) 54 self.assertEqual(len(names), len(stories)) 55 56 def test_run_throw(self): 57 self._test_run(throw=True) 58 59 def test_run_default(self): 60 self._test_run() 61 62 def _test_run(self, throw: bool = False): 63 tab_count = 2 64 repetitions = 2 65 stories = self._create_stories(tab_count=tab_count) 66 for _ in range(repetitions): 67 for _ in stories: 68 for browser in self.browsers: 69 # Record navigation time 70 browser.expect_js(result="1000") 71 browser.expect_js(result="1001") 72 for browser in self.browsers: 73 browser.expected_js = copy.deepcopy(browser.expected_js) 74 75 benchmark = self.benchmark_cls(stories, skippable_tab_count=2) 76 self.assertTrue(len(benchmark.describe()) > 0) 77 runner = Runner( 78 self.out_dir, 79 self.browsers, 80 benchmark, 81 env_config=HostEnvironmentConfig(), 82 env_validation_mode=ValidationMode.SKIP, 83 platform=self.platform, 84 repetitions=repetitions, 85 throw=throw) 86 87 runner.run() 88 assert runner.is_success 89 story_urls = [story.first_url for story in stories] 90 for browser in self.browsers: 91 urls = self.filter_splashscreen_urls(browser.url_list) 92 self.assertEqual(len(urls), repetitions * tab_count) 93 self.assertEqual(story_urls * repetitions * tab_count, urls) 94 self.assertEqual(len(browser.tab_list) - 1, repetitions * tab_count) 95 self.assertEqual(browser.tab_list, [0, 1, 2, 3, 4]) 96 97 with (self.out_dir / 98 f"{self.probe_cls.NAME}.csv").open(encoding="utf-8") as f: 99 csv_data = list(csv.DictReader(f, delimiter="\t")) 100 self.assertListEqual( 101 list(csv_data[0].keys()), ["label", "", "dev", "stable"]) 102 self.assertDictEqual( 103 csv_data[1], 104 { 105 "label": "version", 106 "dev": "102.22.33.44", 107 "stable": "100.22.33.44", 108 # One padding element (after "label"): 109 "": "", 110 }) 111 112 with self.assertLogs(level="INFO") as cm: 113 for probe in runner.probes: 114 for run in runner.runs: 115 probe.log_run_result(run) 116 output = "\n".join(cm.output) 117 self.assertIn("Memory results", output) 118 self.assertIn(f"Score {tab_count}", output) 119 120 with self.assertLogs(level="INFO") as cm: 121 for probe in runner.probes: 122 probe.log_browsers_result(runner.browser_group) 123 output = "\n".join(cm.output) 124 self.assertIn("Memory results", output) 125 self.assertIn("102.22.33.44", output) 126 self.assertIn("100.22.33.44", output) 127 128 129if __name__ == "__main__": 130 test_helper.run_pytest(__file__) 131