blob: 67c88be4fe7cd7e09b22092616947fec025d9b3c [file] [log] [blame]
Tor Norbye1aa2e092014-08-20 17:01:23 -07001import os
2
3def main():
4 import sys
5
6 #Separate the nose params and the pydev params.
7 pydev_params = []
8 other_test_framework_params = []
9 found_other_test_framework_param = None
10
11 NOSE_PARAMS = '--nose-params'
12 PY_TEST_PARAMS = '--py-test-params'
13
14 for arg in sys.argv[1:]:
15 if not found_other_test_framework_param and arg != NOSE_PARAMS and arg != PY_TEST_PARAMS:
16 pydev_params.append(arg)
17
18 else:
19 if not found_other_test_framework_param:
20 found_other_test_framework_param = arg
21 else:
22 other_test_framework_params.append(arg)
Tor Norbye3a2425a2013-11-04 10:16:08 -080023
24
Tor Norbye1aa2e092014-08-20 17:01:23 -070025 #Here we'll run either with nose or with the pydev_runfiles.
26 import pydev_runfiles
27 import pydev_runfiles_xml_rpc
28 import pydevd_constants
29 from pydevd_file_utils import _NormFile
Tor Norbye3a2425a2013-11-04 10:16:08 -080030
Tor Norbye1aa2e092014-08-20 17:01:23 -070031 DEBUG = 0
32 if DEBUG:
33 sys.stdout.write('Received parameters: %s\n' % (sys.argv,))
34 sys.stdout.write('Params for pydev: %s\n' % (pydev_params,))
35 if found_other_test_framework_param:
36 sys.stdout.write('Params for test framework: %s, %s\n' % (found_other_test_framework_param, other_test_framework_params))
Tor Norbye3a2425a2013-11-04 10:16:08 -080037
Tor Norbye3a2425a2013-11-04 10:16:08 -080038 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -070039 configuration = pydev_runfiles.parse_cmdline([sys.argv[0]] + pydev_params)
Tor Norbye3a2425a2013-11-04 10:16:08 -080040 except:
Tor Norbye1aa2e092014-08-20 17:01:23 -070041 sys.stderr.write('Command line received: %s\n' % (sys.argv,))
42 raise
43 pydev_runfiles_xml_rpc.InitializeServer(configuration.port) #Note that if the port is None, a Null server will be initialized.
Tor Norbye3a2425a2013-11-04 10:16:08 -080044
Tor Norbye1aa2e092014-08-20 17:01:23 -070045 NOSE_FRAMEWORK = 1
46 PY_TEST_FRAMEWORK = 2
Tor Norbye3a2425a2013-11-04 10:16:08 -080047 try:
Tor Norbye1aa2e092014-08-20 17:01:23 -070048 if found_other_test_framework_param:
49 test_framework = 0 #Default (pydev)
50 if found_other_test_framework_param == NOSE_PARAMS:
51 import nose
52 test_framework = NOSE_FRAMEWORK
53
54 elif found_other_test_framework_param == PY_TEST_PARAMS:
55 import pytest
56 test_framework = PY_TEST_FRAMEWORK
57
58 else:
59 raise ImportError()
60
61 else:
62 raise ImportError()
63
64 except ImportError:
65 if found_other_test_framework_param:
66 sys.stderr.write('Warning: Could not import the test runner: %s. Running with the default pydev unittest runner instead.\n' % (
67 found_other_test_framework_param,))
68
69 test_framework = 0
70
71 #Clear any exception that may be there so that clients don't see it.
72 #See: https://sourceforge.net/tracker/?func=detail&aid=3408057&group_id=85796&atid=577329
73 if hasattr(sys, 'exc_clear'):
74 sys.exc_clear()
75
76 if test_framework == 0:
77
78 pydev_runfiles.main(configuration)
79
Tor Norbye3a2425a2013-11-04 10:16:08 -080080 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -070081 #We'll convert the parameters to what nose or py.test expects.
82 #The supported parameters are:
83 #runfiles.py --config-file|-t|--tests <Test.test1,Test2> dirs|files --nose-params xxx yyy zzz
84 #(all after --nose-params should be passed directly to nose)
Tor Norbye3a2425a2013-11-04 10:16:08 -080085
Tor Norbye1aa2e092014-08-20 17:01:23 -070086 #In java:
87 #--tests = Constants.ATTR_UNITTEST_TESTS
88 #--config-file = Constants.ATTR_UNITTEST_CONFIGURATION_FILE
Tor Norbye3a2425a2013-11-04 10:16:08 -080089
90
Tor Norbye1aa2e092014-08-20 17:01:23 -070091 #The only thing actually handled here are the tests that we want to run, which we'll
92 #handle and pass as what the test framework expects.
Tor Norbye3a2425a2013-11-04 10:16:08 -080093
Tor Norbye1aa2e092014-08-20 17:01:23 -070094 py_test_accept_filter = {}
95 files_to_tests = configuration.files_to_tests
Tor Norbye3a2425a2013-11-04 10:16:08 -080096
Tor Norbye1aa2e092014-08-20 17:01:23 -070097 if files_to_tests:
98 #Handling through the file contents (file where each line is a test)
99 files_or_dirs = []
100 for file, tests in files_to_tests.items():
101 if test_framework == NOSE_FRAMEWORK:
102 for test in tests:
103 files_or_dirs.append(file + ':' + test)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800104
Tor Norbye1aa2e092014-08-20 17:01:23 -0700105 elif test_framework == PY_TEST_FRAMEWORK:
106 file = _NormFile(file)
107 py_test_accept_filter[file] = tests
108 files_or_dirs.append(file)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800109
Tor Norbye3a2425a2013-11-04 10:16:08 -0800110 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700111 raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800112
Tor Norbye1aa2e092014-08-20 17:01:23 -0700113 else:
114 if configuration.tests:
115 #Tests passed (works together with the files_or_dirs)
116 files_or_dirs = []
117 for file in configuration.files_or_dirs:
118 if test_framework == NOSE_FRAMEWORK:
119 for t in configuration.tests:
120 files_or_dirs.append(file + ':' + t)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800121
Tor Norbye1aa2e092014-08-20 17:01:23 -0700122 elif test_framework == PY_TEST_FRAMEWORK:
123 file = _NormFile(file)
124 py_test_accept_filter[file] = configuration.tests
125 files_or_dirs.append(file)
Tor Norbye3a2425a2013-11-04 10:16:08 -0800126
127 else:
Tor Norbye1aa2e092014-08-20 17:01:23 -0700128 raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,))
129 else:
130 #Only files or dirs passed (let it do the test-loading based on those paths)
131 files_or_dirs = configuration.files_or_dirs
Tor Norbye3a2425a2013-11-04 10:16:08 -0800132
Tor Norbye1aa2e092014-08-20 17:01:23 -0700133 argv = other_test_framework_params + files_or_dirs
Tor Norbye3a2425a2013-11-04 10:16:08 -0800134
135
Tor Norbye1aa2e092014-08-20 17:01:23 -0700136 if test_framework == NOSE_FRAMEWORK:
137 #Nose usage: http://somethingaboutorange.com/mrl/projects/nose/0.11.2/usage.html
138 #show_stdout_option = ['-s']
139 #processes_option = ['--processes=2']
140 argv.insert(0, sys.argv[0])
141 if DEBUG:
142 sys.stdout.write('Final test framework args: %s\n' % (argv[1:],))
143
144 import pydev_runfiles_nose
145 PYDEV_NOSE_PLUGIN_SINGLETON = pydev_runfiles_nose.StartPydevNosePluginSingleton(configuration)
146 argv.append('--with-pydevplugin')
147 nose.run(argv=argv, addplugins=[PYDEV_NOSE_PLUGIN_SINGLETON])
148
149 elif test_framework == PY_TEST_FRAMEWORK:
150 if DEBUG:
151 sys.stdout.write('Final test framework args: %s\n' % (argv,))
152 sys.stdout.write('py_test_accept_filter: %s\n' % (py_test_accept_filter,))
153
154 import os
155
156 try:
157 xrange
158 except:
159 xrange = range
160
161 for i in xrange(len(argv)):
162 arg = argv[i]
163 #Workaround bug in py.test: if we pass the full path it ends up importing conftest
164 #more than once (so, always work with relative paths).
165 if os.path.isfile(arg) or os.path.isdir(arg):
166 from pydev_imports import relpath
167 arg = relpath(arg)
168 argv[i] = arg
169
170 d = os.path.dirname(__file__)
171 if d not in sys.path:
172 sys.path.insert(0, d)
173
174 import pickle, zlib, base64
175
176 # Update environment PYTHONPATH so that it finds our plugin if using xdist.
177 os.environ['PYTHONPATH'] = os.pathsep.join(sys.path)
178
179 # Set what should be skipped in the plugin through an environment variable
180 s = base64.b64encode(zlib.compress(pickle.dumps(py_test_accept_filter)))
181 if pydevd_constants.IS_PY3K:
182 s = s.decode('ascii') # Must be str in py3.
183 os.environ['PYDEV_PYTEST_SKIP'] = s
184
185 # Identifies the main pid (i.e.: if it's not the main pid it has to connect back to the
186 # main pid to give xml-rpc notifications).
187 os.environ['PYDEV_MAIN_PID'] = str(os.getpid())
188 os.environ['PYDEV_PYTEST_SERVER'] = str(configuration.port)
189
190 argv.append('-p')
191 argv.append('pydev_runfiles_pytest2')
192 pytest.main(argv)
193
194 else:
195 raise AssertionError('Cannot handle test framework: %s at this point.' % (test_framework,))
Tor Norbye3a2425a2013-11-04 10:16:08 -0800196
197
Tor Norbye3a2425a2013-11-04 10:16:08 -0800198if __name__ == '__main__':
Tor Norbye1aa2e092014-08-20 17:01:23 -0700199 try:
200 main()
201 finally:
202 try:
203 #The server is not a daemon thread, so, we have to ask for it to be killed!
204 import pydev_runfiles_xml_rpc
205 pydev_runfiles_xml_rpc.forceServerKill()
206 except:
207 pass #Ignore any errors here
208
209 import sys
210 import threading
211 if hasattr(sys, '_current_frames') and hasattr(threading, 'enumerate'):
212 import time
213 import traceback
214
215 class DumpThreads(threading.Thread):
216 def run(self):
217 time.sleep(10)
218
219 thread_id_to_name = {}
220 try:
221 for t in threading.enumerate():
222 thread_id_to_name[t.ident] = '%s (daemon: %s)' % (t.name, t.daemon)
223 except:
224 pass
225
226 stack_trace = [
227 '===============================================================================',
228 'pydev pyunit runner: Threads still found running after tests finished',
229 '================================= Thread Dump =================================']
230
231 for thread_id, stack in sys._current_frames().items():
232 stack_trace.append('\n-------------------------------------------------------------------------------')
233 stack_trace.append(" Thread %s" % thread_id_to_name.get(thread_id, thread_id))
234 stack_trace.append('')
235
236 if 'self' in stack.f_locals:
237 sys.stderr.write(str(stack.f_locals['self'])+'\n')
238
239 for filename, lineno, name, line in traceback.extract_stack(stack):
240 stack_trace.append(' File "%s", line %d, in %s' % (filename, lineno, name))
241 if line:
242 stack_trace.append(" %s" % (line.strip()))
243 stack_trace.append('\n=============================== END Thread Dump ===============================')
244 sys.stderr.write('\n'.join(stack_trace))
245
246
247 dump_current_frames_thread = DumpThreads()
248 dump_current_frames_thread.setDaemon(True) # Daemon so that this thread doesn't halt it!
249 dump_current_frames_thread.start()