blob: b79040709039c5c4f235bfa3073721ae98fca09e [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
Dennis Kempin64f513f2012-08-10 15:09:18 -070027$ touchtests get [--from filename] testname gestures-log|evdev-log|activity-log
28Runs a test and prints the requested log of a specific test. In case the
29--from option is used, the test will not be run, but the log will be loaded from
30the test results stored in file at 'filename'.
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070031
32$ touchtests add [platform] [activity_log] [cmt_log]
33Adds a new test case. Each test belongs to a platform "lumpy", "cr48", etc.
34activity_log and cmt_log should point to the file names of log files collected
35from the device.
36You can trim activity_log in tp_view, touchtests will automatically trim the
37cmt_log accordingly.
38The test will be named after the filename of the activity_log and a dummy
39validation script is automatically generated.
40
41General Info:
42-------------
43testname arguments:
44Tests are always names as [platform]/[name of test case]. You can find the tests
45available in the tests folder.
46For example: lumpy/scroll_test
47
48Tests Folder:
49The tests folder contains a folder for each platform and all the test cases.
50Each test case is made up of 3 files:
51[testcase].py which contains the validation script
52[testcase].log which contains the input_event log
53[testcase].props which contains user_defined properties passed to gestures lib.
54
55Platform folders:
56To add a new platform you need to add a new folder to the Tests folder, and
57generate a platform.dat file. This can be done using the evemu-describe tool
58on the target platform:
59
60$ gmerge utouch-evemu
61$ evemu-describe /path/to/device > platform.dat
62"""
63
64
65def HelpExit():
66 """
67 Print help text and exit
68 """
69 print _help_text
70 exit()
71
Dennis Kempin1479e742012-07-31 17:31:01 -070072def Verify(device, glob):
73 verifier = TestVerifier(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"],
74 device)
75 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
76 cases = runner.DiscoverTestCases(glob)
77
78 for case in cases:
79 print "###", case.name
80 report = verifier.Verify(case)
81 print report
82
Dennis Kempin12968302012-08-09 15:37:09 -070083def Run(glob, out_file=None, ref_file=None):
Dennis Kempin4bc397b2012-08-08 16:51:47 -070084 print "Running tests..."
Dennis Kempin725ee5b2012-08-10 14:17:15 -070085 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070086 results = runner.RunAll(glob)
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070087
Dennis Kempin725ee5b2012-08-10 14:17:15 -070088 # print reports
Dennis Kempin4bc397b2012-08-08 16:51:47 -070089 for key, value in results.items():
90 print "### Validation report for", key
91 print value["logs"]["validation"]
Dennis Kempin725ee5b2012-08-10 14:17:15 -070092 print value["error"]
Dennis Kempin4bc397b2012-08-08 16:51:47 -070093
Dennis Kempin725ee5b2012-08-10 14:17:15 -070094 # load reference
Dennis Kempin12968302012-08-09 15:37:09 -070095 ref = {}
96 if ref_file:
97 ref = json.load(open(ref_file))
98
Dennis Kempin725ee5b2012-08-10 14:17:15 -070099 # format result table
100 table = Table()
101 table.title = "Test Results"
102 table.header("Test", "reference score", "new score", "delta")
103
Dennis Kempin8cb1a892012-08-06 15:19:17 -0700104 for key, value in results.items():
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700105 def ResultStr(value):
106 # format result to string
107 if value["result"] == "success":
108 return "%s (%.4f)" % (value["result"], value["score"])
109 else:
110 return value["result"]
111
112 # format reference and delta column
113 ref_score = ""
114 delta_str = ""
115 regression = False
Dennis Kempin12968302012-08-09 15:37:09 -0700116 if key in ref:
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700117 ref_score = ResultStr(ref[key])
118 delta = value["score"] - ref[key]["score"]
119 if math.fabs(delta) < 1e-10:
120 # don't color, but line up with other values
121 delta_str = " %.4f " % delta
122 elif delta < 0:
123 regression = True
124 # color red
125 delta_str = "\x1b[91m%+.4f\x1b[0m" % delta
126 else:
127 # color green
128 delta_str = "\x1b[92m%+.4f\x1b[0m" % delta
129 table.row(key, ref_score, ResultStr(value), delta_str)
130
131 print table
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700132
Dennis Kempin12968302012-08-09 15:37:09 -0700133 if out_file:
134 json.dump(results, open(out_file, "w"), indent=2)
135 print "results stored in:", out_file
136
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700137 if regression:
138 print "\x1b[91mThere are regressions present in this test run!\x1b[0m"
139 exit(-1)
140
Dennis Kempin64f513f2012-08-10 15:09:18 -0700141def Get(test_name, what, file=None):
142 if file:
143 data = json.load(open(file))
144 results = data[test_name]
145 else:
146 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
147 data = runner.RunAll(test_name)
148 results = data[test_name]
149
150 if what == "gestures-log":
151 print results["logs"]["gestures"]
152 elif what == "evdev-log":
153 print results["logs"]["evdev"]
154 elif what == "activity-log":
155 print results["logs"]["activity"]
156 elif what == "gestures":
157 print results["gestures"]
158 elif what == "events":
159 print results["events"]
160
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700161def Add(platform, activity_log, event_log):
162 """
163 Adds a new test case.
164 """
165 # determine test name from activity_log name
166 testname = path.splitext(path.basename(activity_log))[0]
167 testname = path.join(platform, testname)
Dennis Kempin31c0fbd2012-07-30 13:20:37 -0700168 factory = TestFactory(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
169 case = factory.CreateTest(testname, activity_log, event_log)
170
Dennis Kempin49fe8a52012-08-03 11:27:40 -0700171 print "Test \"" + case.name + "\" created"
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700172
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700173def Main():
174 """
175 Main entry point for the console interface
176 """
177
178 # setup paths from environment variables
179 if "TESTS_DIR" not in os.environ:
180 print "Require TESTS_DIR environment variable"
181 exit(-1)
182
183 if "REPLAY_TOOL" not in os.environ:
184 print "Require REPLAY_TOOL environment variable"
185 exit(-1)
186
187 TestCase.tests_path = os.environ["TESTS_DIR"]
188 TestCase.replay_tool = os.environ["REPLAY_TOOL"]
189
190 # parse arguments and call command methods
191 if len(sys.argv) < 2:
192 HelpExit()
193
194 # call command method according to command line arguments
Dennis Kempin12968302012-08-09 15:37:09 -0700195 # todo: use an option parser library
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700196 cmd = sys.argv[1]
197
Dennis Kempin12968302012-08-09 15:37:09 -0700198 if cmd == "run":
199 if len(sys.argv) == 3:
200 test_name = sys.argv[2]
201 Run(test_name)
202 elif len(sys.argv) == 5 and sys.argv[2] == "--out":
203 test_name = sys.argv[4]
204 out = sys.argv[3]
205 Run(test_name, out)
206 elif len(sys.argv) == 5 and sys.argv[2] == "--ref":
207 test_name = sys.argv[4]
208 ref_file = sys.argv[3]
209 Run(test_name, None, ref_file)
210 else:
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700211 HelpExit()
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700212
Dennis Kempin64f513f2012-08-10 15:09:18 -0700213 elif cmd == "get":
214 if len(sys.argv) == 4:
215 test_name = sys.argv[3]
216 what = sys.argv[2]
217 Get(test_name, what)
218 elif len(sys.argv) == 6 and sys.argv[2] == "--from":
219 test_name = sys.argv[5]
220 what = sys.argv[4]
221 file = sys.argv[3]
222 Get(test_name, what, file)
223 else:
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700224 HelpExit()
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700225
Dennis Kempin1479e742012-07-31 17:31:01 -0700226 elif cmd == "verify":
227 if len(sys.argv) < 4:
228 HelpExit()
229 device_name = sys.argv[2]
230 test_name = sys.argv[3]
231 Verify(device_name, test_name)
232
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700233 elif cmd == "add":
234 if len(sys.argv) < 5:
235 HelpExit()
236 platform = sys.argv[2]
237 activity_log = sys.argv[3]
238 event_log = sys.argv[4]
239 Add(platform, activity_log, event_log)
240
241 else:
242 HelpExit()
243
244if __name__ == "__main__":
245 Main()