1*9c5db199SXin Li# Copyright 2022 The Chromium OS Authors. All rights reserved. 2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 3*9c5db199SXin Li# found in the LICENSE file. 4*9c5db199SXin Li 5*9c5db199SXin Liimport os 6*9c5db199SXin Liimport shutil 7*9c5db199SXin Li 8*9c5db199SXin Lifrom autotest_lib.server import autotest, test 9*9c5db199SXin Lifrom autotest_lib.client.common_lib import error 10*9c5db199SXin Li 11*9c5db199SXin Li 12*9c5db199SXin Liclass test_sequence(test.test): 13*9c5db199SXin Li """ 14*9c5db199SXin Li test_sequence extends the base test implementation to allow for 15*9c5db199SXin Li encapsulating a series of (client or server) tests which must 16*9c5db199SXin Li be run in a given sequence. 17*9c5db199SXin Li """ 18*9c5db199SXin Li 19*9c5db199SXin Li def initialize(self, sequence): 20*9c5db199SXin Li """ 21*9c5db199SXin Li initialize implements the initialize call in test.test, is called before 22*9c5db199SXin Li execution of the test 23*9c5db199SXin Li 24*9c5db199SXin Li @param sequence: the sequence of tests constructed in the wrapper 25*9c5db199SXin Li @param sequence_verdicts: verdicts from each executed test in the 26*9c5db199SXin Li sequence. Passed by reference and used by the caller to 27*9c5db199SXin Li annotate results. 28*9c5db199SXin Li """ 29*9c5db199SXin Li self._sequenced_tests = sequence 30*9c5db199SXin Li self._sequence_verdicts = {} 31*9c5db199SXin Li self._results_path = self.job._server_offload_dir_path() 32*9c5db199SXin Li self._wrapper_results_dir = os.path.join(self._results_path, 33*9c5db199SXin Li self.tagged_testname) 34*9c5db199SXin Li 35*9c5db199SXin Li def process_test_results_post_hook(self): 36*9c5db199SXin Li """ 37*9c5db199SXin Li process_test_results is used as a post_run_hook to record results to the 38*9c5db199SXin Li status.log file following the execution of the run. For tests that were 39*9c5db199SXin Li completed (i.e. no exceptions occurred to end the sequence), results are 40*9c5db199SXin Li moved to the top level from the child results directory 41*9c5db199SXin Li """ 42*9c5db199SXin Li for test, args, server_test in self._sequenced_tests: 43*9c5db199SXin Li if test not in self._sequence_verdicts: 44*9c5db199SXin Li continue 45*9c5db199SXin Li 46*9c5db199SXin Li if server_test: 47*9c5db199SXin Li self.surface_server_test_resultsdir(test) 48*9c5db199SXin Li else: 49*9c5db199SXin Li self.surface_client_test_resultsdir(test) 50*9c5db199SXin Li annotated_testname = self.tagged_testname + "." + test 51*9c5db199SXin Li self.job.record('START', None, annotated_testname) 52*9c5db199SXin Li self.job.record('INFO', None, annotated_testname) 53*9c5db199SXin Li if self._sequence_verdicts[test]: 54*9c5db199SXin Li self.job.record('END GOOD', None, annotated_testname, "") 55*9c5db199SXin Li else: 56*9c5db199SXin Li self.job.record('END FAIL', None, annotated_testname, "") 57*9c5db199SXin Li 58*9c5db199SXin Li def execute_sequenced_test(self, client, test, argv, server_test): 59*9c5db199SXin Li """ 60*9c5db199SXin Li execute_sequenced_test runs a single test from the sequence with the 61*9c5db199SXin Li given argument vector 62*9c5db199SXin Li 63*9c5db199SXin Li @param test: test name (url) to run 64*9c5db199SXin Li @param argv: argument dictionary to run the test with 65*9c5db199SXin Li 66*9c5db199SXin Li @raises error.TestFail: on failure of the wrapped tests 67*9c5db199SXin Li """ 68*9c5db199SXin Li try: 69*9c5db199SXin Li self._sequence_verdicts[test] = True 70*9c5db199SXin Li if server_test: 71*9c5db199SXin Li err = self.job.run_test(test, **argv) 72*9c5db199SXin Li if err == False: 73*9c5db199SXin Li raise error.TestFail() 74*9c5db199SXin Li else: 75*9c5db199SXin Li client.run_test(test, check_client_result=True, **argv) 76*9c5db199SXin Li except: 77*9c5db199SXin Li self._sequence_verdicts[test] = False 78*9c5db199SXin Li self.postprocess() 79*9c5db199SXin Li raise error.TestFail('Sequenced test %s failed, reason: ' % test) 80*9c5db199SXin Li 81*9c5db199SXin Li def surface_client_test_resultsdir(self, test): 82*9c5db199SXin Li """ 83*9c5db199SXin Li surface_client_test_resultsdir retrieves the child test results from a 84*9c5db199SXin Li sequenced client job 85*9c5db199SXin Li 86*9c5db199SXin Li @param test: the child test name to grab results from 87*9c5db199SXin Li """ 88*9c5db199SXin Li wrapped_test_results_path = os.path.join(self._wrapper_results_dir, 89*9c5db199SXin Li test) 90*9c5db199SXin Li tagged_destination = os.path.join(self._results_path, 91*9c5db199SXin Li self.tagged_testname + "." + test) 92*9c5db199SXin Li shutil.move(wrapped_test_results_path, tagged_destination) 93*9c5db199SXin Li 94*9c5db199SXin Li def surface_server_test_resultsdir(self, test): 95*9c5db199SXin Li """ 96*9c5db199SXin Li surface_server_test_resultsdir renames the server test results from a sequenced child 97*9c5db199SXin Li 98*9c5db199SXin Li @param test: the child test name to grab results from 99*9c5db199SXin Li """ 100*9c5db199SXin Li wrapped_test_results_path = os.path.join(self._results_path, test) 101*9c5db199SXin Li tagged_destination = os.path.join(self._results_path, 102*9c5db199SXin Li self.tagged_testname + "." + test) 103*9c5db199SXin Li shutil.move(wrapped_test_results_path, tagged_destination) 104*9c5db199SXin Li 105*9c5db199SXin Li def run_once(self, host=None): 106*9c5db199SXin Li """ 107*9c5db199SXin Li run_once implements the run_once call in test.test, is called to begin 108*9c5db199SXin Li execution of the test 109*9c5db199SXin Li 110*9c5db199SXin Li @param host: host from control file with which to run the test 111*9c5db199SXin Li """ 112*9c5db199SXin Li client_at = autotest.Autotest(host) 113*9c5db199SXin Li for test, argv, server_test in self._sequenced_tests: 114*9c5db199SXin Li self.execute_sequenced_test(client_at, test, argv, server_test) 115*9c5db199SXin Li 116*9c5db199SXin Li def postprocess(self): 117*9c5db199SXin Li """ 118*9c5db199SXin Li postprocess is the post routine for test.test. We must add our post_hook 119*9c5db199SXin Li in this function (as opposed to the initialize call) because if added in 120*9c5db199SXin Li initialize, this will be called after each child server test as well as 121*9c5db199SXin Li at the end of the function 122*9c5db199SXin Li """ 123*9c5db199SXin Li self.job.add_post_run_hook(self.process_test_results_post_hook) 124