Fix run.py (#71)
* fix run.py * run.py: fix Windows support * fix test listing
This commit is contained in:
		
				
					committed by
					
						 Benjamin Sergeant
						Benjamin Sergeant
					
				
			
			
				
	
			
			
			
						parent
						
							a41d08343c
						
					
				
				
					commit
					d7a0bc212d
				
			
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +1,2 @@ | |||||||
| build | build | ||||||
|  | *.pyc | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								test/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								test/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -7,3 +7,4 @@ node_modules | |||||||
| ixwebsocket | ixwebsocket | ||||||
| Makefile | Makefile | ||||||
| build | build | ||||||
|  | ixwebsocket_unittest.xml | ||||||
|   | |||||||
| @@ -5,12 +5,11 @@ | |||||||
| cmake_minimum_required (VERSION 3.4.1) | cmake_minimum_required (VERSION 3.4.1) | ||||||
| project (ixwebsocket_unittest) | project (ixwebsocket_unittest) | ||||||
|  |  | ||||||
| set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../third_party/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH}) |  | ||||||
| find_package(Sanitizers) |  | ||||||
|  |  | ||||||
| set (CMAKE_CXX_STANDARD 14) | set (CMAKE_CXX_STANDARD 14) | ||||||
|  |  | ||||||
| if (NOT WIN32) | if (NOT WIN32) | ||||||
|  |   set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../third_party/sanitizers-cmake/cmake" ${CMAKE_MODULE_PATH}) | ||||||
|  |   find_package(Sanitizers) | ||||||
|   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") |   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") | ||||||
|   set(CMAKE_LD_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") |   set(CMAKE_LD_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread") | ||||||
|   option(USE_TLS "Add TLS support" ON) |   option(USE_TLS "Add TLS support" ON) | ||||||
| @@ -51,7 +50,10 @@ if (NOT WIN32) | |||||||
| endif() | endif() | ||||||
|  |  | ||||||
| add_executable(ixwebsocket_unittest ${SOURCES}) | add_executable(ixwebsocket_unittest ${SOURCES}) | ||||||
| add_sanitizers(ixwebsocket_unittest) |  | ||||||
|  | if (NOT WIN32) | ||||||
|  |   add_sanitizers(ixwebsocket_unittest) | ||||||
|  | endif() | ||||||
|  |  | ||||||
| if (APPLE AND USE_TLS) | if (APPLE AND USE_TLS) | ||||||
|     target_link_libraries(ixwebsocket_unittest "-framework foundation" "-framework security") |     target_link_libraries(ixwebsocket_unittest "-framework foundation" "-framework security") | ||||||
|   | |||||||
							
								
								
									
										105
									
								
								test/run.py
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								test/run.py
									
									
									
									
									
								
							| @@ -28,9 +28,9 @@ try: | |||||||
| except ImportError: | except ImportError: | ||||||
|     hasClick = False |     hasClick = False | ||||||
|  |  | ||||||
|  | BUILD_TYPE = 'Debug' | ||||||
| DEFAULT_EXE = 'ixwebsocket_unittest' | XML_OUTPUT_FILE = 'ixwebsocket_unittest.xml' | ||||||
|  | TEST_EXE_PATH = None | ||||||
|  |  | ||||||
| class Command(object): | class Command(object): | ||||||
|     """Run system commands with timeout |     """Run system commands with timeout | ||||||
| @@ -65,7 +65,7 @@ class Command(object): | |||||||
|             return True, self.process.returncode |             return True, self.process.returncode | ||||||
|  |  | ||||||
|  |  | ||||||
| def runCommand(cmd, assertOnFailure=True, timeout=None): | def runCommand(cmd, abortOnFailure=True, timeout=None): | ||||||
|     '''Small wrapper to run a command and make sure it succeed''' |     '''Small wrapper to run a command and make sure it succeed''' | ||||||
|  |  | ||||||
|     if timeout is None: |     if timeout is None: | ||||||
| @@ -73,16 +73,13 @@ def runCommand(cmd, assertOnFailure=True, timeout=None): | |||||||
|  |  | ||||||
|     print('\nRunning', cmd) |     print('\nRunning', cmd) | ||||||
|     command = Command(cmd) |     command = Command(cmd) | ||||||
|     timedout, ret = command.run(timeout) |     succeed, ret = command.run(timeout) | ||||||
|  |  | ||||||
|     if timedout: |     if not succeed or ret != 0: | ||||||
|         print('Unittest timed out') |         msg = 'cmd {}\nfailed with error code {}'.format(cmd, ret) | ||||||
|  |  | ||||||
|     msg = 'cmd {} failed with error code {}'.format(cmd, ret) |  | ||||||
|     if ret != 0: |  | ||||||
|         print(msg) |         print(msg) | ||||||
|         if assertOnFailure: |         if abortOnFailure: | ||||||
|             assert False |             sys.exit(-1) | ||||||
|  |  | ||||||
|  |  | ||||||
| def runCMake(sanitizer, buildDir): | def runCMake(sanitizer, buildDir): | ||||||
| @@ -91,12 +88,6 @@ def runCMake(sanitizer, buildDir): | |||||||
|     (remove build sub-folder). |     (remove build sub-folder). | ||||||
|     ''' |     ''' | ||||||
|  |  | ||||||
|     # CMake installed via Self Service ends up here. |  | ||||||
|     cmake_executable = '/Applications/CMake.app/Contents/bin/cmake' |  | ||||||
|  |  | ||||||
|     if not os.path.exists(cmake_executable): |  | ||||||
|         cmake_executable = 'cmake' |  | ||||||
|  |  | ||||||
|     sanitizersFlags = { |     sanitizersFlags = { | ||||||
|         'asan': '-DSANITIZE_ADDRESS=On', |         'asan': '-DSANITIZE_ADDRESS=On', | ||||||
|         'ubsan': '-DSANITIZE_UNDEFINED=On', |         'ubsan': '-DSANITIZE_UNDEFINED=On', | ||||||
| @@ -110,19 +101,22 @@ def runCMake(sanitizer, buildDir): | |||||||
|     if not os.path.exists(cmakeExecutable): |     if not os.path.exists(cmakeExecutable): | ||||||
|         cmakeExecutable = 'cmake' |         cmakeExecutable = 'cmake' | ||||||
|  |  | ||||||
|     generator = '"Unix Makefiles"' |  | ||||||
|     if platform.system() == 'Windows': |     if platform.system() == 'Windows': | ||||||
|         generator = '"NMake Makefiles"' |         #generator = '"NMake Makefiles"' | ||||||
|  |         generator = '"Visual Studio 16 2019"' | ||||||
|  |     else: | ||||||
|  |         generator = '"Unix Makefiles"' | ||||||
|  |  | ||||||
|     fmt = ''' |     CMAKE_BUILD_TYPE = BUILD_TYPE | ||||||
| {cmakeExecutable} -H. \ |  | ||||||
|  |     fmt = '{cmakeExecutable} -H. \ | ||||||
|     {sanitizerFlag} \ |     {sanitizerFlag} \ | ||||||
|     -B{buildDir} \ |     -B"{buildDir}" \ | ||||||
|     -DCMAKE_BUILD_TYPE=Debug \ |     -DCMAKE_BUILD_TYPE={CMAKE_BUILD_TYPE} \ | ||||||
|     -DUSE_TLS=1 \ |     -DUSE_TLS=1 \ | ||||||
|     -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ |     -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ | ||||||
|     -G{generator} |     -G{generator}' | ||||||
| ''' |  | ||||||
|     cmakeCmd = fmt.format(**locals()) |     cmakeCmd = fmt.format(**locals()) | ||||||
|     runCommand(cmakeCmd) |     runCommand(cmakeCmd) | ||||||
|  |  | ||||||
| @@ -133,10 +127,10 @@ def runTest(args, buildDir, xmlOutput, testRunName): | |||||||
|     if args is None: |     if args is None: | ||||||
|         args = '' |         args = '' | ||||||
|  |  | ||||||
|     fmt = '{buildDir}/{DEFAULT_EXE} -o {xmlOutput} -n "{testRunName}" -r junit "{args}"' |     testCommand = '{} -o {} -n "{}" -r junit "{}"'.format(TEST_EXE_PATH, xmlOutput, testRunName, args) | ||||||
|     testCommand = fmt.format(**locals()) |  | ||||||
|     runCommand(testCommand, |     runCommand(testCommand, | ||||||
|                assertOnFailure=False) |                abortOnFailure=False) | ||||||
|  |  | ||||||
|  |  | ||||||
| def validateTestSuite(xmlOutput): | def validateTestSuite(xmlOutput): | ||||||
| @@ -296,8 +290,7 @@ def executeJobs(jobs): | |||||||
| def computeAllTestNames(buildDir): | def computeAllTestNames(buildDir): | ||||||
|     '''Compute all test case names, by executing the unittest in a custom mode''' |     '''Compute all test case names, by executing the unittest in a custom mode''' | ||||||
|  |  | ||||||
|     executable = os.path.join(buildDir, DEFAULT_EXE) |     cmd = '"{}" --list-test-names-only'.format(TEST_EXE_PATH) | ||||||
|     cmd = '"{}" --list-test-names-only'.format(executable) |  | ||||||
|     names = os.popen(cmd).read().splitlines() |     names = os.popen(cmd).read().splitlines() | ||||||
|     names.sort()  # Sort test names for execution determinism |     names.sort()  # Sort test names for execution determinism | ||||||
|     return names |     return names | ||||||
| @@ -344,7 +337,7 @@ def generateXmlOutput(results, xmlOutput, testRunName, runTime): | |||||||
|         }) |         }) | ||||||
|  |  | ||||||
|         systemOut = ET.Element('system-out') |         systemOut = ET.Element('system-out') | ||||||
|         systemOut.text = result['output'].decode('utf-8') |         systemOut.text = result['output'].decode('utf-8', 'ignore') | ||||||
|         testCase.append(systemOut) |         testCase.append(systemOut) | ||||||
|  |  | ||||||
|         if not result['success']: |         if not result['success']: | ||||||
| @@ -365,16 +358,19 @@ def run(testName, buildDir, sanitizer, xmlOutput, testRunName, buildOnly, useLLD | |||||||
|     runCMake(sanitizer, buildDir) |     runCMake(sanitizer, buildDir) | ||||||
|  |  | ||||||
|     # build with make |     # build with make | ||||||
|     makeCmd = 'make' |     #makeCmd = 'cmake --build ' | ||||||
|     jobs = '-j8' |     #jobs = '-j8' | ||||||
|  |  | ||||||
|     if platform.system() == 'Windows': |     #if platform.system() == 'Windows': | ||||||
|         makeCmd = 'nmake' |     #    makeCmd = 'nmake' | ||||||
|  |  | ||||||
|         # nmake does not have a -j option |         # nmake does not have a -j option | ||||||
|         jobs = '' |     #    jobs = '' | ||||||
|  |  | ||||||
|     runCommand('{} -C {} {}'.format(makeCmd, buildDir, jobs)) |     #runCommand('{} -C {} {}'.format(makeCmd, buildDir, jobs)) | ||||||
|  |  | ||||||
|  |     # build with cmake | ||||||
|  |     runCommand('cmake --build ' + buildDir) | ||||||
|  |  | ||||||
|     if buildOnly: |     if buildOnly: | ||||||
|         return |         return | ||||||
| @@ -409,12 +405,7 @@ def run(testName, buildDir, sanitizer, xmlOutput, testRunName, buildOnly, useLLD | |||||||
|             continue |             continue | ||||||
|  |  | ||||||
|         # testName can contains spaces, so we enclose them in double quotes |         # testName can contains spaces, so we enclose them in double quotes | ||||||
|         executable = os.path.join(buildDir, DEFAULT_EXE) |         cmd = '{} "{}" "{}" > "{}" 2>&1'.format(lldb, TEST_EXE_PATH, testName, outputPath) | ||||||
|  |  | ||||||
|         if platform.system() == 'Windows': |  | ||||||
|             executable += '.exe' |  | ||||||
|  |  | ||||||
|         cmd = '{} "{}" "{}" > "{}" 2>&1'.format(lldb, executable, testName, outputPath) |  | ||||||
|  |  | ||||||
|         jobs.append({ |         jobs.append({ | ||||||
|             'name': testName, |             'name': testName, | ||||||
| @@ -454,8 +445,6 @@ def main(): | |||||||
|     if not os.path.exists(buildDir): |     if not os.path.exists(buildDir): | ||||||
|         os.makedirs(buildDir) |         os.makedirs(buildDir) | ||||||
|  |  | ||||||
|     defaultOutput = DEFAULT_EXE + '.xml' |  | ||||||
|  |  | ||||||
|     parser = argparse.ArgumentParser(description='Build and Run the engine unittest') |     parser = argparse.ArgumentParser(description='Build and Run the engine unittest') | ||||||
|  |  | ||||||
|     sanitizers = ['tsan', 'asan', 'ubsan', 'none'] |     sanitizers = ['tsan', 'asan', 'ubsan', 'none'] | ||||||
| @@ -481,14 +470,29 @@ def main(): | |||||||
|  |  | ||||||
|     # Default sanitizer is tsan |     # Default sanitizer is tsan | ||||||
|     sanitizer = args.sanitizer |     sanitizer = args.sanitizer | ||||||
|     if args.sanitizer is None: |  | ||||||
|  |     if args.no_sanitizer: | ||||||
|  |         sanitizer = 'none' | ||||||
|  |     elif args.sanitizer is None: | ||||||
|         sanitizer = 'tsan' |         sanitizer = 'tsan' | ||||||
|  |  | ||||||
|  |     # Sanitizers display lots of strange errors on Linux on CI, | ||||||
|  |     # which looks like false positives | ||||||
|  |     if platform.system() != 'Darwin': | ||||||
|  |         sanitizer = 'none' | ||||||
|  |  | ||||||
|     defaultRunName = 'ixengine_{}_{}'.format(platform.system(), sanitizer) |     defaultRunName = 'ixengine_{}_{}'.format(platform.system(), sanitizer) | ||||||
|  |  | ||||||
|     xmlOutput = args.output or defaultOutput |     xmlOutput = args.output or XML_OUTPUT_FILE | ||||||
|     testRunName = args.run_name or os.getenv('IXENGINE_TEST_RUN_NAME') or defaultRunName |     testRunName = args.run_name or os.getenv('IXENGINE_TEST_RUN_NAME') or defaultRunName | ||||||
|  |  | ||||||
|  |     global TEST_EXE_PATH | ||||||
|  |  | ||||||
|  |     if platform.system() == 'Windows': | ||||||
|  |         TEST_EXE_PATH = os.path.join(buildDir, BUILD_TYPE, 'ixwebsocket_unittest.exe') | ||||||
|  |     else: | ||||||
|  |         TEST_EXE_PATH = os.path.join(buildDir, 'ixwebsocket_unittest') | ||||||
|  |  | ||||||
|     if args.list: |     if args.list: | ||||||
|         # catch2 exit with a different error code when requesting the list of files |         # catch2 exit with a different error code when requesting the list of files | ||||||
|         try: |         try: | ||||||
| @@ -505,11 +509,6 @@ def main(): | |||||||
|         print('LLDB is only supported on Apple at this point') |         print('LLDB is only supported on Apple at this point') | ||||||
|         args.lldb = False |         args.lldb = False | ||||||
|  |  | ||||||
|     # Sanitizers display lots of strange errors on Linux on CI, |  | ||||||
|     # which looks like false positives |  | ||||||
|     if platform.system() != 'Darwin': |  | ||||||
|         sanitizer = 'none' |  | ||||||
|  |  | ||||||
|     return run(args.test, buildDir, sanitizer, xmlOutput,  |     return run(args.test, buildDir, sanitizer, xmlOutput,  | ||||||
|                testRunName, args.build_only, args.lldb) |                testRunName, args.build_only, args.lldb) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user