Skip to content

Commit 20b9269

Browse files
kalutesV8 LUCI CQ
authored andcommitted
Add an optional teardown action block to pages
Add an optional teardown action block that is executed only after all playback iterations are complete. Change-Id: If3f3e3795df9e05f1ed193fb58a61f15d1179e93 Reviewed-on: https://chromium-review.googlesource.com/c/crossbench/+/6678071 Reviewed-by: Charles Dick <[email protected]> Commit-Queue: Kameron Lutes <[email protected]>
1 parent 0040119 commit 20b9269

File tree

7 files changed

+90
-27
lines changed

7 files changed

+90
-27
lines changed

crossbench/action_runner/base.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,22 @@ def info_stack(self) -> exception.TInfoStack:
8181
def bond(self) -> BondActionRunner:
8282
return BondActionRunner()
8383

84-
def teardown(self, run: Run) -> None:
85-
del run
84+
def teardown(self,
85+
run: Run,
86+
page: InteractivePage,
87+
teardown: Optional[ActionBlock] = None) -> None:
88+
if teardown:
89+
try:
90+
with exception.annotate("teardown"):
91+
self._info_stack = ("teardown",)
92+
teardown.run_with(self, run, page)
93+
except Exception:
94+
page.create_failure_artifacts(run, "failure")
95+
raise
96+
97+
self._teardown_impl()
98+
99+
def _teardown_impl(self) -> None:
86100
pass
87101

88102
def run_blocks(self, run: Run, page: InteractivePage,

crossbench/action_runner/default_action_runner.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,7 @@ def bond(self) -> BondActionRunner:
128128
return self._bond
129129

130130
@override
131-
def teardown(self, run: Run) -> None:
132-
del run
131+
def _teardown_impl(self) -> None:
133132
if self._bond:
134133
self._bond.teardown()
135134

crossbench/benchmarks/loading/config/page.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class PageConfig(ConfigObject):
3535
secrets: Secrets = Secrets()
3636
login: LoginBlock | None = None
3737
setup: ActionBlock | None = None
38+
teardown: Optional[ActionBlock] = None
3839
blocks: tuple[ActionBlock, ...] = tuple()
3940

4041
@classmethod
@@ -99,6 +100,7 @@ def config_parser(cls) -> ConfigParser[Self]:
99100
parser.add_argument("secrets", type=Secrets, default=Secrets())
100101
parser.add_argument("login", type=LoginBlock)
101102
parser.add_argument("setup", type=ActionBlock)
103+
parser.add_argument("teardown", type=ActionBlock)
102104
parser.add_argument(
103105
"blocks",
104106
aliases=("actions", "url", "urls"),

crossbench/benchmarks/loading/loading_benchmark.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,18 @@ def _story_from_config(cls, args: argparse.Namespace, config: PageConfig,
230230
if not config.blocks:
231231
return LivePage(label, config.first_url, duration, playback, tabs,
232232
args.about_blank_duration)
233-
return InteractivePage(label, config.blocks, config.setup, config.login,
234-
config.secrets, playback, tabs,
235-
args.about_blank_duration, args.run_login,
236-
args.run_setup)
233+
return InteractivePage(
234+
name=label,
235+
blocks=config.blocks,
236+
setup=config.setup,
237+
teardown=config.teardown,
238+
login=config.login,
239+
secrets=config.secrets,
240+
playback=playback,
241+
tabs=tabs,
242+
about_blank_duration=args.about_blank_duration,
243+
run_login=args.run_login,
244+
run_setup=args.run_setup)
237245

238246
@override
239247
def create_stories(self, separate: bool) -> Sequence[Page]:

crossbench/benchmarks/loading/page/interactive.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def __init__(self,
3232
name: str,
3333
blocks: tuple[ActionBlock, ...],
3434
setup: Optional[ActionBlock] = None,
35+
teardown: Optional[ActionBlock] = None,
3536
login: Optional[LoginBlock] = None,
3637
secrets: Optional[Secrets] = None,
3738
playback: PlaybackController = PlaybackController.default(),
@@ -47,6 +48,7 @@ def __init__(self,
4748
assert not any(block.is_login for block in blocks), (
4849
"No login blocks allowed as normal action block")
4950
self._setup_block = setup
51+
self._teardown_block: Optional[ActionBlock] = teardown
5052
self._login_block = login
5153
self._run_login = run_login
5254
self._run_setup = run_setup
@@ -62,6 +64,10 @@ def login_block(self) -> Optional[ActionBlock]:
6264
def setup_block(self) -> Optional[ActionBlock]:
6365
return self._setup_block
6466

67+
@property
68+
def teardown_block(self) -> Optional[ActionBlock]:
69+
return self._teardown_block
70+
6571
@property
6672
def blocks(self) -> tuple[ActionBlock, ...]:
6773
return self._blocks
@@ -102,7 +108,9 @@ def setup(self, run: Run) -> None:
102108
@override
103109
def teardown(self, run: Run) -> None:
104110
action_runner = get_action_runner(run)
105-
action_runner.teardown(run)
111+
run.browser.performance_mark("teardown-start", self._name)
112+
action_runner.teardown(run, self, self.teardown_block)
113+
run.browser.performance_mark("teardown-end", self._name)
106114

107115
def run_once(self, run: Run) -> None:
108116
action_runner = get_action_runner(run)

tests/crossbench/benchmarks/loading/config/test_page.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ def test_parse_action_sequence(self):
148148
self.assertEqual(config.first_url, "http://test.com/click")
149149
self.assertIsNone(config.login)
150150
self.assertIsNone(config.setup)
151+
self.assertIsNone(config.teardown)
151152
self.assertEqual(len(tuple(config.actions())), 2)
152153

153154
def test_parse_actions_dict(self):
@@ -163,6 +164,7 @@ def test_parse_actions_dict(self):
163164
config_1 = PageConfig.parse(config_data)
164165
self.assertIsNone(config_1.login)
165166
self.assertIsNone(config_1.setup)
167+
self.assertIsNone(config_1.teardown)
166168
self.assertEqual(config_1.first_url, "http://test.com/click")
167169
self.assertEqual(len(tuple(config_1.actions())), 2)
168170

@@ -185,6 +187,7 @@ def test_parse_login_block(self):
185187
login = config.login
186188
self.assertTrue(login.is_login)
187189
self.assertIsNone(config.setup)
190+
self.assertIsNone(config.teardown)
188191
self.assertFalse(config.blocks[0].is_login)
189192
self.assertEqual(config.first_url, "http://test.com/charts")
190193
self.assertEqual(len(config.blocks), 1)
@@ -207,6 +210,7 @@ def test_parse_setup_block(self):
207210
config = PageConfig.parse(config_data)
208211
self.assertEqual(len(config.login), 1)
209212
self.assertEqual(len(config.setup), 2)
213+
self.assertIsNone(config.teardown)
210214
self.assertEqual(len(config.blocks), 1)
211215
self.assertEqual(config.login.first_url, "http://test.com/login")
212216
self.assertEqual(config.setup.first_url, "http://test.com/setup")
@@ -224,6 +228,25 @@ def test_parse_login_block_preset(self):
224228
self.assertEqual(len(config.blocks), 1)
225229
self.assertEqual(len(tuple(config.actions())), 1)
226230

231+
def test_parse_teardown_block(self):
232+
config_data = {
233+
"actions": ["http://test.com/charts",],
234+
"teardown": [{
235+
"action": "get",
236+
"url": "http://test.com/teardown"
237+
}, {
238+
"action": "click",
239+
"selector": "#foo"
240+
}],
241+
}
242+
243+
config = PageConfig.parse(config_data)
244+
self.assertIsNone(config.setup)
245+
self.assertEqual(len(config.blocks), 1)
246+
self.assertEqual(config.blocks[0].first_url, "http://test.com/charts")
247+
self.assertEqual(len(config.teardown), 2)
248+
self.assertEqual(config.teardown.first_url, "http://test.com/teardown")
249+
227250

228251
if __name__ == "__main__":
229252
test_helper.run_pytest(__file__)

tests/crossbench/benchmarks/loading/test_loading.py

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,10 @@ def test_iteration_performance_marks_single_run(self):
221221

222222
for browser in self.browsers:
223223
# one mark for iteration start, one for iteration end
224-
self.assertEqual(len(browser.performance_marks), 2)
225-
self.assertEqual(browser.performance_marks[0],
226-
"crossbench-iteration-start")
227-
self.assertEqual(browser.performance_marks[1], "crossbench-iteration-end")
224+
self.assertListEqual(
225+
browser.performance_marks,
226+
["crossbench-iteration-start", "crossbench-iteration-end"] +
227+
["crossbench-teardown-start", "crossbench-teardown-end"] * 2)
228228

229229
def test_iteration_performance_marks_repeat_run(self):
230230
repeats: int = 3
@@ -237,13 +237,10 @@ def test_iteration_performance_marks_repeat_run(self):
237237
self._test_run(stories)
238238

239239
for browser in self.browsers:
240-
# one mark for iteration start, one for iteration end
241-
self.assertEqual(len(browser.performance_marks), 2 * repeats)
242-
for i in range(repeats):
243-
self.assertEqual(browser.performance_marks[i * 2],
244-
"crossbench-iteration-start")
245-
self.assertEqual(browser.performance_marks[(i * 2) + 1],
246-
"crossbench-iteration-end")
240+
self.assertListEqual(
241+
browser.performance_marks,
242+
(["crossbench-iteration-start", "crossbench-iteration-end"] * repeats)
243+
+ ["crossbench-teardown-start", "crossbench-teardown-end"] * 2)
247244

248245
def test_run_repeat_separate(self):
249246
url1 = "https://www.example.com/test1"
@@ -446,7 +443,7 @@ def test_actions_config(self):
446443
self.assertListEqual([url_1, url_2],
447444
browser.url_list[self.SPLASH_URLS_LEN:])
448445

449-
def multiple_pages_with_setup_blocks_config(self):
446+
def multiple_pages_with_setup_and_teardown_blocks_config(self):
450447
config = {
451448
"pages": {
452449
"first_page": {
@@ -457,7 +454,11 @@ def multiple_pages_with_setup_blocks_config(self):
457454
"actions": [{
458455
"action": "wait",
459456
"duration": "1s"
460-
}]
457+
}],
458+
"teardown": [{
459+
"action": "js",
460+
"script": "TEARDOWN ONE",
461+
}],
461462
},
462463
"second_page": {
463464
"setup": [{
@@ -467,18 +468,24 @@ def multiple_pages_with_setup_blocks_config(self):
467468
"actions": [{
468469
"action": "wait",
469470
"duration": "1s"
470-
}]
471+
}],
472+
"teardown": [{
473+
"action": "js",
474+
"script": "TEARDOWN TWO",
475+
}],
471476
}
472477
}
473478
}
474479
return config
475480

476-
def test_pages_with_multiple_setup_blocks(self):
481+
def test_pages_with_multiple_setup_and_teardown_blocks(self):
477482
for browser in self.browsers:
478483
browser.expect_js(JsInvocation(None, "SETUP ONE"))
479484
browser.expect_js(JsInvocation(None, "SETUP TWO"))
485+
browser.expect_js(JsInvocation(None, "TEARDOWN ONE"))
486+
browser.expect_js(JsInvocation(None, "TEARDOWN TWO"))
480487

481-
config = self.multiple_pages_with_setup_blocks_config()
488+
config = self.multiple_pages_with_setup_and_teardown_blocks_config()
482489
config_file = pathlib.Path("test/page_config.json")
483490
self.fs.create_file(config_file, contents=json.dumps(config))
484491
with self._patch_get_browser():
@@ -489,9 +496,11 @@ def test_pages_with_multiple_setup_blocks(self):
489496
self.assertEqual(
490497
browser.performance_marks,
491498
["crossbench-setup-start", "crossbench-setup-end"] * 2 + # 2 pages
492-
["crossbench-iteration-start", "crossbench-iteration-end"])
499+
["crossbench-iteration-start", "crossbench-iteration-end"] +
500+
["crossbench-teardown-start", "crossbench-teardown-end"] * 2)
493501
self.assertEqual(browser.performance_marks_details,
494-
["first_page"] * 2 + ["second_page"] * 2 + [None, None])
502+
["first_page"] * 2 + ["second_page"] * 2 + [None, None] +
503+
["first_page"] * 2 + ["second_page"] * 2)
495504

496505
def setup_expected_google_login_js(self):
497506
expected_scripts: list[JsInvocation] = [

0 commit comments

Comments
 (0)