Home | History | Annotate | Download | only in network_WiFi_BluetoothStreamPerf
      1 # Copyright 2015 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 import logging
      5 import time
      6 
      7 
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.client.common_lib.cros.network import ping_runner
     10 from autotest_lib.client.common_lib.cros.network import xmlrpc_datatypes
     11 from autotest_lib.client.cros.chameleon import chameleon_audio_helper
     12 from autotest_lib.client.cros.chameleon import chameleon_audio_ids
     13 from autotest_lib.server.cros.audio import audio_test
     14 from autotest_lib.server.cros.multimedia import remote_facade_factory
     15 from autotest_lib.server.cros.network import netperf_runner
     16 from autotest_lib.server.cros.network import netperf_session
     17 from autotest_lib.server.cros.network import wifi_cell_test_base
     18 
     19 
     20 class network_WiFi_BluetoothStreamPerf(wifi_cell_test_base.WiFiCellTestBase):
     21     """Test maximal achievable bandwidth on several channels per band.
     22 
     23     Conducts a performance test for a set of specified router configurations
     24     and reports results as keyval pairs.
     25 
     26     """
     27 
     28     version = 1
     29 
     30     NETPERF_CONFIGS = [
     31             netperf_runner.NetperfConfig(
     32                        netperf_runner.NetperfConfig.TEST_TYPE_TCP_STREAM),
     33             netperf_runner.NetperfConfig(
     34                        netperf_runner.NetperfConfig.TEST_TYPE_TCP_MAERTS),
     35             netperf_runner.NetperfConfig(
     36                        netperf_runner.NetperfConfig.TEST_TYPE_UDP_STREAM),
     37             netperf_runner.NetperfConfig(
     38                        netperf_runner.NetperfConfig.TEST_TYPE_UDP_MAERTS),
     39     ]
     40 
     41 
     42     def parse_additional_arguments(self, commandline_args, additional_params):
     43         """Hook into super class to take control files parameters.
     44 
     45         @param commandline_args dict of parsed parameters from the autotest.
     46         @param additional_params list of HostapConfig objects.
     47 
     48         """
     49         self._ap_configs = additional_params
     50 
     51 
     52     def test_one(self, session, config, ap_config_tag, bt_tag):
     53         """Run one iteration of wifi testing.
     54 
     55         @param session NetperfSession session
     56         @param config NetperfConfig config
     57         @param ap_config_tag string for AP configuration
     58         @param bt_tag string for BT operation
     59 
     60         """
     61         get_ping_config = lambda period: ping_runner.PingConfig(
     62                 self.context.get_wifi_addr(), interval=1, count=period)
     63 
     64         logging.info('testing config %s, ap_config %s, BT:%s',
     65                      config.tag, ap_config_tag, bt_tag)
     66         test_str = '_'.join([ap_config_tag, bt_tag])
     67         time.sleep(1)
     68 
     69         # Record the signal level.
     70         signal_level = self.context.client.wifi_signal_level
     71         signal_description = '_'.join(['signal', test_str])
     72         self.write_perf_keyval({signal_description: signal_level})
     73 
     74         # Run netperf and log the results.
     75         results = session.run(config)
     76         if not results:
     77             logging.error('Failed to take measurement for %s',
     78                           config.tag)
     79             return
     80         values = [result.throughput for result in results]
     81         self.output_perf_value(config.tag + '_' + bt_tag, values, units='Mbps',
     82                                higher_is_better=True,
     83                                graph=ap_config_tag)
     84         result = netperf_runner.NetperfResult.from_samples(results)
     85         self.write_perf_keyval(result.get_keyval(
     86             prefix='_'.join([config.tag, test_str])))
     87 
     88         # Log the drop in throughput compared with the 'BT_disconnected'
     89         # baseline.  Only positive values are valid.  Report the drop as a
     90         # whole integer percentage of (base_through-through)/base_through.
     91         if bt_tag == 'BT_disconnected':
     92             self.base_through = result.throughput
     93         elif self.base_through > 0:
     94             drop = int( (self.base_through - result.throughput) * 100 /
     95                         self.base_through)
     96             self.output_perf_value(config.tag + '_' + bt_tag + '_drop',
     97                                    drop, units='percent_drop',
     98                                    higher_is_better=False,
     99                                    graph=ap_config_tag + '_drop')
    100             self.write_perf_keyval({'_'.join([config.tag, test_str, 'drop']):
    101                                    drop})
    102             logging.info('logging drop value as %d%%', drop)
    103 
    104         # Test latency with ping.
    105         result_ping = self.context.client.ping(get_ping_config(3))
    106         self.write_perf_keyval(
    107             { '_'.join(['ping', test_str]): result_ping.avg_latency })
    108         logging.info('Ping statistics with %s: %r', bt_tag, result_ping)
    109 
    110 
    111 
    112     def run_once(self, host):
    113         """Test body."""
    114         start_time = time.time()
    115 
    116         # Setup Bluetooth widgets and their binder, but do not yet connect.
    117         audio_test.audio_test_requirement()
    118         factory = remote_facade_factory.RemoteFacadeFactory(
    119                 host, results_dir=self.resultsdir)
    120         chameleon_board = host.chameleon
    121         if chameleon_board is None:
    122             raise error.TestNAError("No chameleon device is present")
    123 
    124         chameleon_board.setup_and_reset(self.outputdir)
    125         widget_factory = chameleon_audio_helper.AudioWidgetFactory(
    126                 factory, host)
    127         source = widget_factory.create_widget(
    128             chameleon_audio_ids.CrosIds.BLUETOOTH_HEADPHONE)
    129         bluetooth_widget = widget_factory.create_widget(
    130             chameleon_audio_ids.PeripheralIds.BLUETOOTH_DATA_RX)
    131         binder = widget_factory.create_binder(
    132                 source, bluetooth_widget)
    133         audio_test_file = 'http://commondatastorage.googleapis.com/' \
    134                           'chromiumos-test-assets-public/audio_test/' \
    135                           'chameleon/Headphone/test_256_16.mp3'
    136 
    137 
    138         for ap_config in self._ap_configs:
    139             # Set up the router and associate the client with it.
    140             self.context.configure(ap_config)
    141             assoc_params = xmlrpc_datatypes.AssociationParameters(
    142                     ssid=self.context.router.get_ssid(),
    143                     security_config=ap_config.security_config)
    144             self.context.assert_connect_wifi(assoc_params)
    145             session = netperf_session.NetperfSession(self.context.client,
    146                                                      self.context.router)
    147             session.MEASUREMENT_MAX_SAMPLES = 6.
    148 
    149 
    150             # Warmup the wifi path and measure signal.
    151             session.warmup_stations()
    152             ap_config_tag = ap_config.perf_loggable_description
    153 
    154             for config in self.NETPERF_CONFIGS:
    155                 self.base_through = 0
    156                 self.test_one(session, config, ap_config_tag, 'BT_disconnected')
    157                 with chameleon_audio_helper.bind_widgets(binder):
    158                     self.test_one(session, config, ap_config_tag,
    159                                   'BT_connected_but_not_streaming')
    160                     logging.info('Playing an audio test file')
    161                     browser_facade = factory.create_browser_facade()
    162                     browser_facade.new_tab(audio_test_file)
    163                     self.test_one(session, config, ap_config_tag,
    164                                   'BT_streaming_audiofile')
    165                 self.test_one(session, config, ap_config_tag,
    166                               'BT_disconnected_again')
    167 
    168             # Clean up router and client state for the next run.
    169             self.context.client.shill.disconnect(self.context.router.get_ssid())
    170             self.context.router.deconfig()
    171 
    172         end_time = time.time()
    173         logging.info('Running time %0.1f seconds.', end_time - start_time)
    174 
    175