summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/contrib/tts/runner.py
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2015-05-13 13:21:33 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-05-14 18:04:10 +0100
commit80ca4f00f82cd2f58fe5cda38c8cc5a719c887b6 (patch)
treef2d5a130213c37b8aed1fb07fecf46eb9e5e1a13 /bitbake/lib/toaster/contrib/tts/runner.py
parent23f5b009e0ebf59cfcc9ae90a1084468fc88e42f (diff)
downloadpoky-80ca4f00f82cd2f58fe5cda38c8cc5a719c887b6.tar.gz
bitbake: toaster/contrib: adding TTS squashed patch
In order to move the Toaster Test System in Toaster itself, we create a contrib directory. The TTS is added as a squashed patch with no history. It contains code contributed by Ke Zou <ke.zou@windriver.com>. (Bitbake rev: 7d24fea2b5dcaac6add738b6fb4700d698824286) Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/contrib/tts/runner.py')
-rwxr-xr-xbitbake/lib/toaster/contrib/tts/runner.py200
1 files changed, 200 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/contrib/tts/runner.py b/bitbake/lib/toaster/contrib/tts/runner.py
new file mode 100755
index 0000000000..d2a6099bdb
--- /dev/null
+++ b/bitbake/lib/toaster/contrib/tts/runner.py
@@ -0,0 +1,200 @@
1#!/usr/bin/python
2
3# ex:ts=4:sw=4:sts=4:et
4# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
5#
6# Copyright (C) 2015 Alexandru Damian for Intel Corp.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License version 2 as
10# published by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program; if not, write to the Free Software Foundation, Inc.,
19# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21
22# This is the main test execution controller. It is designed to be run
23# manually from the command line, or to be called from a different program
24# that schedules test execution.
25#
26# Execute runner.py -h for help.
27
28
29
30from __future__ import print_function
31import optparse
32import sys, os
33import unittest, inspect, importlib
34import logging, pprint, json
35
36from shellutils import *
37
38import config
39
40# we also log to a file, in addition to console, because our output is important
41__log_file_name =os.path.join(os.path.dirname(__file__),"log/tts_%d.log" % config.OWN_PID)
42mkdirhier(os.path.dirname(__log_file_name))
43__log_file = open(__log_file_name, "w")
44__file_handler = logging.StreamHandler(__log_file)
45__file_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s: %(message)s"))
46
47config.logger.addHandler(__file_handler)
48
49
50# set up log directory
51try:
52 if not os.path.exists(config.LOGDIR):
53 os.mkdir(config.LOGDIR)
54 else:
55 if not os.path.isdir(config.LOGDIR):
56 raise Exception("Expected log dir '%s' is not actually a directory." % config.LOGDIR)
57except OSError as e:
58 raise e
59
60# creates the under-test-branch as a separate directory
61def set_up_test_branch(settings, branch_name):
62 testdir = "%s/%s.%d" % (settings['workdir'], config.TEST_DIR_NAME, config.OWN_PID)
63
64 # creates the host dir
65 if os.path.exists(testdir):
66 raise Exception("Test dir '%s'is already there, aborting" % testdir)
67 os.mkdir(testdir)
68
69 # copies over the .git from the localclone
70 run_shell_cmd("cp -a '%s'/.git '%s'" % (settings['localclone'], testdir))
71
72 # add the remote if it doesn't exist
73 crt_remotes = run_shell_cmd("git remote -v", cwd = testdir)
74 remotes = [word for line in crt_remotes.split("\n") for word in line.split()]
75 if not config.CONTRIB_REPO in remotes:
76 remote_name = "tts_contrib"
77 run_shell_cmd("git remote add %s %s" % (remote_name, config.CONTRIB_REPO), cwd = testdir)
78 else:
79 remote_name = remotes[remotes.index(config.CONTRIB_REPO) - 1]
80
81 # do the fetch
82 run_shell_cmd("git fetch %s -p" % remote_name, cwd=testdir)
83
84 # do the checkout
85 run_shell_cmd("git checkout origin/master && git branch -D %s; git checkout %s/%s -b %s && git reset --hard" % (branch_name,remote_name,branch_name,branch_name), cwd=testdir)
86
87 return testdir
88
89
90def __search_for_tests():
91 # we find all classes that can run, and run them
92 tests = []
93 for dir_name, dirs_list, files_list in os.walk(os.path.dirname(os.path.abspath(__file__))):
94 for f in [f[:-3] for f in files_list if f.endswith(".py") and not f.startswith("__init__")]:
95 config.logger.debug("Inspecting module %s", f)
96 current_module = importlib.import_module(f)
97 crtclass_names = vars(current_module)
98 for v in crtclass_names:
99 t = crtclass_names[v]
100 if isinstance(t, type(unittest.TestCase)) and issubclass(t, unittest.TestCase):
101 tests.append((f,v))
102 break
103 return tests
104
105
106# boilerplate to self discover tests and run them
107def execute_tests(dir_under_test, testname):
108
109 if testname is not None and "." in testname:
110 tests = []
111 tests.append(tuple(testname.split(".", 2)))
112 else:
113 tests = __search_for_tests()
114
115 # let's move to the directory under test
116 crt_dir = os.getcwd()
117 os.chdir(dir_under_test)
118
119 # execute each module
120 try:
121 config.logger.debug("Discovered test clases: %s" % pprint.pformat(tests))
122 suite = unittest.TestSuite()
123 loader = unittest.TestLoader()
124 result = unittest.TestResult()
125 for m,t in tests:
126 suite.addTest(loader.loadTestsFromName("%s.%s" % (m,t)))
127 config.logger.info("Running %d test(s)", suite.countTestCases())
128 suite.run(result)
129
130 if len(result.errors) > 0:
131 map(lambda x: config.logger.error("Exception on test: %s" % pprint.pformat(x)), result.errors)
132
133 if len(result.failures) > 0:
134 map(lambda x: config.logger.error("Failed test: %s:\n%s\n" % (pprint.pformat(x[0]), "\n".join(["-- %s" % x for x in eval(pprint.pformat(x[1])).split("\n")]))), result.failures)
135
136 config.logger.info("Test results: %d ran, %d errors, %d failures" % (result.testsRun, len(result.errors), len(result.failures)))
137
138 except Exception as e:
139 import traceback
140 config.logger.error("Exception while running test. Tracedump: \n%s", traceback.format_exc(e))
141 finally:
142 os.chdir(crt_dir)
143 return len(result.failures)
144
145# verify that we had a branch-under-test name as parameter
146def validate_args():
147 from optparse import OptionParser
148 parser = OptionParser(usage="usage: %prog [options] branch_under_test")
149
150 parser.add_option("-t", "--test-dir", dest="testdir", default=None, help="Use specified directory to run tests, inhibits the checkout.")
151 parser.add_option("-s", "--single", dest="singletest", default=None, help="Run only the specified test")
152
153 (options, args) = parser.parse_args()
154 if len(args) < 1:
155 raise Exception("Please specify the branch to run on. Use option '-h' when in doubt.")
156 return (options, args)
157
158
159
160
161# load the configuration options
162def read_settings():
163 if not os.path.exists(config.SETTINGS_FILE) or not os.path.isfile(config.SETTINGS_FILE):
164 raise Exception("Config file '%s' cannot be openend" % config.SETTINGS_FILE);
165 return json.loads(open(config.SETTINGS_FILE, "r").read())
166
167
168# cleanup !
169def clean_up(testdir):
170 # TODO: delete the test dir
171 #run_shell_cmd("rm -rf -- '%s'" % testdir)
172 pass
173
174if __name__ == "__main__":
175 (options, args) = validate_args()
176
177 settings = read_settings()
178 need_cleanup = False
179
180 testdir = None
181 no_failures = 1
182 try:
183 if options.testdir is not None and os.path.exists(options.testdir):
184 testdir = options.testdir
185 config.logger.info("No checkout, using %s" % testdir)
186 else:
187 need_cleanup = True
188 testdir = set_up_test_branch(settings, args[0]) # we expect a branch name as first argument
189
190 config.testdir = testdir # we let tests know where to run
191 no_failures = execute_tests(testdir, options.singletest)
192
193 except ShellCmdException as e :
194 import traceback
195 config.logger.error("Error while setting up testing. Traceback: \n%s" % traceback.format_exc(e))
196 finally:
197 if need_cleanup and testdir is not None:
198 clean_up(testdir)
199
200 sys.exit(no_failures)