blob: fc2bc389350ab76c801485d64c268537d0082722 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001import os
2import unittest
3import subprocess
4from oeqa.oetest import oeRuntimeTest
5from oeqa.utils.decorators import *
6
7#in the future these lists could be moved outside of module
8errors = ["error", "cannot", "can\'t", "failed"]
9
10common_errors = [
11 "(WW) warning, (EE) error, (NI) not implemented, (??) unknown.",
12 "dma timeout",
13 "can\'t add hid device:",
14 "usbhid: probe of ",
15 "_OSC failed (AE_ERROR)",
16 "_OSC failed (AE_SUPPORT)",
17 "AE_ALREADY_EXISTS",
18 "ACPI _OSC request failed (AE_SUPPORT)",
19 "can\'t disable ASPM",
20 "Failed to load module \"vesa\"",
21 "Failed to load module vesa",
22 "Failed to load module \"modesetting\"",
23 "Failed to load module modesetting",
24 "Failed to load module \"glx\"",
25 "Failed to load module \"fbdev\"",
26 "Failed to load module fbdev",
27 "Failed to load module glx",
28 "[drm] Cannot find any crtc or sizes - going 1024x768",
29 "_OSC failed (AE_NOT_FOUND); disabling ASPM",
30 "Open ACPI failed (/var/run/acpid.socket) (No such file or directory)",
31 "NX (Execute Disable) protection cannot be enabled: non-PAE kernel!",
32 "hd.: possibly failed opcode",
33 'NETLINK INITIALIZATION FAILED',
34 'kernel: Cannot find map file',
35 'omap_hwmod: debugss: _wait_target_disable failed',
36 'VGA arbiter: cannot open kernel arbiter, no multi-card support',
37 'Failed to find URL:http://ipv4.connman.net/online/status.html',
38 'Online check failed for',
Patrick Williamsf1e5d692016-03-30 15:21:19 -050039 'netlink init failed',
40 'Fast TSC calibration',
Patrick Williamsc124f4f2015-09-15 14:41:29 -050041 ]
42
43x86_common = [
44 '[drm:psb_do_init] *ERROR* Debug is',
45 'wrong ELF class',
46 'Could not enable PowerButton event',
47 'probe of LNXPWRBN:00 failed with error -22',
48] + common_errors
49
50qemux86_common = [
Patrick Williamsc124f4f2015-09-15 14:41:29 -050051 'wrong ELF class',
52 "fail to add MMCONFIG information, can't access extended PCI configuration space under this bridge.",
53 "can't claim BAR ",
54] + common_errors
55
56ignore_errors = {
57 'default' : common_errors,
58 'qemux86' : [
59 'Failed to access perfctr msr (MSR',
60 ] + qemux86_common,
61 'qemux86-64' : qemux86_common,
62 'qemumips' : [
63 'Failed to load module "glx"',
64 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
65 ] + common_errors,
66 'qemumips64' : [
67 'pci 0000:00:00.0: [Firmware Bug]: reg 0x..: invalid BAR (can\'t size)',
68 ] + common_errors,
69 'qemuppc' : [
70 'PCI 0000:00 Cannot reserve Legacy IO [io 0x0000-0x0fff]',
71 'host side 80-wire cable detection failed, limiting max speed',
72 'mode "640x480" test failed',
73 'Failed to load module "glx"',
74 ] + common_errors,
75 'qemuarm' : [
76 'mmci-pl18x: probe of fpga:05 failed with error -22',
77 'mmci-pl18x: probe of fpga:0b failed with error -22',
78 'Failed to load module "glx"'
79 ] + common_errors,
80 'qemuarm64' : [
81 'Fatal server error:',
82 '(EE) Server terminated with error (1). Closing log file.',
83 ] + common_errors,
84 'emenlow' : [
85 '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
86 '(EE) Failed to load module "psb"',
87 '(EE) Failed to load module psb',
88 '(EE) Failed to load module "psbdrv"',
89 '(EE) Failed to load module psbdrv',
90 '(EE) open /dev/fb0: No such file or directory',
91 '(EE) AIGLX: reverting to software rendering',
92 ] + x86_common,
Patrick Williamsf1e5d692016-03-30 15:21:19 -050093 'intel-core2-32' : [
Patrick Williamsc124f4f2015-09-15 14:41:29 -050094 'ACPI: No _BQC method, cannot determine initial brightness',
95 '[Firmware Bug]: ACPI: No _BQC method, cannot determine initial brightness',
96 '(EE) Failed to load module "psb"',
97 '(EE) Failed to load module psb',
98 '(EE) Failed to load module "psbdrv"',
99 '(EE) Failed to load module psbdrv',
100 '(EE) open /dev/fb0: No such file or directory',
101 '(EE) AIGLX: reverting to software rendering',
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500102 "controller can't do DEVSLP, turning off",
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500103 ] + x86_common,
104 'intel-corei7-64' : [
105 "controller can't do DEVSLP, turning off",
106 ] + common_errors,
107 'crownbay' : x86_common,
108 'genericx86' : x86_common,
109 'genericx86-64' : x86_common,
110 'edgerouter' : [
111 'Fatal server error:',
112 ] + common_errors,
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500113 'jasperforest' : [
114 'Activated service \'org.bluez\' failed:',
115 'Unable to find NFC netlink family',
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500116 ] + common_errors,
117}
118
119log_locations = ["/var/log/","/var/log/dmesg", "/tmp/dmesg_output.log"]
120
121class ParseLogsTest(oeRuntimeTest):
122
123 @classmethod
124 def setUpClass(self):
125 self.errors = errors
126 self.ignore_errors = ignore_errors
127 self.log_locations = log_locations
128 self.msg = ""
129
130 def getMachine(self):
131 return oeRuntimeTest.tc.d.getVar("MACHINE", True)
132
133 #get some information on the CPU of the machine to display at the beginning of the output. This info might be useful in some cases.
134 def getHardwareInfo(self):
135 hwi = ""
136 (status, cpu_name) = self.target.run("cat /proc/cpuinfo | grep \"model name\" | head -n1 | awk 'BEGIN{FS=\":\"}{print $2}'")
137 (status, cpu_physical_cores) = self.target.run("cat /proc/cpuinfo | grep \"cpu cores\" | head -n1 | awk {'print $4'}")
138 (status, cpu_logical_cores) = self.target.run("cat /proc/cpuinfo | grep \"processor\" | wc -l")
139 (status, cpu_arch) = self.target.run("uname -m")
140 hwi += "Machine information: \n"
141 hwi += "*******************************\n"
142 hwi += "Machine name: "+self.getMachine()+"\n"
143 hwi += "CPU: "+str(cpu_name)+"\n"
144 hwi += "Arch: "+str(cpu_arch)+"\n"
145 hwi += "Physical cores: "+str(cpu_physical_cores)+"\n"
146 hwi += "Logical cores: "+str(cpu_logical_cores)+"\n"
147 hwi += "*******************************\n"
148 return hwi
149
150 #go through the log locations provided and if it's a folder create a list with all the .log files in it, if it's a file just add
151 #it to that list
152 def getLogList(self, log_locations):
153 logs = []
154 for location in log_locations:
155 (status, output) = self.target.run("test -f "+str(location))
156 if (status == 0):
157 logs.append(str(location))
158 else:
159 (status, output) = self.target.run("test -d "+str(location))
160 if (status == 0):
161 (status, output) = self.target.run("find "+str(location)+"/*.log -maxdepth 1 -type f")
162 if (status == 0):
163 output = output.splitlines()
164 for logfile in output:
165 logs.append(os.path.join(location,str(logfile)))
166 return logs
167
168 #copy the log files to be parsed locally
169 def transfer_logs(self, log_list):
170 target_logs = 'target_logs'
171 if not os.path.exists(target_logs):
172 os.makedirs(target_logs)
173 for f in log_list:
174 self.target.copy_from(f, target_logs)
175
176 #get the local list of logs
177 def get_local_log_list(self, log_locations):
178 self.transfer_logs(self.getLogList(log_locations))
179 logs = [ os.path.join('target_logs',f) for f in os.listdir('target_logs') if os.path.isfile(os.path.join('target_logs',f)) ]
180 return logs
181
182 #build the grep command to be used with filters and exclusions
183 def build_grepcmd(self, errors, ignore_errors, log):
184 grepcmd = "grep "
185 grepcmd +="-Ei \""
186 for error in errors:
187 grepcmd += error+"|"
188 grepcmd = grepcmd[:-1]
189 grepcmd += "\" "+str(log)+" | grep -Eiv \'"
190 try:
191 errorlist = ignore_errors[self.getMachine()]
192 except KeyError:
193 self.msg += "No ignore list found for this machine, using default\n"
194 errorlist = ignore_errors['default']
195 for ignore_error in errorlist:
196 ignore_error = ignore_error.replace("(", "\(")
197 ignore_error = ignore_error.replace(")", "\)")
198 ignore_error = ignore_error.replace("'", ".")
199 ignore_error = ignore_error.replace("?", "\?")
200 ignore_error = ignore_error.replace("[", "\[")
201 ignore_error = ignore_error.replace("]", "\]")
202 ignore_error = ignore_error.replace("*", "\*")
203 grepcmd += ignore_error+"|"
204 grepcmd = grepcmd[:-1]
205 grepcmd += "\'"
206 return grepcmd
207
208 #grep only the errors so that their context could be collected. Default context is 10 lines before and after the error itself
209 def parse_logs(self, errors, ignore_errors, logs, lines_before = 10, lines_after = 10):
210 results = {}
211 rez = []
212 grep_output = ''
213 for log in logs:
214 result = None
215 thegrep = self.build_grepcmd(errors, ignore_errors, log)
216 try:
217 result = subprocess.check_output(thegrep, shell=True)
218 except:
219 pass
220 if (result is not None):
221 results[log.replace('target_logs/','')] = {}
222 rez = result.splitlines()
223 for xrez in rez:
224 command = "grep \"\\"+str(xrez)+"\" -B "+str(lines_before)+" -A "+str(lines_after)+" "+str(log)
225 try:
226 grep_output = subprocess.check_output(command, shell=True)
227 except:
228 pass
229 results[log.replace('target_logs/','')][xrez]=grep_output
230 return results
231
232 #get the output of dmesg and write it in a file. This file is added to log_locations.
233 def write_dmesg(self):
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500234 (status, dmesg) = self.target.run("dmesg > /tmp/dmesg_output.log")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500235
236 @testcase(1059)
237 @skipUnlessPassed('test_ssh')
238 def test_parselogs(self):
239 self.write_dmesg()
240 log_list = self.get_local_log_list(self.log_locations)
241 result = self.parse_logs(self.errors, self.ignore_errors, log_list)
242 print self.getHardwareInfo()
243 errcount = 0
244 for log in result:
245 self.msg += "Log: "+log+"\n"
246 self.msg += "-----------------------\n"
247 for error in result[log]:
248 errcount += 1
249 self.msg += "Central error: "+str(error)+"\n"
250 self.msg += "***********************\n"
251 self.msg += result[str(log)][str(error)]+"\n"
252 self.msg += "***********************\n"
253 self.msg += "%s errors found in logs." % errcount
254 self.assertEqual(errcount, 0, msg=self.msg)