Remove old test runner.
This commit is contained in:
parent
cf687f9c70
commit
bf08dd1e3d
506
jsonld-tests.php
506
jsonld-tests.php
|
@ -1,506 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* PHP unit tests for JSON-LD.
|
|
||||||
*
|
|
||||||
* @author Dave Longley
|
|
||||||
*
|
|
||||||
* Copyright (c) 2011-2013 Digital Bazaar, Inc. All rights reserved.
|
|
||||||
*/
|
|
||||||
require_once('jsonld.php');
|
|
||||||
|
|
||||||
// send errors to stdout
|
|
||||||
ini_set('display_errors', 'stdout');
|
|
||||||
|
|
||||||
// determine EOL for output based on command line php or webpage php
|
|
||||||
$isCli = defined('STDIN');
|
|
||||||
$eol = $isCli ? "\n" : '<br/>';
|
|
||||||
|
|
||||||
// EARL report
|
|
||||||
$earl = (object)array(
|
|
||||||
'@context' => (object)array(
|
|
||||||
'doap' => 'http://usefulinc.com/ns/doap#',
|
|
||||||
'foaf' => 'http://xmlns.com/foaf/0.1/',
|
|
||||||
'dc' => 'http://purl.org/dc/terms/',
|
|
||||||
'earl' => 'http://www.w3.org/ns/earl#',
|
|
||||||
'xsd' => 'http://www.w3.org/2001/XMLSchema#',
|
|
||||||
'doap:homepage' => (object)array('@type' => '@id'),
|
|
||||||
'doap:license' => (object)array('@type' => '@id'),
|
|
||||||
'dc:creator' => (object)array('@type' => '@id'),
|
|
||||||
'foaf:homepage' => (object)array('@type' => '@id'),
|
|
||||||
'subjectOf' => (object)array('@reverse' => 'earl:subject'),
|
|
||||||
'earl:assertedBy' => (object)array('@type' => '@id'),
|
|
||||||
'earl:mode' => (object)array('@type' => '@id'),
|
|
||||||
'earl:test' => (object)array('@type' => '@id'),
|
|
||||||
'earl:outcome' => (object)array('@type' => '@id'),
|
|
||||||
'dc:date' => (object)array('@type' => 'xsd:date')
|
|
||||||
),
|
|
||||||
'@id' => 'https://github.com/digitalbazaar/php-json-ld',
|
|
||||||
'@type' => array('doap:Project', 'earl:TestSubject', 'earl:Software'),
|
|
||||||
'doap:name' => 'php-json-ld',
|
|
||||||
'dc:title' => 'php-json-ld',
|
|
||||||
'doap:homepage' => 'https://github.com/digitalbazaar/php-json-ld',
|
|
||||||
'doap:license' => 'https://github.com/digitalbazaar/php-json-ld/blob/master/LICENSE',
|
|
||||||
'doap:description' => 'A JSON-LD processor for PHP',
|
|
||||||
'doap:programming-language' => 'PHP',
|
|
||||||
'dc:creator' => 'https://github.com/dlongley',
|
|
||||||
'doap:developer' => (object)array(
|
|
||||||
'@id' => 'https://github.com/dlongley',
|
|
||||||
'@type' => array('foaf:Person', 'earl:Assertor'),
|
|
||||||
'foaf:name' => 'Dave Longley',
|
|
||||||
'foaf:homepage' => 'https://github.com/dlongley'
|
|
||||||
),
|
|
||||||
'dc:date' => array(
|
|
||||||
'@value' => gmdate('Y-m-d'),
|
|
||||||
'@type' => 'xsd:date'
|
|
||||||
),
|
|
||||||
'subjectOf' => array()
|
|
||||||
);
|
|
||||||
|
|
||||||
function error_handler($errno, $errstr, $errfile, $errline) {
|
|
||||||
global $eol;
|
|
||||||
echo "$eol$errstr$eol";
|
|
||||||
array_walk(
|
|
||||||
debug_backtrace(),
|
|
||||||
create_function(
|
|
||||||
'$a,$b',
|
|
||||||
'echo "{$a[\'function\']}()' .
|
|
||||||
'(".basename($a[\'file\']).":{$a[\'line\']}); ' . $eol . '";'));
|
|
||||||
throw new Exception();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!$isCli) {
|
|
||||||
set_error_handler('error_handler');
|
|
||||||
}
|
|
||||||
|
|
||||||
function deep_compare($expect, $result) {
|
|
||||||
if(is_array($expect)) {
|
|
||||||
if(!is_array($result)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(count($expect) !== count($result)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
foreach($expect as $i => $v) {
|
|
||||||
if(!deep_compare($v, $result[$i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_object($expect)) {
|
|
||||||
if(!is_object($result)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(count(get_object_vars($expect)) !== count(get_object_vars($result))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
foreach($expect as $k => $v) {
|
|
||||||
if(!property_exists($result, $k) || !deep_compare($v, $result->{$k})) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $expect === $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function expanded_compare($x, $y, $is_list=false) {
|
|
||||||
if($x === $y) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if(gettype($x) !== gettype($y)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(is_array($x)) {
|
|
||||||
if(!is_array($y) || count($x) !== count($y)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$rval = true;
|
|
||||||
if($is_list) {
|
|
||||||
// compare in order
|
|
||||||
for($i = 0; $rval && $i < count($x); ++$i) {
|
|
||||||
$rval = expanded_compare($x[$i], $y[$i], false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// compare in any order
|
|
||||||
$iso = array();
|
|
||||||
for($i = 0; $rval && $i < count($x); ++$i) {
|
|
||||||
$rval = false;
|
|
||||||
for($j = 0; !$rval && $j < count($y); ++$j) {
|
|
||||||
if(!isset($iso[$j])) {
|
|
||||||
if(expanded_compare($x[$i], $y[$j], false)) {
|
|
||||||
$iso[$j] = $i;
|
|
||||||
$rval = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$rval = $rval && (count($iso) === count($x));
|
|
||||||
}
|
|
||||||
return $rval;
|
|
||||||
}
|
|
||||||
if(is_object($x)) {
|
|
||||||
$x_keys = array_keys((array)$x);
|
|
||||||
$y_keys = array_keys((array)$y);
|
|
||||||
if(count($x_keys) !== count($y_keys)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
foreach($x_keys as $key) {
|
|
||||||
if(!property_exists($y, $key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!expanded_compare($x->{$key}, $y->{$key}, $key === '@list')) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads test JSON files.
|
|
||||||
*
|
|
||||||
* @param string $file the file to read.
|
|
||||||
* @param string $filepath the test filepath.
|
|
||||||
*
|
|
||||||
* @return string the read JSON.
|
|
||||||
*/
|
|
||||||
function read_test_json($file, $filepath) {
|
|
||||||
global $eol;
|
|
||||||
|
|
||||||
try {
|
|
||||||
$file = $filepath . '/' . $file;
|
|
||||||
return json_decode(file_get_contents($file));
|
|
||||||
}
|
|
||||||
catch(Exception $e) {
|
|
||||||
echo "Exception while parsing file: '$file'$eol";
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads test N-Quads files.
|
|
||||||
*
|
|
||||||
* @param string $file the file to read.
|
|
||||||
* @param string $filepath the test filepath.
|
|
||||||
*
|
|
||||||
* @return string the read N-Quads.
|
|
||||||
*/
|
|
||||||
function read_test_nquads($file, $filepath) {
|
|
||||||
global $eol;
|
|
||||||
|
|
||||||
try {
|
|
||||||
$file = $filepath . '/' . $file;
|
|
||||||
return file_get_contents($file);
|
|
||||||
}
|
|
||||||
catch(Exception $e) {
|
|
||||||
echo "Exception while parsing file: '$file'$eol";
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON-encodes the given input (does not escape slashes).
|
|
||||||
*
|
|
||||||
* @param mixed $input the input to encode.
|
|
||||||
*
|
|
||||||
* @return the encoded input.
|
|
||||||
*/
|
|
||||||
function jsonld_encode($input) {
|
|
||||||
// newer PHP has a flag to avoid escaped '/'
|
|
||||||
if(defined('JSON_UNESCAPED_SLASHES')) {
|
|
||||||
$options = JSON_UNESCAPED_SLASHES;
|
|
||||||
if(defined('JSON_PRETTY_PRINT')) {
|
|
||||||
$options |= JSON_PRETTY_PRINT;
|
|
||||||
}
|
|
||||||
$json = json_encode($input, $options);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// use a simple string replacement of '\/' to '/'.
|
|
||||||
$json = str_replace('\\/', '/', json_encode($input));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $json;
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestRunner {
|
|
||||||
public function __construct() {
|
|
||||||
// set up groups, add root group
|
|
||||||
$this->groups = array();
|
|
||||||
$this->group('');
|
|
||||||
|
|
||||||
$this->passed = 0;
|
|
||||||
$this->failed = 0;
|
|
||||||
$this->total = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function group($name) {
|
|
||||||
$this->groups[] = (object)array(
|
|
||||||
'name' => $name,
|
|
||||||
'tests' => array(),
|
|
||||||
'count' => 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function ungroup() {
|
|
||||||
array_pop($this->groups);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function test($name) {
|
|
||||||
$this->groups[count($this->groups) - 1]->tests[] = $name;
|
|
||||||
$this->total += 1;
|
|
||||||
|
|
||||||
$line = '';
|
|
||||||
foreach($this->groups as $g) {
|
|
||||||
$line .= ($line === '') ? $g->name : ('/' . $g->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
$g = $this->groups[count($this->groups) - 1];
|
|
||||||
if($g->name !== '') {
|
|
||||||
$count = '' . $g->count;
|
|
||||||
$end = 4 - strlen($count);
|
|
||||||
for($i = 0; $i < $end; ++$i) {
|
|
||||||
$count = '0' . $count;
|
|
||||||
}
|
|
||||||
$line .= ' ' . $count;
|
|
||||||
$g->count += 1;
|
|
||||||
}
|
|
||||||
$line .= '/' . array_pop($g->tests) . '... ';
|
|
||||||
echo $line;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function check($test, $expect, $result, $type) {
|
|
||||||
global $eol;
|
|
||||||
|
|
||||||
$compare_json = !in_array('jld:ToRDFTest', $type);
|
|
||||||
$relabel = in_array('jld:FlattenTest', $type);
|
|
||||||
$expanded = $relabel || in_array('jld:ExpandTest', $type);
|
|
||||||
if($relabel) {
|
|
||||||
$expect = jsonld_relabel_blank_nodes($expect);
|
|
||||||
$result = jsonld_relabel_blank_nodes($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
$pass = false;
|
|
||||||
if($compare_json) {
|
|
||||||
$pass = (json_encode($expect) === json_encode($result));
|
|
||||||
}
|
|
||||||
if(!$pass) {
|
|
||||||
$pass = deep_compare($expect, $result) ||
|
|
||||||
($expanded && expanded_compare($expect, $result, $relabel));
|
|
||||||
}
|
|
||||||
if(!$pass && $relabel) {
|
|
||||||
echo "WARN tried normalization...";
|
|
||||||
$expect_normalized = jsonld_normalize(
|
|
||||||
$expect, array('format' => 'application/nquads'));
|
|
||||||
$result_normalized = jsonld_normalize(
|
|
||||||
$result, array('format' => 'application/nquads'));
|
|
||||||
$pass = ($expect_normalized === $result_normalized);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($pass) {
|
|
||||||
$this->passed += 1;
|
|
||||||
echo "PASS$eol";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$this->failed += 1;
|
|
||||||
echo "FAIL$eol";
|
|
||||||
echo 'Expect: ' . jsonld_encode($expect) . $eol;
|
|
||||||
echo 'Result: ' . jsonld_encode($result) . $eol;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function load($filepath) {
|
|
||||||
global $eol;
|
|
||||||
$manifests = array();
|
|
||||||
|
|
||||||
// get full path
|
|
||||||
$filepath = realpath($filepath);
|
|
||||||
echo "Reading manifest files from: '$filepath'$eol";
|
|
||||||
|
|
||||||
// read each test file from the directory
|
|
||||||
$files = array();
|
|
||||||
$handle = opendir($filepath);
|
|
||||||
if($handle) {
|
|
||||||
while(($file = readdir($handle)) !== false) {
|
|
||||||
if($file !== '..' and $file !== '.') {
|
|
||||||
$files[] = $filepath . '/' . $file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir($handle);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new Exception('Could not open directory.');
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($files as $file) {
|
|
||||||
$info = pathinfo($file);
|
|
||||||
// FIXME: hackish, manifests are now JSON-LD
|
|
||||||
if(strstr($info['basename'], 'manifest') !== false &&
|
|
||||||
$info['extension'] == 'jsonld') {
|
|
||||||
echo "Reading manifest file: '$file'$eol";
|
|
||||||
|
|
||||||
try {
|
|
||||||
$manifest = json_decode(file_get_contents($file));
|
|
||||||
}
|
|
||||||
catch(Exception $e) {
|
|
||||||
echo "Exception while parsing file: '$file'$eol";
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
|
|
||||||
$manifest->filename = $file;
|
|
||||||
$manifest->filepath = $filepath;
|
|
||||||
$manifests[] = $manifest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo count($manifests) . " manifest file(s) read.$eol";
|
|
||||||
return $manifests;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run($manifests) {
|
|
||||||
/* Manifest format: {
|
|
||||||
name: <optional manifest name>,
|
|
||||||
sequence: [{
|
|
||||||
'name': <test name>,
|
|
||||||
'@type': ["test:TestCase", "jld:<type of test>"],
|
|
||||||
'input': <input file for test>,
|
|
||||||
'context': <context file for add context test type>,
|
|
||||||
'frame': <frame file for frame test type>,
|
|
||||||
'expect': <expected result file>,
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
global $eol;
|
|
||||||
global $earl;
|
|
||||||
foreach($manifests as $manifest) {
|
|
||||||
if(property_exists($manifest, 'name')) {
|
|
||||||
$this->group($manifest->name);
|
|
||||||
}
|
|
||||||
$filepath = $manifest->filepath;
|
|
||||||
$idBase = 'http://json-ld.org/test-suite/tests/' .
|
|
||||||
basename($manifest->filename);
|
|
||||||
foreach($manifest->sequence as $test) {
|
|
||||||
// read test input files
|
|
||||||
$type = $test->{'@type'};
|
|
||||||
$options = array(
|
|
||||||
'base' => 'http://json-ld.org/test-suite/tests/' . $test->input,
|
|
||||||
'useNativeTypes' => true);
|
|
||||||
|
|
||||||
$pass = false;
|
|
||||||
try {
|
|
||||||
if(in_array('jld:ApiErrorTest', $type)) {
|
|
||||||
echo "Skipping test \"{$test->name}\" of type: " .
|
|
||||||
json_encode($type) . $eol;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if(in_array('jld:NormalizeTest', $type)) {
|
|
||||||
$this->test($test->name);
|
|
||||||
$input = read_test_json($test->input, $filepath);
|
|
||||||
$test->expect = read_test_nquads($test->expect, $filepath);
|
|
||||||
$options['format'] = 'application/nquads';
|
|
||||||
$result = jsonld_normalize($input, $options);
|
|
||||||
}
|
|
||||||
else if(in_array('jld:ExpandTest', $type)) {
|
|
||||||
$this->test($test->name);
|
|
||||||
$input = read_test_json($test->input, $filepath);
|
|
||||||
$test->expect = read_test_json($test->expect, $filepath);
|
|
||||||
$result = jsonld_expand($input, $options);
|
|
||||||
}
|
|
||||||
else if(in_array('jld:CompactTest', $type)) {
|
|
||||||
$this->test($test->name);
|
|
||||||
$input = read_test_json($test->input, $filepath);
|
|
||||||
$test->context = read_test_json($test->context, $filepath);
|
|
||||||
$test->expect = read_test_json($test->expect, $filepath);
|
|
||||||
$result = jsonld_compact($input, $test->context, $options);
|
|
||||||
}
|
|
||||||
else if(in_array('jld:FlattenTest', $type)) {
|
|
||||||
$this->test($test->name);
|
|
||||||
$input = read_test_json($test->input, $filepath);
|
|
||||||
$test->expect = read_test_json($test->expect, $filepath);
|
|
||||||
$result = jsonld_flatten($input, null, $options);
|
|
||||||
}
|
|
||||||
else if(in_array('jld:FrameTest', $type)) {
|
|
||||||
$this->test($test->name);
|
|
||||||
$input = read_test_json($test->input, $filepath);
|
|
||||||
$test->frame = read_test_json($test->frame, $filepath);
|
|
||||||
$test->expect = read_test_json($test->expect, $filepath);
|
|
||||||
$result = jsonld_frame($input, $test->frame, $options);
|
|
||||||
}
|
|
||||||
else if(in_array('jld:FromRDFTest', $type)) {
|
|
||||||
$this->test($test->name);
|
|
||||||
$input = read_test_nquads($test->input, $filepath);
|
|
||||||
$test->expect = read_test_json($test->expect, $filepath);
|
|
||||||
$result = jsonld_from_rdf($input, $options);
|
|
||||||
}
|
|
||||||
else if(in_array('jld:ToRDFTest', $type)) {
|
|
||||||
$this->test($test->name);
|
|
||||||
$input = read_test_json($test->input, $filepath);
|
|
||||||
$test->expect = read_test_nquads($test->expect, $filepath);
|
|
||||||
$options['format'] = 'application/nquads';
|
|
||||||
$result = jsonld_to_rdf($input, $options);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
echo "Skipping test \"{$test->name}\" of type: " .
|
|
||||||
json_encode($type) . $eol;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check results
|
|
||||||
$pass = $this->check($test, $test->expect, $result, $type);
|
|
||||||
}
|
|
||||||
catch(JsonLdException $e) {
|
|
||||||
echo $eol . $e;
|
|
||||||
$this->failed += 1;
|
|
||||||
echo "FAIL$eol";
|
|
||||||
}
|
|
||||||
|
|
||||||
$earl->subjectOf[] = (object)array(
|
|
||||||
'@type' => 'earl:Assertion',
|
|
||||||
'earl:assertedBy' => $earl->{'doap:developer'}->{'@id'},
|
|
||||||
'earl:mode' => 'earl:automatic',
|
|
||||||
'earl:test' => $idBase . (property_exists($test, '@id') ?
|
|
||||||
$test->{'@id'} : ''),
|
|
||||||
'earl:result' => (object)array(
|
|
||||||
'@type' => 'earl:TestResult',
|
|
||||||
'dc:date' => gmdate(DateTime::ISO8601),
|
|
||||||
'earl:outcome' => 'earl:' . ($pass ? 'passed' : 'failed'),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if(property_exists($manifest, 'name')) {
|
|
||||||
$this->ungroup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get command line options
|
|
||||||
$options = getopt('d:e:');
|
|
||||||
if($options === false || !array_key_exists('d', $options)) {
|
|
||||||
$dvar = 'path to json-ld.org/test-suite/tests';
|
|
||||||
$evar = 'file to write EARL report to';
|
|
||||||
echo "Usage: php jsonld-tests.php -d <$dvar> [-e <$evar>]$eol";
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// load and run tests
|
|
||||||
$tr = new TestRunner();
|
|
||||||
$tr->group('JSON-LD');
|
|
||||||
$tr->run($tr->load($options['d']));
|
|
||||||
$tr->ungroup();
|
|
||||||
echo "Done. Total:{$tr->total} Passed:{$tr->passed} Failed:{$tr->failed}$eol";
|
|
||||||
|
|
||||||
// write out EARL report
|
|
||||||
if(array_key_exists('e', $options)) {
|
|
||||||
$fd = fopen($options['e'], 'w');
|
|
||||||
fwrite($fd, jsonld_encode($earl));
|
|
||||||
fclose($fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end of file, omit ?> */
|
|
Loading…
Reference in a new issue