• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 unittest
9
10import hjson
11
12from crossbench import plt
13from crossbench.cli.config.driver import (AmbiguousDriverIdentifier,
14                                          BrowserDriverType, DriverConfig)
15from crossbench.exception import ArgumentTypeMultiException
16from crossbench.plt.chromeos_ssh import ChromeOsSshPlatform
17from tests import test_helper
18from tests.crossbench.cli.config.base import (ADB_DEVICES_OUTPUT,
19                                              XCTRACE_DEVICES_SINGLE_OUTPUT,
20                                              BaseConfigTestCase)
21
22
23class BrowserDriverTypeTestCase(unittest.TestCase):
24
25  def test_default(self):
26    self.assertEqual(BrowserDriverType.default(), BrowserDriverType.WEB_DRIVER)
27
28  def test_parse_invalid(self):
29    for invalid in ["invalid", None, [], (), {}]:
30      with self.assertRaises(argparse.ArgumentTypeError):
31        BrowserDriverType.parse(invalid)
32
33  def test_parse_str(self):
34    test_data = {
35        "": BrowserDriverType.default(),
36        "selenium": BrowserDriverType.WEB_DRIVER,
37        "webdriver": BrowserDriverType.WEB_DRIVER,
38        "applescript": BrowserDriverType.APPLE_SCRIPT,
39        "osa": BrowserDriverType.APPLE_SCRIPT,
40        "android": BrowserDriverType.ANDROID,
41        "adb": BrowserDriverType.ANDROID,
42        "iphone": BrowserDriverType.IOS,
43        "ios": BrowserDriverType.IOS,
44        "ssh": BrowserDriverType.LINUX_SSH,
45        "chromeos-ssh": BrowserDriverType.CHROMEOS_SSH,
46    }
47    for value, result in test_data.items():
48      self.assertEqual(BrowserDriverType.parse(value), result)
49
50  def test_parse_enum(self):
51    for driver_type in BrowserDriverType:
52      self.assertEqual(BrowserDriverType.parse(driver_type), driver_type)
53
54
55class DriverConfigTestCase(BaseConfigTestCase):
56
57  def test_default(self):
58    default = DriverConfig.default()
59    self.assertEqual(default.type, BrowserDriverType.WEB_DRIVER)
60    self.assertTrue(default.is_local)
61    self.assertFalse(default.is_remote)
62
63  def test_parse_invalid(self):
64    with self.assertRaises(argparse.ArgumentTypeError):
65      _ = DriverConfig.parse("")
66    with self.assertRaises(argparse.ArgumentTypeError):
67      _ = DriverConfig.parse(":")
68    with self.assertRaises(argparse.ArgumentTypeError):
69      _ = DriverConfig.parse("{:}")
70    with self.assertRaises(argparse.ArgumentTypeError):
71      _ = DriverConfig.parse("}")
72    with self.assertRaises(argparse.ArgumentTypeError):
73      _ = DriverConfig.parse("{")
74
75  def test_parse_driver_path_invalid(self):
76    driver_path = self.out_dir / "driver"
77    with self.assertRaises(argparse.ArgumentTypeError) as cm:
78      _ = DriverConfig.parse(str(driver_path))
79    self.assertIn(str(driver_path), str(cm.exception))
80
81    self.fs.create_file(driver_path)
82    with self.assertRaises(argparse.ArgumentTypeError) as cm:
83      _ = DriverConfig.parse(str(driver_path))
84    message = str(cm.exception)
85    self.assertIn(str(driver_path), message)
86    self.assertIn("empty", message)
87
88  def test_parse_driver_path(self):
89    chromedriver_path = self.out_dir / "chromedriver"
90    self.fs.create_file(chromedriver_path, st_size=100)
91    driver = DriverConfig.parse(str(chromedriver_path))
92    self.assertEqual(driver.path, chromedriver_path)
93
94    config = {"path": str(chromedriver_path)}
95    driver_2 = DriverConfig.parse(config)
96    self.assertEqual(driver_2.path, chromedriver_path)
97    self.assertEqual(driver, driver_2)
98
99  def test_parse_dict_device_id_conflict(self):
100    self.platform.sh_results = []
101    config_dict = {
102        "type": "adb",
103        "device_id": "1234",
104        "settings": {
105            "device_id": "ABCD"
106        }
107    }
108    with self.assertRaises(argparse.ArgumentTypeError) as cm:
109      DriverConfig.parse(config_dict)
110    self.assertIn("1234", str(cm.exception))
111    self.assertIn("ABCD", str(cm.exception))
112
113  def test_parse_dict_chromeos_ssh(self):
114    config_dict = {
115        "type": "chromeos-ssh",
116        "settings": {
117            "host": "chromeos6-row17-rack14-host7",
118            "port": "9515",
119            "ssh_port": "22",
120            "ssh_user": "root"
121        }
122    }
123    ssh_user = config_dict["settings"]["ssh_user"]
124    ssh_host = config_dict["settings"]["host"]
125    self.platform.expect_sh("ssh", "-p", config_dict["settings"]["ssh_port"],
126                            f"{ssh_user}@{ssh_host}",
127                            f"'[' -e {ChromeOsSshPlatform.AUTOLOGIN_PATH} ']'")
128    config = DriverConfig.parse(config_dict)
129    assert isinstance(config, DriverConfig)
130    self.assertEqual(config.type, BrowserDriverType.CHROMEOS_SSH)
131    self.assertTrue(config.is_remote)
132    self.assertFalse(config.is_local)
133    platform = config.get_platform()
134    assert isinstance(platform, ChromeOsSshPlatform)
135    self.assertEqual(platform.host, "chromeos6-row17-rack14-host7")
136    self.assertEqual(platform.port, 9515)
137    self.assertEqual(platform.ssh_port, 22)
138    self.assertEqual(platform.ssh_user, "root")
139
140  def test_parse_inline_json_adb(self):
141    self.platform.sh_results = [ADB_DEVICES_OUTPUT]
142    config_dict = {"type": "adb", "settings": {"device_id": "0a388e93"}}
143    config_1 = DriverConfig.parse(hjson.dumps(config_dict))
144    assert isinstance(config_1, DriverConfig)
145    self.assertEqual(config_1.type, BrowserDriverType.ANDROID)
146    self.assertEqual(config_1.device_id, "0a388e93")
147    self.assertEqual(config_1.settings["device_id"], "0a388e93")
148    self.assertTrue(config_1.is_remote)
149    self.assertFalse(config_1.is_local)
150    self.assertIsNone(config_1.adb_bin)
151
152    self.platform.sh_results = [ADB_DEVICES_OUTPUT]
153    config_2 = DriverConfig.parse_dict(config_dict)
154    assert isinstance(config_2, DriverConfig)
155    self.assertEqual(config_2.type, BrowserDriverType.ANDROID)
156    self.assertEqual(config_2.device_id, "0a388e93")
157    self.assertEqual(config_2.settings["device_id"], "0a388e93")
158    self.assertTrue(config_2.is_remote)
159    self.assertFalse(config_2.is_local)
160    self.assertIsNone(config_2.adb_bin)
161    self.assertEqual(config_1, config_2)
162
163    self.platform.sh_results = [ADB_DEVICES_OUTPUT]
164    config_dict = {"type": "adb", "device_id": "0a388e93"}
165    config_3 = DriverConfig.parse_dict(config_dict)
166    assert isinstance(config_3, DriverConfig)
167    self.assertEqual(config_3.type, BrowserDriverType.ANDROID)
168    self.assertEqual(config_3.device_id, "0a388e93")
169    self.assertTrue(config_3.is_remote)
170    self.assertFalse(config_3.is_local)
171    self.assertIsNone(config_3.settings)
172    self.assertIsNone(config_2.adb_bin)
173    self.assertNotEqual(config_1, config_3)
174    self.assertNotEqual(config_2, config_3)
175
176  def test_parse_custom_adb_bin(self):
177    adb_bin = self.out_dir / "adb"
178    self.platform.sh_results = [ADB_DEVICES_OUTPUT]
179    config_dict = {
180        "type": "adb",
181        "device_id": "0a388e93",
182        "adb_bin": str(adb_bin)
183    }
184    with self.assertRaises(argparse.ArgumentTypeError) as cm:
185      _ = DriverConfig.parse(hjson.dumps(config_dict))
186    self.assertIn(str(adb_bin), str(cm.exception))
187    self.fs.create_file(adb_bin, st_size=100)
188    config = DriverConfig.parse(hjson.dumps(config_dict))
189    assert isinstance(config, DriverConfig)
190    self.assertEqual(config.type, BrowserDriverType.ANDROID)
191    self.assertEqual(config.adb_bin, adb_bin)
192
193  def test_parse_adb_phone_identifier_unknown(self):
194    self.platform.sh_results = [ADB_DEVICES_OUTPUT]
195    if self.platform.is_macos:
196      self.platform.expect_sh(result=XCTRACE_DEVICES_SINGLE_OUTPUT)
197
198    with self.assertRaises(argparse.ArgumentTypeError) as cm:
199      _ = DriverConfig.parse("Unknown Device X")
200    self.assertIn("Unknown Device X", str(cm.exception))
201
202  def test_parse_adb_phone_identifier_multiple(self):
203    self.platform.sh_results = [ADB_DEVICES_OUTPUT]
204    with self.assertRaises(ArgumentTypeMultiException) as cm:
205      _ = DriverConfig.parse("emulator.*")
206    message: str = str(cm.exception)
207    self.assertIn("emulator-5554", message)
208    self.assertIn("emulator-5556", message)
209    self.assertTrue(len(cm.exception), 1)
210    self.assertTrue(cm.exception.matching(AmbiguousDriverIdentifier))
211    self.assertEqual(len(self.platform.sh_cmds), 1)
212
213  def test_parse_adb_phone_identifier(self):
214    self.platform.sh_results = [ADB_DEVICES_OUTPUT, ADB_DEVICES_OUTPUT]
215
216    config = DriverConfig.parse("Nexus_7")
217    assert isinstance(config, DriverConfig)
218    self.assertEqual(len(self.platform.sh_cmds), 2)
219
220    self.assertEqual(config.type, BrowserDriverType.ANDROID)
221    self.assertEqual(config.device_id, "0a388e93")
222    self.assertTrue(config.is_remote)
223    self.assertFalse(config.is_local)
224
225  def test_parse_adb_phone_serial(self):
226    self.platform.sh_results = [ADB_DEVICES_OUTPUT, ADB_DEVICES_OUTPUT]
227
228    config = DriverConfig.parse("0a388e93")
229    assert isinstance(config, DriverConfig)
230    self.assertEqual(len(self.platform.sh_cmds), 2)
231
232    self.assertEqual(config.type, BrowserDriverType.ANDROID)
233    self.assertEqual(config.device_id, "0a388e93")
234
235  @unittest.skipIf(not plt.PLATFORM.is_macos, "Incompatible platform")
236  def test_parse_ios_phone_serial(self):
237    self.platform.sh_results = [
238        ADB_DEVICES_OUTPUT, XCTRACE_DEVICES_SINGLE_OUTPUT,
239        XCTRACE_DEVICES_SINGLE_OUTPUT
240    ]
241
242    config = DriverConfig.parse("00001111-11AA22BB33DD")
243    assert isinstance(config, DriverConfig)
244    self.assertEqual(len(self.platform.sh_cmds), 3)
245
246    self.assertEqual(config.type, BrowserDriverType.IOS)
247    self.assertEqual(config.device_id, "00001111-11AA22BB33DD")
248
249
250if __name__ == "__main__":
251  test_helper.run_pytest(__file__)
252