1# Lint as: python2, python3
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""A Batch of Bluetooth Multiple Devices health tests"""
7
8import time
9from autotest_lib.server.cros.bluetooth.bluetooth_adapter_quick_tests import \
10     BluetoothAdapterQuickTests
11from autotest_lib.server.cros.bluetooth.bluetooth_adapter_hidreports_tests \
12     import BluetoothAdapterHIDReportTests
13
14class bluetooth_AdapterMDHealth(BluetoothAdapterQuickTests,
15                                BluetoothAdapterHIDReportTests):
16    """A Batch of Bluetooth multiple devices health tests. This test is written
17       as a batch of tests in order to reduce test time, since auto-test ramp up
18       time is costy. The batch is using BluetoothAdapterQuickTests wrapper
19       methods to start and end a test and a batch of tests.
20
21       This class can be called to run the entire test batch or to run a
22       specific test only
23    """
24
25    test_wrapper = BluetoothAdapterQuickTests.quick_test_test_decorator
26    batch_wrapper = BluetoothAdapterQuickTests.quick_test_batch_decorator
27
28
29    def discover_and_pair(self, device):
30        """ Discovers and pairs given device. Automatically connects too.
31
32        @param device: meta object for bt peer device
33        """
34        self.test_discover_device(device.address)
35        time.sleep(self.TEST_SLEEP_SECS)
36        self.test_pairing(device.address, device.pin, trusted=True)
37        time.sleep(self.TEST_SLEEP_SECS)
38        self.test_connection_by_adapter(device.address)
39
40
41    def pair_and_test_connection(self, devtuples):
42        """ Tests connection and pairing with multiple devices
43
44        @param devtuples: array of tuples consisting of the following:
45            * device: meta object for peer device
46            * device_test: Optional; test function to run w/
47                           device (eg. mouse click)
48        """
49        try:
50            for device, _ in devtuples:
51                self.discover_and_pair(device)
52
53            # Sleep for a few seconds to give HID controllers time to
54            # initialize, may prevent some flakiness in tests
55            time.sleep(self.TEST_SLEEP_SECS)
56
57            for device, device_test in devtuples:
58                if device_test is not None:
59                    device_test(device)
60
61        finally:
62            for device, _ in devtuples:
63                self.test_disconnection_by_adapter(device.address)
64                self.test_remove_pairing(device.address)
65
66
67    @test_wrapper('One classic and one BLE connection',
68                  devices={'BLE_MOUSE':1, 'KEYBOARD':1}, supports_floss=True)
69    def md_two_connections_test(self):
70        """test whether DUT can connect to classic keyboard and ble mouse at the
71           same time
72        """
73        devices = [
74            (self.devices['BLE_MOUSE'][0], self.test_mouse_left_click),
75            (self.devices['KEYBOARD'][0], self.run_keyboard_tests)
76        ]
77
78        self.pair_and_test_connection(devices)
79
80
81    @test_wrapper('Two BLE connections',
82                  devices={
83                          'BLE_MOUSE': 1,
84                          'BLE_KEYBOARD': 1
85                  },
86                  supports_floss=True)
87    def md_two_ble_hid_connections_test(self):
88        """ test whether DUT can connect to ble keyboard and ble mouse at the
89            same time
90        """
91        devices = [
92            (self.devices['BLE_MOUSE'][0], self.test_mouse_left_click),
93            (self.devices['BLE_KEYBOARD'][0], self.run_keyboard_tests)
94        ]
95
96        self.pair_and_test_connection(devices)
97
98
99    @test_wrapper('Two classic connections',
100                  devices={
101                          'MOUSE': 1,
102                          'KEYBOARD': 1
103                  },
104                  supports_floss=True)
105    def md_two_cl_hid_connections_test(self):
106        """ test whether DUT can connect to classic mouse and classic keyboard
107            at the same time
108        """
109        devices = [
110            (self.devices['MOUSE'][0], self.test_mouse_left_click),
111            (self.devices['KEYBOARD'][0], self.run_keyboard_tests)
112        ]
113
114        self.pair_and_test_connection(devices)
115
116
117    @batch_wrapper('Multiple Devices Health')
118    def md_health_batch_run(self, num_iterations=1, test_name=None):
119        """Run the multiple devices health test batch or a specific given test.
120           The wrapper of this method is implemented in batch_decorator.
121           Using the decorator a test batch method can implement the only its
122           core tests invocations and let the decorator handle the wrapper,
123           which is taking care for whether to run a specific test or the
124           batch as a whole, and running the batch in iterations
125
126           @param num_iterations: how many interations to run
127           @param test_name: specifc test to run otherwise None to run the
128                             whole batch
129        """
130        self.md_two_connections_test()
131        self.md_two_ble_hid_connections_test()
132        self.md_two_cl_hid_connections_test()
133
134
135    def run_once(self,
136                 host,
137                 num_iterations=1,
138                 args_dict=None,
139                 test_name=None,
140                 flag='Quick Health',
141                 floss=False):
142        """Run the batch of Bluetooth stand health tests
143
144        @param host: the DUT, usually a chromebook
145        @param num_iterations: the number of rounds to execute the test
146        """
147        # Initialize and run the test batch or the requested specific test
148        self.quick_test_init(host,
149                             use_btpeer=True,
150                             flag=flag,
151                             args_dict=args_dict,
152                             floss=floss)
153        self.md_health_batch_run(num_iterations, test_name)
154        self.quick_test_cleanup()
155