blob: 926622763fd9984ad36395d5d4b9a688effc8b22 [file] [log] [blame]
Charlie Mooney3cca6ba2014-11-19 16:15:28 -08001# 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
Charlie Mooney4291c4e2015-06-15 10:15:30 -07005import inspect
Charlie Mooney3cca6ba2014-11-19 16:15:28 -08006import optparse
Charlie Mooney985cf402015-01-08 15:15:59 -08007import os
Charlie Mooney3cca6ba2014-11-19 16:15:28 -08008import sys
Charlie Mooney4291c4e2015-06-15 10:15:30 -07009from subprocess import Popen, PIPE
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080010
Charlie Mooney389e1f32015-03-06 13:33:20 -080011import colorama as color
Charlie Mooneye0d06c42015-01-27 11:32:51 -080012
Amirhossein Simjouraf7e16a2015-05-13 16:31:57 -040013from remote import ChromeOSTouchDevice, AndroidTouchDevice, mt
Amirhossein Simjour3f1774c2015-06-16 13:45:13 -040014from remote import ElanTouchScreenDevice, ElanTouchDevice, SynapticsTouchDevice
Charlie Mooney985cf402015-01-08 15:15:59 -080015from report import Report
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080016from test_suite import TestSuite
17
Charlie Mooneyff8b3322016-06-14 14:58:12 -070018REPORT_LOCATION_FORMAT = '%s_report.html'
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080019
20def parse_arguments():
Amirhossein Simjour3f1774c2015-06-16 13:45:13 -040021 VALID_DUT_TYPES = ['chromeos', 'android', 'elan_i2c', 'elan_ts_i2c',
22 'synaptics_ts_i2c', 'replay']
Charlie Mooney73051762015-02-06 11:52:38 -080023 VALID_MODES = ['performance', 'noise', 'full']
Charlie Mooney51969622016-06-21 14:31:49 -070024 VALID_PROTOCOLS = [mt.MTA, mt.MTB, mt.STYLUS, 'auto']
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080025 parser = optparse.OptionParser()
26
27 # DUT specification information
28 parser.add_option('-a', '--addr', dest='addr', default=None,
Charlie Mooneye0d06c42015-01-27 11:32:51 -080029 help=('The address of the DUT (ip for CrOS, Device ID '
Charlie Mooney985cf402015-01-08 15:15:59 -080030 'for Android, or a filename to replay old results).'))
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080031 parser.add_option('-t', '--type', dest='dut_type', default=None,
Charlie Mooney985cf402015-01-08 15:15:59 -080032 help='The type of DUT (android, chromeos, or replay).')
Charlie Mooney63e30ba2015-10-21 14:35:43 -070033 parser.add_option('-d', '--device_num', dest='device_num',
34 default=None, type=int,
35 help='The device number of the touch sensor if you know it')
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080036 parser.add_option('--touchscreen', dest='is_touchscreen',
37 default=False, action='store_true',
Charlie Mooneye0d06c42015-01-27 11:32:51 -080038 help=('Use the touchscreen (instead of touchpad) on '
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080039 'the device.'))
40
Charlie Mooneye0d06c42015-01-27 11:32:51 -080041 parser.add_option('--protocol', dest='protocol', default='auto',
42 help=('Manually specify the multitouch protocol for the '
43 'DUT. This should be detected automatically, but '
Charlie Mooney51969622016-06-21 14:31:49 -070044 'in the event that fails, you may specify "mtb", '
45 '"mta", or "stylus" with this flag to over-ride it.'))
Charlie Mooney08661912015-04-16 09:20:34 -070046 parser.add_option('-n', '--name', dest='name', default='unknown_device',
47 help='The name of this DUT. This is used by the robot to '
48 'store calibration data and is only needed if you are '
49 'using the touchbot. Simply keep the name consistent '
50 'across multiple tests on the same DUT to avoid '
51 'having to recalibrate the robot each time.')
Charlie Mooneye0d06c42015-01-27 11:32:51 -080052
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080053 # Lab equipment specification
54 parser.add_option('-r', '--robot', dest='has_robot',
55 default=False, action='store_true',
Charlie Mooneye0d06c42015-01-27 11:32:51 -080056 help=('Indicate that you have a Google Touchbot that '
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080057 'will perform your gestures for you.'))
58 parser.add_option('-f', '--fn_gen', dest='has_fn_gen',
59 default=False, action='store_true',
Charlie Mooneye0d06c42015-01-27 11:32:51 -080060 help=('Indicate that you have an HP 33120A function '
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080061 'generator to automate the electric noise tests.'))
Charlie Mooney73051762015-02-06 11:52:38 -080062 parser.add_option('-m', '--mode', dest='mode', default='performance',
63 help=('Which mode to run the test suite in. Options are '
64 '(performance, noise, or full) with performance as '
65 'the default selection.'))
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080066
67 # Test suite settings
68 parser.add_option('-i', '--iterations', dest='num_iterations', default=1,
69 type=int, help=('The number of test iterations to run.'))
Charlie Mooney3d00bdc2015-05-08 12:58:35 -070070 parser.add_option('--title', dest='title', default=None,
71 help='An optional title to put at the top of the report.')
Charlie Mooney4291c4e2015-06-15 10:15:30 -070072 parser.add_option('--test_version', dest='test_version', default=None,
73 help=('An optionally overridden test version string. This '
74 'string will appear at the top of the report. If '
75 'left undefined the most recent git commit hash is '
76 'used by default.'))
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080077
78 (options, args) = parser.parse_args()
79
80 if options.dut_type not in VALID_DUT_TYPES:
Charlie Mooney985cf402015-01-08 15:15:59 -080081 print 'ERROR: invalid dut type "%s"' % options.dut_type
82 print 'valid dut types are: %s' % str(VALID_DUT_TYPES)
83 sys.exit(1)
Charlie Mooneydb3ea552015-07-06 14:10:49 -070084 elif options.dut_type == 'chromeos' and not options.addr:
Charlie Mooney985cf402015-01-08 15:15:59 -080085 print 'ERROR: You must supply an IP address for ChromeOS DUTs'
86 sys.exit(1)
Amirhossein Simjour9e9ea2e2015-07-16 11:25:24 -040087 # Aardvark setup does not support the physical button
88 elif options.dut_type in ['android', 'elan_ts_i2c',
89 'elan_i2c', 'synaptics_ts_i2c']:
Charlie Mooneydb3ea552015-07-06 14:10:49 -070090 options.is_touchscreen = True
91
Charlie Mooneye0d06c42015-01-27 11:32:51 -080092 if options.protocol not in VALID_PROTOCOLS:
93 print 'ERROR: invalid protocol "%s"' % options.protocol
94 print 'valid protocols are: %s' % str(VALID_PROTOCOLS)
95 sys.exit(1)
Charlie Mooney73051762015-02-06 11:52:38 -080096 if options.mode not in VALID_MODES:
97 print 'ERROR: invalid mode "%s"' % options.mode
98 print 'valid modes are: %s' % str(VALID_MODES)
99 sys.exit(1)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800100
Charlie Mooney4291c4e2015-06-15 10:15:30 -0700101 # If they didn't manually specify a test_version string, generate the default
102 # By looking up the most recent commit in the touch_firmware_test git repo.
103 if options.test_version is None:
104 src_file = inspect.getfile(inspect.currentframe())
105 root_path = os.path.dirname(os.path.realpath(src_file))
106 git_path = os.path.join(root_path, '.git')
107 args = ['git', '--git-dir', git_path, 'log', '--oneline', '-n1']
108 options.test_version = Popen(args, stdout=PIPE).communicate()[0]
109
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800110 return options, args
111
112
Charlie Mooneyd5712b82015-02-23 12:06:59 -0800113def initialize_touch_device(options):
114 """ Using the supplied options connect to the DUT """
115 # Open a connection to the device specified
Charlie Mooney389e1f32015-03-06 13:33:20 -0800116 print (color.Style.DIM + color.Fore.RED +
117 'Please do not touch the device until the test starts!')
118 print 'Connecting to remote touch device...'
Charlie Mooneyd5712b82015-02-23 12:06:59 -0800119 if options.dut_type == 'chromeos':
Charlie Mooney389e1f32015-03-06 13:33:20 -0800120 touch_dev = ChromeOSTouchDevice(options.addr, options.is_touchscreen,
Charlie Mooneyfeeb07c2015-12-16 11:43:48 -0800121 options.protocol,
122 device_num=options.device_num)
Charlie Mooneyd5712b82015-02-23 12:06:59 -0800123 elif options.dut_type == 'android':
Charlie Mooney63e30ba2015-10-21 14:35:43 -0700124 touch_dev = AndroidTouchDevice(options.addr, True, options.protocol,
125 options.device_num)
Amirhossein Simjour7a71f332015-04-10 15:18:37 -0400126 elif options.dut_type == 'elan_i2c':
Amirhossein Simjouraf7e16a2015-05-13 16:31:57 -0400127 touch_dev = ElanTouchDevice(options.addr)
128 elif options.dut_type == 'elan_ts_i2c':
129 touch_dev = ElanTouchScreenDevice(options.addr)
Amirhossein Simjour3f1774c2015-06-16 13:45:13 -0400130 elif options.dut_type == 'synaptics_ts_i2c':
131 touch_dev = SynapticsTouchDevice(options.addr)
Charlie Mooneyd5712b82015-02-23 12:06:59 -0800132 else:
133 return None
134
Charlie Mooneyd5712b82015-02-23 12:06:59 -0800135 return touch_dev
Charlie Mooney985cf402015-01-08 15:15:59 -0800136
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800137def main():
Jingkui Wange4095d62018-05-01 12:56:05 -0700138 base_dir = os.getenv('TOUCH_REPORT_OUTPUT', '.')
139 print base_dir
Charlie Mooney389e1f32015-03-06 13:33:20 -0800140 color.init(autoreset=True)
141
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800142 # Parse and validate the command line arguments
143 options, args = parse_arguments()
144
Charlie Mooney985cf402015-01-08 15:15:59 -0800145 if options.dut_type != 'replay':
Charlie Mooney818c60c2015-04-21 15:10:44 -0700146 # Connect to the DUT
147 touch_dev = initialize_touch_device(options)
148
Charlie Mooney985cf402015-01-08 15:15:59 -0800149 # Create a test flow object that will run the test step by step
Charlie Mooneyd5712b82015-02-23 12:06:59 -0800150 test_suite = TestSuite(touch_dev, options, args)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800151
Charlie Mooney985cf402015-01-08 15:15:59 -0800152 # Run through the entire test suite in turn
153 while test_suite.RunNextTestAndVariation():
154 pass
Charlie Mooneyc68f9c32015-04-16 15:23:22 -0700155 test_suite.StopPlotter()
Charlie Mooney985cf402015-01-08 15:15:59 -0800156
157 # The test suite should have a fully populated Report object now, filled
158 # with the results of all the test runs.
159 report = test_suite.report
160
161 # Save this report into a default location as a backup in case you want
162 # to replay it later.
Jingkui Wange4095d62018-05-01 12:56:05 -0700163 report.SaveToDisk(base_dir + '/last_report.p')
Charlie Mooney985cf402015-01-08 15:15:59 -0800164 else:
Charlie Mooney389e1f32015-03-06 13:33:20 -0800165 # We are trying to replay an old report from a file on disk. Load it
Charlie Mooney985cf402015-01-08 15:15:59 -0800166 # directly from the specified file instead of running the test over again.
167 report = Report.FromFile(options.addr)
168
169 # Generate an HTML version of the Report and write it to disk
Charlie Mooneyff8b3322016-06-14 14:58:12 -0700170 report_filename = REPORT_LOCATION_FORMAT % options.mode
Jingkui Wange4095d62018-05-01 12:56:05 -0700171 report_path = base_dir + "/" + report_filename;
Charlie Mooney74bad592015-05-21 12:38:02 -0700172 print (color.Fore.MAGENTA + 'FW Testing Complete. Report is being generated '
Jingkui Wange4095d62018-05-01 12:56:05 -0700173 'now, and will be stored on disk as "%s"' % report_path)
Charlie Mooney985cf402015-01-08 15:15:59 -0800174 html_report = report.GenerateHtml()
Jingkui Wange4095d62018-05-01 12:56:05 -0700175 with open(report_path, 'w') as fo:
Charlie Mooney985cf402015-01-08 15:15:59 -0800176 fo.write(html_report)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800177
178 return 0
179
180
181if __name__ == "__main__":
182 sys.exit(main())