blob: 267eafc39358c5c3d02f87106434892e22123264 [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 Mooney985cf402015-01-08 15:15:59 -080010from report import Report
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080011
12
13class TestSuite:
14 """ This class represents a collection of tests and is used to run them
15
16 A TestSuite object will set up a connection to the DUT, robot, etc, and
17 determine which tests can be run. Once the object is instantiated,
18 RunNextTestAndVariation() can be run repeatedly to work your way through
19 the entire suite.
20 """
21
22 NO_EVENTS_DETECTED_TIMEOUT_S = 5
23
Charlie Mooneyd5712b82015-02-23 12:06:59 -080024 def __init__(self, touch_dev, options, args):
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080025 color.init(autoreset=True)
26
27 self.options = options
Charlie Mooneyd5712b82015-02-23 12:06:59 -080028 self.touch_dev = touch_dev
Charlie Mooneyaf9d5122014-12-04 15:15:52 -080029 tests.validator.BaseValidator._device = self.touch_dev
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080030
Charlie Mooneydaaaa242015-02-03 14:20:23 -080031 # Connect to the function generator if the operator says they have one
32 self.fn_generator = None
33 if options.has_fn_gen:
34 self.fn_generator = tests.noise.HP33120A()
35 if not self.fn_generator.IsValid():
36 self.fn_generator = None
37 options.has_fn_gen = False
38 print 'Error: Unable to connect to function generator!'
39
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080040 # Compute the list of tests to run
41 self.tests = tests.generate_test_list(options)
Charlie Mooney73051762015-02-06 11:52:38 -080042 if not self.tests:
43 print color.Fore.RED + 'Warning: No tests selected!'
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080044 self.curr_test = 0
45 self.curr_variation = 0
Charlie Mooneyaf9d5122014-12-04 15:15:52 -080046 self.curr_iteration = 1
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080047
Charlie Mooney985cf402015-01-08 15:15:59 -080048 # Create a new Report that will store all the test Results
49 self.report = Report()
50
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080051 def RunNextTestAndVariation(self):
52 """ Run the next test.
53
54 This function runs the next test/variation combination in the test suite
55 and advances the internal state to the next one automatically. When
56 finished, this function return True if there are more tests to run, and
57 False if the whole test suite is done.
58
59 After a TestSuite is instantiated, this function should be called
60 repeatedly until it returns False to go through all tests, variations,
61 and iterations.
62 """
Charlie Mooney73051762015-02-06 11:52:38 -080063 if self.curr_test >= len(self.tests):
64 return False
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080065 test = self.tests[self.curr_test]
66
67 # Print the header for this new test and variation
68 prompt = test.PromptForVariation(self.curr_variation)
69 print color.Fore.WHITE + '-' * 80
70 print color.Fore.BLUE + test.name
71 print color.Fore.GREEN + prompt
72
Charlie Mooneydaaaa242015-02-03 14:20:23 -080073 # Start the function generator (if applicable)
74 if self.fn_generator:
75 waveform = test.WaveformForVariation(self.curr_variation)
76 if waveform:
77 self.fn_generator.GenerateFunction(*waveform)
78 else:
79 self.fn_generator.Off()
80
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080081 # Start collecting data
82 print 'Opening connection with DUT... ',
83 self.touch_dev.BeginEventStream()
84 print 'Connection established!'
85
86 # Wait a long time for the first event, then have a much shorter
87 # timeout on subsequent incoming events
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080088 events = []
Charlie Mooneyd5712b82015-02-23 12:06:59 -080089 plotter = TouchPlotter(self.touch_dev)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080090 print 'Waiting for 1st event...',
91 event = self.touch_dev.NextEvent(TestSuite.NO_EVENTS_DETECTED_TIMEOUT_S)
92 if not event:
Charlie Mooneye0d06c42015-01-27 11:32:51 -080093 print ('\rNo MT events collected before timeout (%d seconds)!' %
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080094 TestSuite.NO_EVENTS_DETECTED_TIMEOUT_S),
95 while event:
Charlie Mooney86b5cf12014-12-04 09:34:09 -080096 plotter.add_event(event)
Charlie Mooneye0d06c42015-01-27 11:32:51 -080097 print '\rCollected %d MT events' % len(events),
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080098 events.append(event)
99 event = self.touch_dev.NextEvent(test.timeout)
100 print
Charlie Mooney97d73c12015-01-09 08:57:03 -0800101 plot_image_png = plotter.end()
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800102
103 # Run the validators on these events
Charlie Mooneye0d06c42015-01-27 11:32:51 -0800104 snapshots = mt.process(events, protocol=self.touch_dev.protocol)
Charlie Mooneyaf9d5122014-12-04 15:15:52 -0800105 results = test.RunAllValidators(snapshots)
Charlie Mooney985cf402015-01-08 15:15:59 -0800106
Charlie Mooney5e9a10f2015-01-13 14:54:27 -0800107 # Bundle the Validator results with some details of which gesture was used
108 # during the test for easier debugging.
109 test_result = tests.TestResult(results, prompt, plot_image_png)
110
Charlie Mooney985cf402015-01-08 15:15:59 -0800111 # Add the results into our report (And have it print them to stdout, too)
Charlie Mooney5e9a10f2015-01-13 14:54:27 -0800112 self.report.AddTestResult(test_result, verbose=True)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800113
114 # Advance the test suite to the next test and variation and return an
115 # indicator as to whether this was the last thing to do or not.
116 next_test, next_var = self._Advance()
117 return (next_test is not None)
118
119 def _Advance(self):
120 """ Move on to the next test/variation pair
121
122 This function increments all the interal counters, according to the
123 number of tests, their variations, and the selected number of iterations
124 and returns the test object and the variation number that should be
125 done next.
126
127 When the TestSuite is complete, this function will return None, None
128 otherwise it will return the next Test object and the variation number
129 the test suite is on.
130 """
131 if self.curr_test >= len(self.tests):
132 return None, None
133 test = self.tests[self.curr_test]
134
135 if self.curr_variation >= len(test.variations):
136 self.curr_test += 1
137 self.curr_variation = 0
138 self.curr_iteration = 0
139 return self._Advance()
140
141 if self.curr_iteration >= self.options.num_iterations:
142 self.curr_variation += 1
143 self.curr_iteration = 0
144 return self._Advance()
145
146 self.curr_iteration += 1
147 return test, self.curr_variation