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 argparse 8import datetime as dt 9import unittest 10 11from crossbench.benchmarks.loading.config.login.google import GoogleLogin 12from crossbench.benchmarks.loading.config.page import PageConfig 13from tests import test_helper 14 15 16class PageConfigTestsCase(unittest.TestCase): 17 18 def test_parse_empty(self): 19 with self.assertRaises(argparse.ArgumentTypeError) as cm: 20 PageConfig.parse("") 21 self.assertIn("empty", str(cm.exception).lower()) 22 23 def test_parse_unknown_type(self): 24 with self.assertRaises(argparse.ArgumentTypeError) as cm: 25 PageConfig.parse(self) 26 self.assertIn("type", str(cm.exception)) 27 28 def test_parse_blank(self): 29 config = PageConfig.parse("about:blank") 30 self.assertIsNone(config.label) 31 self.assertEqual(config.any_label, "blank") 32 self.assertEqual(config.first_url, "about:blank") 33 34 def test_parse_file(self): 35 config = PageConfig.parse("file://foo/bar/custom.html") 36 self.assertIsNone(config.label) 37 self.assertEqual(config.any_label, "custom.html") 38 self.assertEqual(config.first_url, "file://foo/bar/custom.html") 39 40 def test_parse_url(self): 41 config = PageConfig.parse("http://www.a.com") 42 self.assertEqual(config.first_url, "http://www.a.com") 43 self.assertEqual(config.duration, dt.timedelta()) 44 self.assertIsNone(config.label) 45 self.assertEqual(config.any_label, "a.com") 46 47 def test_parse_url_ftp_invalid(self): 48 with self.assertRaises(argparse.ArgumentTypeError) as cm: 49 _ = PageConfig.parse("ftp://www.a.com") 50 self.assertIn("ftp", str(cm.exception)) 51 52 def test_parse_invalid_url(self): 53 for invalid in ("ssh://test.com/bar", "", "http://invalid host/"): 54 with self.subTest(url=invalid): 55 with self.assertRaises(argparse.ArgumentTypeError): 56 PageConfig.parse(invalid) 57 58 def test_parse_url_no_protocol(self): 59 config = PageConfig.parse("www.a.com") 60 self.assertEqual(config.duration, dt.timedelta()) 61 self.assertIsNone(config.label) 62 self.assertEqual(config.any_label, "a.com") 63 64 def test_parse_url_numbers(self): 65 config = PageConfig.parse("123.a.com") 66 self.assertEqual(config.first_url, "https://123.a.com") 67 self.assertEqual(config.duration, dt.timedelta()) 68 self.assertIsNone(config.label) 69 self.assertEqual(config.any_label, "123.a.com") 70 71 def test_parse_with_duration(self): 72 config = PageConfig.parse("http://news.b.com,123s") 73 self.assertEqual(config.first_url, "http://news.b.com") 74 self.assertEqual(config.duration.total_seconds(), 123) 75 self.assertIsNone(config.label) 76 self.assertEqual(config.any_label, "news.b.com") 77 78 def test_parse_invalid_multiple_urls(self): 79 with self.assertRaises(argparse.ArgumentTypeError): 80 PageConfig.parse("111.a.com,222.b.com") 81 with self.assertRaises(argparse.ArgumentTypeError): 82 PageConfig.parse("111s,222.b.com") 83 84 def test_parse_multiple_comma(self): 85 # duration splitting should happen in the caller 86 config = PageConfig.parse("www.b.com/foo?bar=a,b,c,d,123s") 87 self.assertEqual(config.first_url, "https://www.b.com/foo?bar=a,b,c,d") 88 self.assertEqual(config.duration.total_seconds(), 123) 89 self.assertIsNone(config.label) 90 self.assertEqual(config.any_label, "b.com") 91 92 def test_parse_invalid(self): 93 for invalid in ("", {}, [], None): 94 with self.subTest(invalid=invalid): 95 with self.assertRaises(argparse.ArgumentTypeError): 96 PageConfig.parse(invalid) 97 98 def test_parse_sequence_urls(self): 99 config_urls = [ 100 "http://test.com/0", 101 "http://test.com/0,123s", 102 ] 103 config_1 = PageConfig.parse(config_urls) 104 self.assertIsNone(config_1.login) 105 self.assertIsNone(config_1.label) 106 self.assertEqual(config_1.any_label, "test.com") 107 self.assertEqual(config_1.first_url, "http://test.com/0") 108 self.assertEqual(len(config_1.blocks), 1) 109 self.assertEqual(len(tuple(config_1.actions())), 2) 110 self.assertEqual(config_1.blocks[0].actions[0].url, "http://test.com/0") 111 self.assertEqual(config_1.blocks[0].actions[1].url, 112 "http://test.com/0,123s") 113 114 config_data = {"urls": config_urls} 115 config_2 = PageConfig.parse(config_data) 116 self.assertEqual(config_1, config_2) 117 config_data = {"actions": config_urls} 118 config_3 = PageConfig.parse(config_data) 119 self.assertEqual(config_1, config_3) 120 self.assertEqual(config_2, config_3) 121 122 def test_parse_sequence_preset_urls(self): 123 # Known url names only work at PageConfig level at this point. 124 config_urls = [ 125 "cnn", 126 ] 127 config = PageConfig.parse(config_urls) 128 self.assertIsNone(config.login) 129 self.assertIsNone(config.setup) 130 self.assertIsNone(config.label) 131 self.assertEqual(config.any_label, "cnn") 132 self.assertEqual(config.first_url, "https://cnn") 133 self.assertEqual(len(config.blocks), 1) 134 135 def test_parse_actions_no_get(self): 136 with self.assertRaises(argparse.ArgumentTypeError) as cm: 137 PageConfig.parse([{"action": "click", "selector": "#foo"}]) 138 self.assertIn("get", str(cm.exception)) 139 140 def test_parse_action_sequence(self): 141 config = PageConfig.parse([{ 142 "action": "get", 143 "url": "http://test.com/click" 144 }, { 145 "action": "click", 146 "selector": "#foo" 147 }]) 148 self.assertEqual(config.first_url, "http://test.com/click") 149 self.assertIsNone(config.login) 150 self.assertIsNone(config.setup) 151 self.assertEqual(len(tuple(config.actions())), 2) 152 153 def test_parse_actions_dict(self): 154 config_data = { 155 "actions": [{ 156 "action": "get", 157 "url": "http://test.com/click" 158 }, { 159 "action": "click", 160 "selector": "#foo" 161 }] 162 } 163 config_1 = PageConfig.parse(config_data) 164 self.assertIsNone(config_1.login) 165 self.assertIsNone(config_1.setup) 166 self.assertEqual(config_1.first_url, "http://test.com/click") 167 self.assertEqual(len(tuple(config_1.actions())), 2) 168 169 config_data = {"blocks": config_data["actions"]} 170 config_2 = PageConfig.parse(config_data) 171 self.assertEqual(config_1, config_2) 172 173 def test_parse_login_block(self): 174 config_data = { 175 "login": [{ 176 "action": "get", 177 "url": "http://test.com/login" 178 }, { 179 "action": "click", 180 "selector": "#foo" 181 }], 182 "urls": ["http://test.com/charts",] 183 } 184 config = PageConfig.parse(config_data) 185 login = config.login 186 self.assertTrue(login.is_login) 187 self.assertIsNone(config.setup) 188 self.assertFalse(config.blocks[0].is_login) 189 self.assertEqual(config.first_url, "http://test.com/charts") 190 self.assertEqual(len(config.blocks), 1) 191 self.assertEqual(len(tuple(config.actions())), 1) 192 self.assertEqual(len(login), 2) 193 self.assertEqual(login.actions[0].url, "http://test.com/login") 194 195 def test_parse_setup_block(self): 196 config_data = { 197 "login": ["http://test.com/login"], 198 "setup": [{ 199 "action": "get", 200 "url": "http://test.com/setup" 201 }, { 202 "action": "click", 203 "selector": "#foo" 204 }], 205 "actions": ["http://test.com/charts",] 206 } 207 config = PageConfig.parse(config_data) 208 self.assertEqual(len(config.login), 1) 209 self.assertEqual(len(config.setup), 2) 210 self.assertEqual(len(config.blocks), 1) 211 self.assertEqual(config.login.first_url, "http://test.com/login") 212 self.assertEqual(config.setup.first_url, "http://test.com/setup") 213 self.assertEqual(config.blocks[0].first_url, "http://test.com/charts") 214 215 def test_parse_login_block_preset(self): 216 config_data = {"login": "google", "urls": ["http://test.com/charts",]} 217 config = PageConfig.parse(config_data) 218 login = config.login 219 self.assertTrue(login.is_login) 220 self.assertIsInstance(login, GoogleLogin) 221 self.assertIsNone(config.setup) 222 self.assertFalse(config.blocks[0].is_login) 223 self.assertEqual(config.first_url, "http://test.com/charts") 224 self.assertEqual(len(config.blocks), 1) 225 self.assertEqual(len(tuple(config.actions())), 1) 226 227 228if __name__ == "__main__": 229 test_helper.run_pytest(__file__) 230