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

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerresolv-newwith_gc
Last change on this file since bacc36c was bacc36c, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Major test cleanup by modularizing further into pybin

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