1# Copyright 2018 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import os
7import time
8from commands import getstatusoutput
9
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.common_lib.cros import chromedriver
12from autotest_lib.client.cros.graphics import graphics_utils
13
14
15class bluetooth_TurnOnOffUI(graphics_utils.GraphicsTest):
16
17    """Go to settings and turn on BT On/Off"""
18    version = 1
19    SETTINGS_UI_TAG = "settings-ui"
20    SHADOW_ROOT_JS = 'return arguments[0].shadowRoot'
21    SETTINGS_MAIN_CSS = 'settings-main#main'
22    SETTINGS_BASE_PAGE_CSS = 'settings-basic-page'
23    SETTINGS_BT_PAGE = "settings-bluetooth-page"
24    SETTINGS_URL = "chrome://settings"
25    ENABLE_BT_CSS = 'paper-toggle-button#enableBluetooth'
26    DELAY_BW_TOGGLE_ON_OFF = 3
27
28    def initialize(self):
29        """Autotest initialize function"""
30        super(bluetooth_TurnOnOffUI, self).initialize(raise_error_on_hang=True)
31
32    def cleanup(self):
33        """Autotest cleanup function"""
34        if self._GSC:
35            keyvals = self._GSC.get_memory_difference_keyvals()
36            for key, val in keyvals.iteritems():
37                self.output_perf_value(
38                    description=key,
39                    value=val,
40                    units='bytes',
41                    higher_is_better=False)
42            self.write_perf_keyval(keyvals)
43        super(bluetooth_TurnOnOffUI, self).cleanup()
44        # If test fails then script will collect the screen shot to know at
45        # which instance failure occurred.
46        if not self.success:
47            graphics_utils.take_screenshot(os.path.join(self.debugdir),
48                                           "chrome")
49
50    def open_settings(self, driver):
51        """Open Settings
52
53        @param driver: chrome driver object
54        @return: Returns settings page web element
55        """
56        logging.info("Opening settings.")
57        driver.get(self.SETTINGS_URL)
58        logging.debug("Current tab is %s", driver.title)
59        return self.settings_frame(driver)
60
61    def settings_frame(self, driver):
62        """Finds basic settings page web element
63
64        @param driver: chrome driver object
65        @return: Returns settings page web element
66        """
67        settings_ui = driver.find_element_by_tag_name(self.SETTINGS_UI_TAG)
68        settings_ui_shroot = driver.execute_script(self.SHADOW_ROOT_JS,
69                                                   settings_ui)
70        settings_main = settings_ui_shroot.find_element_by_css_selector(
71            self.SETTINGS_MAIN_CSS)
72        settings_basic_page = driver.execute_script(self.SHADOW_ROOT_JS,
73                                                    settings_main). \
74            find_element_by_css_selector(self.SETTINGS_BASE_PAGE_CSS)
75        return driver.execute_script(self.SHADOW_ROOT_JS, settings_basic_page)
76
77    def bluetooth_page(self, driver):
78        """BT settings page
79
80        @param driver: chrome driver object
81        @return: Bluetooth page web element
82        """
83        settings = self.open_settings(driver)
84        basic_page = settings.find_element_by_id('basicPage')
85        bt_device_page = basic_page.find_element_by_tag_name(
86            self.SETTINGS_BT_PAGE)
87        driver.execute_script('return arguments[0].scrollIntoView()',
88                              bt_device_page)
89        return driver.execute_script(self.SHADOW_ROOT_JS, bt_device_page)
90
91    def is_bluetooth_enabled(self):
92        """Returns True if BT is enabled otherwise False"""
93
94        status, output = getstatusoutput('hciconfig hci0')
95        if status:
96            raise error.TestError("Failed execute hciconfig")
97        return 'UP RUNNING' in output
98
99    def turn_on_bluetooth(self, bt_page):
100        """Turn on BT through UI
101
102        @param: bt_page:Bluetooth page web element
103        """
104        if self.is_bluetooth_enabled():
105            logging.info('Bluetooth is turned on already..')
106        else:
107            bt_page.find_element_by_css_selector(self.ENABLE_BT_CSS).click()
108            time.sleep(self.DELAY_BW_TOGGLE_ON_OFF)
109            if self.is_bluetooth_enabled():
110                logging.info('Turned on BT successfully..')
111            else:
112                raise error.TestFail('BT is not turned on..')
113
114    def turn_off_bluetooth(self, bt_page):
115        """Turn off BT through UI
116
117        @param: bt_page:Bluetooth page web element
118        """
119        if not self.is_bluetooth_enabled():
120            logging.info('Bluetooth is turned off already within time.')
121        else:
122            bt_page.find_element_by_css_selector(self.ENABLE_BT_CSS).click()
123            time.sleep(self.DELAY_BW_TOGGLE_ON_OFF)
124            if not self.is_bluetooth_enabled():
125                logging.info('Turned off BT successfully..')
126            else:
127                raise error.TestFail('Bluetooth is not turned off within time')
128
129    def run_once(self, iteration_count=3):
130        """Turn on/off bluetooth through UI
131
132        @param iteration_count: Number of iterations to toggle on/off
133
134        """
135        self.success = False
136        with chromedriver.chromedriver() as chromedriver_instance:
137            driver = chromedriver_instance.driver
138            bt_page = self.bluetooth_page(driver)
139            self.turn_off_bluetooth(bt_page)
140            for iteration in xrange(1, iteration_count + 1):
141                logging.info("**** Turn on/off BT iteration: %d ****",
142                             iteration)
143                self.turn_on_bluetooth(bt_page)
144                self.turn_off_bluetooth(bt_page)
145        self.success = True
146