1 |
jfenwick |
2266 |
|
2 |
|
|
import shutil, os, datetime, sys, os.path, time |
3 |
|
|
|
4 |
|
|
#This script does not use the python, platform independent path manipulation stuff. |
5 |
|
|
#It probably should |
6 |
|
|
|
7 |
|
|
SVNURL="https://shake200.esscc.uq.edu.au/svn/esys13/trunk" |
8 |
|
|
NUMJs=4 |
9 |
|
|
TOPDIR=str(datetime.date.today()) |
10 |
|
|
ERRMAIL="j.fenwick1@uq.edu.au" |
11 |
|
|
EXECUTELOCATION="/scratch/jfenwick/AUTOTESTS" |
12 |
|
|
OUTSIDEDIR=os.getcwd() |
13 |
|
|
TESTSLEEP=30*60 |
14 |
|
|
|
15 |
|
|
SRCMSG="This message was sent by prepare.py running as "+str(os.environ['USER'])+" on "+str(os.environ['HOSTNAME']+"\n") |
16 |
|
|
|
17 |
|
|
#Settings for actual tests appear below the class declarations |
18 |
|
|
|
19 |
|
|
|
20 |
|
|
def failure(msg): |
21 |
|
|
print "Terminating - Error "+str(msg) |
22 |
|
|
print "Should be sending mail to "+str(ERRMAIL) |
23 |
|
|
mailcmd="cat << ENDMSG |mail -s 'Esys unit tests failed to execute properly' "+ERRMAIL+"\n" |
24 |
|
|
mailcmd=mailcmd+"Error preparing for test run:\n"+msg+"\n" |
25 |
|
|
mailcmd=mailcmd+SRCMSG |
26 |
|
|
mailcmd=mailcmd+"ENDMSG\n" |
27 |
|
|
os.system(mailcmd) |
28 |
|
|
sys.exit(1) |
29 |
|
|
|
30 |
|
|
def progress(msg): |
31 |
|
|
print msg |
32 |
|
|
|
33 |
|
|
class TestConfiguration(object): |
34 |
|
|
def __init__(self, name, opts, omp, mpi, binexec, pythonexec): |
35 |
|
|
self.name=name |
36 |
|
|
self.opts=opts |
37 |
|
|
self.omp=omp |
38 |
|
|
self.mpi=mpi |
39 |
|
|
self.binexec=binexec |
40 |
|
|
self.pythonexec=pythonexec |
41 |
|
|
|
42 |
|
|
def getHeader(): |
43 |
|
|
res="#!/bin/bash\n" |
44 |
|
|
res=res+'MAIL_RECIPIENTS="'+ERRMAIL+'"\n' |
45 |
|
|
res=res+"function report()\n{\n" |
46 |
|
|
res=res+" NOW=`date '+%Y/%m/%d %H:%M'`\n" |
47 |
|
|
res=res+" cat > $LOGDIR/message << END_MSG\n" |
48 |
|
|
res=res+"Sucessful configurations:\n" |
49 |
|
|
res=res+"$SUCCESSFUL\n\n" |
50 |
|
|
res=res+"Failed on configuration:\n" |
51 |
|
|
res=res+"$ATTEMPTING\n\n" |
52 |
|
|
res=res+"Tests ran from $START until $NOW.\n" |
53 |
|
|
res=res+"Log files can be found in $FINALLOGDIR.\n" |
54 |
|
|
res=res+"END_MSG\n" |
55 |
|
|
res=res+"}\n" |
56 |
|
|
res=res+"function progress()\n{\n" |
57 |
|
|
res=res+" echo $1\n" |
58 |
|
|
res=res+" echo $1 >> $PROGRESSFILE\n" |
59 |
|
|
res=res+"}\n" |
60 |
|
|
res=res+"function failure()\n{\n echo $1\n" |
61 |
|
|
res=res+" report\n" |
62 |
|
|
res=res+" touch $LOGDIR/Failure\n" |
63 |
|
|
res=res+" if [ -f stdout_cpu_0001.out ];then cp std_cpu_* $TESTLOGDIR;fi\n" |
64 |
|
|
res=res+" exit 1\n}\n" |
65 |
|
|
res=res+"cd "+EXECUTELOCATION+"/"+TOPDIR+"\n" |
66 |
|
|
res=res+"TOP=`pwd`\nLOGDIR=$TOP/Logs\nPROGRESSFILE=$LOGDIR/progress\nOLDPYTH=$PYTHONPATH\nOLDLD=$LD_LIBRARY_PATH\n" |
67 |
|
|
res=res+". /usr/share/modules/init/sh #So the module command works\n" |
68 |
|
|
res=res+"module load subversion-1.3.1\nmodule load escript/current\nmodule load pbs\nmodule load mayavi/gcc-4.1.2/mayavi-1.5\n" |
69 |
|
|
res=res+"module load mplayer/gcc-4.1.2/mplayer-1.0rc2\n\n" |
70 |
|
|
res=res+"SCRIPTNAME=$0\n" |
71 |
|
|
res=res+"START=`date '+%Y/%m/%d %H:%M'`\n" |
72 |
|
|
res=res+"TESTLOGDIR=$LOGDIR\n" |
73 |
|
|
res=res+"FINALLOGDIR="+OUTSIDEDIR+"/"+TOPDIR+"_Logs\n" |
74 |
|
|
return res |
75 |
|
|
|
76 |
|
|
def toString(self): |
77 |
|
|
runcount=1 |
78 |
|
|
res="" |
79 |
|
|
print "Processing "+self.name |
80 |
|
|
for o in self.omp: |
81 |
|
|
print "o="+str(o) |
82 |
|
|
for m in self.mpi: |
83 |
|
|
print " m="+str(m) |
84 |
|
|
cmd="bash utest.sh 'mpiexec -np"+str(m)+"' $TESTROOT/lib/pythonMPI >$TESTLOGDIR/output 2>&1" |
85 |
|
|
res=res+"cp -r "+self.name+"_src "+self.name+"_test"+str(runcount)+"\n" |
86 |
|
|
res=res+"cd "+self.name+"_test"+str(runcount)+"\n" |
87 |
|
|
res=res+"TESTROOT=`pwd`\n" |
88 |
|
|
res=res+"TESTLOGDIR=$LOGDIR/"+self.name+"_test"+str(runcount)+"\n" |
89 |
|
|
res=res+"mkdir $TESTLOGDIR\n" |
90 |
|
|
res=res+"export OMP_NUM_THREADS="+str(o)+"\n" |
91 |
|
|
res=res+"export PYTHONPATH=`pwd`:$OLDPYTH\n" |
92 |
|
|
res=res+"export LD_LIBRARY_PATH=`pwd`/lib:$OLDLD\n" |
93 |
|
|
res=res+'RUNNAME="'+self.name+' omp='+str(o)+' mpi='+str(m)+'"\n' |
94 |
|
|
res=res+'ATTEMPTING=$RUNNAME\n' |
95 |
|
|
res=res+'progress "Starting '+cmd+'"\n' |
96 |
|
|
res=res+cmd+' || failure "'+cmd+'"\n' |
97 |
|
|
res=res+"if [ -f stdout_cpu_0001.out ];then cp std_cpu_* $TESTLOGDIR;fi\n" |
98 |
|
|
res=res+'SUCCESSFUL="$SUCCESSFUL, $RUNNAME"\n' |
99 |
|
|
res=res+'progress "completed '+cmd+'"\n' |
100 |
|
|
res=res+'ATTEMPTING=None\n' |
101 |
|
|
res=res+"export OMP_NUM_THREADS=1\n" |
102 |
|
|
res=res+"cd $TOP\n" |
103 |
|
|
res=res+"rm -rf "+self.name+"_test"+str(runcount)+"\n\n" |
104 |
|
|
runcount=runcount+1 |
105 |
|
|
if len(self.mpi)==0: |
106 |
|
|
print " m=()" |
107 |
|
|
cmd="bash utest.sh '' python $TESTROOT/lib/pythonMPI >$TESTLOGDIR/output 2>&1" |
108 |
|
|
res=res+"cp -r "+self.name+"_src "+self.name+"_test"+str(runcount)+"\n" |
109 |
|
|
res=res+"cd "+self.name+"_test"+str(runcount)+"\n" |
110 |
|
|
res=res+"TESTROOT=`pwd`\n" |
111 |
|
|
res=res+"TESTLOGDIR=$LOGDIR/"+self.name+"_test"+str(runcount)+"\n" |
112 |
|
|
res=res+"mkdir $TESTLOGDIR\n" |
113 |
|
|
res=res+"export OMP_NUM_THREADS="+str(o)+"\n" |
114 |
|
|
res=res+"export LD_LIBRARY_PATH=`pwd`/lib:$OLDLD\n" |
115 |
|
|
res=res+"export PYTHONPATH=`pwd`:$OLDPYTH\n" |
116 |
|
|
res=res+'RUNNAME="'+self.name+' omp='+str(o)+' mpi=n/a"\n' |
117 |
|
|
res=res+'ATTEMPTING=$RUNNAME\n' |
118 |
|
|
res=res+'progress "Starting '+cmd+'"\n' |
119 |
|
|
res=res+cmd+" || failure \""+cmd+"\" \n" |
120 |
|
|
res=res+"if [ -f stdout_cpu_0001.out ];then cp std_cpu_* $TESTLOGDIR;fi\n" |
121 |
|
|
res=res+'ATTEMPTING=None\n' |
122 |
|
|
res=res+'progress "completed '+cmd+'"\n' |
123 |
|
|
res=res+"cd $TOP\n" |
124 |
|
|
res=res+"rm -rf "+self.name+"_test"+str(runcount)+"\n\n" |
125 |
|
|
runcount=runcount+1 |
126 |
|
|
res=res+"rm -rf "+self.name+"_src\n" |
127 |
|
|
res=res+"\ncd $TOP\n\n" |
128 |
|
|
return res |
129 |
|
|
|
130 |
|
|
def getFooter(): |
131 |
|
|
res="\ntouch $LOGDIR/Success\n" |
132 |
|
|
res=res+"report" |
133 |
|
|
return res |
134 |
|
|
|
135 |
|
|
getHeader=staticmethod(getHeader) |
136 |
|
|
getFooter=staticmethod(getFooter) |
137 |
|
|
|
138 |
|
|
#Test settings |
139 |
|
|
testconfs=[] |
140 |
|
|
testconfs.append(TestConfiguration("OMPNoMPI","",omp=(1,8),mpi=(),binexec="",pythonexec="python")) |
141 |
|
|
testconfs.append(TestConfiguration("MPI","usempi=yes",omp=(1,),mpi=(1,8),binexec="mpiexec -np ",pythonexec="lib/pythonMPI")) |
142 |
|
|
|
143 |
|
|
LOGDIR=OUTSIDEDIR+"/"+TOPDIR+"_Logs" |
144 |
|
|
|
145 |
|
|
if os.path.exists(LOGDIR): |
146 |
|
|
failure("Logs directory for "+TOPDIR+" already exists.") |
147 |
|
|
sys.exit(1) |
148 |
|
|
|
149 |
|
|
try: |
150 |
|
|
os.mkdir(TOPDIR) |
151 |
|
|
os.chdir(TOPDIR) |
152 |
|
|
except OSError: |
153 |
|
|
failure("Unable to create top directory "+TOPDIR+" does it exist already?") |
154 |
|
|
sys.exit(1) |
155 |
|
|
|
156 |
|
|
try: |
157 |
|
|
os.mkdir("Logs") |
158 |
|
|
except OSError: |
159 |
|
|
failure("Unable to create Logs directory ") |
160 |
|
|
sys.exit(1) |
161 |
|
|
|
162 |
|
|
coresult=os.system("svn export "+SVNURL+" src") |
163 |
|
|
if coresult!=0: |
164 |
|
|
failure("Unable to export working copy") |
165 |
|
|
sys.exit(1) |
166 |
|
|
|
167 |
|
|
|
168 |
|
|
|
169 |
|
|
|
170 |
|
|
dir=os.getcwd() |
171 |
|
|
for conf in testconfs: |
172 |
|
|
progress("Creating "+conf.name+"_src") |
173 |
|
|
# res=os.system("cp -r src "+conf.name+"_src") |
174 |
|
|
# if res!=0: |
175 |
|
|
# failure("Error copying src to "+conf.name+"_src") |
176 |
|
|
try: |
177 |
|
|
shutil.copytree("src",conf.name+"_src") |
178 |
|
|
except Error: |
179 |
|
|
failure("copying src to "+conf.name+"_src") |
180 |
|
|
os.chdir(conf.name+"_src") |
181 |
|
|
cmdstr="scons -j"+str(NUMJs)+" "+conf.opts+" install_all build_tests build_py_tests" |
182 |
|
|
progress(cmdstr) |
183 |
|
|
res=os.system(cmdstr) |
184 |
|
|
os.chdir(str(dir)) |
185 |
|
|
if res!=0: |
186 |
|
|
failure("running scons build failed for "+conf.name+"_src") |
187 |
|
|
|
188 |
|
|
progress("Builds complete") |
189 |
|
|
progress("Removing export copy") |
190 |
|
|
shutil.rmtree("src",ignore_errors=True) |
191 |
|
|
progress("Building test file") |
192 |
|
|
|
193 |
|
|
try: |
194 |
|
|
testfile=open("dotests.sh","w") |
195 |
|
|
testfile.write(TestConfiguration.getHeader()) |
196 |
|
|
for c in testconfs: |
197 |
|
|
testfile.write(c.toString()) |
198 |
|
|
testfile.write(TestConfiguration.getFooter()) |
199 |
|
|
testfile.close() |
200 |
|
|
import stat |
201 |
|
|
os.chmod("dotests.sh",stat.S_IEXEC|stat.S_IREAD) |
202 |
|
|
except IOError: |
203 |
|
|
failure("Creating testfile") |
204 |
|
|
|
205 |
|
|
progress("Building test file complete") |
206 |
|
|
progress("Copying files to exec area") |
207 |
|
|
os.chdir(OUTSIDEDIR) |
208 |
|
|
try: |
209 |
|
|
shutil.copytree(TOPDIR,EXECUTELOCATION+"/"+TOPDIR) |
210 |
|
|
except Error: |
211 |
|
|
failure("copying to work area") |
212 |
|
|
progress("Copy to exec area complete") |
213 |
|
|
|
214 |
|
|
print "Submitting test" |
215 |
|
|
|
216 |
|
|
######### test section |
217 |
|
|
|
218 |
|
|
os.chdir(EXECUTELOCATION) |
219 |
|
|
os.chdir(TOPDIR) |
220 |
|
|
|
221 |
|
|
|
222 |
|
|
try: |
223 |
|
|
# res=os.system("bash dotests.sh") |
224 |
|
|
res=os.system("qsub -l select=1:ncpus=8:mem=31gb dotests.sh") |
225 |
|
|
except OSError: |
226 |
|
|
failure("Submitting tests") |
227 |
|
|
|
228 |
|
|
os.chdir(OUTSIDEDIR) |
229 |
|
|
|
230 |
|
|
print "Sleeping for "+str(TESTSLEEP)+" seconds to wait for results." |
231 |
|
|
time.sleep(TESTSLEEP) |
232 |
|
|
print "Waking up." |
233 |
|
|
|
234 |
|
|
######################## |
235 |
|
|
|
236 |
|
|
try: |
237 |
|
|
shutil.copytree(EXECUTELOCATION+"/"+TOPDIR+"/Logs",OUTSIDEDIR+"/"+TOPDIR+"_Logs") |
238 |
|
|
except OSError: |
239 |
|
|
failure("Log copy failed") |
240 |
|
|
|
241 |
|
|
cleanupfailure=False |
242 |
|
|
|
243 |
|
|
try: |
244 |
|
|
shutil.rmtree(EXECUTELOCATION+"/"+TOPDIR) |
245 |
|
|
shutil.rmtree(OUTSIDEDIR+"/"+TOPDIR) |
246 |
|
|
except OSError: |
247 |
|
|
cleanupfailure=True |
248 |
|
|
|
249 |
|
|
#Now we sum up |
250 |
|
|
#if Logs/Failure or Logs/Success does not exist send message about tests not completing. |
251 |
|
|
if not os.path.exists(LOGDIR+"/Success") and not os.path.exists(LOGDIR+"/Failure"): |
252 |
|
|
mailcmd="cat << ENDMSG |mail -s 'Esys unit tests failed to execute properly' "+ERRMAIL+"\n" |
253 |
|
|
mailcmd=mailcmd+"For some reason no Success or failure is recorded for unit tests in "+LOGDIR+"\n" |
254 |
|
|
mailcmd=mailcmd+"\nAlso: the cleanup of work areas failed. "+EXECUTELOCATION+"/"+TOPDIR+" or "+OUTSIDEDIR+"/"+TOPDIR+"\n" |
255 |
|
|
mailcmd=mailcmd+SRCMSG |
256 |
|
|
mailcmd=mailcmd+"ENDMSG\n" |
257 |
|
|
os.system(mailcmd) |
258 |
|
|
sys.exit(1) |
259 |
|
|
|
260 |
|
|
|
261 |
|
|
if os.path.exists(LOGDIR+"/Failure"): |
262 |
|
|
os.system("echo 'Also: the cleanup of work areas failed. "+EXECUTELOCATION+"/"+TOPDIR+" or "+OUTSIDEDIR+"/"+TOPDIR+"' >> "+LOGDIR+"/message\n") |
263 |
|
|
os.system("echo '"+SRCMSG+"' >> "+LOGDIR+"/message\n") |
264 |
|
|
mailcmd="cat "+LOGDIR+"/message | mail -s 'Esys unit tests failed' "+ERRMAIL+"\n" |
265 |
|
|
os.system(mailcmd) |
266 |
|
|
sys.exit(1) |
267 |
|
|
#so we must have succeeded |
268 |
|
|
|
269 |
|
|
if cleanupfailure: |
270 |
|
|
os.system("echo '"+SRCMSG+"' >> "+LOGDIR+"/message\n") |
271 |
|
|
mailcmd="cat "+LOGDIR+"/message | mail -s 'Esys unit tests cleanup failed - tests succeeded' "+ERRMAIL+"\n" |
272 |
|
|
res=os.system(mailcmd) |
273 |
|
|
sys.exit(res) |
274 |
|
|
else: |
275 |
|
|
os.system("echo '"+SRCMSG+"' >> "+LOGDIR+"/message\n") |
276 |
|
|
mailcmd="cat "+LOGDIR+"/message | mail -s 'Esys unit tests succeeded' "+ERRMAIL+"\n" |
277 |
|
|
res=os.system(mailcmd) |
278 |
|
|
sys.exit(res) |
279 |
|
|
|