blob: a469ffe7cf137da68e3515b87cb72f2223dcff91 [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 Mooneyd5712b82015-02-23 12:06:59 -080092 plotter = TouchPlotter(self.touch_dev)
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 Mooney97d73c12015-01-09 08:57:03 -0800104 plot_image_png = plotter.end()
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800105
106 # Run the validators on these events
Charlie Mooneyaf9d5122014-12-04 15:15:52 -0800107 results = test.RunAllValidators(snapshots)
Charlie Mooney985cf402015-01-08 15:15:59 -0800108
Charlie Mooney5e9a10f2015-01-13 14:54:27 -0800109 # Bundle the Validator results with some details of which gesture was used
110 # during the test for easier debugging.
111 test_result = tests.TestResult(results, prompt, plot_image_png)
112
Charlie Mooney985cf402015-01-08 15:15:59 -0800113 # Add the results into our report (And have it print them to stdout, too)
Charlie Mooney5e9a10f2015-01-13 14:54:27 -0800114 self.report.AddTestResult(test_result, verbose=True)
Charlie Mooney3cca6ba2014-11-19 16:15:28 -0800115
116 # Advance the test suite to the next test and variation and return an
117 # indicator as to whether this was the last thing to do or not.
118 next_test, next_var = self._Advance()
119 return (next_test is not None)
120
121 def _Advance(self):
122 """ Move on to the next test/variation pair
123
124 This function increments all the interal counters, according to the
125 number of tests, their variations, and the selected number of iterations
126 and returns the test object and the variation number that should be
127 done next.
128
129 When the TestSuite is complete, this function will return None, None
130 otherwise it will return the next Test object and the variation number
131 the test suite is on.
132 """
133 if self.curr_test >= len(self.tests):
134 return None, None
135 test = self.tests[self.curr_test]
136
137 if self.curr_variation >= len(test.variations):
138 self.curr_test += 1
139 self.curr_variation = 0
140 self.curr_iteration = 0
141 return self._Advance()
142
143 if self.curr_iteration >= self.options.num_iterations:
144 self.curr_variation += 1
145 self.curr_iteration = 0
146 return self._Advance()
147
148 self.curr_iteration += 1
149 return test, self.curr_variation