1# Copyright (c) 2013 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 json
6import logging
7import os
8import socket
9import time
10
11from autotest_lib.client.bin import test
12from autotest_lib.client.common_lib import error
13from autotest_lib.client.common_lib.cros import chromedriver
14from autotest_lib.client.cros.video import histogram_verifier
15
16import config_manager
17import test_utils
18
19#histogram fields to be verified
20MEDIA_GVD_INIT_STATUS = 'Cast.Sender.VideoEncodeAcceleratorInitializeSuccess'
21MEDIA_GVD_BUCKET = 1
22
23class desktopui_SonicExtension(test.test):
24    """Test loading the sonic extension through chromedriver."""
25    version = 1
26    wait_time = 5
27    dep = 'sonic_extension'
28
29    def _install_sonic_extension(self):
30        dep_dir = os.path.join(self.autodir, 'deps', self.dep)
31        logging.info('Installing sonic extension into %s', dep_dir)
32        self.job.install_pkg(self.dep, 'dep', dep_dir)
33        return dep_dir
34
35
36    def _check_manifest(self, extension_path):
37        """Checks the manifest for a public key.
38
39        The sonic extension is an autotest dependency and will get
40        installed through install_pkg as a component extension (with
41        a public key). Any other method of installation is supported
42        too, as long as it has a public key.
43
44        @param extension_path: A path to the directory of the extension
45            that contains a manifest.json.
46
47        @raises TestError: If the extension doesn't have a public key.
48        """
49        manifest_json_file = os.path.join(extension_path, 'manifest.json')
50        with open(manifest_json_file, 'r') as f:
51            manifest_json = json.loads(f.read())
52            if not manifest_json.get('key'):
53                raise error.TestError('Not a component extension, cannot '
54                                      'proceed with sonic test')
55
56
57    def initialize(self, test_config, sonic_hostname, sonic_build='00000',
58        extension_dir=None):
59        """Initialize the test.
60
61        @param extension_dir: Directory of a custom extension.
62            If one isn't supplied, the latest ToT extension is
63            downloaded and loaded into chromedriver.
64        @param live: Use a live url if True. Start a test server
65            and server a hello world page if False.
66        """
67        super(desktopui_SonicExtension, self).initialize()
68
69        if not extension_dir:
70            self._extension_dir = self._install_sonic_extension()
71        else:
72            self._extension_dir = extension_dir
73        if not os.path.exists(self._extension_dir):
74            raise error.TestError('Failed to install sonic extension.')
75        logging.info('extension: %s', self._extension_dir)
76        self._check_manifest(self._extension_dir)
77        self._test_utils_page = 'e2e_test_utils.html'
78        self._test_config = test_config
79        self._sonic_hostname = sonic_hostname
80        self._sonic_build = sonic_build
81        self._settings = config_manager.ConfigurationManager(
82                self._test_config).get_config_settings()
83        self._test_utils = test_utils.TestUtils()
84
85
86    def cleanup(self):
87        """Clean up the test environment, e.g., stop local http server."""
88        super(desktopui_SonicExtension, self).cleanup()
89
90    def _get_run_information(self, driver, settings):
91        """Get all the information about the test run.
92
93        @param driver: The webdriver instance of the test
94        @param settings: The settings and information about the test
95        @return A json that contains all the different information
96            about the test run
97        """
98        information = {}
99        if 'machine_name' in settings:
100            information['machine_name'] = settings['machine_name']
101        else:
102            information['machine_name'] = socket.gethostname()
103        information['network_profile'] = settings['network_profile']
104        information['chrome_version'] = self._test_utils.get_chrome_version(
105                driver)
106        information['chrome_revision'] = self._test_utils.get_chrome_revision(
107                driver)
108        information['sonic_build'] = self._sonic_build
109        information['video_name'] = settings.get('video_name',
110                                                 settings['video_site'])
111        information['comments'] = settings['comments']
112        return information
113
114    def run_once(self):
115        """Run the test code."""
116        # TODO: When we've cloned the sonic test repo get these from their
117        # test config files.
118        logging.info('Starting sonic client test.')
119        kwargs = {
120            'extension_paths': [self._extension_dir],
121            'is_component': True,
122            'extra_chrome_flags': [self._settings['extra_flags']],
123        }
124        with chromedriver.chromedriver(**kwargs) as chromedriver_instance:
125            driver = chromedriver_instance.driver
126            extension = chromedriver_instance.get_extension(
127                    self._extension_dir)
128            extension_id = extension.extension_id
129            time.sleep(self.wait_time)
130            self._test_utils.close_popup_tabs(driver)
131            self._test_utils.block_setup_dialog(driver, extension_id)
132            test_info = self._get_run_information(driver, self._settings)
133            logging.info('Starting tabcast to extension: %s', extension_id)
134            self._test_utils.set_mirroring_options(
135                    driver, extension_id, self._settings)
136            current_tab_handle = driver.current_window_handle
137            self._test_utils.start_v2_mirroring_test_utils(
138                    driver, extension_id, self._sonic_hostname,
139                    self._settings['video_site'],
140                    self._settings['full_screen'] == 'on')
141            self._test_utils.set_focus_tab(driver, current_tab_handle)
142            driver.switch_to_window(current_tab_handle)
143            cpu_usage = self._test_utils.cpu_usage_interval(
144                    int(self._settings['mirror_duration']))
145            self._test_utils.stop_v2_mirroring_test_utils(driver, extension_id)
146            crash_id = self._test_utils.upload_v2_mirroring_logs(
147                    driver, extension_id)
148            test_info['crash_id'] = crash_id
149            if self._settings.get('sender_root_dir'):
150                cpu_bound = self._test_utils.compute_cpu_utilization(cpu_usage)
151                info_json_file = os.path.join(self._settings['sender_root_dir'],
152                                              'test_information.json')
153                cpu_json_file = os.path.join(
154                        self._settings['sender_root_dir'], 'cpu_data.json')
155                cpu_bound_json_file = os.path.join(
156                        self._settings['sender_root_dir'], 'cpu_bound.json')
157                json.dump(test_info, open(info_json_file, 'wb'))
158                json.dump(cpu_usage, open(cpu_json_file, 'wb'))
159                json.dump(cpu_bound, open(cpu_bound_json_file, 'wb'))
160            time.sleep(self.wait_time)
161            #To cehck encoder acceleration used while casting
162            histogram_verifier.verify(
163                 chromedriver_instance.chrome_instance,
164                 MEDIA_GVD_INIT_STATUS, MEDIA_GVD_BUCKET)
165