19 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
20 stdout, stderr = p.communicate()
22 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
23 stdout, stderr = p.communicate(input=data)
25 return stdout.decode(
'utf-8'), stderr.decode(
'utf-8'), p.returncode
29 if fileName
is not None:
30 stderr = stderr.replace(fileName,
'.tmp.cpp')
32 stderr = re.sub(
'(.*).cpp:',
'.tmp:', stderr)
36 stderr = re.sub(
'/(.*)/(.*?:[0-9]+):',
'... \\2:', stderr)
37 stderr = re.sub(
'RecoveryExpr 0x[a-f0-9]+ ',
'RecoveryExpr ', stderr)
42 def testCompare(tmpFileName, stdout, expectFile, f, args, time):
43 expect = open(expectFile,
'r', encoding=
'utf-8').read()
47 stdout = stdout.replace(
'\r\n',
'\n')
50 print(
'[FAILED] %s - %s' %(f, time))
52 for line
in difflib.unified_diff(expect.splitlines(keepends=
True), stdout.splitlines(keepends=
True), fromfile=expectFile, tofile=
'stdout', n=3):
53 print(
'%s' %((line[1:]
if line.startswith(
' ')
else line) ), end=
'')
55 print(
'[PASSED] %-50s - %s' %(f, time))
63 cppStd = cppStd.replace(
'-std=',
'/std:')
64 cppStd = cppStd.replace(
'2a',
'latest')
66 cmd = [args[
'cxx'], cppStd,
'-D__cxa_guard_acquire(x)=true',
'-D__cxa_guard_release(x)',
'-D__cxa_guard_abort(x)',
'-I', os.getcwd()]
69 arch = platform.architecture()[0]
70 if (arch !=
'64bit')
or ((arch ==
'64bit')
and (sys.platform ==
'darwin')):
73 cmd.extend([
'/nologo',
'/EHsc',
'/IGNORE:C4335'])
76 if '-std=c++98' == cppStd:
77 cmd += [
'-Dalignas(x)=']
79 cmd += [
'-c', tmpFileName]
81 stdout, stderr, returncode =
runCmd(cmd)
83 compileErrorFile = os.path.join(mypath, fileName +
'.cerr')
85 if os.path.isfile(compileErrorFile):
86 ce = open(compileErrorFile,
'r', encoding=
'utf-8').read()
90 print(f
'[PASSED] Compile: {f}')
93 compileErrorFile = os.path.join(mypath, fileName +
'.ccerr')
94 if os.path.isfile(compileErrorFile):
95 ce = open(compileErrorFile,
'r', encoding=
'utf-8').read()
96 stderr = stderr.replace(tmpFileName,
'.tmp.cpp')
99 print(
'f[PASSED] Compile: {f}')
102 print(f
'[ERROR] Compile failed: {f}')
105 if os.path.isfile(compileErrorFile):
106 print(
'unused file: %s' %(compileErrorFile))
108 ext =
'obj' if os.name ==
'nt' else 'o'
110 objFileName =
'%s.%s' %(os.path.splitext(os.path.basename(tmpFileName))[0], ext)
111 os.remove(objFileName)
113 print(f
'[PASSED] Compile: {f}')
121 parser = argparse.ArgumentParser(description=
'Description of your program')
122 parser.add_argument(
'--insights', help=
'C++ Insights binary', required=
True)
123 parser.add_argument(
'--cxx', help=
'C++ compiler to used', default=
'/usr/local/clang-current/bin/clang++')
124 parser.add_argument(
'--failure-is-ok', help=
'Failing tests are ok', default=
False, action=
'store_true')
125 parser.add_argument(
'--update-tests', help=
'Update failing tests', default=
False, action=
'store_true')
126 parser.add_argument(
'--std', help=
'C++ Standard to used', default=
'c++17')
127 parser.add_argument(
'--use-libcpp', help=
'Use libst++', default=
False, action=
'store_true')
128 parser.add_argument(
'--llvm-prof-dir', help=
'LLVM profiles data dir', default=
'')
129 parser.add_argument(
'args', nargs=argparse.REMAINDER)
130 args = vars(parser.parse_args())
132 insightsPath = args[
'insights']
133 remainingArgs = args[
'args']
134 bFailureIsOk = args[
'failure_is_ok']
135 bUpdateTests = args[
'update_tests']
136 defaultCppStd = f
"-std={args['std']}"
138 if args[
'llvm_prof_dir'] !=
'':
139 os.environ[
'LLVM_PROFILE_FILE'] = os.path.join(args[
'llvm_prof_dir'],
'prof%p.profraw')
141 if 0 == len(remainingArgs):
142 cppFiles = [f
for f
in os.listdir(mypath)
if (os.path.isfile(os.path.join(mypath, f))
and f.endswith(
'.cpp'))]
144 cppFiles = remainingArgs
151 regEx = re.compile(
'.*cmdline:(.*)')
152 regExInsights = re.compile(
'.*cmdlineinsights:(.*)')
154 for f
in sorted(cppFiles):
155 fileName = os.path.splitext(f)[0]
156 expectFile = os.path.join(mypath, fileName +
'.expect')
157 ignoreFile = os.path.join(mypath, fileName +
'.ignore')
158 cppStd = defaultCppStd
161 fh = open(f,
'r', encoding=
'utf-8')
162 fileHeader = fh.readline()
163 fileHeader += fh.readline()
164 m = regEx.search(fileHeader)
168 m = regExInsights.search(fileHeader)
170 insightsOpts = m.group(1).split(
' ')
172 if not os.path.isfile(expectFile)
and not os.path.isfile(ignoreFile):
173 print(f
'Missing expect/ignore for: {f}')
177 if os.path.isfile(ignoreFile):
178 print(f
'Ignoring: {f}')
182 cmd = [insightsPath, f]
184 if args[
'use_libcpp']:
185 cmd.append(
'-use-libc++')
188 if len(insightsOpts):
189 cmd.extend(insightsOpts)
191 cmd.extend([
'--', cppStd,
'-m64'])
193 begin = datetime.datetime.now()
194 stdout, stderr, returncode =
runCmd(cmd)
195 end = datetime.datetime.now()
198 compileErrorFile = os.path.join(mypath, fileName +
'.cerr')
199 if os.path.isfile(compileErrorFile):
200 ce = open(compileErrorFile,
'r', encoding=
'utf-8').read()
204 ce = re.sub(
'(.*).cpp:',
'.tmp:', ce)
205 ce = re.sub(
'(.*).cpp.',
'.tmp:', ce)
206 stderr = re.sub(
'(Error while processing.*.cpp.)',
'', stderr)
210 if ((ce == stderr)
and (1 == returncode))
or os.path.exists(os.path.join(mypath, fileName +
'.failure')):
211 print(f
'[PASSED] Transform: {f}')
215 print(f
'[ERROR] Transform: {f}')
219 print(f
'Insight crashed for: {f} with: {returncode}')
225 fd, tmpFileName = tempfile.mkstemp(
'.cpp')
227 with os.fdopen(fd,
'w', encoding=
'utf-8')
as tmp:
231 equal =
testCompare(tmpFileName, stdout, expectFile, f, args, end-begin)
232 bCompiles, stderr =
testCompile(tmpFileName, f, args, fileName, cppStd)
233 compileErrorFile = os.path.join(mypath, fileName +
'.cerr')
236 if (bCompiles
and equal)
or bFailureIsOk:
239 if bCompiles
and not equal:
240 open(expectFile,
'w', encoding=
'utf-8').write(stdout)
241 print(
'Updating test')
242 elif not bCompiles
and os.path.exists(compileErrorFile):
243 open(expectFile,
'w', encoding=
'utf-8').write(stdout)
244 open(compileErrorFile,
'w', encoding=
'utf-8').write(stderr)
245 print(
'Updating test cerr')
249 os.remove(tmpFileName)
253 expectedToPass = len(cppFiles)-missingExpected
254 print(
'-----------------------------------------------------------------')
255 print(f
'Tests passed: {filesPassed}/{expectedToPass}')
257 print(f
'Insights crashed: {crashes}')
258 print(f
'Missing expected files: {missingExpected}')
260 passed = (0 == missingExpected)
and (expectedToPass == filesPassed)
262 return (passed
is False)
def testCompare(tmpFileName, stdout, expectFile, f, args, time)
def runCmd(cmd, data=None)
def testCompile(tmpFileName, f, args, fileName, cppStd)
def cleanStderr(stderr, fileName=None)