return String.format("%.1f %sB", (double)v / (1L << (z*10)), " KMGTPE".charAt(z));
}
+def calculateCoverage(FileTreeBuilder targetTree) {
+ int coveredNum = 0
+ int coverageSum = 0
+ int maxCoverage = 0
+ int totalCoverage = 0
+
+ targetTree.dir('coverage') {
+ delegate.file('index.html') { indexFile ->
+ if (!indexFile.exists()) {
+ return
+ }
+
+ def coverageArray = ( indexFile.text =~ />(\d+)%</ )
+ coverageArray.each() { matched, coverage ->
+ int coverageVal = coverage as Integer
+ coveredNum++
+ coverageSum += coverageVal
+ maxCoverage = maxCoverage > coverageVal ? maxCoverage : coverageVal
+ }
+
+ if (coveredNum > 0) {
+ totalCoverage = coverageSum / coveredNum
+ }
+ }
+ }
+
+ return [maxCoverage, totalCoverage]
+}
+
+def parseLogs(FileTreeBuilder targetTree) {
+ int runs = 0
+ int errors = 0
+ int lines = 0
+ int sumExecs = 0
+ int maxRssMb = 0
+ int avgExecs = 0
+
+ targetTree.file('runs') { runDir ->
+ runDir.eachDir() { run ->
+ runs++
+ run.eachFileMatch(~/[a-z]+\-[a-z0-9]+/) { crashInput ->
+ errors++
+ }
+ run.eachFileMatch(~/.*\.log/) { logFile ->
+ def logMatcher = ( logFile.text =~ /.*exec\/s:\s+(\d+)\s+rss:\s+(\d+).*/ )
+ if (!logMatcher.hasGroup()) {
+ log.println("Failed to parse log: " + logFile.getName())
+ return
+ }
+
+ logMatcher.each() { matched, execStr, rssStr ->
+ lines++
+ sumExecs += execStr as Integer
+ int rss = rssStr as Integer
+ maxRssMb = maxRssMb > rss ? maxRssMb : rss
+ }
+ }
+ }
+ }
+
+ if (lines > 0) {
+ avgExecs = sumExecs / lines
+ }
+
+ return [avgExecs, maxRssMb, runs, errors]
+}
+
+def getCorpusSize(File targetFile) {
+ File corpusTar = new File(targetFile.getAbsolutePath() + "/corpus/generated_corpus.tar.gz")
+ long corpusSize = 0L
+
+ if (corpusTar.exists()) {
+ String gzipOut = ("gzip -l " + corpusTar.getAbsolutePath()).execute().text
+ def corpusSizeMatcher = (gzipOut =~ /\s*\d+\s+(\d+).*/)
+ assert corpusSizeMatcher.hasGroup()
+ corpusSize = corpusSizeMatcher[0][1] as Long
+ }
+
+ return formatSize(corpusSize)
+}
+
def xml = markupBuilder.bind() { builder ->
builder.section(name: 'Fuzzing Results', fontcolor: '0x000000') {
builder.table(sorttable: 'no') {
project.eachDir() { targetFile ->
String projectName = targetFile.getParentFile().getName()
String targetName = targetFile.getName()
- int totalCoverage = 0
- int maxCoverage = 0
- int runs = 0
- int errors = 0
- File corpusTar = new File(targetFile.getAbsolutePath() + "/corpus/generated_corpus.tar.gz")
- long corpusSize = 0L
- int sumExecs = 0
- int avgExecs = 0
- int maxRssMb = 0
- int lines = 0
FileTreeBuilder targetTree = new FileTreeBuilder(targetFile)
-
- targetTree.dir('coverage') {
- delegate.file('index.html') {
- if (!delegate.exists()) {
- log.println('Coverage not found')
- return
- }
-
- int coveredNum = 0
- int coverageSum = 0
- def coverageArray = ( delegate.text =~ />(\d+)%</ )
- coverageArray.each() { matched, coverage ->
- int coverageVal = coverage as Integer
- coveredNum++
- coverageSum += coverageVal
- maxCoverage = maxCoverage > coverageVal ? maxCoverage : coverageVal
- }
-
- if (coveredNum > 0) {
- totalCoverage = coverageSum / coveredNum
- }
- }
- }
-
- targetTree.file('runs') { runDir ->
- runDir.eachDir() { run ->
- runs++
- run.eachFileMatch(~/[a-z]+\-[a-z0-9]+/) { crashInput ->
- errors++
- }
- run.eachFileMatch(~/.*\.log/) { logFile ->
- def logMatcher = ( logFile.text =~ /.*exec\/s:\s+(\d+)\s+rss:\s+(\d+).*/ )
- if (!logMatcher.hasGroup()) {
- log.println("Failed to parse log: " + logFile.getName())
- return
- }
-
- logMatcher.each() { matched, execStr, rssStr ->
- lines++
- sumExecs += execStr as Integer
- int rss = rssStr as Integer
- maxRssMb = maxRssMb > rss ? maxRssMb : rss
- }
- }
- }
- }
-
- if (lines > 0) {
- avgExecs = sumExecs / lines
- }
-
- if (corpusTar.exists()) {
- String gzipOut = ("gzip -l " + corpusTar.getAbsolutePath()).execute().text
- def corpusSizeMatcher = (gzipOut =~ /\s*\d+\s+(\d+).*/)
- assert corpusSizeMatcher.hasGroup()
- corpusSize = corpusSizeMatcher[0][1] as Long
- }
+ def (int maxCoverage, int totalCoverage) = calculateCoverage(targetTree)
+ def (int avgExecs, int maxRssMb, int runs, int errors) = parseLogs(targetTree)
String color = errors == 0 ? '#6bff63' : '#ff6262'
- String corpusSizeStr = formatSize(corpusSize)
+ String corpusSizeStr = getCorpusSize(targetFile)
+
builder.tr {
builder.td(value: projectName, bgcolor: color, fontattribute: 'bold', href: 'http://fusion/fuzzing/' + projectName)
builder.td(value: targetName, bgcolor: color, fontattribute: 'bold', href: 'http://fusion/fuzzing/' + projectName + '/' + targetName)