3 # This file is part of the LibreOffice project.
4 # This Source Code Form is subject to the terms of the Mozilla Public
5 # License, v. 2.0. If a copy of the MPL was not distributed with this
6 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
17 def parseFile(dirname
, filename
, lastCommit
):
19 curTestComment
, total
= None, None
21 path
= os
.path
.join(dirname
, filename
)
23 trigger
= "desc: Trigger: Client Request: "
24 trigger_len
= len(trigger
)
26 totals_len
= len(totals
)
28 with
open(path
,'r') as callgrindFile
:
29 lines
= callgrindFile
.readlines()
32 if line
.startswith(trigger
):
33 curTestComment
= line
[trigger_len
:].replace("\n","")
34 elif line
.startswith(totals
):
35 total
= line
[totals_len
:].replace("\n","")
37 if curTestComment
is None or total
is None:
40 testName
= os
.path
.basename(dirname
).replace(".test.core","")
42 lastCommitId
, lastCommitDate
= lastCommit
43 if lastCommitId
not in colsResult
:
44 colsResult
[lastCommitId
] = {}
45 colsResult
[lastCommitId
]['date'] = lastCommitDate
46 colsResult
[lastCommitId
]['values'] = {}
48 colsResult
[lastCommitId
]['values'][curTestComment
] = total
50 return [lastCommitId
, lastCommitDate
, testName
, curTestComment
, total
, filename
]
52 def processDirectory(rootDir
, needsCsvHeader
, lastCommit
):
57 results
.append(["lastCommit", "lastCommitDate", "test filename", "dump comment", "count", "filename"])
59 for dirName
, subdirList
, fileList
in os
.walk(rootDir
):
60 files
= [f
for f
in fileList
if f
.startswith("callgrind.out.")]
62 found
= parseFile(dirName
, fname
, lastCommit
)
67 def getLastCommitInfo():
69 stream
= os
.popen("git log --date=iso")
70 line
= stream
.readline()
71 commitId
= line
.replace("commit ","").replace("\n","")
72 line
= stream
.readline()
73 line
= stream
.readline()
74 commitDate
= line
.replace("Date: ","").replace("\n","").strip()
76 return commitId
, commitDate
82 Parses the callgrind results of make perfcheck
86 --csv-file\t\t the target CSV file - new or containing previous tests - default : perfcheckResult.csv
87 --source-directory\t directory containing make perfcheck output - default : ./workdir/CppunitTest
88 --alert-type\t\t mode for calculating alerts - valid values : previous first
89 --alert-value\t\t alert threshold in % - default = 10
91 --help\t\t this message
93 Columned output is dumped into csv-file + ".col"
95 Alerts, if any, are displayed in standard output
100 class WrongArguments(Exception):
103 def analyzeArgs(args
):
106 opts
, args
= getopt
.getopt(args
, 'x', [
107 'csv-file=', 'source-directory=', 'alert-type=', 'alert-value=', 'help'])
108 except getopt
.GetoptError
:
111 targetFileName
= "perfcheckResult.csv"
112 sourceDirectory
= "./workdir/CppunitTest"
120 elif o
== "--csv-file":
122 elif o
== "--source-directory":
124 elif o
== "--alert-type":
126 elif o
== "--alert-value":
127 alertValue
= float(a
)
131 return targetFileName
, sourceDirectory
, alertType
, alertValue
133 def readCsvFile(targetFilename
):
135 with
open(targetFilename
, 'r') as csvfile
:
136 reader
= csv
.reader(csvfile
, delimiter
="\t")
141 # do not process empty lines
145 curId
, curDate
, curTestName
, curTestComment
, curValue
, currCallgrindFile
= line
147 if curTestComment
not in allTests
:
148 allTests
.append(curTestComment
)
150 if curId
not in colsResult
:
151 colsResult
[curId
] = {}
152 colsResult
[curId
]['date'] = curDate
153 colsResult
[curId
]['values'] = {}
155 colsResult
[curId
]['values'][curTestComment
] = curValue
157 if __name__
== '__main__':
161 targetFileName
, sourceDirectory
, alertType
, alertValue
= analyzeArgs(sys
.argv
[1:])
162 except WrongArguments
:
166 # check if sourceDirectory exists
167 if not os
.path
.isdir(sourceDirectory
):
168 print("sourceDirectory %s not found - Aborting" % (sourceDirectory
))
171 # read the complete CSV file
172 if os
.path
.isfile(targetFileName
):
173 readCsvFile(targetFileName
)
174 needsCsvHeader
= False
176 needsCsvHeader
= True
179 lastCommitId
, lastCommitDate
= getLastCommitInfo()
181 # walker through directory
182 if lastCommitId
not in colsResult
:
184 lastCommit
= (lastCommitId
, lastCommitDate
)
185 results
= processDirectory(sourceDirectory
, needsCsvHeader
, lastCommit
)
186 ppResults
= "\n".join(["\t".join(row
) for row
in results
])
188 print('\nNew results\n' + ppResults
)
191 with
open(targetFileName
,'a') as csvfile
:
192 writer
= csv
.writer(csvfile
, delimiter
='\t')
193 writer
.writerows(results
)
194 print("\nCSV file written at " + targetFileName
+ '\n')
197 print("\nCSV file up to date " + targetFileName
+ '\n')
200 # build columned output
203 mLine
= '\t'.join(["commit", "date"] + allTests
) + '\n'
207 with
open(targetFileName
+ '.col','w') as fileResult
:
209 mLine
+= k
+ "\t" + colsResult
[k
]['date'] + "\t"
211 if t
in colsResult
[k
]['values']:
212 mValue
= colsResult
[k
]['values'][t
]
213 if t
not in alertTest
:
215 alertTest
[t
][colsResult
[k
]['date']] = mValue
218 mLine
+= mValue
+ "\t"
221 # write columned result
222 fileResult
.write(mLine
)
224 print("Columned file written at " + targetFileName
+ '.col\n')
235 testDict
= alertTest
[t
]
238 keylist
= sorted(testDict
.keys())
239 maxVal
= float(testDict
[keylist
[-1]])
242 if alertType
== "previous":
244 minVal
= float(testDict
[keylist
[-2]])
246 minVal
= float(testDict
[keylist
[0]])
249 delta
= 100 * ((maxVal
-minVal
)/minVal
)
253 if delta
> float(alertValue
):
254 alertResult
+= t
+ "\t" + "{:.2f}".format(delta
) + " %\n"
256 if alertResult
!= "":
257 print("!!!!!!!! ALERT !!!!!!!\n")