klayout/macbuild/macQAT.py

329 lines
13 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#===============================================================================
# File: "macbuild/macQAT.py"
#
# The top Python script to run "ut_runner" after building KLayout
# (http://www.klayout.de/index.php) version 0.29.7 or later on different
# Apple Mac OSX platforms.
#
# This script must be copied to a "*.macQAT/" directory to run.
#===============================================================================
import sys
import os
import datetime
from time import sleep
import platform
import optparse
import subprocess
#-------------------------------------------------------------------------------
## To set global variables including present directory and platform info.
#
#-------------------------------------------------------------------------------
def SetGlobals():
global ProjectDir # project directory where "ut_runner" exists
global RunnerUsage # True to print the usage of 'ut_runner'
global StartKLayout # True to start the KLayout main GUI window
global Run # True to run this script
global ContinueOnError # True to continue after an error
global TestsExcluded # list of tests to exclude
global Arguments # other arguments
global GitSHA1 # Git's short SHA1 value of the HEAD
global TimeStamp # time stamp
global WorkDir # work directory name
global LogFile # log file name
global Usage # string on usage
global DryRun # dry-run mode; print the command line and exit
# auxiliary variables on platform
global System # 6-tuple from platform.uname()
global Node # - do -
global Release # - do -
global Version # - do -
global Machine # - do -
global Processor # - do -
global Bit # machine bit-size
Usage = "\n"
Usage += "----------------------------------------------------------------------------------------\n"
Usage += "<< Usage of 'macQAT.py' >>\n"
Usage += " for running 'ut_runner' after building KLayout.\n"
Usage += "\n"
Usage += "$ [python] ./macQAT.py\n"
Usage += " option & argument : descriptions | default value\n"
Usage += " -----------------------------------------------------------------+---------------\n"
Usage += " [-u|--usage] : print usage of 'ut_runner'and exit | disabled\n"
Usage += " |\n"
Usage += " [-k|--klayout] : just start the KLayout main GUI window | disabled\n"
Usage += " <-r|--run> : run this script | disabled\n"
Usage += " [-s|--stop] : stop on error | disabled\n"
Usage += " [-x|--exclude <tests>] : exclude test(s) such as 'pymod,pya' | ''\n"
Usage += " : you can use this option multiple times |\n"
Usage += " [-a|--args <string>] : arguments other than '-x' and '-c' | ''\n"
Usage += " : you can use this option multiple times |\n"
Usage += " [--dryrun] : print the command line and exit | disabled\n"
Usage += " [-?|--?] : print this usage and exit | disabled\n"
Usage += "--------------------------------------------------------------------+-------------------\n"
ProjectDir = os.getcwd()
RunnerUsage = False
StartKLayout = False
Run = False
ContinueOnError = True
TestsExcluded = list()
Arguments = list()
GitSHA1 = GetGitShortSHA1()
TimeStamp = GetTimeStamp()
WorkDir = "QATest_%s_%s__%s" % (GitSHA1, TimeStamp, os.path.basename(ProjectDir) )
LogFile = WorkDir + ".log"
DryRun = False
(System, Node, Release, Version, Machine, Processor) = platform.uname()
#-------------------------------------------------------------------------------
## Get git's short SHA1 value of the HEAD
#
# @return SHA1 value string
#-------------------------------------------------------------------------------
def GetGitShortSHA1():
command = "git rev-parse --short HEAD 2>/dev/null"
sha1val = os.popen( command ).read().strip()
return sha1val
#-------------------------------------------------------------------------------
## Get the time stamp
#
# @return time stamp string
#-------------------------------------------------------------------------------
def GetTimeStamp():
ts = datetime.datetime.today()
return "%04d_%02d%02d_%02d%02d" % (ts.year, ts.month, ts.day, ts.hour, ts.minute)
#-------------------------------------------------------------------------------
## To parse the command line arguments
#
#-------------------------------------------------------------------------------
def ParseCommandLineArguments():
global Usage
global RunnerUsage
global StartKLayout
global Run
global ContinueOnError
global TestsExcluded
global Arguments
global DryRun
p = optparse.OptionParser( usage=Usage )
p.add_option( '-u', '--usage',
action='store_true',
dest='runner_usage',
default=False,
help="print usage of 'ut_runner' and exit (false)" )
p.add_option( '-k', '--klayout',
action='store_true',
dest='start_KLayout',
default=False,
help='just start the KLayout main GUI window (false)' )
p.add_option( '-r', '--run',
action='store_true',
dest='runme',
default=False,
help='run this script (false)' )
p.add_option( '-s', '--stop',
action='store_true',
dest='stop_on_error',
default=False,
help='stop on error (false)' )
p.add_option( '-x', '--exclude',
action='append',
dest='exclude_tests',
help="exclude test(s) such as 'pymod,pya' ('')" )
p.add_option( '-a', '--args',
action='append',
dest='arguments',
help="arguments other than '-x' and '-c' ('')" )
p.add_option( '--dryrun',
action='store_true',
dest='dryrun',
default=False,
help='print the command line and exit (false)' )
p.add_option( '-?', '--??',
action='store_true',
dest='checkusage',
default=False,
help='check usage (false)' )
p.set_defaults( runner_usage = False,
start_KLayout = False,
runme = False,
stop_on_error = False,
exclude_tests = list(),
arguments = list(),
dryrun = False,
checkusage = False )
opt, args = p.parse_args()
if opt.checkusage:
print(Usage)
quit()
RunnerUsage = opt.runner_usage
StartKLayout = opt.start_KLayout
Run = opt.runme
ContinueOnError = not opt.stop_on_error
if not len(opt.exclude_tests) == 0:
excluded_tests = list()
for item in opt.exclude_tests:
excluded_tests += [ subitem.strip() for subitem in item.split(',') ]
TestsExcluded = sorted(list(set(excluded_tests)))
else:
TestsExcluded = []
Arguments = opt.arguments
DryRun = opt.dryrun
#-------------------------------------------------------------------------------
## Hide/Show the private directory
#
#-------------------------------------------------------------------------------
def HidePrivateDir():
if os.path.isdir( "../private" ):
os.rename( "../private", "../private.stash" )
def ShowPrivateDir():
if os.path.isdir( "../private.stash" ):
os.rename( "../private.stash", "../private" )
#-------------------------------------------------------------------------------
## Export environment variables for "ut_runner"
#
#-------------------------------------------------------------------------------
def ExportEnvVariables():
global ProjectDir
global WorkDir
global MyEnviron # my environment variables; can be independently used later
# In older versions of subprocess module, 'env=None' argument is not provided
MyEnviron = os.environ.copy()
MyEnviron[ 'TESTSRC' ] = ".."
MyEnviron[ 'TESTTMP' ] = WorkDir
if System == "Darwin":
MyEnviron[ 'DYLD_LIBRARY_PATH' ] = "%s:%s/db_plugins:%s/lay_plugins:%s/pymod" % (ProjectDir, ProjectDir, ProjectDir, ProjectDir)
MyEnviron[ 'MallocNanoZone' ] = "0"
MyEnviron[ 'ASAN_OPTIONS' ] = "ast_unwind_on_malloc=0:verbosity=1:detect_leaks=0:abort_on_error=0:halt_on_error=0:symbolize=1"
for env in [ 'TESTSRC', 'TESTTMP', 'DYLD_LIBRARY_PATH', 'MallocNanoZone', 'ASAN_OPTIONS' ]:
os.environ[env] = MyEnviron[env]
else:
MyEnviron[ 'LD_LIBRARY_PATH' ] = "%s:%s/db_plugins:%s/lay_plugins:%s/pymod" % (ProjectDir, ProjectDir, ProjectDir, ProjectDir)
for env in [ 'TESTSRC', 'TESTTMP', 'LD_LIBRARY_PATH' ]:
os.environ[env] = MyEnviron[env]
#-------------------------------------------------------------------------------
## Start the KLayout main GUI window
#
#-------------------------------------------------------------------------------
def StartKLatyouGUIWindow():
if System == "Darwin":
command = "./klayout.app/Contents/MacOS/klayout"
else:
command = "./klayout"
subprocess.call( command, shell=False )
#-------------------------------------------------------------------------------
## Run the tester
#
# @param[in] command command string to run
# @param[in] logfile log file name
#-------------------------------------------------------------------------------
def RunTester( command, logfile="" ):
proc = subprocess.Popen( command.split(),
stdout=subprocess.PIPE, \
stderr=subprocess.STDOUT, \
universal_newlines=True )
if not logfile == "":
with proc.stdout, open( logfile, 'w' ) as file:
for line in proc.stdout:
sys.stdout.write(line)
file.write(line)
proc.wait()
else:
with proc.stdout:
for line in proc.stdout:
sys.stdout.write(line)
proc.wait()
#-------------------------------------------------------------------------------
# Main function
#-------------------------------------------------------------------------------
def Main():
#-------------------------------------------------------
# [1] Initialize
#-------------------------------------------------------
SetGlobals()
ParseCommandLineArguments()
ExportEnvVariables()
#-------------------------------------------------------
# [2] Print the runner's usage
#-------------------------------------------------------
if RunnerUsage:
command = './ut_runner --help-all'
RunTester( command )
quit()
#-------------------------------------------------------
# [3] Start the KLayout main GUI window
#-------------------------------------------------------
if StartKLayout:
StartKLatyouGUIWindow()
#-------------------------------------------------------
# [4] Run the unit tester
#-------------------------------------------------------
if not Run and not StartKLayout:
print( "! pass <-r|--run> option to run the QA tests" )
print( "! pass <-k|--klayout> option to start the KLayout main GUI window" )
print(Usage)
quit()
if Run:
command = './ut_runner'
if ContinueOnError:
command += " -c"
for item in TestsExcluded:
command += ' -x %s' % item
if not len(Arguments) == 0:
for arg in Arguments:
command += " %s" % arg
print( "" )
print( "### Dumping the log to <%s>" % LogFile )
print( "------------------------------------------------------------------------" )
print( " Git SHA1 = %s" % GitSHA1 )
print( " Time stamp = %s" % TimeStamp )
print( " Command line = %s" % command )
print( "------------------------------------------------------------------------" )
if DryRun:
quit()
sleep(1.0)
HidePrivateDir()
RunTester( command, logfile=LogFile )
ShowPrivateDir()
#===================================================================================
if __name__ == "__main__":
Main()
#---------------
# End of file
#---------------