runAllTests.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import os
  2. import os.path
  3. import subprocess
  4. import colorama
  5. from colorama import init,Fore, Back, Style
  6. import argparse
  7. from TestScripts.Regression.Commands import *
  8. import yaml
  9. import sys
  10. import itertools
  11. from pathlib import Path
  12. import sqlite3
  13. # Command to get last runid
  14. lastID="""SELECT runid FROM RUN ORDER BY runid DESC LIMIT 1
  15. """
  16. addNewIDCmd="""INSERT INTO RUN VALUES(?,date('now'))
  17. """
  18. benchID = 0
  19. regID = 0
  20. def getLastRunID(c):
  21. r=c.execute(lastID)
  22. result=r.fetchone()
  23. if result is None:
  24. return(0)
  25. else:
  26. return(int(result[0]))
  27. def addNewID(c,newid):
  28. print(" New run ID = %d" % newid)
  29. c.execute(addNewIDCmd,(newid,))
  30. c.commit()
  31. # Small state machine
  32. def updateTestStatus(testStatusForThisBuild,newTestStatus):
  33. if testStatusForThisBuild == NOTESTFAILED:
  34. if newTestStatus == NOTESTFAILED:
  35. return(NOTESTFAILED)
  36. if newTestStatus == MAKEFAILED:
  37. return(MAKEFAILED)
  38. if newTestStatus == TESTFAILED:
  39. return(TESTFAILED)
  40. if testStatusForThisBuild == MAKEFAILED:
  41. if newTestStatus == NOTESTFAILED:
  42. return(MAKEFAILED)
  43. if newTestStatus == MAKEFAILED:
  44. return(MAKEFAILED)
  45. if newTestStatus == TESTFAILED:
  46. return(TESTFAILED)
  47. if testStatusForThisBuild == TESTFAILED:
  48. if newTestStatus == NOTESTFAILED:
  49. return(TESTFAILED)
  50. if newTestStatus == MAKEFAILED:
  51. return(TESTFAILED)
  52. if newTestStatus == TESTFAILED:
  53. return(TESTFAILED)
  54. if testStatusForThisBuild == FLOWFAILURE:
  55. return(testStatusForThisBuild)
  56. if testStatusForThisBuild == CALLFAILURE:
  57. return(testStatusForThisBuild)
  58. # Analyze the configuration flags (like loopunroll etc ...)
  59. def analyzeFlags(flags):
  60. onoffFlags = []
  61. for f in flags:
  62. if type(f) is dict:
  63. for var in f:
  64. if type(f[var]) is bool:
  65. if f[var]:
  66. onoffFlags.append(["-D%s=ON" % (var)])
  67. else:
  68. onoffFlags.append(["-D%s=OFF" % (var)])
  69. else:
  70. onoffFlags.append(["-D%s=%s" % (var,f[var])])
  71. else:
  72. onoffFlags.append(["-D" + f +"=ON","-D" + f +"=OFF"])
  73. allConfigs=cartesian(*onoffFlags)
  74. return(allConfigs)
  75. # Extract the cmake for a specific compiler
  76. # and the flag configuration to use for this compiler.
  77. # This flags configuration will override the global one
  78. def analyzeToolchain(toolchain, globalConfig):
  79. config=globalConfig
  80. cmake=""
  81. sim=True
  82. if type(toolchain) is str:
  83. cmake=toolchain
  84. else:
  85. for t in toolchain:
  86. if type(t) is dict:
  87. if "FLAGS" in t:
  88. hasConfig=True
  89. config = analyzeFlags(t["FLAGS"])
  90. if "SIM" in t:
  91. sim = t["SIM"]
  92. if type(t) is str:
  93. cmake=t
  94. return(cmake,config,sim)
  95. def cartesian(*somelists):
  96. r=[]
  97. for element in itertools.product(*somelists):
  98. r.append(list(element))
  99. return(r)
  100. root = Path(os.getcwd()).parent.parent.parent
  101. testFailed = 0
  102. init()
  103. parser = argparse.ArgumentParser(description='Parse test description')
  104. parser.add_argument('-i', nargs='?',type = str, default="testrunConfig.yaml",help="Config file")
  105. parser.add_argument('-r', nargs='?',type = str, default=root, help="Root folder")
  106. parser.add_argument('-n', nargs='?',type = int, default=0, help="ID value when launching in parallel")
  107. parser.add_argument('-b', action='store_true', help="Benchmark mode")
  108. parser.add_argument('-f', nargs='?',type = str, default="desc.txt",help="Test description file")
  109. parser.add_argument('-p', nargs='?',type = str, default="FVP",help="Platform for running")
  110. parser.add_argument('-db', nargs='?',type = str,help="Benchmark database")
  111. parser.add_argument('-regdb', nargs='?',type = str,help="Regression database")
  112. parser.add_argument('-sqlite', nargs='?',default="/usr/bin/sqlite3",type = str,help="sqlite executable")
  113. parser.add_argument('-debug', action='store_true', help="Debug mode")
  114. parser.add_argument('-nokeep', action='store_true', help="Do not keep build folder")
  115. args = parser.parse_args()
  116. if args.debug:
  117. setDebugMode()
  118. if args.nokeep:
  119. setNokeepBuildFolder()
  120. # Create missing database files
  121. # if the db arguments are specified
  122. if args.db is not None:
  123. if not os.path.exists(args.db):
  124. createDb(args.sqlite,args.db)
  125. conn = sqlite3.connect(args.db)
  126. try:
  127. currentID = getLastRunID(conn)
  128. benchID = currentID + 1
  129. print("Bench db")
  130. addNewID(conn,benchID)
  131. finally:
  132. conn.close()
  133. if args.regdb is not None:
  134. if not os.path.exists(args.regdb):
  135. createDb(args.sqlite,args.regdb)
  136. conn = sqlite3.connect(args.regdb)
  137. try:
  138. currentID = getLastRunID(conn)
  139. regID = currentID + 1
  140. print("Regression db")
  141. addNewID(conn,regID)
  142. finally:
  143. conn.close()
  144. with open(args.i,"r") as f:
  145. config=yaml.safe_load(f)
  146. #print(config)
  147. #print(config["IMPLIEDFLAGS"])
  148. patternConfig={}
  149. if "PATTERNS" in config:
  150. patternConfig={
  151. "patterns":os.path.join(config["PATTERNS"],"Patterns")
  152. ,"parameters":os.path.join(config["PATTERNS"],"Parameters")
  153. }
  154. flags = config["FLAGS"]
  155. allConfigs = analyzeFlags(flags)
  156. if isDebugMode():
  157. allConfigs=[allConfigs[0]]
  158. failedBuild = {}
  159. # Test all builds
  160. folderCreated=False
  161. def logFailedBuild(root,f):
  162. with open(os.path.join(fullTestFolder(root),"buildStatus_%d.txt" % args.n),"w") as status:
  163. for build in f:
  164. s = f[build]
  165. if s == MAKEFAILED:
  166. status.write("%s : Make failure\n" % build)
  167. if s == TESTFAILED:
  168. status.write("%s : Test failure\n" % build)
  169. if s == FLOWFAILURE:
  170. status.write("%s : Flow failure\n" % build)
  171. if s == CALLFAILURE:
  172. status.write("%s : Subprocess failure\n" % build)
  173. def buildAndTest(compiler,theConfig,cmake,sim):
  174. # Run all tests for AC6
  175. try:
  176. for core in config['CORES']:
  177. configNb = 0
  178. if compiler in config['CORES'][core]:
  179. msg("Testing Core %s\n" % core)
  180. for flagConfig in theConfig:
  181. folderCreated = False
  182. configNb = configNb + 1
  183. buildStr = "build_%s_%s_%d" % (compiler,core,configNb)
  184. toUnset = None
  185. toSet = None
  186. if 'UNSET' in config:
  187. if compiler in config['UNSET']:
  188. if core in config['UNSET'][compiler]:
  189. toUnset = config['UNSET'][compiler][core]
  190. if 'SET' in config:
  191. if compiler in config['SET']:
  192. if core in config['SET'][compiler]:
  193. toSet = config['SET'][compiler][core]
  194. build = BuildConfig(toUnset,toSet,args.r,
  195. buildStr,
  196. config['COMPILERS'][core][compiler],
  197. cmake,
  198. config['CORES'][core][compiler],
  199. config["CMAKE"]
  200. )
  201. flags = []
  202. if core in config["IMPLIEDFLAGS"]:
  203. flags += config["IMPLIEDFLAGS"][core]
  204. flags += flagConfig
  205. if compiler in config["IMPLIEDFLAGS"]:
  206. flags += config["IMPLIEDFLAGS"][compiler]
  207. build.createFolder()
  208. # Run all tests for the build
  209. testStatusForThisBuild = NOTESTFAILED
  210. try:
  211. # This is saving the flag configuration
  212. build.createArchive(flags)
  213. msg("Config " + str(flagConfig) + "\n")
  214. build.createCMake(core,flags,args.b,args.p)
  215. for test in config["TESTS"]:
  216. msg(test["testName"]+"\n")
  217. testClass=test["testClass"]
  218. test = build.getTest(testClass)
  219. fvp = None
  220. if 'FVP' in config:
  221. if core in config['FVP']:
  222. fvp = config['FVP'][core]
  223. if 'SIM' in config:
  224. if core in config['SIM']:
  225. fvp = config['SIM'][core]
  226. newTestStatus = test.runAndProcess(patternConfig,compiler,fvp,sim,args.b,args.db,args.regdb,benchID,regID)
  227. testStatusForThisBuild = updateTestStatus(testStatusForThisBuild,newTestStatus)
  228. if testStatusForThisBuild != NOTESTFAILED:
  229. failedBuild[buildStr] = testStatusForThisBuild
  230. # Final script status
  231. testFailed = 1
  232. build.archiveResults()
  233. finally:
  234. build.cleanFolder()
  235. else:
  236. msg("No toolchain %s for core %s" % (compiler,core))
  237. except TestFlowFailure as flow:
  238. errorMsg("Error flow id %d\n" % flow.errorCode())
  239. failedBuild[buildStr] = FLOWFAILURE
  240. logFailedBuild(args.r,failedBuild)
  241. sys.exit(1)
  242. except CallFailure:
  243. errorMsg("Call failure\n")
  244. failedBuild[buildStr] = CALLFAILURE
  245. logFailedBuild(args.r,failedBuild)
  246. sys.exit(1)
  247. ############## Builds for all toolchains
  248. if not isDebugMode():
  249. preprocess(args.f)
  250. generateAllCCode(patternConfig)
  251. else:
  252. msg("Debug Mode\n")
  253. for t in config["TOOLCHAINS"]:
  254. cmake,localConfig,sim = analyzeToolchain(config["TOOLCHAINS"][t],allConfigs)
  255. msg("Testing toolchain %s\n" % t)
  256. buildAndTest(t,localConfig,cmake,sim)
  257. logFailedBuild(args.r,failedBuild)
  258. sys.exit(testFailed)