blob: da8cd9ec9a6e4348d7cc1efa23bb1ab235991a0d [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 Kempin963fb152013-01-11 15:40:19 -080017from test_runner import ParallelTestRunner as 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
Andrew de los Reyesb2d1c8a2012-08-17 18:40:28 -070027$ touchtests get [--from filename] gestures-log|evdev-log|activity-log testname
Dennis Kempin64f513f2012-08-10 15:09:18 -070028Runs 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
Dennis Kempin7a2f40b2012-08-10 15:13:54 -070032$ touchtests add [name] [activity_log] [cmt_log]
33Adds a new test case. The name has to include the platform and can optionally
34specify a subfolder where the test should be stored.
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070035activity_log and cmt_log should point to the file names of log files collected
36from the device.
37You can trim activity_log in tp_view, touchtests will automatically trim the
38cmt_log accordingly.
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070039
40General Info:
41-------------
42testname arguments:
43Tests are always names as [platform]/[name of test case]. You can find the tests
44available in the tests folder.
45For example: lumpy/scroll_test
46
47Tests Folder:
48The tests folder contains a folder for each platform and all the test cases.
49Each test case is made up of 3 files:
50[testcase].py which contains the validation script
51[testcase].log which contains the input_event log
52[testcase].props which contains user_defined properties passed to gestures lib.
53
54Platform folders:
55To add a new platform you need to add a new folder to the Tests folder, and
56generate a platform.dat file. This can be done using the evemu-describe tool
57on the target platform:
58
59$ gmerge utouch-evemu
60$ evemu-describe /path/to/device > platform.dat
61"""
62
63
64def HelpExit():
65 """
66 Print help text and exit
67 """
68 print _help_text
69 exit()
70
Dennis Kempin1479e742012-07-31 17:31:01 -070071def Verify(device, glob):
72 verifier = TestVerifier(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"],
73 device)
Dennis Kempin926a6b22013-01-22 12:20:10 -080074 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"],
75 os.environ["XORG_CONF_DIR"])
Dennis Kempin1479e742012-07-31 17:31:01 -070076 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 Kempin926a6b22013-01-22 12:20:10 -080085 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"],
86 os.environ["XORG_CONF_DIR"])
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070087 results = runner.RunAll(glob)
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070088
Dennis Kempin725ee5b2012-08-10 14:17:15 -070089 # print reports
Andrew de los Reyesbf5fa422012-10-17 16:45:45 -070090 sorted_results_items = sorted(results.items())
91 for key, value in sorted_results_items:
Dennis Kempin4bc397b2012-08-08 16:51:47 -070092 print "### Validation report for", key
93 print value["logs"]["validation"]
Dennis Kempin725ee5b2012-08-10 14:17:15 -070094 print value["error"]
Dennis Kempin4bc397b2012-08-08 16:51:47 -070095
Dennis Kempin725ee5b2012-08-10 14:17:15 -070096 # load reference
Dennis Kempin12968302012-08-09 15:37:09 -070097 ref = {}
98 if ref_file:
99 ref = json.load(open(ref_file))
100
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700101 # format result table
102 table = Table()
103 table.title = "Test Results"
104 table.header("Test", "reference score", "new score", "delta")
105
Chung-yih Wangd5aa52f2013-01-22 15:45:26 +0800106 regression = False
Andrew de los Reyesbf5fa422012-10-17 16:45:45 -0700107 for key, value in sorted_results_items:
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700108 def ResultStr(value):
109 # format result to string
110 if value["result"] == "success":
111 return "%s (%.4f)" % (value["result"], value["score"])
112 else:
113 return value["result"]
114
115 # format reference and delta column
116 ref_score = ""
117 delta_str = ""
Dennis Kempin12968302012-08-09 15:37:09 -0700118 if key in ref:
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700119 ref_score = ResultStr(ref[key])
120 delta = value["score"] - ref[key]["score"]
121 if math.fabs(delta) < 1e-10:
122 # don't color, but line up with other values
123 delta_str = " %.4f " % delta
124 elif delta < 0:
125 regression = True
126 # color red
127 delta_str = "\x1b[91m%+.4f\x1b[0m" % delta
128 else:
129 # color green
130 delta_str = "\x1b[92m%+.4f\x1b[0m" % delta
131 table.row(key, ref_score, ResultStr(value), delta_str)
132
133 print table
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700134
Dennis Kempin12968302012-08-09 15:37:09 -0700135 if out_file:
136 json.dump(results, open(out_file, "w"), indent=2)
137 print "results stored in:", out_file
138
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700139 if regression:
140 print "\x1b[91mThere are regressions present in this test run!\x1b[0m"
141 exit(-1)
142
Dennis Kempin64f513f2012-08-10 15:09:18 -0700143def Get(test_name, what, file=None):
144 if file:
145 data = json.load(open(file))
146 results = data[test_name]
147 else:
Dennis Kempin926a6b22013-01-22 12:20:10 -0800148 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"],
149 os.environ["XORG_CONF_DIR"])
Dennis Kempin64f513f2012-08-10 15:09:18 -0700150 data = runner.RunAll(test_name)
151 results = data[test_name]
152
153 if what == "gestures-log":
154 print results["logs"]["gestures"]
155 elif what == "evdev-log":
156 print results["logs"]["evdev"]
157 elif what == "activity-log":
158 print results["logs"]["activity"]
159 elif what == "gestures":
160 print results["gestures"]
161 elif what == "events":
162 print results["events"]
163
Dennis Kempin7a2f40b2012-08-10 15:13:54 -0700164def Add(testname, activity_log, event_log):
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700165 """
166 Adds a new test case.
167 """
168 # determine test name from activity_log name
Dennis Kempin31c0fbd2012-07-30 13:20:37 -0700169 factory = TestFactory(os.environ["TESTS_DIR"], os.environ["REPLAY_TOOL"])
170 case = factory.CreateTest(testname, activity_log, event_log)
171
Dennis Kempin49fe8a52012-08-03 11:27:40 -0700172 print "Test \"" + case.name + "\" created"
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700173
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700174def Main():
175 """
176 Main entry point for the console interface
177 """
178
179 # setup paths from environment variables
180 if "TESTS_DIR" not in os.environ:
181 print "Require TESTS_DIR environment variable"
182 exit(-1)
183
184 if "REPLAY_TOOL" not in os.environ:
185 print "Require REPLAY_TOOL environment variable"
186 exit(-1)
187
188 TestCase.tests_path = os.environ["TESTS_DIR"]
189 TestCase.replay_tool = os.environ["REPLAY_TOOL"]
190
191 # parse arguments and call command methods
192 if len(sys.argv) < 2:
193 HelpExit()
194
195 # call command method according to command line arguments
Dennis Kempin12968302012-08-09 15:37:09 -0700196 # todo: use an option parser library
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700197 cmd = sys.argv[1]
198
Dennis Kempin12968302012-08-09 15:37:09 -0700199 if cmd == "run":
200 if len(sys.argv) == 3:
201 test_name = sys.argv[2]
202 Run(test_name)
203 elif len(sys.argv) == 5 and sys.argv[2] == "--out":
204 test_name = sys.argv[4]
205 out = sys.argv[3]
206 Run(test_name, out)
207 elif len(sys.argv) == 5 and sys.argv[2] == "--ref":
208 test_name = sys.argv[4]
209 ref_file = sys.argv[3]
210 Run(test_name, None, ref_file)
211 else:
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700212 HelpExit()
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700213
Dennis Kempin64f513f2012-08-10 15:09:18 -0700214 elif cmd == "get":
215 if len(sys.argv) == 4:
216 test_name = sys.argv[3]
217 what = sys.argv[2]
218 Get(test_name, what)
219 elif len(sys.argv) == 6 and sys.argv[2] == "--from":
220 test_name = sys.argv[5]
221 what = sys.argv[4]
222 file = sys.argv[3]
223 Get(test_name, what, file)
224 else:
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700225 HelpExit()
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700226
Dennis Kempin1479e742012-07-31 17:31:01 -0700227 elif cmd == "verify":
228 if len(sys.argv) < 4:
229 HelpExit()
230 device_name = sys.argv[2]
231 test_name = sys.argv[3]
232 Verify(device_name, test_name)
233
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700234 elif cmd == "add":
235 if len(sys.argv) < 5:
236 HelpExit()
Dennis Kempin7a2f40b2012-08-10 15:13:54 -0700237 testname = sys.argv[2]
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700238 activity_log = sys.argv[3]
239 event_log = sys.argv[4]
Dennis Kempin7a2f40b2012-08-10 15:13:54 -0700240 Add(testname, activity_log, event_log)
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700241
242 else:
243 HelpExit()
244
245if __name__ == "__main__":
246 Main()