summaryrefslogtreecommitdiffstats
path: root/tester/covoar/ReportsBase.cc
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2014-05-09 21:50:37 +1000
committerChris Johns <chrisj@rtems.org>2014-06-18 16:48:08 +1200
commit100f517ab37265acdf067e36b6860020ec8b2184 (patch)
tree2316c8b888e11dcbcfbfc66a0c1e31991ea20656 /tester/covoar/ReportsBase.cc
parent4.11: Add ntp patch. (diff)
downloadrtems-tools-100f517ab37265acdf067e36b6860020ec8b2184.tar.bz2
covoar: Merger the covoar source from rtems-testing.git.
Use waf to build covoar.
Diffstat (limited to 'tester/covoar/ReportsBase.cc')
-rw-r--r--tester/covoar/ReportsBase.cc578
1 files changed, 578 insertions, 0 deletions
diff --git a/tester/covoar/ReportsBase.cc b/tester/covoar/ReportsBase.cc
new file mode 100644
index 0000000..d401bdd
--- /dev/null
+++ b/tester/covoar/ReportsBase.cc
@@ -0,0 +1,578 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "ReportsBase.h"
+#include "app_common.h"
+#include "CoverageRanges.h"
+#include "DesiredSymbols.h"
+#include "Explanations.h"
+#include "ObjdumpProcessor.h"
+
+#include "ReportsText.h"
+#include "ReportsHtml.h"
+
+namespace Coverage {
+
+ReportsBase::ReportsBase( time_t timestamp ):
+ reportExtension_m(""),
+ timestamp_m( timestamp )
+{
+}
+
+ReportsBase::~ReportsBase()
+{
+}
+
+FILE* ReportsBase::OpenFile(
+ const char* const fileName
+)
+{
+ int sc;
+ FILE *aFile;
+ std::string file;
+
+ // Create the output directory if it does not already exist
+ sc = mkdir( outputDirectory,0755 );
+ if ( (sc == -1) && (errno != EEXIST) ) {
+ fprintf(stderr, "Unable to create output directory %s\n", outputDirectory);
+ return NULL;
+ }
+
+ file = outputDirectory;
+ file += "/";
+ file += fileName;
+
+ // Open the file.
+ aFile = fopen( file.c_str(), "w" );
+ if ( !aFile ) {
+ fprintf( stderr, "Unable to open %s\n", file.c_str() );
+ }
+ return aFile;
+}
+
+void ReportsBase::WriteIndex(
+ const char* const fileName
+)
+{
+}
+
+FILE* ReportsBase::OpenAnnotatedFile(
+ const char* const fileName
+)
+{
+ return OpenFile(fileName);
+}
+
+FILE* ReportsBase::OpenBranchFile(
+ const char* const fileName,
+ bool hasBranches
+)
+{
+ return OpenFile(fileName);
+}
+
+FILE* ReportsBase::OpenCoverageFile(
+ const char* const fileName
+)
+{
+ return OpenFile(fileName);
+}
+
+FILE* ReportsBase::OpenNoRangeFile(
+ const char* const fileName
+)
+{
+ return OpenFile(fileName);
+}
+
+
+FILE* ReportsBase::OpenSizeFile(
+ const char* const fileName
+)
+{
+ return OpenFile(fileName);
+}
+
+FILE* ReportsBase::OpenSymbolSummaryFile(
+ const char* const fileName
+)
+{
+ return OpenFile(fileName);
+}
+
+void ReportsBase::CloseFile(
+ FILE* aFile
+)
+{
+ fclose( aFile );
+}
+
+void ReportsBase::CloseAnnotatedFile(
+ FILE* aFile
+)
+{
+ CloseFile( aFile );
+}
+
+void ReportsBase::CloseBranchFile(
+ FILE* aFile,
+ bool hasBranches
+)
+{
+ CloseFile( aFile );
+}
+
+void ReportsBase::CloseCoverageFile(
+ FILE* aFile
+)
+{
+ CloseFile( aFile );
+}
+
+void ReportsBase::CloseNoRangeFile(
+ FILE* aFile
+)
+{
+ CloseFile( aFile );
+}
+
+void ReportsBase::CloseSizeFile(
+ FILE* aFile
+)
+{
+ CloseFile( aFile );
+}
+
+void ReportsBase::CloseSymbolSummaryFile(
+ FILE* aFile
+)
+{
+ CloseFile( aFile );
+}
+
+/*
+ * Write annotated report
+ */
+void ReportsBase::WriteAnnotatedReport(
+ const char* const fileName
+) {
+ FILE* aFile = NULL;
+ Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
+ Coverage::CoverageRanges* theBranches;
+ Coverage::CoverageRanges* theRanges;
+ Coverage::CoverageMapBase* theCoverageMap = NULL;
+ uint32_t bAddress = 0;
+ AnnotatedLineState_t state;
+ std::list<Coverage::ObjdumpProcessor::objdumpLine_t>* theInstructions;
+ std::list<Coverage::ObjdumpProcessor::objdumpLine_t>::iterator itr;
+
+ aFile = OpenAnnotatedFile(fileName);
+ if (!aFile)
+ return;
+
+ // Process uncovered branches for each symbol.
+ for (ditr = SymbolsToAnalyze->set.begin();
+ ditr != SymbolsToAnalyze->set.end();
+ ditr++) {
+
+ // If uncoveredRanges and uncoveredBranches don't exist, then the
+ // symbol was never referenced by any executable. Just skip it.
+ if ((ditr->second.uncoveredRanges == NULL) &&
+ (ditr->second.uncoveredBranches == NULL))
+ continue;
+
+ // If uncoveredRanges and uncoveredBranches are empty, then everything
+ // must have been covered for this symbol. Just skip it.
+ if ((ditr->second.uncoveredRanges->set.empty()) &&
+ (ditr->second.uncoveredBranches->set.empty()))
+ continue;
+
+ theCoverageMap = ditr->second.unifiedCoverageMap;
+ bAddress = ditr->second.baseAddress;
+ theInstructions = &(ditr->second.instructions);
+ theRanges = ditr->second.uncoveredRanges;
+ theBranches = ditr->second.uncoveredBranches;
+
+ // Add annotations to each line where necessary
+ AnnotatedStart( aFile );
+ for (itr = theInstructions->begin();
+ itr != theInstructions->end();
+ itr++ ) {
+
+ uint32_t id = 0;
+ std::string annotation = "";
+ std::string line;
+ char textLine[150];
+
+ state = A_SOURCE;
+
+ if ( itr->isInstruction ) {
+ if (!theCoverageMap->wasExecuted( itr->address - bAddress )){
+ annotation = "<== NOT EXECUTED";
+ state = A_NEVER_EXECUTED;
+ id = theRanges->getId( itr->address );
+ } else if (theCoverageMap->isBranch( itr->address - bAddress )) {
+ id = theBranches->getId( itr->address );
+ if (theCoverageMap->wasAlwaysTaken( itr->address - bAddress )){
+ annotation = "<== ALWAYS TAKEN";
+ state = A_BRANCH_TAKEN;
+ } else if (theCoverageMap->wasNeverTaken( itr->address - bAddress )){
+ annotation = "<== NEVER TAKEN";
+ state = A_BRANCH_NOT_TAKEN;
+ }
+ } else {
+ state = A_EXECUTED;
+ }
+ }
+
+ sprintf( textLine, "%-70s", itr->line.c_str() );
+ line = textLine + annotation;
+
+ PutAnnotatedLine( aFile, state, line, id);
+ }
+
+ AnnotatedEnd( aFile );
+ }
+
+ CloseAnnotatedFile( aFile );
+}
+
+/*
+ * Write branch report
+ */
+void ReportsBase::WriteBranchReport(
+ const char* const fileName
+) {
+ Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
+ FILE* report = NULL;
+ Coverage::CoverageRanges::ranges_t::iterator ritr;
+ Coverage::CoverageRanges* theBranches;
+ unsigned int count;
+ bool hasBranches = true;
+
+ if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
+ (BranchInfoAvailable == false) )
+ hasBranches = false;
+
+ // Open the branch report file
+ report = OpenBranchFile( fileName, hasBranches );
+ if (!report)
+ return;
+
+ // If no branches were found of branch coverage is not supported
+ if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
+ (BranchInfoAvailable == false) ) {
+
+ PutNoBranchInfo(report);
+
+ // If branches were found, ...
+ } else {
+
+ // Process uncovered branches for each symbol.
+ count = 0;
+ for (ditr = SymbolsToAnalyze->set.begin();
+ ditr != SymbolsToAnalyze->set.end();
+ ditr++) {
+
+ theBranches = ditr->second.uncoveredBranches;
+
+ if (theBranches && !theBranches->set.empty()) {
+
+ for (ritr = theBranches->set.begin() ;
+ ritr != theBranches->set.end() ;
+ ritr++ ) {
+ count++;
+ PutBranchEntry( report, count, ditr, ritr );
+ }
+ }
+ }
+ }
+
+ CloseBranchFile( report, hasBranches );
+}
+
+/*
+ * Write coverage report
+ */
+void ReportsBase::WriteCoverageReport(
+ const char* const fileName
+)
+{
+ Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
+ FILE* report;
+ Coverage::CoverageRanges::ranges_t::iterator ritr;
+ Coverage::CoverageRanges* theRanges;
+ unsigned int count;
+ FILE* NoRangeFile;
+ std::string NoRangeName;
+
+ // Open special file that captures NoRange informaiton
+ NoRangeName = "no_range_";
+ NoRangeName += fileName;
+ NoRangeFile = OpenNoRangeFile ( NoRangeName.c_str() );
+ if (!NoRangeFile) {
+ return;
+ }
+
+ // Open the coverage report file.
+ report = OpenCoverageFile( fileName );
+ if ( !report ) {
+ return;
+ }
+
+ // Process uncovered ranges for each symbol.
+ count = 0;
+ for (ditr = SymbolsToAnalyze->set.begin();
+ ditr != SymbolsToAnalyze->set.end();
+ ditr++) {
+
+ theRanges = ditr->second.uncoveredRanges;
+
+ // If uncoveredRanges doesn't exist, then the symbol was never
+ // referenced by any executable. There may be a problem with the
+ // desired symbols list or with the executables so put something
+ // in the report.
+ if (theRanges == NULL) {
+ putCoverageNoRange( report, NoRangeFile, count, ditr->first );
+ count++;
+ } else if (!theRanges->set.empty()) {
+
+ for (ritr = theRanges->set.begin() ;
+ ritr != theRanges->set.end() ;
+ ritr++ ) {
+ PutCoverageLine( report, count, ditr, ritr );
+ count++;
+ }
+ }
+ }
+
+ CloseNoRangeFile( NoRangeFile );
+ CloseCoverageFile( report );
+
+}
+
+/*
+ * Write size report
+ */
+void ReportsBase::WriteSizeReport(
+ const char* const fileName
+)
+{
+ Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
+ FILE* report;
+ Coverage::CoverageRanges::ranges_t::iterator ritr;
+ Coverage::CoverageRanges* theRanges;
+ unsigned int count;
+
+ // Open the report file.
+ report = OpenSizeFile( fileName );
+ if ( !report ) {
+ return;
+ }
+
+ // Process uncovered ranges for each symbol.
+ count = 0;
+ for (ditr = SymbolsToAnalyze->set.begin();
+ ditr != SymbolsToAnalyze->set.end();
+ ditr++) {
+
+ theRanges = ditr->second.uncoveredRanges;
+
+ if (theRanges && !theRanges->set.empty()) {
+
+ for (ritr = theRanges->set.begin() ;
+ ritr != theRanges->set.end() ;
+ ritr++ ) {
+ PutSizeLine( report, count, ditr, ritr );
+ count++;
+ }
+ }
+ }
+
+ CloseSizeFile( report );
+}
+
+void ReportsBase::WriteSymbolSummaryReport(
+ const char* const fileName
+)
+{
+ Coverage::DesiredSymbols::symbolSet_t::iterator ditr;
+ FILE* report;
+ unsigned int count;
+
+ // Open the report file.
+ report = OpenSymbolSummaryFile( fileName );
+ if ( !report ) {
+ return;
+ }
+
+ // Process each symbol.
+ count = 0;
+ for (ditr = SymbolsToAnalyze->set.begin();
+ ditr != SymbolsToAnalyze->set.end();
+ ditr++) {
+
+ PutSymbolSummaryLine( report, count, ditr );
+ count++;
+ }
+
+ CloseSymbolSummaryFile( report );
+}
+
+void ReportsBase::WriteSummaryReport(
+ const char* const fileName
+)
+{
+ // Calculate coverage statistics and output results.
+ uint32_t a;
+ uint32_t endAddress;
+ Coverage::DesiredSymbols::symbolSet_t::iterator itr;
+ uint32_t notExecuted = 0;
+ double percentage;
+ Coverage::CoverageMapBase* theCoverageMap;
+ uint32_t totalBytes = 0;
+ FILE* report;
+
+ // Open the report file.
+ report = OpenFile( fileName );
+ if ( !report ) {
+ return;
+ }
+
+ // Look at each symbol.
+ for (itr = SymbolsToAnalyze->set.begin();
+ itr != SymbolsToAnalyze->set.end();
+ itr++) {
+
+ // If the symbol's unified coverage map exists, scan through it
+ // and count bytes.
+ theCoverageMap = itr->second.unifiedCoverageMap;
+ if (theCoverageMap) {
+
+ endAddress = itr->second.stats.sizeInBytes - 1;
+
+ for (a = 0; a <= endAddress; a++) {
+ totalBytes++;
+ if (!theCoverageMap->wasExecuted( a ))
+ notExecuted++;
+ }
+ }
+ }
+
+ percentage = (double) notExecuted;
+ percentage /= (double) totalBytes;
+ percentage *= 100.0;
+
+ fprintf( report, "Bytes Analyzed : %d\n", totalBytes );
+ fprintf( report, "Bytes Not Executed : %d\n", notExecuted );
+ fprintf( report, "Percentage Executed : %5.4g\n", 100.0 - percentage );
+ fprintf( report, "Percentage Not Executed : %5.4g\n", percentage );
+ fprintf(
+ report,
+ "Uncovered ranges found : %d\n",
+ SymbolsToAnalyze->getNumberUncoveredRanges()
+ );
+ if ((SymbolsToAnalyze->getNumberBranchesFound() == 0) ||
+ (BranchInfoAvailable == false) ) {
+ fprintf( report, "No branch information available\n" );
+ } else {
+ fprintf(
+ report,
+ "Total branches found : %d\n",
+ SymbolsToAnalyze->getNumberBranchesFound()
+ );
+ fprintf(
+ report,
+ "Uncovered branches found : %d\n",
+ SymbolsToAnalyze->getNumberBranchesAlwaysTaken() +
+ SymbolsToAnalyze->getNumberBranchesNeverTaken()
+ );
+ fprintf(
+ report,
+ " %d branches always taken\n",
+ SymbolsToAnalyze->getNumberBranchesAlwaysTaken()
+ );
+ fprintf(
+ report,
+ " %d branches never taken\n",
+ SymbolsToAnalyze->getNumberBranchesNeverTaken()
+ );
+ }
+}
+
+void GenerateReports()
+{
+ typedef std::list<ReportsBase *> reportList_t;
+
+ reportList_t reportList;
+ reportList_t::iterator ritr;
+ std::string reportName;
+ ReportsBase* reports;
+
+ time_t timestamp;
+
+
+ timestamp = time(NULL); /* get current cal time */
+ reports = new ReportsText(timestamp);
+ reportList.push_back(reports);
+ reports = new ReportsHtml(timestamp);
+ reportList.push_back(reports);
+
+ for (ritr = reportList.begin(); ritr != reportList.end(); ritr++ ) {
+ reports = *ritr;
+
+ reportName = "index" + reports->ReportExtension();
+ if (Verbose)
+ fprintf(
+ stderr, "Generate %s\n", reportName.c_str()
+ );
+ reports->WriteIndex( reportName.c_str() );
+
+ reportName = "annotated" + reports->ReportExtension();
+ if (Verbose)
+ fprintf(
+ stderr, "Generate %s\n", reportName.c_str()
+ );
+ reports->WriteAnnotatedReport( reportName.c_str() );
+
+ reportName = "branch" + reports->ReportExtension();
+ if (Verbose)
+ fprintf(
+ stderr, "Generate %s\n", reportName.c_str()
+ );
+ reports->WriteBranchReport(reportName.c_str() );
+
+ reportName = "uncovered" + reports->ReportExtension();
+ if (Verbose)
+ fprintf(
+ stderr, "Generate %s\n", reportName.c_str()
+ );
+ reports->WriteCoverageReport(reportName.c_str() );
+
+ reportName = "sizes" + reports->ReportExtension();
+ if (Verbose)
+ fprintf(
+ stderr, "Generate %s\n", reportName.c_str()
+ );
+ reports->WriteSizeReport(reportName.c_str() );
+
+ reportName = "symbolSummary" + reports->ReportExtension();
+ if (Verbose)
+ fprintf(
+ stderr, "Generate %s\n", reportName.c_str()
+ );
+ reports->WriteSymbolSummaryReport(reportName.c_str() );
+ }
+
+ for (ritr = reportList.begin(); ritr != reportList.end(); ritr++ ) {
+ reports = *ritr;
+ delete reports;
+ }
+
+ ReportsBase::WriteSummaryReport( "summary.txt" );
+}
+
+}