blob: 2fdee615220dffeefa262d32860d4a7be263bf94 [file] [log] [blame]
Allen Lif146e872017-08-15 18:24:31 -07001# 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
5"""Mock out test results for puppylab.
6"""
7
8
9import logging
10import os
11import time
12
13import common
14from autotest_lib.client.common_lib import time_utils
15
16# TODO(beeps): The right way to create these status logs is by creating a job
17# object and invoking job.record on it. However we perform this template
18# hack instead for the following reasons:
19# * The templates are a lot easier to understand at first glance, which
20# is really what one wants from a testing interface built for a
21# framework like autotest.
22# * Creating the job is wedged into core autotest code, so it has
23# unintended consequences like checking for hosts/labels etc.
24# * We are guaranteed to create the bare minimum by hand specifying the file
25# to write, and their contents. Job.record ends up checking and creating
26# several non-essential directoris in the process or recording status.
27
28_SUCCESS_TEST_TEMPLATE = (
29 "\tSTART\t%(test_name)s\t%(test_name)s"
30 "\ttimestamp=%(timestamp)s\tlocaltime=%(date)s\n"
31 "\t\tGOOD\t%(test_name)s\t%(test_name)s\ttimestamp=%(timestamp)s\t"
32 "localtime=%(date)s\tcompleted successfully\n"
33 "\tEND GOOD\t%(test_name)s\t%(test_name)s\ttimestamp=%(timestamp)s\t"
34 "localtime=%(date)s")
35
36
37_SUCCESS_JOB_TEMPLATE = (
38 "START\t----\t----\ttimestamp=%(timestamp)s\tlocaltime=%(date)s"
39 "\n\tSTART\t%(test_name)s\t%(test_name)s\ttimestamp=%(timestamp)s\t"
40 "localtime=%(date)s\n\t\tGOOD\t%(test_name)s\t%(test_name)s"
41 "\ttimestamp=%(timestamp)s\tlocaltime=%(date)s\tcompleted "
42 "successfully\n\tEND GOOD\t%(test_name)s\t%(test_name)s"
43 "\ttimestamp=%(timestamp)s\tlocaltime=%(date)s\n"
44 "END GOOD\t----\t----\ttimestamp=%(timestamp)s\tlocaltime=%(date)s")
45
46
47_JOB_KEYVALS_TEMPLATE = "hostname=%(hostname)s\nstatus_version=1\n"
48
49
50class ResultsMocker(object):
51 """Class to mock out the results of a test."""
52
53 def _make_dirs(self):
54 """Create essential directories needed for faking test results.
55
56 @raises ValueError: If the directories crucial to reporting
57 test status already exist.
58 @raises OSError: If we cannot make one of the directories for
59 an os related reason (eg: permissions).
60 @raises AssertionError: If one of the directories silently failed
61 creation.
62 """
63 logging.info("creating dir %s, %s, %s",
64 self.results_dir, self.test_results, self.host_keyval_dir)
65 if not os.path.exists(self.results_dir):
66 os.makedirs(self.results_dir)
67 if not os.path.exists(self.test_results):
68 os.makedirs(self.test_results)
69 if not os.path.exists(self.host_keyval_dir):
70 os.makedirs(self.host_keyval_dir)
71 assert(os.path.exists(self.test_results) and
72 os.path.exists(self.results_dir) and
73 os.path.exists(self.host_keyval_dir))
74
75
76 def __init__(self, test_name, results_dir, machine_name):
77 """Initialize a results mocker.
78
79 @param test_name: The name of the test, eg: dummy_Pass.
80 @param results_dir: The results directory this test will use.
81 @param machine_name: A string representing the hostname the test will
82 run on.
83 """
84 self.results_dir = results_dir
85 self.test_results = os.path.join(results_dir, test_name)
86 self.host_keyval_dir = os.path.join(self.results_dir, 'host_keyvals')
87 self.machine_name = machine_name
88 self.test_name = test_name
89
90 self._make_dirs()
91
92 # Status logs are used by the parser to declare a test as pass/fail.
93 self.job_status = os.path.join(self.results_dir, 'status')
94 self.job_status_log = os.path.join(self.results_dir, 'status.log')
95 self.test_status = os.path.join(self.test_results, 'status')
96
97 # keyvals are used by the parser to figure out fine grained information
98 # about a test. Only job_keyvals are crucial to parsing.
99 self.test_keyvals = os.path.join(self.test_results, 'keyval')
100 self.job_keyvals = os.path.join(self.results_dir, 'keyval')
101 self.host_keyvals = os.path.join(self.results_dir, machine_name)
102
103
104 def _write(self, results_path, results):
105 """Write the content in results to the file in results_path.
106
107 @param results_path: The path to the results file.
108 @param results: The content to write to the file.
109 """
110 logging.info('Writing results to %s', results_path)
111 with open(results_path, 'w') as results_file:
112 results_file.write(results)
113
114
115 def generate_keyvals(self):
116 """Apply templates to keyval files.
117
118 There are 3 important keyvals files, only one of which is actually
119 crucial to results parsing:
120 host_keyvals - information about the DUT
121 job_keyvals - information about the server_job
122 test_keyvals - information about the test
123
124 Parsing cannot complete without the job_keyvals. Everything else is
125 optional. Keyvals are parsed into tko tables.
126 """
127 #TODO(beeps): Include other keyvals.
128 self._write(
129 self.job_keyvals,
130 _JOB_KEYVALS_TEMPLATE %
131 {'hostname': self.machine_name})
132
133
134 def generate_status(self):
135 """Generate status logs.
136
137 3 important status logs are required for successful parsing:
138 test_name/status - core test status
139 results_dir/status - server job status (has test status in it)
140 status.log - compiled final status log
141 """
142 current_timestamp = int(time.time())
143 test_info = {
144 'test_name': self.test_name,
145 'timestamp': current_timestamp,
146 'date': time_utils.epoch_time_to_date_string(
147 current_timestamp, fmt_string='%b %d %H:%M:%S'),
148 }
149 self._write(
150 self.job_status,
151 _SUCCESS_JOB_TEMPLATE % test_info)
152 self._write(
153 self.job_status_log,
154 _SUCCESS_JOB_TEMPLATE % test_info)
155 self._write(
156 self.test_status,
157 _SUCCESS_TEST_TEMPLATE % test_info)
158
159
160 def mock_results(self):
161 """Create mock results in the directories used to init the instance."""
162 self.generate_status()
163 self.generate_keyvals()
164
165