Merge ~sylvain-pineau/checkbox-support:fwts_test_no_syslog into checkbox-support:master

Proposed by Sylvain Pineau
Status: Merged
Approved by: Sylvain Pineau
Approved revision: 47e1157017fb62c3e543694167bf01d566872b9e
Merged at revision: 1b7847741010f40b8135fb54fb1a5761b85f1b2f
Proposed branch: ~sylvain-pineau/checkbox-support:fwts_test_no_syslog
Merge into: checkbox-support:master
Diff against target: 219 lines (+37/-104)
1 file modified
checkbox_support/scripts/fwts_test.py (+37/-104)
Reviewer Review Type Date Requested Status
Maciej Kisielewski Approve
Sylvain Pineau (community) Needs Resubmitting
Review via email: mp+354789@code.launchpad.net

Description of the change

Compute suspend/resume timings from fwts logs to deprecate using syslog.

Tested using suspend/suspend_advanced and a modified version to suspend just 3 times with:

  set -o pipefail; checkbox-support-fwts_test -f none -l $PLAINBOX_SESSION_SHARE/suspend_single -s s3 --s3-sleep-delay=7 --s3-device-check --s3-device-check-delay=15 --s3-multiple=3 | tee $PLAINBOX_SESSION_SHARE/suspend_single_times.log

To post a comment you must log in.
Revision history for this message
Maciej Kisielewski (kissiel) wrote :

Nice stuff. I found one way I think could improve it (see below).
+1

review: Approve
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

fixed following Maciej's advice

review: Needs Resubmitting
Revision history for this message
Maciej Kisielewski (kissiel) wrote :

+1!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/checkbox_support/scripts/fwts_test.py b/checkbox_support/scripts/fwts_test.py
2index f5be29f..3111217 100644
3--- a/checkbox_support/scripts/fwts_test.py
4+++ b/checkbox_support/scripts/fwts_test.py
5@@ -2,10 +2,8 @@
6
7 import sys
8 import re
9-from time import time
10 from argparse import ArgumentParser, RawTextHelpFormatter, REMAINDER
11-from subprocess import Popen, PIPE
12-from syslog import syslog, LOG_INFO
13+from subprocess import Popen, PIPE, DEVNULL
14 from shutil import which
15 import os
16
17@@ -48,42 +46,29 @@ HWE_TESTS = ['version',
18 'oops']
19 # By default, we launch all the tests
20 TESTS = sorted(list(set(QA_TESTS + HWE_TESTS)))
21+SLEEP_TIME_RE = re.compile('(Suspend|Resume):\s+([\d\.]+)\s+seconds.')
22
23
24-def get_sleep_times(start_marker, end_marker, sleep_time, resume_time):
25- logfile = '/var/log/syslog'
26- log_fh = open(logfile, 'r', encoding='UTF-8')
27- line = ''
28- run = 'FAIL'
29- sleep_start_time = 0.0
30- sleep_end_time = 0.0
31- resume_start_time = 0.0
32- resume_end_time = 0.0
33-
34- while start_marker not in line:
35- try:
36- line = log_fh.readline()
37- except UnicodeDecodeError:
38- continue
39- if start_marker in line:
40- loglist = log_fh.readlines()
41-
42- for idx in range(0, len(loglist)):
43- if 'PM: Syncing filesystems' in loglist[idx]:
44- sleep_start_time = re.split('[\[\]]', loglist[idx])[1].strip()
45- if 'ACPI: Low-level resume complete' in loglist[idx]:
46- sleep_end_time = re.split('[\[\]]', loglist[idx - 1])[1].strip()
47- resume_start_time = re.split('[\[\]]', loglist[idx])[1].strip()
48- idx += 1
49- if 'Restarting tasks' in loglist[idx]:
50- resume_end_time = re.split('[\[\]]', loglist[idx])[1].strip()
51- if end_marker in loglist[idx]:
52- run = 'PASS'
53- break
54-
55- sleep_elapsed = float(sleep_end_time) - float(sleep_start_time)
56- resume_elapsed = float(resume_end_time) - float(resume_start_time)
57- return (run, sleep_elapsed, resume_elapsed)
58+def get_sleep_times(log, start_marker):
59+ suspend_time = ''
60+ resume_time = ''
61+ with open(log, 'r', encoding='UTF-8', errors = 'ignore') as f:
62+ line = ''
63+ while start_marker not in line:
64+ line = f.readline()
65+ if start_marker in line:
66+ loglist = f.readlines()
67+ for i, l in enumerate(loglist):
68+ if 'Suspend/Resume Timings:' in l:
69+ suspend_line = loglist[i+1]
70+ resume_line = loglist[i+2]
71+ match = SLEEP_TIME_RE.search(suspend_line)
72+ if match:
73+ suspend_time = float(match.group(2))
74+ match = SLEEP_TIME_RE.search(resume_line)
75+ if match:
76+ resume_time = float(match.group(2))
77+ return (suspend_time, resume_time)
78
79
80 def average_times(runs):
81@@ -92,8 +77,8 @@ def average_times(runs):
82 run_count = 0
83 for run in runs.keys():
84 run_count += 1
85- sleep_total += runs[run][1]
86- resume_total += runs[run][2]
87+ sleep_total += runs[run][0]
88+ resume_total += runs[run][1]
89 sleep_avg = sleep_total / run_count
90 resume_avg = resume_total / run_count
91 print('Average time to sleep: %0.5f' % sleep_avg)
92@@ -163,25 +148,6 @@ def main():
93 'test as FAILED_CRITICAL. You will still be '
94 'notified of all FWTS test failures. '
95 '[Default level: %(default)s]'))
96- sleep_args = parser.add_argument_group('Sleep Options',
97- ('The following arguments are to '
98- 'only be used with the '
99- '--sleep test option'))
100- sleep_args.add_argument('--sleep-time',
101- dest='sleep_time',
102- action='store',
103- help=('The max time in seconds that a system '
104- 'should take\nto completely enter sleep. '
105- 'Anything more than this\ntime will cause '
106- 'that test iteration to fail.\n'
107- '[Default: 10s]'))
108- sleep_args.add_argument('--resume-time',
109- dest='resume_time',
110- action='store',
111- help=('Same as --sleep-time, except this applies '
112- 'to the\ntime it takes a system to fully '
113- 'wake from sleep.\n[Default: 3s]'))
114-
115 group = parser.add_mutually_exclusive_group()
116 group.add_argument('-t', '--test',
117 action='append',
118@@ -242,10 +208,6 @@ def main():
119 'FAILED_ABORTED': -1}
120 fail_priority = fail_levels[args.fail_level]
121
122- # Enforce only using sleep opts with --sleep
123- if args.sleep_time or args.resume_time and not args.sleep:
124- parser.error('--sleep-time and --resume-time only apply to the '
125- '--sleep testing option.')
126 if args.fwts_help:
127 Popen('fwts -h', shell=True).communicate()[0]
128 return 0
129@@ -278,23 +240,6 @@ def main():
130 if s4 in args.sleep:
131 iterations = int(args.sleep.pop(args.sleep.index(s4) + 1))
132 args.sleep.remove(s4)
133- # if we've passed our custom sleep arguments for resume or sleep
134- # time, we need to intercept those as well.
135- resume_time_arg = '--resume-time'
136- sleep_time_arg = '--sleep-time'
137- if resume_time_arg in args.sleep:
138- args.resume_time = int(args.sleep.pop(
139- args.sleep.index(resume_time_arg) + 1))
140- args.sleep.remove(resume_time_arg)
141- if sleep_time_arg in args.sleep:
142- args.sleep_time = int(args.sleep.pop(
143- args.sleep.index(sleep_time_arg) + 1))
144- args.sleep.remove(sleep_time_arg)
145- # if we still haven't set a sleep or resume time, use defauts.
146- if not args.sleep_time:
147- args.sleep_time = 10
148- if not args.resume_time:
149- args.resume_time = 3
150 tests.extend(args.sleep)
151 else:
152 tests.extend(TESTS)
153@@ -306,31 +251,22 @@ def main():
154 progress_indicator = None
155 if detect_progress_indicator():
156 progress_indicator = Popen(detect_progress_indicator(),
157- stdin=PIPE)
158- for iteration in range(0, iterations):
159- timestamp = int(time())
160- start_marker = 'CHECKBOX SLEEP TEST START %s' % timestamp
161- end_marker = 'CHECKBOX SLEEP TEST STOP %s' % timestamp
162- syslog(LOG_INFO, '---' + start_marker + '---' + str(time()))
163+ stdin=PIPE, stderr=DEVNULL)
164+ for iteration in range(1, iterations+1):
165+ marker = '{:=^80}\n'.format(' Iteration {} '.format(iteration))
166+ with open(args.log + '.log', 'a') as f:
167+ f.write(marker)
168 command = ('fwts -q --stdout-summary -r %s %s'
169 % (args.log, ' '.join(tests)))
170 results['sleep'] = (Popen(command, stdout=PIPE, shell=True)
171 .communicate()[0].strip()).decode()
172- syslog(LOG_INFO, '---' + end_marker + '---' + str(time()))
173 if 's4' not in args.sleep:
174- sleep_times = get_sleep_times(start_marker,
175- end_marker,
176- args.sleep_time,
177- args.resume_time)
178- iteration_results[iteration] = sleep_times
179- progress_tuple = (iteration,
180- iteration_results[iteration][0],
181- iteration_results[iteration][1],
182- iteration_results[iteration][2])
183- progress_string = (' - Cycle %s: Status: %s '
184- 'Sleep Elapsed: %0.5f '
185- 'Resume Elapsed: '
186- ' %0.5f' % progress_tuple)
187+ suspend_time, resume_time = get_sleep_times(args.log + '.log',
188+ marker)
189+ iteration_results[iteration] = (suspend_time, resume_time)
190+ progress_string = (
191+ 'Cycle %s/%s - Suspend: %0.2f s - Resume: %0.2f s'
192+ % (iteration, iterations, suspend_time, resume_time))
193 progress_pct = "{}".format(int(100 * iteration / iterations))
194 if "zenity" in detect_progress_indicator():
195 progress_indicator.stdin.write("# {}\n".format(
196@@ -354,15 +290,11 @@ def main():
197 if progress_indicator.poll() is None:
198 progress_indicator.stdin.flush()
199 else:
200- print(progress_string)
201+ print(progress_string, flush=True)
202 if detect_progress_indicator():
203 progress_indicator.terminate()
204-
205 if 's4' not in args.sleep:
206 average_times(iteration_results)
207- for run in iteration_results.keys():
208- if 'FAIL' in iteration_results[run]:
209- results['sleep'] = 'FAILED_CRITICAL'
210 else:
211 for test in tests:
212 # ACPI tests can now be run with --acpitests (fwts >= 15.07.00)
213@@ -451,5 +383,6 @@ def main():
214
215 return 0
216
217+
218 if __name__ == '__main__':
219 sys.exit(main())

Subscribers

People subscribed via source and target branches