static function loadObject($filename) { if (isset(self::$cache[$filename])) { return self::$cache[$filename]; } $D = new PhenomDwarfLineInfo($filename); $D->parse(); self::$cache[$filename] = $D; return $D; }
public function runUnitTests() { // Build any unit tests $this->make('build-tests'); // Now find all the test programs $root = $this->getProjectRoot(); $futures = array(); $cg_files = array(); $obj_files = array(); $coverage = $this->getEnableCoverage(); $tests = $this->getTestsToRun(); foreach ($tests as $relname => $test) { if ($coverage) { $cg = new TempFile(); $cg_files[$relname] = $cg; $obj_files[] = $test; $test = 'valgrind --tool=callgrind --collect-jumps=yes ' . '--callgrind-out-file=' . $cg . ' ' . $test; } $futures[$relname] = new ExecFuture($test); } $results = array(); // Use a smaller limit for SunOS because my test VM has crappy // timing characteristics and that causes timer.t to fail $limit = PHP_OS == 'SunOS' ? 1 : 4; foreach (Futures($futures)->limit($limit) as $test => $future) { list($err, $stdout, $stderr) = $future->resolve(); $results[$test] = $this->parseTestResults($test, $err, $stdout, $stderr); } if ($coverage) { // Find all executables, not just the test executables. // We need to do this because the test executables may not // include all of the possible code (linker decides to omit // it from the image) so we see a skewed representation of // the source lines. $fp = popen("find {$root} -type f -name \\*.a -o -name \\*.so -o -name \\*.dylib", "r"); while (true) { $line = fgets($fp); if ($line === false) { break; } $obj_files[] = trim($line); } // Parse line information from the objects foreach ($obj_files as $object) { PhenomDwarfLineInfo::loadObject($object); } // Now process coverage data files foreach ($cg_files as $relname => $cg) { $CG = new PhenomCallgrindFile((string) $cg); $CG->parse(); $source_files = array(); foreach ($CG->getSourceFiles() as $filename) { if (Filesystem::isDescendant($filename, $root) && !preg_match("/(thirdparty|tests)/", $filename)) { $source_files[$filename] = $filename; } } $cov = array(); foreach ($source_files as $filename) { $relsrc = substr($filename, strlen($root) + 1); $cov[$relsrc] = PhenomCallgrindFile::mergeSourceLineData($filename, array($CG)); } // Update the coverage data for that test. // arcanist will merge the final results $results[$relname]->setCoverage($cov); } } return $results; }
function collectSourceFileData($sourcefile) { $all_lines = array(); $this->getTouchedLines($sourcefile, $all_lines); foreach ($this->getObjectFiles() as $objfile) { PhenomDwarfLineInfo::loadObject($objfile); } $exe_lines = PhenomDwarfLineInfo::mergedSourceLines($sourcefile); $max_line = max($exe_lines); /* now build a string containing the coverage info. * This is compatible with ArcanistUnitTestResult coverage data: * N not executable * C covered * U uncovered * X unreachable (we can't detect that here) */ $cov = str_repeat('N', $max_line); for ($i = 1; $i <= $max_line; $i++) { if (isset($all_lines[$i])) { $cov[$i - 1] = 'C'; } else { if (isset($exe_lines[$i])) { $cov[$i - 1] = 'U'; } } } return $cov; }