blob: f1b8dac2f30ecb639ad245338fd953a4c14452ed [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
7import tests
Charlie Mooney86b5cf12014-12-04 09:34:09 -08008from plotter import TouchPlotter
Charlie Mooney985cf402015-01-08 15:15:59 -08009from report import Report
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080010
11
12class TestSuite:
13 """ This class represents a collection of tests and is used to run them
14
15 A TestSuite object will set up a connection to the DUT, robot, etc, and
16 determine which tests can be run. Once the object is instantiated,
17 RunNextTestAndVariation() can be run repeatedly to work your way through
18 the entire suite.
19 """
20
Charlie Mooney389e1f32015-03-06 13:33:20 -080021 NO_SNAPSHOT_DETECTED_TIMEOUT_MANUAL_S = 60
22 NO_SNAPSHOT_DETECTED_TIMEOUT_ROBOT_S = 5
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080023
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 Mooney389e1f32015-03-06 13:33:20 -080048 self.no_snapshot_timeout = TestSuite.NO_SNAPSHOT_DETECTED_TIMEOUT_MANUAL_S
Charlie Mooneyda8e13f2015-02-24 11:32:05 -080049 if options.has_robot:
Charlie Mooney389e1f32015-03-06 13:33:20 -080050 self.no_snapshot_timeout = TestSuite.NO_SNAPSHOT_DETECTED_TIMEOUT_ROBOT_S
Charlie Mooneyda8e13f2015-02-24 11:32:05 -080051
Charlie Mooney985cf402015-01-08 15:15:59 -080052 # Create a new Report that will store all the test Results
53 self.report = Report()
54
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080055 def RunNextTestAndVariation(self):
56 """ Run the next test.
57
58 This function runs the next test/variation combination in the test suite
59 and advances the internal state to the next one automatically. When
60 finished, this function return True if there are more tests to run, and
61 False if the whole test suite is done.
62
63 After a TestSuite is instantiated, this function should be called
64 repeatedly until it returns False to go through all tests, variations,
65 and iterations.
66 """
Charlie Mooney73051762015-02-06 11:52:38 -080067 if self.curr_test >= len(self.tests):
68 return False
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080069 test = self.tests[self.curr_test]
70
71 # Print the header for this new test and variation
72 prompt = test.PromptForVariation(self.curr_variation)
73 print color.Fore.WHITE + '-' * 80
74 print color.Fore.BLUE + test.name
75 print color.Fore.GREEN + prompt
76
Charlie Mooneydaaaa242015-02-03 14:20:23 -080077 # Start the function generator (if applicable)
78 if self.fn_generator:
79 waveform = test.WaveformForVariation(self.curr_variation)
80 if waveform:
81 self.fn_generator.GenerateFunction(*waveform)
82 else:
83 self.fn_generator.Off()
84
Charlie Mooney389e1f32015-03-06 13:33:20 -080085 # Consume any stray events that happened since the last gesture
86 print 'Waiting for all contacts to leave before recording the gesture...'
87 self.touch_dev.FlushSnapshotBuffer()
Charlie Mooney3cca6ba2014-11-19 16:15:28 -080088
89 # Wait a long time for the first event, then have a much shorter
90 # timeout on subsequent incoming events
Charlie Mooney389e1f32015-03-06 13:33:20 -080091 snapshots = []
Charlie Mooney50171442015-03-17 15:24:51 -070092 plotter = TouchPlotter(self.touch_dev, window_title=prompt)
Charlie Mooney389e1f32015-03-06 13:33:20 -080093 print 'Waiting for 1st snapshot...',
94 snapshot = self.touch_dev.NextSnapshot(self.no_snapshot_timeout)
95 if not snapshot:
96 print ('\rNo MT snapshots collected before timeout (%d seconds)!' %
97 self.no_snapshot_timeout),
98 while snapshot:
99 plotter.add_snapshot(snapshot)
100 snapshots.append(snapshot)
101 print '\rCollected %d MT snapshots' % len(snapshots),
102 snapshot = self.touch_dev.NextSnapshot(test.timeout)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800103 print
Charlie Mooney173396c2015-03-19 15:25:41 -0700104
105 # Prompt to see if the gesture was performed acceptibly by the user before
106 # continuing. If the user is unsatisfied abort before advancing on to the
107 # next test/variation, allowing the test suite to retry this variation.
108 if not self.options.has_robot:
109 CONFIRMATION_PROMPT = 'Accept Gesture? ([y]/n) '
110 yorn = raw_input(CONFIRMATION_PROMPT).lower()
111 while yorn not in ['y', 'n', 'yes', 'no', '']:
112 print color.Fore.RED + 'Error: please enter "y" or "n" only'
113 yorn = raw_input(CONFIRMATION_PROMPT).lower()
114 plot_image_png = plotter.end()
115 if yorn in ['n', 'no']:
116 print color.Fore.RED + 'Operator rejected the gesture. Please retry...'
117 return True
118 else:
119 plot_image_png = plotter.end()
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800120
121 # Run the validators on these events
Charlie Mooneyaf9d5122014-12-04 15:15:52 -0800122 results = test.RunAllValidators(snapshots)
Charlie Mooney985cf402015-01-08 15:15:59 -0800123
Charlie Mooney5e9a10f2015-01-13 14:54:27 -0800124 # Bundle the Validator results with some details of which gesture was used
125 # during the test for easier debugging.
126 test_result = tests.TestResult(results, prompt, plot_image_png)
127
Charlie Mooney985cf402015-01-08 15:15:59 -0800128 # Add the results into our report (And have it print them to stdout, too)
Charlie Mooney5e9a10f2015-01-13 14:54:27 -0800129 self.report.AddTestResult(test_result, verbose=True)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800130
131 # Advance the test suite to the next test and variation and return an
132 # indicator as to whether this was the last thing to do or not.
133 next_test, next_var = self._Advance()
134 return (next_test is not None)
135
136 def _Advance(self):
137 """ Move on to the next test/variation pair
138
139 This function increments all the interal counters, according to the
140 number of tests, their variations, and the selected number of iterations
141 and returns the test object and the variation number that should be
142 done next.
143
144 When the TestSuite is complete, this function will return None, None
145 otherwise it will return the next Test object and the variation number
146 the test suite is on.
147 """
148 if self.curr_test >= len(self.tests):
149 return None, None
150 test = self.tests[self.curr_test]
151
152 if self.curr_variation >= len(test.variations):
153 self.curr_test += 1
154 self.curr_variation = 0
155 self.curr_iteration = 0
156 return self._Advance()
157
158 if self.curr_iteration >= self.options.num_iterations:
159 self.curr_variation += 1
160 self.curr_iteration = 0
161 return self._Advance()
162
163 self.curr_iteration += 1
164 return test, self.curr_variation