First commit
This commit is contained in:
commit
c6e2478c40
13918 changed files with 2303184 additions and 0 deletions
24
sites/all/modules/civicrm/Civi/CiUtil/Arrays.php
Normal file
24
sites/all/modules/civicrm/Civi/CiUtil/Arrays.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil;
|
||||
|
||||
/**
|
||||
* Class Arrays
|
||||
*
|
||||
* @package Civi\CiUtil
|
||||
*/
|
||||
class Arrays {
|
||||
/**
|
||||
* @param $arr
|
||||
* @param $col
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function collect($arr, $col) {
|
||||
$r = array();
|
||||
foreach ($arr as $k => $item) {
|
||||
$r[$k] = $item[$col];
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
}
|
32
sites/all/modules/civicrm/Civi/CiUtil/CSVParser.php
Normal file
32
sites/all/modules/civicrm/Civi/CiUtil/CSVParser.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil;
|
||||
|
||||
/**
|
||||
* Parse phpunit result files
|
||||
*/
|
||||
class CSVParser {
|
||||
|
||||
/**
|
||||
* @param string $csvContent
|
||||
* Content; each row in the row csv should start with two cells:.
|
||||
* - cell 0: the test name
|
||||
* - cell 1: the test status
|
||||
* @return array
|
||||
* (string $testName => string $status)
|
||||
*/
|
||||
public static function parseResults($csvContent) {
|
||||
$fh = fopen('php://memory', 'r+');
|
||||
fwrite($fh, $csvContent);
|
||||
rewind($fh);
|
||||
|
||||
$results = array();
|
||||
while (($r = fgetcsv($fh)) !== FALSE) {
|
||||
$name = str_replace('.', '::', trim($r[0]));
|
||||
$status = trim($r[1]);
|
||||
$results[$name] = $status;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil\Command;
|
||||
|
||||
/**
|
||||
* Class AntagonistCommand
|
||||
*
|
||||
* @package Civi\CiUtil\Command
|
||||
*/
|
||||
class AntagonistCommand {
|
||||
/**
|
||||
* @param $argv
|
||||
*/
|
||||
public static function main($argv) {
|
||||
if (count($argv) != 3) {
|
||||
print "usage: {$argv[0]} <TargetTest::testFunc> </path/to/suite>\n";
|
||||
exit(1);
|
||||
}
|
||||
list ($program, $target, $suite) = $argv;
|
||||
|
||||
$candidateTests = \Civi\CiUtil\PHPUnitScanner::findTestsByPath(array($suite));
|
||||
// $candidateTests = array(
|
||||
// array('class' => 'CRM_Core_RegionTest', 'method' => 'testBlank'),
|
||||
// array('class' => 'CRM_Core_RegionTest', 'method' => 'testDefault'),
|
||||
// array('class' => 'CRM_Core_RegionTest', 'method' => 'testOverride'),
|
||||
// array('class' => 'CRM_Core_RegionTest', 'method' => 'testAllTypes'),
|
||||
// );
|
||||
$antagonist = self::findAntagonist($target, $candidateTests);
|
||||
if ($antagonist) {
|
||||
print_r(array('found an antagonist' => $antagonist));
|
||||
}
|
||||
else {
|
||||
print_r(array('found no antagonists'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $target
|
||||
* E.g. "MyTest::testFoo".
|
||||
* @param array $candidateTests
|
||||
* List of strings (e.g. "MyTest::testFoo").
|
||||
* @return array|null
|
||||
* array contains keys:
|
||||
* - antagonist: array
|
||||
* - file: string
|
||||
* - class: string
|
||||
* - method: string
|
||||
* - expectedResults: array
|
||||
* - actualResults: array
|
||||
*/
|
||||
public static function findAntagonist($target, $candidateTests) {
|
||||
//$phpUnit = new \Civi\CiUtil\EnvTestRunner('./scripts/phpunit', 'EnvTests');
|
||||
$phpUnit = new \Civi\CiUtil\EnvTestRunner('phpunit', 'tests/phpunit/EnvTests.php');
|
||||
$expectedResults = $phpUnit->run(array($target));
|
||||
print_r(array('$expectedResults' => $expectedResults));
|
||||
|
||||
foreach ($candidateTests as $candidateTest) {
|
||||
$candidateTestName = $candidateTest['class'] . '::' . $candidateTest['method'];
|
||||
if ($candidateTestName == $target) {
|
||||
continue;
|
||||
}
|
||||
$actualResults = $phpUnit->run(array(
|
||||
$candidateTestName,
|
||||
$target,
|
||||
));
|
||||
print_r(array('$actualResults' => $actualResults));
|
||||
foreach ($expectedResults as $testName => $expectedResult) {
|
||||
if ($actualResults[$testName] != $expectedResult) {
|
||||
return array(
|
||||
'antagonist' => $candidateTest,
|
||||
'expectedResults' => $expectedResults,
|
||||
'actualResults' => $actualResults,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil\Command;
|
||||
|
||||
/**
|
||||
* Class CompareCommand
|
||||
*
|
||||
* @package Civi\CiUtil\Command
|
||||
*/
|
||||
class CompareCommand {
|
||||
/**
|
||||
* @param $argv
|
||||
*/
|
||||
public static function main($argv) {
|
||||
if (empty($argv[1])) {
|
||||
echo "summary: Compares the output of different test runs\n";
|
||||
echo "usage: phpunit-compare [--out=txt|csv] [--phpunit-json|--jenkins-xml] <file1> <file2>...\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$parser = array('\Civi\CiUtil\PHPUnitParser', 'parseJsonResults');
|
||||
$printerType = 'txt';
|
||||
$suites = array(); // array('file' => string, 'results' => array)
|
||||
for ($i = 1; $i < count($argv); $i++) {
|
||||
switch ($argv[$i]) {
|
||||
case '--phpunit-json':
|
||||
$parser = array('\Civi\CiUtil\PHPUnitParser', 'parseJsonResults');
|
||||
break;
|
||||
|
||||
case '--jenkins-xml':
|
||||
$parser = array('\Civi\CiUtil\JenkinsParser', 'parseXmlResults');
|
||||
break;
|
||||
|
||||
case '--csv':
|
||||
$parser = array('\Civi\CiUtil\CSVParser', 'parseResults');
|
||||
break;
|
||||
|
||||
case '--out=txt':
|
||||
$printerType = 'txt';
|
||||
break;
|
||||
|
||||
case '--out=csv':
|
||||
$printerType = 'csv';
|
||||
break;
|
||||
|
||||
default:
|
||||
$suites[] = array(
|
||||
'file' => $argv[$i],
|
||||
'results' => call_user_func($parser, file_get_contents($argv[$i])),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$tests = array(); // array(string $name)
|
||||
foreach ($suites as $suite) {
|
||||
$tests = array_unique(array_merge(
|
||||
$tests,
|
||||
array_keys($suite['results'])
|
||||
));
|
||||
}
|
||||
sort($tests);
|
||||
|
||||
if ($printerType == 'csv') {
|
||||
$printer = new \Civi\CiUtil\CsvPrinter('php://stdout', \Civi\CiUtil\Arrays::collect($suites, 'file'));
|
||||
}
|
||||
else {
|
||||
$printer = new \Civi\CiUtil\ComparisonPrinter(\Civi\CiUtil\Arrays::collect($suites, 'file'));
|
||||
}
|
||||
foreach ($tests as $test) {
|
||||
$values = array();
|
||||
foreach ($suites as $suite) {
|
||||
$values[] = isset($suite['results'][$test]) ? $suite['results'][$test] : 'MISSING';
|
||||
}
|
||||
|
||||
if (count(array_unique($values)) > 1) {
|
||||
$printer->printRow($test, $values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
21
sites/all/modules/civicrm/Civi/CiUtil/Command/LsCommand.php
Normal file
21
sites/all/modules/civicrm/Civi/CiUtil/Command/LsCommand.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil\Command;
|
||||
|
||||
/**
|
||||
* Class LsCommand
|
||||
*
|
||||
* @package Civi\CiUtil\Command
|
||||
*/
|
||||
class LsCommand {
|
||||
/**
|
||||
* @param $argv
|
||||
*/
|
||||
public static function main($argv) {
|
||||
$paths = $argv;
|
||||
array_shift($paths);
|
||||
foreach (\Civi\CiUtil\PHPUnitScanner::findTestsByPath($paths) as $test) {
|
||||
printf("%s %s %s\n", $test['file'], $test['class'], $test['method']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
59
sites/all/modules/civicrm/Civi/CiUtil/ComparisonPrinter.php
Normal file
59
sites/all/modules/civicrm/Civi/CiUtil/ComparisonPrinter.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil;
|
||||
|
||||
/**
|
||||
* Class ComparisonPrinter
|
||||
*
|
||||
* @package Civi\CiUtil
|
||||
*/
|
||||
class ComparisonPrinter {
|
||||
var $headers;
|
||||
var $hasHeader = FALSE;
|
||||
|
||||
/**
|
||||
* @param $headers
|
||||
*/
|
||||
public function __construct($headers) {
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
public function printHeader() {
|
||||
if ($this->hasHeader) {
|
||||
return;
|
||||
}
|
||||
|
||||
## LEGEND
|
||||
print "LEGEND\n";
|
||||
$i = 1;
|
||||
foreach ($this->headers as $header) {
|
||||
printf("% 2d: %s\n", $i, $header);
|
||||
$i++;
|
||||
}
|
||||
print "\n";
|
||||
|
||||
## HEADER
|
||||
printf("%-90s ", 'TEST NAME');
|
||||
$i = 1;
|
||||
foreach ($this->headers as $header) {
|
||||
printf("%-10d ", $i);
|
||||
$i++;
|
||||
}
|
||||
print "\n";
|
||||
|
||||
$this->hasHeader = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $test
|
||||
* @param $values
|
||||
*/
|
||||
public function printRow($test, $values) {
|
||||
$this->printHeader();
|
||||
printf("%-90s ", $test);
|
||||
foreach ($values as $value) {
|
||||
printf("%-10s ", $value);
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
|
||||
}
|
46
sites/all/modules/civicrm/Civi/CiUtil/CsvPrinter.php
Normal file
46
sites/all/modules/civicrm/Civi/CiUtil/CsvPrinter.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil;
|
||||
|
||||
/**
|
||||
* Class CsvPrinter
|
||||
*
|
||||
* @package Civi\CiUtil
|
||||
*/
|
||||
class CsvPrinter {
|
||||
var $file;
|
||||
var $headers;
|
||||
var $hasHeader = FALSE;
|
||||
|
||||
/**
|
||||
* @param $file
|
||||
* @param $headers
|
||||
*/
|
||||
public function __construct($file, $headers) {
|
||||
$this->file = fopen($file, "w");
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
public function printHeader() {
|
||||
if ($this->hasHeader) {
|
||||
return;
|
||||
}
|
||||
|
||||
$headers = array_values($this->headers);
|
||||
array_unshift($headers, 'TEST NAME');
|
||||
fputcsv($this->file, $headers);
|
||||
|
||||
$this->hasHeader = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $test
|
||||
* @param $values
|
||||
*/
|
||||
public function printRow($test, $values) {
|
||||
$this->printHeader();
|
||||
$row = $values;
|
||||
array_unshift($row, $test);
|
||||
fputcsv($this->file, $row);
|
||||
}
|
||||
|
||||
}
|
37
sites/all/modules/civicrm/Civi/CiUtil/EnvTestRunner.php
Normal file
37
sites/all/modules/civicrm/Civi/CiUtil/EnvTestRunner.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil;
|
||||
|
||||
/**
|
||||
* Parse phpunit result files
|
||||
*/
|
||||
class EnvTestRunner {
|
||||
protected $phpunit;
|
||||
protected $envTestSuite;
|
||||
|
||||
/**
|
||||
* @param string $phpunit
|
||||
* @param string $envTestSuite
|
||||
*/
|
||||
public function __construct($phpunit = "phpunit", $envTestSuite = 'EnvTests') {
|
||||
$this->phpunit = $phpunit;
|
||||
$this->envTestSuite = $envTestSuite;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tests
|
||||
* @return array
|
||||
* (string $testName => string $status)
|
||||
*/
|
||||
public function run($tests) {
|
||||
$envTests = implode(' ', $tests);
|
||||
$jsonFile = tempnam(sys_get_temp_dir(), 'phpunit-json-');
|
||||
unlink($jsonFile);
|
||||
$command = "env PHPUNIT_TESTS=\"$envTests\" {$this->phpunit} --log-json $jsonFile {$this->envTestSuite}";
|
||||
echo "Running [$command]\n";
|
||||
system($command);
|
||||
$results = PHPUnitParser::parseJsonResults(file_get_contents($jsonFile));
|
||||
unlink($jsonFile);
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
35
sites/all/modules/civicrm/Civi/CiUtil/JenkinsParser.php
Normal file
35
sites/all/modules/civicrm/Civi/CiUtil/JenkinsParser.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil;
|
||||
|
||||
/**
|
||||
* Parse Jenkins result files
|
||||
*/
|
||||
class JenkinsParser {
|
||||
/**
|
||||
* @param string $content
|
||||
* Xml data.
|
||||
* @return array
|
||||
* (string $testName => string $status)
|
||||
*/
|
||||
public static function parseXmlResults($content) {
|
||||
$xml = simplexml_load_string($content);
|
||||
$results = array();
|
||||
foreach ($xml->suites as $suites) {
|
||||
foreach ($suites->suite as $suite) {
|
||||
foreach ($suite->cases as $cases) {
|
||||
foreach ($cases->case as $case) {
|
||||
$name = "{$case->className}::{$case->testName}";
|
||||
if ($case->failedSince == 0) {
|
||||
$results[$name] = 'pass';
|
||||
}
|
||||
else {
|
||||
$results[$name] = 'fail';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
38
sites/all/modules/civicrm/Civi/CiUtil/PHPUnitParser.php
Normal file
38
sites/all/modules/civicrm/Civi/CiUtil/PHPUnitParser.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil;
|
||||
|
||||
/**
|
||||
* Parse phpunit result files
|
||||
*/
|
||||
class PHPUnitParser {
|
||||
/**
|
||||
* @param string $content
|
||||
* Phpunit streaming JSON.
|
||||
* @return array
|
||||
* ["$class::$func" => $status]
|
||||
*/
|
||||
protected static function parseJsonStream($content) {
|
||||
$content = '['
|
||||
. strtr($content, array("}{" => "},{"))
|
||||
. ']';
|
||||
return json_decode($content, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
* Json stream.
|
||||
* @return array
|
||||
* (string $testName => string $status)
|
||||
*/
|
||||
public static function parseJsonResults($content) {
|
||||
$records = self::parseJsonStream($content);
|
||||
$results = array();
|
||||
foreach ($records as $r) {
|
||||
if ($r['event'] == 'test') {
|
||||
$results[$r['test']] = $r['status'];
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
97
sites/all/modules/civicrm/Civi/CiUtil/PHPUnitScanner.php
Normal file
97
sites/all/modules/civicrm/Civi/CiUtil/PHPUnitScanner.php
Normal file
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
namespace Civi\CiUtil;
|
||||
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* Search for PHPUnit test cases
|
||||
*/
|
||||
class PHPUnitScanner {
|
||||
/**
|
||||
* @param $path
|
||||
* @return array <string> class names
|
||||
*/
|
||||
public static function _findTestClasses($path) {
|
||||
// print_r(array(
|
||||
// 'loading' => $path,
|
||||
// get_included_files()
|
||||
// ));
|
||||
$origClasses = get_declared_classes();
|
||||
require_once $path;
|
||||
$newClasses = get_declared_classes();
|
||||
|
||||
return preg_grep('/Test$/', array_diff(
|
||||
$newClasses,
|
||||
$origClasses
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $paths
|
||||
* @return array (string $file => string $class)
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function findTestClasses($paths) {
|
||||
$testClasses = array();
|
||||
$finder = new Finder();
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if (is_dir($path)) {
|
||||
foreach ($finder->files()->in($paths)->name('*Test.php') as $file) {
|
||||
$testClass = self::_findTestClasses((string) $file);
|
||||
if (count($testClass) == 1) {
|
||||
$testClasses[(string) $file] = array_shift($testClass);
|
||||
}
|
||||
elseif (count($testClass) > 1) {
|
||||
throw new \Exception("Too many classes in $file");
|
||||
}
|
||||
else {
|
||||
throw new \Exception("Too few classes in $file");
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (is_file($path)) {
|
||||
$testClass = self::_findTestClasses($path);
|
||||
if (count($testClass) == 1) {
|
||||
$testClasses[$path] = array_shift($testClass);
|
||||
}
|
||||
elseif (count($testClass) > 1) {
|
||||
throw new \Exception("Too many classes in $path");
|
||||
}
|
||||
else {
|
||||
throw new \Exception("Too few classes in $path");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $testClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $paths
|
||||
*
|
||||
* @return array
|
||||
* each element is an array with keys:
|
||||
* - file: string
|
||||
* - class: string
|
||||
* - method: string
|
||||
*/
|
||||
public static function findTestsByPath($paths) {
|
||||
$r = array();
|
||||
$testClasses = self::findTestClasses($paths);
|
||||
foreach ($testClasses as $testFile => $testClass) {
|
||||
$clazz = new \ReflectionClass($testClass);
|
||||
foreach ($clazz->getMethods() as $method) {
|
||||
if (preg_match('/^test/', $method->name)) {
|
||||
$r[] = array(
|
||||
'file' => $testFile,
|
||||
'class' => $testClass,
|
||||
'method' => $method->name,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue