blob: 6d47e08962faac2266b793e0eba6116c2b111da8 [file] [log] [blame]
Dennis Kempin22c7c4d2012-07-26 13:04:24 -07001# Copyright (c) 2012 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#
5# This module is the main module for the console interface. It takes care
6# of parsing the command line arguments and formating the output
7from os import path
Dennis Kempin725ee5b2012-08-10 14:17:15 -07008import json
9import math
10import os
11import pprint
12import sys
13
14from table import Table
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070015from test_case import TestCase
Dennis Kempin31c0fbd2012-07-30 13:20:37 -070016from test_factory import TestFactory
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070017from test_runner import TestRunner
Dennis Kempin1479e742012-07-31 17:31:01 -070018from test_verifier import TestVerifier
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070019
20_help_text = """\
21Available Commands:
22-------------------
23$ touchtests run [all|testname]
24Executes tests. Either all of them and presents a resulting overall score.
25Or just a single named test.
26
27$ touchtests debug [testname]
28Same as run, but additionally displays the gestures library log.
29
30$ touchtests log [testname]
31Executes a test and prints the activity_log to stdout. Useful to view the
32results in tp_view.
33
34$ touchtests add [platform] [activity_log] [cmt_log]
35Adds a new test case. Each test belongs to a platform "lumpy", "cr48", etc.
36activity_log and cmt_log should point to the file names of log files collected
37from the device.
38You can trim activity_log in tp_view, touchtests will automatically trim the
39cmt_log accordingly.
40The test will be named after the filename of the activity_log and a dummy
41validation script is automatically generated.
42
43General Info:
44-------------
45testname arguments:
46Tests are always names as [platform]/[name of test case]. You can find the tests
47available in the tests folder.
48For example: lumpy/scroll_test
49
50Tests Folder:
51The tests folder contains a folder for each platform and all the test cases.
52Each test case is made up of 3 files:
53[testcase].py which contains the validation script
54[testcase].log which contains the input_event log
55[testcase].props which contains user_defined properties passed to gestures lib.
56
57Platform folders:
58To add a new platform you need to add a new folder to the Tests folder, and
59generate a platform.dat file. This can be done using the evemu-describe tool
60on the target platform:
61
62$ gmerge utouch-evemu
63$ evemu-describe /path/to/device > platform.dat
64"""
65
66
67def HelpExit():
68 """
69 Print help text and exit
70 """
71 print _help_text
72 exit()
73
Dennis Kempin1479e742012-07-31 17:31:01 -070074def Verify(device, glob):
75 verifier = TestVerifier(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"],
76 device)
77 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
78 cases = runner.DiscoverTestCases(glob)
79
80 for case in cases:
81 print "###", case.name
82 report = verifier.Verify(case)
83 print report
84
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070085
86def Log(glob, debug=False):
87 """
88 Print only the activity log. The user can pipe the output of this command
89 to be used in other tools like tpview.
90 """
91 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
92 cases = runner.DiscoverTestCases(glob)
93
94 # check number of test cases
95 if len(cases) > 1:
96 print "Multiple test cases match '" + str(glob) + "':"
97 for case in cases:
98 print " -", case.name
99 return
100
101 if len(cases) < 1:
102 print "Cannot find test " + glob
103 return
104
105 # run test and print results
106 results = runner.RunTest(cases[0])
107 if results["error"]:
108 print results["error"]
109 return
110
111 print results["logs"]["activity"]
112
113
Dennis Kempin12968302012-08-09 15:37:09 -0700114def Run(glob, out_file=None, ref_file=None):
Dennis Kempin4bc397b2012-08-08 16:51:47 -0700115 print "Running tests..."
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700116 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700117 results = runner.RunAll(glob)
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700118
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700119 # print reports
Dennis Kempin4bc397b2012-08-08 16:51:47 -0700120 for key, value in results.items():
121 print "### Validation report for", key
122 print value["logs"]["validation"]
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700123 print value["error"]
Dennis Kempin4bc397b2012-08-08 16:51:47 -0700124
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700125 # load reference
Dennis Kempin12968302012-08-09 15:37:09 -0700126 ref = {}
127 if ref_file:
128 ref = json.load(open(ref_file))
129
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700130 # format result table
131 table = Table()
132 table.title = "Test Results"
133 table.header("Test", "reference score", "new score", "delta")
134
Dennis Kempin8cb1a892012-08-06 15:19:17 -0700135 for key, value in results.items():
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700136 def ResultStr(value):
137 # format result to string
138 if value["result"] == "success":
139 return "%s (%.4f)" % (value["result"], value["score"])
140 else:
141 return value["result"]
142
143 # format reference and delta column
144 ref_score = ""
145 delta_str = ""
146 regression = False
Dennis Kempin12968302012-08-09 15:37:09 -0700147 if key in ref:
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700148 ref_score = ResultStr(ref[key])
149 delta = value["score"] - ref[key]["score"]
150 if math.fabs(delta) < 1e-10:
151 # don't color, but line up with other values
152 delta_str = " %.4f " % delta
153 elif delta < 0:
154 regression = True
155 # color red
156 delta_str = "\x1b[91m%+.4f\x1b[0m" % delta
157 else:
158 # color green
159 delta_str = "\x1b[92m%+.4f\x1b[0m" % delta
160 table.row(key, ref_score, ResultStr(value), delta_str)
161
162 print table
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700163
Dennis Kempin12968302012-08-09 15:37:09 -0700164 if out_file:
165 json.dump(results, open(out_file, "w"), indent=2)
166 print "results stored in:", out_file
167
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700168 if regression:
169 print "\x1b[91mThere are regressions present in this test run!\x1b[0m"
170 exit(-1)
171
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700172def Add(platform, activity_log, event_log):
173 """
174 Adds a new test case.
175 """
176 # determine test name from activity_log name
177 testname = path.splitext(path.basename(activity_log))[0]
178 testname = path.join(platform, testname)
Dennis Kempin31c0fbd2012-07-30 13:20:37 -0700179 factory = TestFactory(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
180 case = factory.CreateTest(testname, activity_log, event_log)
181
Dennis Kempin49fe8a52012-08-03 11:27:40 -0700182 print "Test \"" + case.name + "\" created"
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700183
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700184def Main():
185 """
186 Main entry point for the console interface
187 """
188
189 # setup paths from environment variables
190 if "TESTS_DIR" not in os.environ:
191 print "Require TESTS_DIR environment variable"
192 exit(-1)
193
194 if "REPLAY_TOOL" not in os.environ:
195 print "Require REPLAY_TOOL environment variable"
196 exit(-1)
197
198 TestCase.tests_path = os.environ["TESTS_DIR"]
199 TestCase.replay_tool = os.environ["REPLAY_TOOL"]
200
201 # parse arguments and call command methods
202 if len(sys.argv) < 2:
203 HelpExit()
204
205 # call command method according to command line arguments
Dennis Kempin12968302012-08-09 15:37:09 -0700206 # todo: use an option parser library
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700207 cmd = sys.argv[1]
208
Dennis Kempin12968302012-08-09 15:37:09 -0700209 if cmd == "run":
210 if len(sys.argv) == 3:
211 test_name = sys.argv[2]
212 Run(test_name)
213 elif len(sys.argv) == 5 and sys.argv[2] == "--out":
214 test_name = sys.argv[4]
215 out = sys.argv[3]
216 Run(test_name, out)
217 elif len(sys.argv) == 5 and sys.argv[2] == "--ref":
218 test_name = sys.argv[4]
219 ref_file = sys.argv[3]
220 Run(test_name, None, ref_file)
221 else:
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700222 HelpExit()
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700223
224 elif cmd == "log":
225 if len(sys.argv) < 3:
226 HelpExit()
227 test_name = sys.argv[2]
228 Log(test_name)
229
Dennis Kempin1479e742012-07-31 17:31:01 -0700230 elif cmd == "verify":
231 if len(sys.argv) < 4:
232 HelpExit()
233 device_name = sys.argv[2]
234 test_name = sys.argv[3]
235 Verify(device_name, test_name)
236
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700237 elif cmd == "add":
238 if len(sys.argv) < 5:
239 HelpExit()
240 platform = sys.argv[2]
241 activity_log = sys.argv[3]
242 event_log = sys.argv[4]
243 Add(platform, activity_log, event_log)
244
245 else:
246 HelpExit()
247
248if __name__ == "__main__":
249 Main()