PageRenderTime 65ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/pytest/autoreport.py

https://github.com/heca/rextest2
Python | 397 lines | 329 code | 29 blank | 39 comment | 13 complexity | 00092e9103bd028dd981c00d0418ca83 MD5 | raw file
  1. #!/usr/local/bin/python
  2. #TODO:
  3. # - try catches
  4. # - globals-
  5. # - os.tmpfile() http://docs.python.org/library/os.html#os.tmpfile
  6. # feature: archives all avatar-test output folders if moveold isnt enabled (or preservelogs is on) wildcard glob
  7. #
  8. import time
  9. import StringIO
  10. import ftplib
  11. import glob
  12. import os
  13. import pycurl
  14. import shutil
  15. import zipfile
  16. import os.path
  17. import platform
  18. # FTP-CONFIG for fileUpload
  19. FTPHOST="xxx"
  20. FTPUSER="xxx"
  21. FTPPASSWD="xxx"
  22. # GITHUB-CONFIG for createGithubIssue
  23. GITHUBLOGIN="rex-test-autoreport" # user
  24. GITHUBAPITOKEN="4b05500b0593b50f4c89dacb6d11449c" #users api token
  25. GITHUBREPO="rex-test-autoreport/issueReportTest" # e.g. "projectowner/project"
  26. #
  27. # OPTIONS
  28. #
  29. # Option for preserving test output files after archive has been created
  30. configPreserveLogs = False
  31. # Option for moving test output files to an old archives folder (debug-standalone-run)
  32. # if preserveLogs is set to false option is ignored
  33. configMoveOld = False
  34. # Option for cleaning up (removing temp files) the the folder after running the script
  35. # default true
  36. configCleanUp = True
  37. # Option for uploading report .zip to host
  38. # default false (needs config)
  39. configUploadFile = False
  40. # Option for making github issue report
  41. # default false (needs config)
  42. configCreateGithubIssue = False
  43. #Option for including test machine info to the report file
  44. includeMachineInfo = True
  45. # CONSTANTS
  46. # configured test cases
  47. TEST0 = "Example-skeleton"
  48. TEST1 = "js-viewer-server-test"
  49. TEST2 = "avatar-test"
  50. # misc
  51. tempCount = "count.txt"
  52. tempErrors = "errors.txt"
  53. #tempCount = tempfile.mktemp()
  54. #tempErrors = tempfile.mktemp()
  55. # VARIABLES
  56. # bools
  57. errors = False
  58. # names
  59. testName = None
  60. # files
  61. html = None
  62. zipName = None
  63. logFile = None
  64. outputFile = None
  65. # directories
  66. logDir = None
  67. oldDir = None
  68. # misc
  69. timeStamp = None
  70. testComment = None
  71. errorPattern = None
  72. def testSkeleton():
  73. global testName
  74. global testComment
  75. global errorPattern
  76. global logDir
  77. global logFile
  78. global outputFile
  79. testName = TEST0
  80. testComment = "This is an example"
  81. logDir = "logs/example"
  82. errorPattern = [
  83. 'example',
  84. 'e.g.'
  85. ]
  86. logFile = [
  87. '1.example',
  88. '2.example',
  89. '3.example'
  90. ]
  91. #files included in the zip archive
  92. outputFile = glob.glob(logDir + '/*') #everything in outputDir, script presumes test outputs everything to its own output folder, files can also be added to a list individually
  93. operation()
  94. def jsViewerServerTest():
  95. global testName
  96. global testComment
  97. global errorPattern
  98. global logDir
  99. global logFile
  100. global outputFile
  101. testName = TEST1
  102. testComment = "This test tries to launch local server and connect to it with the viewer app."
  103. logDir = "logs/jvst-output"
  104. errorPattern = [
  105. 'Error',
  106. 'fail'
  107. ]
  108. logFile = glob.glob(logDir + '/*.out')
  109. outputFile = glob.glob(logDir + '/*') #everything in outputDir
  110. operation()
  111. def avatarTest():
  112. global testName
  113. global testComment
  114. global errorPattern
  115. global logDir
  116. global logFile
  117. global outputFile
  118. testName = TEST2
  119. testComment = "This test tries to connect to the server multiple times and move the avatar around, while recording traffic with tshark"
  120. logDir = "logs/avatar-output"
  121. errorPattern = [
  122. 'Error',
  123. 'fail'
  124. ]
  125. logFile = glob.glob(logDir + '/logs_*/naaliLog*.*.log')
  126. outputFile = glob.glob(logDir + '/*/*') #everything in outputDir
  127. operation()
  128. def operation():
  129. global html
  130. html = testName + "_summary.html"
  131. print("Running autoreport for: " + testName)
  132. whatWentWrong()
  133. if errors:
  134. createSummary()
  135. createArchive()
  136. if configUploadFile:
  137. uploadFile()
  138. if not configPreserveLogs:
  139. #remove files
  140. for f in outputFile:
  141. os.remove(f)
  142. #remove dir
  143. #os.removedirs(logDir)
  144. shutil.rmtree(logDir, ignore_errors=True)
  145. else:
  146. #relocate already archieved files
  147. if configMoveOld:
  148. moveOld()
  149. if configCreateGithubIssue:
  150. createGithubIssue()
  151. if configCleanUp:
  152. cleanUp()
  153. print "Finished..."
  154. def whichTestWasRun(option):
  155. if option == TEST1:
  156. jsViewerServerTest()
  157. elif option == TEST2:
  158. avatarTest()
  159. else:
  160. print("Error: test config not found")
  161. def whatWentWrong():
  162. global errors
  163. errorAmounts = len(errorPattern)*[0]
  164. #reset temp file
  165. with open(tempErrors, 'w') as fo:
  166. fo.write("")
  167. #loop through files
  168. for i in range(0, len(logFile)):
  169. #make sure there is such a file
  170. if os.path.isfile(logFile[i]):
  171. #open file for reading
  172. with open(logFile[i]) as f:
  173. #open tempFile for appending
  174. with open(tempErrors, 'a') as fo:
  175. #write file identifier
  176. fo.write("---" + logFile[i] + "\n")
  177. #go through the file line by line
  178. for line in f:
  179. #compare to all given indicators
  180. for n in range(0, len(errorPattern)):
  181. #if a matching is found print the line to tempFile and set vars for making report files
  182. if errorPattern[n] in line:
  183. #set errors to true, for operation() knows to continue
  184. errors = True
  185. #count errors
  186. #insert new value to n,get previous value with pop(which also removes it) and add one
  187. errorAmounts.insert(n, errorAmounts.pop(n) + 1)
  188. #write errors to file
  189. with open(tempErrors, 'a') as fo:
  190. fo.write(line)
  191. else:
  192. print "Configured logfile not found. Skipping..."
  193. if os.path.isfile(tempCount):
  194. os.remove(tempCount)
  195. #make count tempfile
  196. for i in range(0, len(errorPattern)):
  197. with open(tempCount, 'a') as cnt:
  198. cnt.write(str(errorPattern[i]) + " - " + str(errorAmounts[i]) + "\n")
  199. def createSummary():
  200. global html
  201. print "Creating report...",
  202. try:
  203. htmlReportFile = open(html, 'w')
  204. summaryOperations(htmlReportFile, "start")
  205. if includeMachineInfo == True:
  206. summaryOperations(htmlReportFile, "machine")
  207. summaryOperations(htmlReportFile, "desc")
  208. summaryOperations(htmlReportFile, "found")
  209. summaryOperations(htmlReportFile, "errors")
  210. for i in range(0, len(outputFile)):
  211. summaryOperations(htmlReportFile, "add", outputFile[i])
  212. summaryOperations(htmlReportFile, "total")
  213. summaryOperations(htmlReportFile, "stop")
  214. htmlReportFile.close()
  215. print("successful")
  216. except:
  217. print("failed")
  218. def summaryOperations(htmlReportFile, option, *fileName):
  219. errorFile = open(tempErrors, 'r')
  220. errorOutput = errorFile.read()
  221. errorFile.close()
  222. if option == 'start':
  223. htmlReportFile.write("<html><body><h1>TEST SUMMARY: " + testName + "</h1>")
  224. elif option =='machine':
  225. htmlReportFile.write("<p>Test machine info: " + platform.platform() + "<p>")
  226. elif option == 'desc':
  227. htmlReportFile.write("<p>" + testComment + "</p><hr />")
  228. elif option == 'found':
  229. htmlReportFile.write("<pre>")
  230. with open(tempCount,'r') as a:
  231. for line in a:
  232. htmlReportFile.write(line)
  233. htmlReportFile.write("</pre><hr />")
  234. elif option == 'errors':
  235. htmlReportFile.write("<pre>" + errorOutput + "</pre><hr /><h3>Files:</h3><ul>")
  236. elif option == 'add':
  237. htmlReportFile.write("<li>File: <a href=" + str(fileName) +">" + str(fileName)[2:-3] + "</a></li>") # [2:-3] strip list brackets ('xxx',) --> xxx
  238. elif option == 'total':
  239. htmlReportFile.write("</ul><hr /><p>Total files: " + str(len(outputFile)) + "</p>")
  240. elif option == 'stop':
  241. htmlReportFile.write("</body></html>")
  242. def createArchive():
  243. global timeStamp
  244. global zipName
  245. print "Creating zip... ",
  246. try:
  247. timeStamp = time.strftime("%Y-%m-%dT%H:%M:%S%Z", time.localtime())
  248. zipName = testName + "_" + timeStamp + ".zip"
  249. for i in range(0, len(outputFile)):
  250. if os.path.isfile(outputFile[i]):
  251. zipFiles(outputFile[i])
  252. else:
  253. print "Configured file missing. Skipping over..."
  254. if os.path.isfile(html):
  255. zipFiles(html)
  256. else:
  257. print "Report file missing !"
  258. print("successful")
  259. except:
  260. print("failed")
  261. def zipFiles(file):
  262. #open file for appending
  263. z = zipfile.ZipFile(zipName, 'a',zipfile.ZIP_DEFLATED)
  264. #add created files to a zip archive
  265. z.write(file)
  266. z.close()
  267. def moveOld():
  268. # os.shutil
  269. global oldDir
  270. oldDir = "old/" + testName + "_" + timeStamp
  271. if not os.path.exists(oldDir):
  272. os.makedirs(oldDir)
  273. for i in range(0,len(outputFile)):
  274. shutil.move(outputFile[i], oldDir)
  275. def uploadFile():
  276. # ftplib
  277. #comma to prevent newline
  278. print "Uploading zip... ",
  279. try:
  280. s = ftplib.FTP(FTPHOST, FTPUSER, FTPPASSWD) # server,login, passwd
  281. f = open(zipName,'rb') # file to send (read, binary)
  282. s.storbinary('STOR ' + zipName, f) # Send file
  283. f.close() # Close file and FTP
  284. s.quit()
  285. print("successful")
  286. except:
  287. print("failed ")
  288. global uploadFailed
  289. uploadFailed = True
  290. def createGithubIssue():
  291. githubUrl="https://github.com/"
  292. print "Creating issue: " + githubUrl + GITHUBREPO + "/issues"
  293. url = "http://github.com/api/v2/json/issues/open/" + GITHUBREPO
  294. errorZipLink = "ftp://" + str(FTPHOST) + "/" + zipName
  295. issueTitle="Auto-reported: " + testName
  296. issueBodyInfo="""
  297. Errors were found during a test.
  298. This issue was created automatically by the auto-report script.
  299. """
  300. ziplink = ""
  301. # don't print link if upload is disabled or failed to configured host
  302. if configUploadFile == True and uploadFailed == False:
  303. ziplink = "\n\nError logs for this report can be found in here: " + errorZipLink
  304. # notify reader about upload failing
  305. elif uploadFailed == True:
  306. ziplink = "\n\nUpload failed to ftp host: " + FTPHOST
  307. with open(tempCount, 'r') as cnt:
  308. countPrint = cnt.read()
  309. issueBody = issueBodyInfo + "\n\nFound - count:\n" + countPrint + ziplink
  310. a1 = "login="+GITHUBLOGIN
  311. a2 = "token="+GITHUBAPITOKEN
  312. a3 = "title="+issueTitle
  313. a4 = "body="+issueBody
  314. c = pycurl.Curl()
  315. c.setopt(c.URL, url)
  316. #buffer for redirecting curl output
  317. output = StringIO.StringIO()
  318. c.setopt(pycurl.WRITEFUNCTION, output.write)
  319. c.setopt(c.POSTFIELDS, a1 + '&' + a2 + '&' + a3 + '&' + a4)
  320. c.perform()
  321. def cleanUp():
  322. print "Cleaning up...",
  323. try:
  324. # remove tempfiles
  325. if os.path.isfile(tempErrors):
  326. os.remove(tempErrors)
  327. if os.path.isfile(tempCount):
  328. os.remove(tempCount)
  329. if os.path.isfile(html):
  330. os.remove(html)
  331. print("successful")
  332. except:
  333. print("failed")
  334. def autoreport(test):
  335. whichTestWasRun(test)
  336. if __name__ == "__main__":
  337. #test main for standalone run
  338. tmp = "js-viewer-server-test"
  339. autoreport(tmp)