1# Copyright (c) 2014 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 os
6import logging
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.client.common_lib.cros import chrome
10from autotest_lib.client.cros import touch_playback_test_base
11
12
13class touch_MouseScroll(touch_playback_test_base.touch_playback_test_base):
14    """Plays back mouse scrolls and checks for correct page movement."""
15    version = 1
16
17    _MOUSE_DESCRIPTION = 'amazon_mouse.prop'
18    _APPLE_MOUSE_DES = 'apple_mouse.prop'
19    _EXPECTED_VALUE_1 = 16 # Expected value of one scroll wheel turn.
20    _EXPECTED_DIRECTION = {'down': 1, 'up': -1, 'right': 1, 'left': -1}
21    _TOLLERANCE = 4 # Fast scroll should go at least X times slow scroll.
22
23
24    def _get_scroll_delta(self, name, expected_direction, scroll_vertical=True):
25        """Playback the given test and return the amount the page moved.
26
27        @param name: name of test filename.
28        @param expected_direction: an integer that is + for down and - for up.
29        @param scroll_vertical: True for vertical scroll,
30                                False for horizontal scroll.
31
32        @raise: TestFail if scrolling did not occur in expected direction.
33
34        """
35        self._events.clear_previous_events()
36        self._events.set_default_scroll_position(scroll_vertical)
37        start_scroll = self._events.get_scroll_position(scroll_vertical)
38        self._events.clear_previous_events()
39
40        self._playback(self._gest_file_path[name], touch_type='mouse')
41
42        self._events.wait_for_events_to_complete()
43        end_scroll = self._events.get_scroll_position(scroll_vertical)
44        delta = end_scroll - start_scroll
45        logging.info('Test %s: saw scroll delta of %d.  Expected direction %d.',
46                     name, delta, expected_direction)
47
48        if delta * expected_direction < 0:
49            self._events.log_events()
50            raise error.TestFail('Scroll was in wrong direction!  Delta '
51                                 'for %s was %d.' % (name, delta))
52        return delta
53
54
55    def _verify_single_tick(self, direction, scroll_vertical=True):
56        """Verify that using the scroll wheel goes the right distance.
57
58        Expects a file (playback gesture file) named direction + '_1'.
59
60        @param direction: string indicating direction up, down, right and left.
61        @param scroll_vertical: scroll_vertical is True for vertical scroll
62                                else False
63
64        """
65        name = direction + '_1'
66        expected_direction = self._EXPECTED_DIRECTION[direction]
67        expected_value = self._EXPECTED_VALUE_1 * expected_direction
68        delta = self._get_scroll_delta(name, expected_direction,
69                                       scroll_vertical)
70
71        if delta != expected_value:
72            self._events.log_events()
73            raise error.TestFail('One tick scroll was wrong size: actual=%d, '
74                                 'expected=%d.' % (delta, expected_value))
75
76
77    def _verify_fast_vs_slow(self, direction, scroll_vertical=True):
78        """Verify that fast scrolling goes farther than slow scrolling.
79
80        Expects files (playback gesture file) named direction + '_slow'
81        and direction + '_fast'.
82
83        @param direction: string indicating direction up, down, right and left.
84        @param scroll_vertical: True for vertical scroll,
85                                False for horizontal scroll.
86
87        """
88        slow = direction + '_slow'
89        fast = direction + '_fast'
90        expected = self._EXPECTED_DIRECTION[direction]
91        slow_delta = self._get_scroll_delta(slow, expected, scroll_vertical)
92        fast_delta = self._get_scroll_delta(fast, expected, scroll_vertical)
93
94        if abs(fast_delta) < self._TOLLERANCE * abs(slow_delta):
95            self._events.log_events()
96            raise error.TestFail('Fast scroll should be much farther than '
97                                 'slow! (%s).  %d vs. %d.' %
98                                  (direction, slow_delta, fast_delta))
99
100
101    def run_once(self):
102        """Entry point of this test."""
103
104        # Link path for files to playback on DUT.
105        self._gest_file_path = {}
106        gestures_dir = os.path.join(self.bindir, 'gestures')
107        for filename in os.listdir(gestures_dir):
108            self._gest_file_path[filename] = os.path.join(gestures_dir,
109                                                          filename)
110
111        with chrome.Chrome(init_network_controller=True) as cr:
112            # Open test page.
113            self._open_events_page(cr)
114            self._events.expand_page()
115            self._events.set_prevent_defaults(False)
116
117            # Emulate mouse with vertical scroll feature.
118            mouse_file = os.path.join(self.bindir, self._MOUSE_DESCRIPTION)
119            self._emulate_mouse(property_file=mouse_file)
120            if not self._has_mouse:
121                raise error.TestError('No USB mouse found on this device.')
122            # In test page, position cursor to center.
123            self._blocking_playback(self._gest_file_path['center_cursor'],
124                                    touch_type='mouse')
125            self._events.wait_for_events_to_complete()
126
127            # Test vertical scrolling.
128            for direction in ['down', 'up']:
129                self._verify_single_tick(direction)
130                self._verify_fast_vs_slow(direction)
131
132            # Emulate mouse with horizontal scroll feature.
133            apple_mouse_file = os.path.join(self.bindir, self._APPLE_MOUSE_DES)
134            self._emulate_mouse(property_file=apple_mouse_file)
135            if not self._has_mouse:
136                raise error.TestError('No USB mouse found on this device.')
137
138            # Test horizontal scrolling.
139            for direction in ['right', 'left']:
140                self._verify_single_tick(direction, scroll_vertical=False)
141                self._verify_fast_vs_slow(direction, scroll_vertical=False)
142