blob: 0fe68d4d521139af1814e062878afbf1edaa8b02 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# Copyright (C) 2013 Intel Corporation
2#
3# Released under the MIT license (see COPYING.MIT)
4
5# Main unittest module used by testimage.bbclass
6# This provides the oeRuntimeTest base class which is inherited by all tests in meta/lib/oeqa/runtime.
7
8# It also has some helper functions and it's responsible for actually starting the tests
9
10import os, re, mmap
11import unittest
12import inspect
13import subprocess
14import bb
15from oeqa.utils.decorators import LogResults, gettag
16from sys import exc_info, exc_clear
17
18def getVar(obj):
19 #extend form dict, if a variable didn't exists, need find it in testcase
20 class VarDict(dict):
21 def __getitem__(self, key):
22 return gettag(obj, key)
23 return VarDict()
24
25def checkTags(tc, tagexp):
26 return eval(tagexp, None, getVar(tc))
27
28
29def filterByTagExp(testsuite, tagexp):
30 if not tagexp:
31 return testsuite
32 caseList = []
33 for each in testsuite:
34 if not isinstance(each, unittest.BaseTestSuite):
35 if checkTags(each, tagexp):
36 caseList.append(each)
37 else:
38 caseList.append(filterByTagExp(each, tagexp))
39 return testsuite.__class__(caseList)
40
41def loadTests(tc, type="runtime"):
42 if type == "runtime":
43 # set the context object passed from the test class
44 setattr(oeTest, "tc", tc)
45 # set ps command to use
46 setattr(oeRuntimeTest, "pscmd", "ps -ef" if oeTest.hasPackage("procps") else "ps")
47 # prepare test suite, loader and runner
48 suite = unittest.TestSuite()
49 elif type == "sdk":
50 # set the context object passed from the test class
51 setattr(oeTest, "tc", tc)
52 testloader = unittest.TestLoader()
53 testloader.sortTestMethodsUsing = None
54 suites = [testloader.loadTestsFromName(name) for name in tc.testslist]
55 suites = filterByTagExp(suites, getattr(tc, "tagexp", None))
56
57 def getTests(test):
58 '''Return all individual tests executed when running the suite.'''
59 # Unfortunately unittest does not have an API for this, so we have
60 # to rely on implementation details. This only needs to work
61 # for TestSuite containing TestCase.
62 method = getattr(test, '_testMethodName', None)
63 if method:
64 # leaf case: a TestCase
65 yield test
66 else:
67 # Look into TestSuite.
68 tests = getattr(test, '_tests', [])
69 for t1 in tests:
70 for t2 in getTests(t1):
71 yield t2
72
73 # Determine dependencies between suites by looking for @skipUnlessPassed
74 # method annotations. Suite A depends on suite B if any method in A
75 # depends on a method on B.
76 for suite in suites:
77 suite.dependencies = []
78 suite.depth = 0
79 for test in getTests(suite):
80 methodname = getattr(test, '_testMethodName', None)
81 if methodname:
82 method = getattr(test, methodname)
83 depends_on = getattr(method, '_depends_on', None)
84 if depends_on:
85 for dep_suite in suites:
86 if depends_on in [getattr(t, '_testMethodName', None) for t in getTests(dep_suite)]:
87 if dep_suite not in suite.dependencies and \
88 dep_suite is not suite:
89 suite.dependencies.append(dep_suite)
90 break
91 else:
92 bb.warn("Test %s was declared as @skipUnlessPassed('%s') but that test is either not defined or not active. Will run the test anyway." %
93 (test, depends_on))
94 # Use brute-force topological sort to determine ordering. Sort by
95 # depth (higher depth = must run later), with original ordering to
96 # break ties.
97 def set_suite_depth(suite):
98 for dep in suite.dependencies:
99 new_depth = set_suite_depth(dep) + 1
100 if new_depth > suite.depth:
101 suite.depth = new_depth
102 return suite.depth
103 for index, suite in enumerate(suites):
104 set_suite_depth(suite)
105 suite.index = index
106 suites.sort(cmp=lambda a,b: cmp((a.depth, a.index), (b.depth, b.index)))
107 return testloader.suiteClass(suites)
108
109def runTests(tc, type="runtime"):
110
111 suite = loadTests(tc, type)
112 bb.note("Test modules %s" % tc.testslist)
113 if hasattr(tc, "tagexp") and tc.tagexp:
114 bb.note("Filter test cases by tags: %s" % tc.tagexp)
115 bb.note("Found %s tests" % suite.countTestCases())
116 runner = unittest.TextTestRunner(verbosity=2)
117 result = runner.run(suite)
118
119 return result
120
121@LogResults
122class oeTest(unittest.TestCase):
123
124 longMessage = True
125
126 @classmethod
127 def hasPackage(self, pkg):
128 for item in oeTest.tc.pkgmanifest.split('\n'):
129 if re.match(pkg, item):
130 return True
131 return False
132
133 @classmethod
134 def hasFeature(self,feature):
135
136 if feature in oeTest.tc.imagefeatures or \
137 feature in oeTest.tc.distrofeatures:
138 return True
139 else:
140 return False
141
142class oeRuntimeTest(oeTest):
143 def __init__(self, methodName='runTest'):
144 self.target = oeRuntimeTest.tc.target
145 super(oeRuntimeTest, self).__init__(methodName)
146
147 def setUp(self):
148 # Check if test needs to run
149 if self.tc.sigterm:
150 self.fail("Got SIGTERM")
151 elif (type(self.target).__name__ == "QemuTarget"):
152 self.assertTrue(self.target.check(), msg = "Qemu not running?")
153
154 def tearDown(self):
155 # If a test fails or there is an exception
156 if not exc_info() == (None, None, None):
157 exc_clear()
158 #Only dump for QemuTarget
159 if (type(self.target).__name__ == "QemuTarget"):
160 self.tc.host_dumper.create_dir(self._testMethodName)
161 self.tc.host_dumper.dump_host()
162 self.target.target_dumper.dump_target(
163 self.tc.host_dumper.dump_dir)
164 print ("%s dump data stored in %s" % (self._testMethodName,
165 self.tc.host_dumper.dump_dir))
166
167 #TODO: use package_manager.py to install packages on any type of image
168 def install_packages(self, packagelist):
169 for package in packagelist:
170 (status, result) = self.target.run("smart install -y "+package)
171 if status != 0:
172 return status
173
174class oeSDKTest(oeTest):
175 def __init__(self, methodName='runTest'):
176 self.sdktestdir = oeSDKTest.tc.sdktestdir
177 super(oeSDKTest, self).__init__(methodName)
178
179 @classmethod
180 def hasHostPackage(self, pkg):
181
182 if re.search(pkg, oeTest.tc.hostpkgmanifest):
183 return True
184 return False
185
186 def _run(self, cmd):
187 return subprocess.check_output(cmd, shell=True)
188
189def getmodule(pos=2):
190 # stack returns a list of tuples containg frame information
191 # First element of the list the is current frame, caller is 1
192 frameinfo = inspect.stack()[pos]
193 modname = inspect.getmodulename(frameinfo[1])
194 #modname = inspect.getmodule(frameinfo[0]).__name__
195 return modname
196
197def skipModule(reason, pos=2):
198 modname = getmodule(pos)
199 if modname not in oeTest.tc.testsrequired:
200 raise unittest.SkipTest("%s: %s" % (modname, reason))
201 else:
202 raise Exception("\nTest %s wants to be skipped.\nReason is: %s" \
203 "\nTest was required in TEST_SUITES, so either the condition for skipping is wrong" \
204 "\nor the image really doesn't have the required feature/package when it should." % (modname, reason))
205
206def skipModuleIf(cond, reason):
207
208 if cond:
209 skipModule(reason, 3)
210
211def skipModuleUnless(cond, reason):
212
213 if not cond:
214 skipModule(reason, 3)