blob: 7323c6f2306f7d1ffcb71d005357f5b887465ff6 [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
5import colorama as color
6
Charlie Mooneye0d06c42015-01-27 11:32:51 -08007import mt
Charlie Mooney3cca6ba2014-11-19 16:15:28 -08008import tests
Charlie Mooney86b5cf12014-12-04 09:34:09 -08009from plotter import TouchPlotter
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080010from remote import ChromeOSTouchDevice, AndroidTouchDevice
Charlie Mooney985cf402015-01-08 15:15:59 -080011from report import Report
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080012
13
14class TestSuite:
15 """ This class represents a collection of tests and is used to run them
16
17 A TestSuite object will set up a connection to the DUT, robot, etc, and
18 determine which tests can be run. Once the object is instantiated,
19 RunNextTestAndVariation() can be run repeatedly to work your way through
20 the entire suite.
21 """
22
23 NO_EVENTS_DETECTED_TIMEOUT_S = 5
24
25 def __init__(self, options, args):
26 color.init(autoreset=True)
27
28 self.options = options
29
30 # Open a connection to the device specified
31 if options.dut_type == 'chromeos':
32 self.touch_dev = ChromeOSTouchDevice(self.options.addr,
33 self.options.is_touchscreen)
34 else:
35 self.touch_dev = AndroidTouchDevice(self.options.addr, True)
Charlie Mooneye0d06c42015-01-27 11:32:51 -080036
37 # If the user specified the device's mt protocol override it now
38 if options.protocol != 'auto':
39 self.touch_dev.protocol = options.protocol
40
Charlie Mooneyaf9d5122014-12-04 15:15:52 -080041 tests.validator.BaseValidator._device = self.touch_dev
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080042
Charlie Mooneydaaaa242015-02-03 14:20:23 -080043 # Connect to the function generator if the operator says they have one
44 self.fn_generator = None
45 if options.has_fn_gen:
46 self.fn_generator = tests.noise.HP33120A()
47 if not self.fn_generator.IsValid():
48 self.fn_generator = None
49 options.has_fn_gen = False
50 print 'Error: Unable to connect to function generator!'
51
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080052 # Compute the list of tests to run
53 self.tests = tests.generate_test_list(options)
Charlie Mooney73051762015-02-06 11:52:38 -080054 if not self.tests:
55 print color.Fore.RED + 'Warning: No tests selected!'
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080056 self.curr_test = 0
57 self.curr_variation = 0
Charlie Mooneyaf9d5122014-12-04 15:15:52 -080058 self.curr_iteration = 1
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080059
Charlie Mooney985cf402015-01-08 15:15:59 -080060 # Create a new Report that will store all the test Results
61 self.report = Report()
62
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080063 def RunNextTestAndVariation(self):
64 """ Run the next test.
65
66 This function runs the next test/variation combination in the test suite
67 and advances the internal state to the next one automatically. When
68 finished, this function return True if there are more tests to run, and
69 False if the whole test suite is done.
70
71 After a TestSuite is instantiated, this function should be called
72 repeatedly until it returns False to go through all tests, variations,
73 and iterations.
74 """
Charlie Mooney73051762015-02-06 11:52:38 -080075 if self.curr_test >= len(self.tests):
76 return False
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080077 test = self.tests[self.curr_test]
78
79 # Print the header for this new test and variation
80 prompt = test.PromptForVariation(self.curr_variation)
81 print color.Fore.WHITE + '-' * 80
82 print color.Fore.BLUE + test.name
83 print color.Fore.GREEN + prompt
84
Charlie Mooneydaaaa242015-02-03 14:20:23 -080085 # Start the function generator (if applicable)
86 if self.fn_generator:
87 waveform = test.WaveformForVariation(self.curr_variation)
88 if waveform:
89 self.fn_generator.GenerateFunction(*waveform)
90 else:
91 self.fn_generator.Off()
92
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080093 # Start collecting data
94 print 'Opening connection with DUT... ',
95 self.touch_dev.BeginEventStream()
96 print 'Connection established!'
97
98 # Wait a long time for the first event, then have a much shorter
99 # timeout on subsequent incoming events
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800100 events = []
Charlie Mooney350fbc32015-01-07 13:27:09 -0800101 plotter = TouchPlotter(self.touch_dev.x_min, self.touch_dev.x_max,
Charlie Mooneye0d06c42015-01-27 11:32:51 -0800102 self.touch_dev.y_min, self.touch_dev.y_max,
Charlie Mooney8dc2aef2015-02-02 14:20:34 -0800103 self.touch_dev.p_min, self.touch_dev.p_max,
Charlie Mooneye0d06c42015-01-27 11:32:51 -0800104 self.touch_dev.protocol)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800105 print 'Waiting for 1st event...',
106 event = self.touch_dev.NextEvent(TestSuite.NO_EVENTS_DETECTED_TIMEOUT_S)
107 if not event:
Charlie Mooneye0d06c42015-01-27 11:32:51 -0800108 print ('\rNo MT events collected before timeout (%d seconds)!' %
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800109 TestSuite.NO_EVENTS_DETECTED_TIMEOUT_S),
110 while event:
Charlie Mooney86b5cf12014-12-04 09:34:09 -0800111 plotter.add_event(event)
Charlie Mooneye0d06c42015-01-27 11:32:51 -0800112 print '\rCollected %d MT events' % len(events),
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800113 events.append(event)
114 event = self.touch_dev.NextEvent(test.timeout)
115 print
Charlie Mooney97d73c12015-01-09 08:57:03 -0800116 plot_image_png = plotter.end()
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800117
118 # Run the validators on these events
Charlie Mooneye0d06c42015-01-27 11:32:51 -0800119 snapshots = mt.process(events, protocol=self.touch_dev.protocol)
Charlie Mooneyaf9d5122014-12-04 15:15:52 -0800120 results = test.RunAllValidators(snapshots)
Charlie Mooney985cf402015-01-08 15:15:59 -0800121
Charlie Mooney5e9a10f2015-01-13 14:54:27 -0800122 # Bundle the Validator results with some details of which gesture was used
123 # during the test for easier debugging.
124 test_result = tests.TestResult(results, prompt, plot_image_png)
125
Charlie Mooney985cf402015-01-08 15:15:59 -0800126 # Add the results into our report (And have it print them to stdout, too)
Charlie Mooney5e9a10f2015-01-13 14:54:27 -0800127 self.report.AddTestResult(test_result, verbose=True)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800128
129 # Advance the test suite to the next test and variation and return an
130 # indicator as to whether this was the last thing to do or not.
131 next_test, next_var = self._Advance()
132 return (next_test is not None)
133
134 def _Advance(self):
135 """ Move on to the next test/variation pair
136
137 This function increments all the interal counters, according to the
138 number of tests, their variations, and the selected number of iterations
139 and returns the test object and the variation number that should be
140 done next.
141
142 When the TestSuite is complete, this function will return None, None
143 otherwise it will return the next Test object and the variation number
144 the test suite is on.
145 """
146 if self.curr_test >= len(self.tests):
147 return None, None
148 test = self.tests[self.curr_test]
149
150 if self.curr_variation >= len(test.variations):
151 self.curr_test += 1
152 self.curr_variation = 0
153 self.curr_iteration = 0
154 return self._Advance()
155
156 if self.curr_iteration >= self.options.num_iterations:
157 self.curr_variation += 1
158 self.curr_iteration = 0
159 return self._Advance()
160
161 self.curr_iteration += 1
162 return test, self.curr_variation