[Autotest] Add stylus tap playback test.

Use recorded gestures to play a stylus tap from the kernel.
Check whether Chrome registered it as a click.  Very similar
to touch_TouchscreenTaps, but we will eventually want to
handle stylus hover so it's a separate test.

Like all playback tests, files are pulled from the public
chromiumos-test-assets-public/touch_playback/ google storage
folder.  Currently this test will only run on Caroline.

BUG=chromium:641203
TEST=ran on Caroline

Change-Id: I9b623136c371157cf1402a3d7788a8823769990d
Reviewed-on: https://chromium-review.googlesource.com/489807
Commit-Ready: Katherine Threlkeld <kathrelkeld@chromium.org>
Tested-by: Katherine Threlkeld <kathrelkeld@chromium.org>
Reviewed-by: Kalin Stoyanov <kalin@chromium.org>
diff --git a/client/cros/touch_playback_test_base.py b/client/cros/touch_playback_test_base.py
index 1aeae59..2998a94 100644
--- a/client/cros/touch_playback_test_base.py
+++ b/client/cros/touch_playback_test_base.py
@@ -83,6 +83,10 @@
                  a hw_id but does not.
 
         """
+        if type(gestures) is not list:
+            raise error.TestError('find_test_files() takes a LIST, not a '
+                                   '%s!' % type(gestures))
+
         if not self.player.has(input_type):
             raise error.TestError('Device does not have a %s!' % input_type)
 
diff --git a/client/site_tests/touch_StylusTaps/control b/client/site_tests/touch_StylusTaps/control
new file mode 100644
index 0000000..b4aee6a
--- /dev/null
+++ b/client/site_tests/touch_StylusTaps/control
@@ -0,0 +1,24 @@
+# Copyright 2017 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+AUTHOR = "kathrelkeld"
+NAME = "touch_StylusTaps"
+PURPOSE = "Test that stylus presses are interpreted as clicks."
+CRITERIA = """
+This test will fail if, after playback of touch events, taps do not appear
+on test page.
+"""
+ATTRIBUTES = "suite:bvt-perbuild, suite:touch"
+TIME = "SHORT"
+TEST_CATEGORY = "Functional"
+TEST_CLASS = "touch"
+TEST_TYPE = "client"
+DEPENDENCIES = "stylus"
+
+DOC = """
+Uses kernel playback and a javascript page to play and listen for stylus taps.
+If all goes well, the click count will increase.
+"""
+
+job.run_test('touch_StylusTaps')
diff --git a/client/site_tests/touch_StylusTaps/touch_StylusTaps.py b/client/site_tests/touch_StylusTaps/touch_StylusTaps.py
new file mode 100644
index 0000000..3b351ff
--- /dev/null
+++ b/client/site_tests/touch_StylusTaps/touch_StylusTaps.py
@@ -0,0 +1,48 @@
+# Copyright 2017 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.common_lib.cros import chrome
+from autotest_lib.client.cros import touch_playback_test_base
+
+
+class touch_StylusTaps(touch_playback_test_base.touch_playback_test_base):
+    """Checks that stylus touches are translated into clicks."""
+    version = 1
+
+    _CLICK_NAME = 'tap'
+
+    def _check_for_click(self):
+        """Playback and check whether click occurred.  Fail if not.
+
+        @raises: TestFail if no click or hover occurred.
+
+        """
+        cases = [(self._CLICK_NAME, 1)]
+        for (filename, expected_count) in cases:
+            self._events.clear_previous_events()
+            self._blocking_playback(filepath=self._filepaths[filename],
+                                    touch_type='stylus')
+            self._events.wait_for_events_to_complete()
+
+            actual_count = self._events.get_click_count()
+            if actual_count is not expected_count:
+                self._events.log_events()
+                raise error.TestFail('Saw %d clicks when %s were expected!' % (
+                        actual_count, expected_count))
+
+    def run_once(self):
+        """Entry point of this test."""
+        self._filepaths = self._find_test_files('stylus', [self._CLICK_NAME])
+        if not self._filepaths:
+            logging.info('Missing gesture files, Aborting test.')
+            return
+
+        # Log in and start test.
+        with chrome.Chrome(init_network_controller=True) as cr:
+            self._open_events_page(cr)
+            self._events.set_prevent_defaults(False)
+            self._check_for_click()