blob: 78531ed84b7fef30a1044af77e80919dc0cce9ca [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 Kempin22c7c4d2012-07-26 13:04:24 -070018
19_help_text = """\
20Available Commands:
21-------------------
22$ touchtests run [all|testname]
23Executes tests. Either all of them and presents a resulting overall score.
24Or just a single named test.
25
Andrew de los Reyesb2d1c8a2012-08-17 18:40:28 -070026$ touchtests get [--from filename] gestures-log|evdev-log|activity-log testname
Dennis Kempin64f513f2012-08-10 15:09:18 -070027Runs a test and prints the requested log of a specific test. In case the
28--from option is used, the test will not be run, but the log will be loaded from
29the test results stored in file at 'filename'.
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070030
Dennis Kempin7a2f40b2012-08-10 15:13:54 -070031$ touchtests add [name] [activity_log] [cmt_log]
32Adds a new test case. The name has to include the platform and can optionally
33specify a subfolder where the test should be stored.
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070034activity_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.
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070038
39General Info:
40-------------
41testname arguments:
42Tests are always names as [platform]/[name of test case]. You can find the tests
43available in the tests folder.
44For example: lumpy/scroll_test
45
46Tests Folder:
47The tests folder contains a folder for each platform and all the test cases.
48Each test case is made up of 3 files:
49[testcase].py which contains the validation script
50[testcase].log which contains the input_event log
51[testcase].props which contains user_defined properties passed to gestures lib.
52
53Platform folders:
54To add a new platform you need to add a new folder to the Tests folder, and
55generate a platform.dat file. This can be done using the evemu-describe tool
56on the target platform:
57
58$ gmerge utouch-evemu
59$ evemu-describe /path/to/device > platform.dat
60"""
61
62
63def HelpExit():
64 """
65 Print help text and exit
66 """
67 print _help_text
68 exit()
69
Dennis Kempin1479e742012-07-31 17:31:01 -070070def Verify(device, glob):
Dennis Kempin774b0622013-02-08 13:14:54 -080071 verifier = TestVerifier(os.environ["TESTS_DIR"], device)
72 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["XORG_CONF_DIR"])
Dennis Kempin1479e742012-07-31 17:31:01 -070073 cases = runner.DiscoverTestCases(glob)
74
75 for case in cases:
76 print "###", case.name
77 report = verifier.Verify(case)
78 print report
79
Dennis Kempin12968302012-08-09 15:37:09 -070080def Run(glob, out_file=None, ref_file=None):
Dennis Kempin4bc397b2012-08-08 16:51:47 -070081 print "Running tests..."
Dennis Kempin774b0622013-02-08 13:14:54 -080082 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["XORG_CONF_DIR"])
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070083 results = runner.RunAll(glob)
Dennis Kempin22c7c4d2012-07-26 13:04:24 -070084
Dennis Kempin725ee5b2012-08-10 14:17:15 -070085 # print reports
Andrew de los Reyesbf5fa422012-10-17 16:45:45 -070086 sorted_results_items = sorted(results.items())
87 for key, value in sorted_results_items:
Dennis Kempin4bc397b2012-08-08 16:51:47 -070088 print "### Validation report for", key
89 print value["logs"]["validation"]
Dennis Kempin725ee5b2012-08-10 14:17:15 -070090 print value["error"]
Dennis Kempin4bc397b2012-08-08 16:51:47 -070091
Dennis Kempin725ee5b2012-08-10 14:17:15 -070092 # load reference
Dennis Kempin12968302012-08-09 15:37:09 -070093 ref = {}
94 if ref_file:
95 ref = json.load(open(ref_file))
96
Dennis Kempin725ee5b2012-08-10 14:17:15 -070097 # format result table
98 table = Table()
99 table.title = "Test Results"
100 table.header("Test", "reference score", "new score", "delta")
101
Chung-yih Wangd5aa52f2013-01-22 15:45:26 +0800102 regression = False
Andrew de los Reyesbf5fa422012-10-17 16:45:45 -0700103 for key, value in sorted_results_items:
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700104 def ResultStr(value):
105 # format result to string
106 if value["result"] == "success":
107 return "%s (%.4f)" % (value["result"], value["score"])
108 else:
109 return value["result"]
110
111 # format reference and delta column
112 ref_score = ""
113 delta_str = ""
Dennis Kempin12968302012-08-09 15:37:09 -0700114 if key in ref:
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700115 ref_score = ResultStr(ref[key])
116 delta = value["score"] - ref[key]["score"]
117 if math.fabs(delta) < 1e-10:
118 # don't color, but line up with other values
119 delta_str = " %.4f " % delta
120 elif delta < 0:
121 regression = True
122 # color red
123 delta_str = "\x1b[91m%+.4f\x1b[0m" % delta
124 else:
125 # color green
126 delta_str = "\x1b[92m%+.4f\x1b[0m" % delta
127 table.row(key, ref_score, ResultStr(value), delta_str)
128
129 print table
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700130
Dennis Kempin12968302012-08-09 15:37:09 -0700131 if out_file:
132 json.dump(results, open(out_file, "w"), indent=2)
133 print "results stored in:", out_file
134
Dennis Kempin725ee5b2012-08-10 14:17:15 -0700135 if regression:
136 print "\x1b[91mThere are regressions present in this test run!\x1b[0m"
137 exit(-1)
138
Dennis Kempin64f513f2012-08-10 15:09:18 -0700139def Get(test_name, what, file=None):
140 if file:
141 data = json.load(open(file))
142 results = data[test_name]
143 else:
Dennis Kempin774b0622013-02-08 13:14:54 -0800144 runner = TestRunner(os.environ["TESTS_DIR"], os.environ["XORG_CONF_DIR"])
Dennis Kempin64f513f2012-08-10 15:09:18 -0700145 data = runner.RunAll(test_name)
146 results = data[test_name]
147
148 if what == "gestures-log":
149 print results["logs"]["gestures"]
150 elif what == "evdev-log":
151 print results["logs"]["evdev"]
152 elif what == "activity-log":
153 print results["logs"]["activity"]
154 elif what == "gestures":
155 print results["gestures"]
156 elif what == "events":
157 print results["events"]
158
Dennis Kempin7a2f40b2012-08-10 15:13:54 -0700159def Add(testname, activity_log, event_log):
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700160 """
161 Adds a new test case.
162 """
163 # determine test name from activity_log name
Dennis Kempin774b0622013-02-08 13:14:54 -0800164 factory = TestFactory(os.environ["TESTS_DIR"])
Dennis Kempin31c0fbd2012-07-30 13:20:37 -0700165 case = factory.CreateTest(testname, activity_log, event_log)
166
Dennis Kempin49fe8a52012-08-03 11:27:40 -0700167 print "Test \"" + case.name + "\" created"
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700168
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700169def Main():
170 """
171 Main entry point for the console interface
172 """
173
174 # setup paths from environment variables
175 if "TESTS_DIR" not in os.environ:
176 print "Require TESTS_DIR environment variable"
177 exit(-1)
178
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700179 TestCase.tests_path = os.environ["TESTS_DIR"]
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700180
181 # parse arguments and call command methods
182 if len(sys.argv) < 2:
183 HelpExit()
184
185 # call command method according to command line arguments
Dennis Kempin12968302012-08-09 15:37:09 -0700186 # todo: use an option parser library
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700187 cmd = sys.argv[1]
188
Dennis Kempin12968302012-08-09 15:37:09 -0700189 if cmd == "run":
190 if len(sys.argv) == 3:
191 test_name = sys.argv[2]
192 Run(test_name)
193 elif len(sys.argv) == 5 and sys.argv[2] == "--out":
194 test_name = sys.argv[4]
195 out = sys.argv[3]
196 Run(test_name, out)
197 elif len(sys.argv) == 5 and sys.argv[2] == "--ref":
198 test_name = sys.argv[4]
199 ref_file = sys.argv[3]
200 Run(test_name, None, ref_file)
201 else:
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700202 HelpExit()
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700203
Dennis Kempin64f513f2012-08-10 15:09:18 -0700204 elif cmd == "get":
205 if len(sys.argv) == 4:
206 test_name = sys.argv[3]
207 what = sys.argv[2]
208 Get(test_name, what)
209 elif len(sys.argv) == 6 and sys.argv[2] == "--from":
210 test_name = sys.argv[5]
211 what = sys.argv[4]
212 file = sys.argv[3]
213 Get(test_name, what, file)
214 else:
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700215 HelpExit()
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700216
Dennis Kempin1479e742012-07-31 17:31:01 -0700217 elif cmd == "verify":
218 if len(sys.argv) < 4:
219 HelpExit()
220 device_name = sys.argv[2]
221 test_name = sys.argv[3]
222 Verify(device_name, test_name)
223
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700224 elif cmd == "add":
225 if len(sys.argv) < 5:
226 HelpExit()
Dennis Kempin7a2f40b2012-08-10 15:13:54 -0700227 testname = sys.argv[2]
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700228 activity_log = sys.argv[3]
229 event_log = sys.argv[4]
Dennis Kempin7a2f40b2012-08-10 15:13:54 -0700230 Add(testname, activity_log, event_log)
Dennis Kempin22c7c4d2012-07-26 13:04:24 -0700231
232 else:
233 HelpExit()
234
235if __name__ == "__main__":
236 Main()