From 41dfa21869cc3c3f848dfcfb4507eac6a543e8cf Mon Sep 17 00:00:00 2001
From: Grigoris Pavlakis <grigpavl@ece.auth.gr>
Date: Fri, 22 Mar 2019 18:40:16 +0200
Subject: [PATCH] Commit for saving the current state in order to hunt down a
 last-minute bug

Finalize pipeline scripts, waiting for review

Fix pipeline passing on GitLab CI when it should fail
---
 ci/cppcheck-misra.sh | 16 ++++++----
 ci/summarizer.py     | 71 +++++++++++++++++++++++++++-----------------
 2 files changed, 54 insertions(+), 33 deletions(-)

diff --git a/ci/cppcheck-misra.sh b/ci/cppcheck-misra.sh
index 2df95340..96e0c9cd 100755
--- a/ci/cppcheck-misra.sh
+++ b/ci/cppcheck-misra.sh
@@ -7,23 +7,29 @@
 # $ ci/cppcheck-misra.sh
 #
 
-echo -e "\u001b[34;1mRunning cppcheck with MISRA C(2012) rule compliance tests...\u001b[0m"
-
+echo -e "\u001b[34;1mGetting prerequisites...\u001b[0m"
 # grab the MISRA addon and the cppcheck addon interface from github
-curl https://raw.githubusercontent.com/danmar/cppcheck/f4b5b156d720c712f6ce99f6e01d8c1b3f800d52/addons/misra.py > misra.py
-curl https://raw.githubusercontent.com/danmar/cppcheck/f4b5b156d720c712f6ce99f6e01d8c1b3f800d52/addons/cppcheckdata.py > cppcheckdata.py
+curl https://raw.githubusercontent.com/danmar/cppcheck/f4b5b156d720c712f6ce99f6e01d8c1b3f800d52/addons/misra.py > ci/misra.py
+curl https://raw.githubusercontent.com/danmar/cppcheck/f4b5b156d720c712f6ce99f6e01d8c1b3f800d52/addons/cppcheckdata.py > ci/cppcheckdata.py
 
 # generate dump files (XML representations of AST etc.) for all headers, source files etc.
+echo -e "\u001b[34;1mGenerating dump files...\u001b[0m"
 for file in $(find inc/ src/ -type f \( -iname "*.cpp" -or -iname "*.hpp" \))
 do 
     cppcheck --dump $file
 done
 
 # run the MISRA checks against the dumps and send the results to a file
+echo -e "\u001b[34;1mRunning MISRA C(2012) rule compliance tests...\u001b[0m"
 for file in $(find inc/ src/ -type f -name "*.dump")
 do 
-    python misra.py $file >> ci/report.msr 2>&1
+    python ci/misra.py $file >> ci/report.msr 2>&1
 done
 
 # pre-process the generated report to remove all useless strings
+echo -e "\u001b[34;1mPre-processing report...\u001b[0m"
 sed -i -r 's/(.*Script.*)|(.*Checking.*)|(.*MISRA.*)//gm; /(^$)/d; s/(\s\(.*\)\s)//gm; s/(\]|\[)//gm; s/(misra-c2012-)//gm' ci/report.msr
+
+# run the summarizer for a nice, clean summary of errors
+echo -e "\u001b[34;1mSummarizing results...\u001b[0m"
+python ci/summarizer.py ci/report.msr
diff --git a/ci/summarizer.py b/ci/summarizer.py
index 68e62dc5..17c2ffdc 100755
--- a/ci/summarizer.py
+++ b/ci/summarizer.py
@@ -1,51 +1,66 @@
-#!/bin/env python3
+#!/bin/env python
 
 from sys import argv
+from sys import exit
 from collections import Counter
 
-script, reportfile = argv
+'''
+Naive parser and pretty printer for the MISRA reports by cppcheck
+'''
 
+script, reportfile = argv
 def analyze():
-    errorsMap = {}
+    '''
+    A really dumb parser for the pre-processed report generated by cppcheck
+    '''
+    errorsMap = {} # keys: filenames, values: list of tuples containing rule violated and line
     file = open(reportfile, 'r')
     fileLines = file.readlines()
-    cppcheckNumOfErrors = len(fileLines)
-    linesSeen = set()
+    cppcheckNumOfErrors = len(fileLines) # number of errors in the original report (most of these are duplicates)
+    linesSeen = set() # contains the unique lines from the file
     
-    for line in fileLines:  # remove duplicate lines
-        if line not in linesSeen:
-            linesSeen.add(line)
+    if len(fileLines) == 0:
+        print("\033[1m\033[92mStatic analysis for MISRA compliance complete. No errors found.")
+        return 0
+    else:
+        for line in fileLines:  # remove duplicate lines
+            if line not in linesSeen:
+                linesSeen.add(line)
             
-    for line in linesSeen:
-        lineContents = line.split(':')
-        fileName = lineContents[0]
-        error = (lineContents[1], lineContents[2].strip('\n'))
-
-        if fileName not in errorsMap.keys():
-            errorsMap[fileName] = list()
-            errorsMap[fileName].append(error)
-        else:
-            errorsMap[fileName].append(error)
+        for line in linesSeen: # after cleaning up the duplicates, split the line into parts
+            lineContents = line.split(':')
+            fileName = lineContents[0] # first part is the filename (index 0)
+            error = (lineContents[1], lineContents[2].strip('\n')) # index 1: line number, index 2: number of violated rule
+
+            if fileName not in errorsMap.keys():
+                errorsMap[fileName] = list()  # create a new list for the new filename and append the tuple in it
+                errorsMap[fileName].append(error)
+            else:
+                errorsMap[fileName].append(error) # do not append if it already exists
             
-    return errorsMap
+        return errorsMap # return the completed error dictionary
+
 
 def prettyprint(errors):
+    '''
+    Prettyprints the contents of the error dictionary with colors and stuff
+    '''
     print("\033[1m\033[91m=================================================\n")
     print("\033[1m       Static analysis results: Error Summary        \n")
     for key in errors:
         for error in errors[key]:
             print("\033[1mFile \033[93m{0}\033[91m violates rule \033[93m#{1}\033[91m of the MISRA C 2012 standard at line \033[93m{2}\033[91m".format(key, error[1], error[0]))
-    print()
     print("\033[1m=================================================\033[0m\n")
 
-    
 
-if __name__ == "__main__":
+def run():
     errors = analyze()
-    if len(errors) == 0:
-        print("\033[1m\033[92mStatic analysis for MISRA compliance complete. No errors found.")
-        exit(0)
-    else:
+    if isinstance(errors, dict):
         prettyprint(errors)
-        exit(1)
-    
+        exit(127)
+    elif isinstance(errors, int) and errors == 0:
+        exit(0)
+
+
+if __name__ == "__main__":
+    run()
-- 
GitLab