tapString = trim($tapString); } /** * Parse a given TAP format string and return an array of tests and their status. */ public function parse() { // Split up the TAP string into an array of lines, then // trim all of the lines so there's no leading or trailing whitespace. $lines = explode("\n", $this->tapString); $lines = array_map(function ($line) { return trim($line); }, $lines); // Check TAP version: $versionLine = array_shift($lines); if ($versionLine != 'TAP version 13') { throw new \Exception('TapParser only supports TAP version 13'); } if (preg_match(self::TEST_COVERAGE_PATTERN, $lines[count($lines) - 1])) { array_pop($lines); if ($lines[count($lines) - 1] == "") { array_pop($lines); } } $matches = array(); $totalTests = 0; if (preg_match(self::TEST_COUNTS_PATTERN, $lines[0], $matches)) { array_shift($lines); $totalTests = (int) $matches[2]; } if (preg_match(self::TEST_COUNTS_PATTERN, $lines[count($lines) - 1], $matches)) { array_pop($lines); $totalTests = (int) $matches[2]; } $rtn = $this->processTestLines($lines); if ($totalTests != count($rtn)) { throw new \Exception('Invalid TAP string, number of tests does not match specified test count.'); } return $rtn; } protected function processTestLines($lines) { $rtn = array(); foreach ($lines as $line) { $matches = array(); if (preg_match(self::TEST_LINE_PATTERN, $line, $matches)) { $ok = ($matches[1] == 'ok' ? true : false); if (!$ok) { $this->failures++; } $item = array( 'pass' => $ok, 'suite' => $matches[2], 'test' => $matches[3], ); $rtn[] = $item; } elseif (preg_match(self::TEST_SKIP_PATTERN, $line, $matches)) { $rtn[] = array('message' => 'SKIP'); } elseif (preg_match(self::TEST_MESSAGE_PATTERN, $line, $matches)) { $rtn[count($rtn) - 1]['message'] = $matches[1]; } } return $rtn; } public function getTotalFailures() { return $this->failures; } }