source: src/tests/pybin/tools.py@ a4248de1

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr no_list persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since a4248de1 was 4e1572f, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

  • Property mode set to 100644
File size: 6.5 KB
RevLine 
[bacc36c]1from __future__ import print_function
2
[c07d724]3import __main__
4import argparse
[bacc36c]5import multiprocessing
[c07d724]6import os
7import re
[bacc36c]8import signal
[c07d724]9import stat
[bacc36c]10import sys
[f85bc15]11import fileinput
[c07d724]12
[bacc36c]13from pybin import settings
[c07d724]14from subprocess import Popen, PIPE, STDOUT
15
[bacc36c]16################################################################################
17# shell helpers
18################################################################################
19
[c07d724]20# helper functions to run terminal commands
[bacc36c]21def sh(cmd, print2stdout = True, input = None):
22 # add input redirection if needed
23 if input and os.path.isfile(input):
24 cmd += " < %s" % input
25
26 # if this is a dry_run, only print the commands that would be ran
27 if settings.dry_run :
[c07d724]28 print("cmd: %s" % cmd)
29 return 0, None
[bacc36c]30
31 # otherwise create a pipe and run the desired command
32 else :
[c07d724]33 proc = Popen(cmd, stdout=None if print2stdout else PIPE, stderr=STDOUT, shell=True)
34 out, err = proc.communicate()
35 return proc.returncode, out
36
[f85bc15]37def is_ascii(fname):
38 if not os.path.isfile(fname):
39 return False
40
41 code, out = sh("file %s" % fname, print2stdout = False)
42 if code != 0:
43 return False
44
45 match = re.search(".*: (.*)", out)
46
47 if not match:
48 return False
49
50 return match.group(1) == "ASCII text"
51
[c07d724]52# Remove 1 or more files silently
[bacc36c]53def rm( files ):
[c07d724]54 try:
55 for file in files:
[bacc36c]56 sh("rm -f %s > /dev/null 2>&1" % file )
[c07d724]57 except TypeError:
[bacc36c]58 sh("rm -f %s > /dev/null 2>&1" % files )
[c07d724]59
[a95c117]60# Create 1 or more directory
61def mkdir( files ):
62 try:
63 for file in files:
64 sh("mkdir -p %s" % os.path.dirname(file) )
65 except TypeError:
66 sh("mkdir -p %s" % os.path.dirname(files) )
67
[c07d724]68def chdir( dest = __main__.__file__ ):
69 abspath = os.path.abspath(dest)
70 dname = os.path.dirname(abspath)
71 os.chdir(dname)
72
[bacc36c]73# diff two files
74def diff( lhs, rhs ):
75 # diff the output of the files
76 diff_cmd = ("diff --ignore-all-space "
77 "--ignore-blank-lines "
78 "--old-group-format='\t\tmissing lines :\n"
79 "%%<' \\\n"
80 "--new-group-format='\t\tnew lines :\n"
81 "%%>' \\\n"
82 "--unchanged-group-format='%%=' \\"
83 "--changed-group-format='\t\texpected :\n"
84 "%%<"
85 "\t\tgot :\n"
86 "%%>\n' \\\n"
87 "--new-line-format='\t\t%%dn\t%%L' \\\n"
88 "--old-line-format='\t\t%%dn\t%%L' \\\n"
89 "--unchanged-line-format='' \\\n"
90 "%s %s")
91
92 # fetch return code and error from the diff command
93 return sh(diff_cmd % (lhs, rhs), False)
94
95# call make
96def make(target, flags = '', redirects = '', error_file = None, silent = False):
97 test_param = """test="%s" """ % (error_file) if error_file else ''
98 cmd = ' '.join([
99 settings.make,
100 '-s' if silent else '',
101 test_param,
[f3b9efc]102 settings.debug.flags,
[bacc36c]103 flags,
104 target,
105 redirects
106 ])
107 return sh(cmd)
108
[ed45af6]109def which(program):
110 import os
111 def is_exe(fpath):
112 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
113
114 fpath, fname = os.path.split(program)
115 if fpath:
116 if is_exe(program):
117 return program
118 else:
119 for path in os.environ["PATH"].split(os.pathsep):
120 exe_file = os.path.join(path, program)
121 if is_exe(exe_file):
122 return exe_file
123
124 return None
[bacc36c]125################################################################################
126# file handling
127################################################################################
128
[c07d724]129# helper function to replace patterns in a file
130def file_replace(fname, pat, s_after):
[f85bc15]131 file = fileinput.FileInput(fname, inplace=True, backup='.bak')
132 for line in file:
133 print(line.replace(pat, s_after), end='')
134 file.close()
[c07d724]135
[0ad0c55]136# helper function to check if a files contains only a specific string
[c07d724]137def fileContainsOnly(file, text) :
138 with open(file) as f:
139 ff = f.read().strip()
140 result = ff == text.strip()
141
142 return result;
143
144# check whether or not a file is executable
145def fileIsExecutable(file) :
146 try :
147 fileinfo = os.stat(file)
148 return bool(fileinfo.st_mode & stat.S_IXUSR)
149 except Exception as inst:
150 print(type(inst)) # the exception instance
151 print(inst.args) # arguments stored in .args
152 print(inst)
153 return False
154
[bacc36c]155# transform path to canonical form
156def canonicalPath(path):
[f85bc15]157 abspath = os.path.abspath(__main__.__file__)
158 dname = os.path.dirname(abspath)
159 return os.path.join(dname, os.path.normpath(path) )
[c07d724]160
[bacc36c]161# compare path even if form is different
162def pathCmp(lhs, rhs):
163 return canonicalPath( lhs ) == canonicalPath( rhs )
[c07d724]164
[bacc36c]165# walk all files in a path
166def pathWalk( op ):
167 def step(_, dirname, names):
168 for name in names:
169 path = os.path.join(dirname, name)
170 op( path )
171
172 # Start the walk
[56de5932]173 dname = settings.SRCDIR
[f85bc15]174 os.path.walk(dname, step, '')
[bacc36c]175
176################################################################################
177# system
178################################################################################
179# count number of jobs to create
180def jobCount( options, tests ):
181 # check if the user already passed in a number of jobs for multi-threading
[d142ec5]182 if not options.jobs:
183 make_flags = os.environ.get('MAKEFLAGS')
184 force = bool(make_flags)
185 make_jobs_fds = re.search("--jobserver-(auth|fds)=\s*([0-9]+),([0-9]+)", make_flags) if make_flags else None
186 if make_jobs_fds :
187 tokens = os.read(int(make_jobs_fds.group(2)), 1024)
188 options.jobs = len(tokens)
189 os.write(int(make_jobs_fds.group(3)), tokens)
190 else :
191 options.jobs = multiprocessing.cpu_count()
[bacc36c]192 else :
[d142ec5]193 force = True
[bacc36c]194
195 # make sure we have a valid number of jobs that corresponds to user input
196 if options.jobs <= 0 :
197 print('ERROR: Invalid number of jobs', file=sys.stderr)
198 sys.exit(1)
199
[d142ec5]200 return min( options.jobs, len(tests) ), force
[bacc36c]201
202# setup a proper processor pool with correct signal handling
203def setupPool(jobs):
204 original_sigint_handler = signal.signal(signal.SIGINT, signal.SIG_IGN)
205 pool = multiprocessing.Pool(jobs)
206 signal.signal(signal.SIGINT, original_sigint_handler)
207
208 return pool
209
210# handle signals in scope
211class SignalHandling():
212 def __enter__(self):
213 # enable signal handling
214 signal.signal(signal.SIGINT, signal.SIG_DFL)
215
216 def __exit__(self, type, value, traceback):
217 # disable signal handling
218 signal.signal(signal.SIGINT, signal.SIG_IGN)
219
220################################################################################
221# misc
222################################################################################
223
224# check if arguments is yes or no
225def yes_no(string):
226 if string == "yes" :
227 return True
228 if string == "no" :
229 return False
230 raise argparse.ArgumentTypeError(msg)
[f3b9efc]231 return False
232
[ed45af6]233def fancy_print(text):
234 column = which('column')
235 if column:
236 cmd = "%s 2> /dev/null" % column
237 print(cmd)
238 proc = Popen(cmd, stdin=PIPE, stderr=None, shell=True)
239 proc.communicate(input=text)
240 else:
241 print(text)
Note: See TracBrowser for help on using the repository browser.