Exemple #1
0
 /**
  * Parse an individual .gcov file.
  **/
 public function ParseGcovFile($fileinfo)
 {
     $coverageFileLog = new CoverageFileLog();
     $coverageFileLog->AggregateBuildId = $this->AggregateBuildId;
     $coverageFileLog->PreviousAggregateParentId = $this->PreviousAggregateParentId;
     $coverageFile = new CoverageFile();
     $coverage = new Coverage();
     $coverage->CoverageFile = $coverageFile;
     // Begin parsing this file.
     // The first thing we look for is the full path to this source file.
     $file = new SplFileObject($fileinfo);
     $path = '';
     while (!$file->eof()) {
         $gcovLine = $file->current();
         $term = ':Source:';
         $pos = strpos($gcovLine, $term);
         if ($pos !== false) {
             $path = substr($gcovLine, $pos + strlen($term));
             break;
         }
         $file->next();
     }
     if (empty($path)) {
         return;
     }
     // Check if this file belongs to a different SubProject.
     $buildid = $this->Build->Id;
     if (!empty($this->SubProjectPath) && strpos($path, $this->SubProjectPath) === false) {
         // Find the SubProject that corresponds to this path.
         $query = "SELECT id, name, path FROM subproject\n                WHERE projectid = {$this->ProjectId} AND\n                endtime = '1980-01-01 00:00:00' AND\n                path != '' AND\n                '{$path}' LIKE CONCAT('%',path,'%')";
         $result = pdo_query($query);
         if (!$result || pdo_num_rows($result) == 0) {
             add_log("No SubProject found for '{$path}'", 'ParseGcovFile', LOG_INFO, $this->ProjectId, $this->Build->Id);
             return;
         }
         $row = pdo_fetch_array($result);
         $subprojectid = $row['id'];
         $subprojectname = $row['name'];
         $subprojectpath = $row['path'];
         // Find the sibling build that performed this SubProject.
         $siblingBuild = new Build();
         $query = 'SELECT b.id FROM build AS b
             INNER JOIN subproject2build AS sp2b ON (sp2b.buildid=b.id)
             WHERE b.parentid=
             (SELECT parentid FROM build WHERE id=' . $this->Build->Id . ")\n                AND sp2b.subprojectid={$subprojectid}";
         $row = pdo_single_row_query($query);
         if ($row && array_key_exists('id', $row)) {
             $buildid = $row['id'];
             $siblingBuild->Id = $buildid;
             $siblingBuild->FillFromId($buildid);
         } else {
             // Build doesn't exist yet, add it here.
             $siblingBuild->Name = $this->Build->Name;
             $siblingBuild->ProjectId = $this->ProjectId;
             $siblingBuild->SiteId = $this->Build->SiteId;
             $siblingBuild->SetParentId($this->Build->GetParentId());
             $siblingBuild->SetStamp($this->Build->GetStamp());
             $siblingBuild->SetSubProject($subprojectname);
             $siblingBuild->StartTime = $this->Build->StartTime;
             $siblingBuild->EndTime = $this->Build->EndTime;
             $siblingBuild->SubmitTime = gmdate(FMT_DATETIME);
             add_build($siblingBuild, 0);
             $buildid = $siblingBuild->Id;
         }
         $coverageFileLog->Build = $siblingBuild;
         // Remove any part of the file path that comes before
         // the subproject path.
         $path = substr($path, strpos($path, $subprojectpath));
         // Replace the subproject path with '.'
         $path = substr_replace($path, '.', 0, strlen($subprojectpath));
     } else {
         // If this source file isn't from the source or binary directory
         // we shouldn't include it in our coverage report.
         if (!empty($this->SubProjectPath) && strpos($path, $this->SubProjectPath) !== false) {
             $path = substr($path, strpos($path, $this->SubProjectPath));
             $path = substr_replace($path, '.', 0, strlen($this->SubProjectPath));
         } elseif (strpos($path, $this->SourceDirectory) !== false) {
             $path = str_replace($this->SourceDirectory, '.', trim($path));
         } elseif (strpos($path, $this->BinaryDirectory) !== false) {
             $path = str_replace($this->BinaryDirectory, '.', trim($path));
         } else {
             return;
         }
         $coverageFileLog->Build = $this->Build;
     }
     // Get a reference to the coverage summary for this build.
     if ($buildid === $this->Build->Id) {
         $coverageSummary = $this->CoverageSummary;
     } else {
         if (!array_key_exists($buildid, $this->SubProjectSummaries)) {
             $coverageSummary = new CoverageSummary();
             $coverageSummary->BuildId = $buildid;
             $this->SubProjectSummaries[$buildid] = $coverageSummary;
         } else {
             $coverageSummary = $this->SubProjectSummaries[$buildid];
         }
     }
     // Use a regexp to resolve any /../ in this path.
     // We can't use realpath() because we're referencing a path that
     // doesn't exist on the server.
     // For a source file that contains:
     //   #include "src/../include/foo.h"
     // CDash will report the covered file as include/foo.h
     $pattern = "#/[^/]*?/\\.\\./#";
     while (strpos($path, "/../") !== false) {
         $path = preg_replace($pattern, "/", $path, 1);
     }
     $coverageFile->FullPath = trim($path);
     $lineNumber = 0;
     // The lack of rewind is intentional.
     while (!$file->eof()) {
         $gcovLine = $file->current();
         // "Ordinary" entries in a .gcov file take the following format:
         // <lineNumber>: <timesHit>: <source code at that line>
         // So we check if this line matches the format & parse the
         // data out of it if so.
         $fields = explode(':', $gcovLine, 3);
         if (count($fields) > 2) {
             // Separate out delimited values from this line.
             $timesHit = trim($fields[0]);
             $lineNumber = trim($fields[1]);
             $sourceLine = rtrim($fields[2]);
             if ($lineNumber > 0) {
                 $coverageFile->File .= $sourceLine;
                 // cannot be <br/> for backward compatibility.
                 $coverageFile->File .= '<br>';
             }
             // This is how gcov indicates a line of unexecutable code.
             if ($timesHit === '-') {
                 $file->next();
                 continue;
             }
             // This is how gcov indicates an uncovered line.
             if ($timesHit === '#####') {
                 $timesHit = 0;
             }
             $coverageFileLog->AddLine($lineNumber - 1, $timesHit);
             $file->next();
         } else {
             $coveredBranches = 0;
             $uncoveredBranches = 0;
             $throwBranches = 0;
             $fallthroughBranches = 0;
             while (count($fields) < 3 && !$file->eof()) {
                 // Parse branch coverage here.
                 if (substr($gcovLine, 0, 6) === 'branch') {
                     // Figure out whether this branch was covered or not.
                     if (strpos($gcovLine, 'taken 0%') !== false) {
                         $uncoveredBranches += 1;
                     } else {
                         $coveredBranches += 1;
                     }
                     // Also keep track of the different types of branches encountered.
                     if (strpos($gcovLine, '(throw)') !== false) {
                         $throwBranches += 1;
                     } elseif (strpos($gcovLine, '(fallthrough)') !== false) {
                         $fallthroughBranches += 1;
                     }
                 }
                 $file->next();
                 $gcovLine = $file->current();
                 $fields = explode(':', $gcovLine);
             }
             // Don't report branch coverage for this line if we only
             // encountered (throw) and (fallthrough) branches here.
             $totalBranches = $coveredBranches + $uncoveredBranches;
             if ($totalBranches > 0 && $totalBranches > $throwBranches + $fallthroughBranches) {
                 $coverageFileLog->AddBranch($lineNumber - 1, $coveredBranches, $totalBranches);
             }
         }
     }
     // Save these models to the database.
     $coverageFile->TrimLastNewline();
     $coverageFile->Update($buildid);
     $coverageFileLog->BuildId = $buildid;
     $coverageFileLog->FileId = $coverageFile->Id;
     $coverageFileLog->Insert(true);
     // Query the filelog to get how many lines & branches were covered.
     // We do this after inserting the filelog because we want to accurately
     // reflect the union of the current and previously existing results
     // (if any).
     $stats = $coverageFileLog->GetStats();
     $coverage->LocUntested = $stats['locuntested'];
     $coverage->LocTested = $stats['loctested'];
     $coverage->Covered = 1;
     $coverage->BranchesUntested = $stats['branchesuntested'];
     $coverage->BranchesTested = $stats['branchestested'];
     // Add any labels.
     if (array_key_exists($path, $this->Labels)) {
         foreach ($this->Labels[$path] as $labelText) {
             $label = new Label();
             $label->SetText($labelText);
             $coverage->AddLabel($label);
         }
     }
     // Add this Coverage to our summary.
     $coverageSummary->AddCoverage($coverage);
 }
 /**
  * Parse an individual .gcov file.
  **/
 function ParseGcovFile($fileinfo)
 {
     $coverageFileLog = new CoverageFileLog();
     $coverageFile = new CoverageFile();
     $coverage = new Coverage();
     $coverage->CoverageFile = $coverageFile;
     // Begin parsing this file.
     // The first thing we look for is the full path to this source file.
     $file = new SplFileObject($fileinfo);
     $path = '';
     while (!$file->eof()) {
         $gcovLine = $file->current();
         $term = ":Source:";
         $pos = strpos($gcovLine, $term);
         if ($pos !== false) {
             $path = substr($gcovLine, $pos + strlen($term));
             break;
         }
         $file->next();
     }
     if (empty($path)) {
         return;
     }
     // If this source file isn't from the source or binary directory
     // we shouldn't include it in our coverage report.
     if (strpos($path, $this->SourceDirectory) !== false) {
         $path = str_replace($this->SourceDirectory, ".", trim($path));
     } else {
         if (strpos($path, $this->BinaryDirectory) !== false) {
             $path = str_replace($this->BinaryDirectory, ".", trim($path));
         } else {
             return;
         }
     }
     $coverageFile->FullPath = $path;
     $lineNumber = 0;
     // The lack of rewind is intentional.
     while (!$file->eof()) {
         $gcovLine = $file->current();
         // "Ordinary" entries in a .gcov file take the following format:
         // <lineNumber>: <timesHit>: <source code at that line>
         // So we check if this line matches the format & parse the
         // data out of it if so.
         $fields = explode(":", $gcovLine, 3);
         if (count($fields) > 2) {
             // Separate out delimited values from this line.
             $timesHit = trim($fields[0]);
             $lineNumber = trim($fields[1]);
             $sourceLine = trim($fields[2]);
             if ($lineNumber > 0) {
                 $coverageFile->File .= $sourceLine;
                 // cannot be <br/> for backward compatibility.
                 $coverageFile->File .= '<br>';
             }
             // This is how gcov indicates a line of unexecutable code.
             if ($timesHit === '-') {
                 $file->next();
                 continue;
             }
             // This is how gcov indicates an uncovered line.
             if ($timesHit === '#####') {
                 $timesHit = 0;
                 $coverage->LocUntested += 1;
                 $this->CoverageSummary->LocUntested += 1;
             } else {
                 $coverage->Covered = 1;
                 $coverage->LocTested += 1;
                 $this->CoverageSummary->LocTested += 1;
             }
             $coverageFileLog->AddLine($lineNumber - 1, $timesHit);
             $file->next();
         } else {
             $coveredBranches = 0;
             $uncoveredBranches = 0;
             $throwBranches = 0;
             $fallthroughBranches = 0;
             while (count($fields) < 3 && !$file->eof()) {
                 // Parse branch coverage here.
                 if (substr($gcovLine, 0, 6) === "branch") {
                     // Figure out whether this branch was covered or not.
                     if (strpos($gcovLine, "taken 0%") !== false) {
                         $uncoveredBranches += 1;
                     } else {
                         $coveredBranches += 1;
                     }
                     // Also keep track of the different types of branches encountered.
                     if (strpos($gcovLine, "(throw)") !== false) {
                         $throwBranches += 1;
                     } else {
                         if (strpos($gcovLine, "(fallthrough)") !== false) {
                             $fallthroughBranches += 1;
                         }
                     }
                 }
                 $file->next();
                 $gcovLine = $file->current();
                 $fields = explode(":", $gcovLine);
             }
             // Don't report branch coverage for this line if we only
             // encountered (throw) and (fallthrough) branches here.
             $totalBranches = $coveredBranches + $uncoveredBranches;
             if ($totalBranches > 0 && $totalBranches > $throwBranches + $fallthroughBranches) {
                 $coverageFileLog->AddBranch($lineNumber - 1, $coveredBranches, $totalBranches);
             }
         }
     }
     // Get the ID for this coverage file, or create a new empty one
     //if it doesn't already exist.
     $sql = pdo_query("SELECT id FROM coveragefile WHERE fullpath='{$path}' AND file IS NULL");
     if (pdo_num_rows($sql) == 0) {
         pdo_query("INSERT INTO coveragefile (fullpath) VALUES ('{$path}')");
         $fileid = pdo_insert_id("coveragefile");
     } else {
         $coveragefile_array = pdo_fetch_array($sql);
         $fileid = $coveragefile_array["id"];
     }
     $coverageFile->Id = $fileid;
     // Save these models to the database.
     $coverageFile->Update($this->BuildId);
     $coverageFileLog->BuildId = $this->BuildId;
     $coverageFileLog->FileId = $coverageFile->Id;
     $coverageFileLog->Insert();
     // Add any labels.
     if (array_key_exists($path, $this->Labels)) {
         foreach ($this->Labels[$path] as $labelText) {
             $label = new Label();
             $label->SetText($labelText);
             $coverage->AddLabel($label);
         }
     }
     // Add this Coverage to our summary.
     $this->CoverageSummary->AddCoverage($coverage);
 }