New port of jsonld.js.

This commit is contained in:
Dave Longley 2012-04-23 12:57:06 -04:00
parent de770b30fd
commit cdce63a99c
2 changed files with 3545 additions and 3114 deletions

View file

@ -12,8 +12,7 @@ require_once('jsonld.php');
$isCli = defined('STDIN'); $isCli = defined('STDIN');
$eol = $isCli ? "\n" : '<br/>'; $eol = $isCli ? "\n" : '<br/>';
function error_handler($errno, $errstr, $errfile, $errline) function error_handler($errno, $errstr, $errfile, $errline) {
{
global $eol; global $eol;
echo "$eol$errstr$eol"; echo "$eol$errstr$eol";
array_walk( array_walk(
@ -25,123 +24,100 @@ function error_handler($errno, $errstr, $errfile, $errline)
throw new Exception(); throw new Exception();
return false; return false;
} }
if(!$isCli) if(!$isCli) {
{
set_error_handler('error_handler'); set_error_handler('error_handler');
} }
function _sortKeys($obj) function deep_compare($expect, $result) {
{ if(is_array($expect)) {
$rval; if(!is_array($result)) {
return false;
if($obj === null)
{
$rval = null;
} }
else if(is_array($obj)) if(count($expect) !== count($result)) {
{ return false;
$rval = array(); }
foreach($obj as $o) foreach($expect as $i => $v) {
{ if(!deep_compare($v, $result[$i])) {
$rval[] = _sortKeys($o); return false;
} }
} }
else if(is_object($obj)) return true;
{
$rval = new stdClass();
$keys = array_keys((array)$obj);
sort($keys);
foreach($keys as $key)
{
$rval->$key = _sortKeys($obj->$key);
}
}
else
{
$rval = $obj;
} }
return $rval; 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(!deep_compare($v, $result->{$k})) {
return false;
}
}
} }
function _stringifySorted($obj, $indent) return $expect === $result;
{
/*
$flags = JSON_UNESCAPED_SLASHES;
if($indent)
{
$flags |= JSON_PRETTY_PRINT;
}*/
return str_replace('\\/', '/', json_encode(_sortKeys($obj)));//, $flags);
} }
/** /**
* Reads test JSON files. * Reads test JSON files.
* *
* @param file the file to read. * @param string $file the file to read.
* @param filepath the test filepath. * @param string $filepath the test filepath.
* *
* @return the read JSON. * @return string the read JSON.
*/ */
function _readTestJson($file, $filepath) function read_test_json($file, $filepath) {
{
$rval;
global $eol; global $eol;
try try {
{
$file = $filepath . '/' . $file; $file = $filepath . '/' . $file;
$rval = json_decode(file_get_contents($file)); return json_decode(file_get_contents($file));
} }
catch(Exception $e) catch(Exception $e) {
{
echo "Exception while parsing file: '$file'$eol"; echo "Exception while parsing file: '$file'$eol";
throw $e; throw $e;
} }
return $rval;
} }
class TestRunner class TestRunner {
{ public function __construct() {
public function __construct()
{
// set up groups, add root group // set up groups, add root group
$this->groups = array(); $this->groups = array();
$this->group(''); $this->group('');
$this->passed = 0;
$this->failed = 0;
$this->total = 0;
} }
public function group($name) public function group($name) {
{ $this->groups[] = (object)array(
$group = new stdClass(); 'name' => $name,
$group->name = $name; 'tests' => array(),
$group->tests = array(); 'count' => 1);
$group->count = 1;
$this->groups[] = $group;
} }
public function ungroup() public function ungroup() {
{
array_pop($this->groups); array_pop($this->groups);
} }
public function test($name) public function test($name) {
{
$this->groups[count($this->groups) - 1]->tests[] = $name; $this->groups[count($this->groups) - 1]->tests[] = $name;
$this->total += 1;
$line = ''; $line = '';
foreach($this->groups as $g) foreach($this->groups as $g) {
{
$line .= ($line === '') ? $g->name : ('/' . $g->name); $line .= ($line === '') ? $g->name : ('/' . $g->name);
} }
$g = $this->groups[count($this->groups) - 1]; $g = $this->groups[count($this->groups) - 1];
if($g->name !== '') if($g->name !== '') {
{
$count = '' . $g->count; $count = '' . $g->count;
$end = 4 - strlen($count); $end = 4 - strlen($count);
for($i = 0; $i < $end; ++$i) for($i = 0; $i < $end; ++$i) {
{
$count = '0' . $count; $count = '0' . $count;
} }
$line .= ' ' . $count; $line .= ' ' . $count;
@ -151,36 +127,31 @@ class TestRunner
echo $line; echo $line;
} }
public function check($expect, $result, $indent=false) public function check($test, $expect, $result) {
{
global $eol; global $eol;
// sort and use given indent level if(strpos($test->{'@type'}, 'NormalizeTest') !== false) {
$expect = _stringifySorted($expect, $indent); $pass = JsonLdProcessor::compareNormalized($expect, $result);
$result = _stringifySorted($result, $indent);
$fail = false;
if($expect === $result)
{
$line = 'PASS';
} }
else else {
{ $pass = deep_compare($expect, $result);
$line = 'FAIL';
$fail = true;
} }
echo "$line$eol"; if($pass) {
if($fail) $this->passed += 1;
{ echo "PASS$eol";
}
else {
$this->failed += 1;
echo "FAIL$eol";
echo 'Expect: ' . print_r($expect, true) . $eol; echo 'Expect: ' . print_r($expect, true) . $eol;
echo 'Result: ' . print_r($result, true) . $eol; echo 'Result: ' . print_r($result, true) . $eol;
/* /*
$flags = JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT; $flags = JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT;
echo 'Legible Expect: ' . echo 'JSON Expect: ' .
json_encode(json_decode(expect, $flags)) . $eol; json_encode(json_decode(expect, $flags)) . $eol;
echo 'Legible Result: ' . echo 'JSON Result: ' .
json_encode(json_decode(result, $flags)) . $eol; json_encode(json_decode(result, $flags)) . $eol;
*/ */
@ -189,8 +160,7 @@ class TestRunner
} }
} }
public function load($filepath) public function load($filepath) {
{
global $eol; global $eol;
$manifests = array(); $manifests = array();
@ -201,10 +171,8 @@ class TestRunner
// read each test file from the directory // read each test file from the directory
$files = array(); $files = array();
$handle = opendir($filepath); $handle = opendir($filepath);
if($handle) if($handle) {
{ while(($file = readdir($handle)) !== false) {
while(($file = readdir($handle)) !== false)
{
if($file !== '..' and $file !== '.') if($file !== '..' and $file !== '.')
{ {
$files[] = $filepath . '/' . $file; $files[] = $filepath . '/' . $file;
@ -212,26 +180,21 @@ class TestRunner
} }
closedir($handle); closedir($handle);
} }
else else {
{
throw new Exception('Could not open directory.'); throw new Exception('Could not open directory.');
} }
foreach($files as $file) foreach($files as $file) {
{
$info = pathinfo($file); $info = pathinfo($file);
// FIXME: hackish, manifests are now JSON-LD // FIXME: hackish, manifests are now JSON-LD
if(strstr($info['basename'], 'manifest') !== false and if(strstr($info['basename'], 'manifest') !== false &&
$info['extension'] == 'jsonld') $info['extension'] == 'jsonld') {
{
echo "Reading manifest file: '$file'$eol"; echo "Reading manifest file: '$file'$eol";
try try {
{
$manifest = json_decode(file_get_contents($file)); $manifest = json_decode(file_get_contents($file));
} }
catch(Exception $e) catch(Exception $e) {
{
echo "Exception while parsing file: '$file'$eol"; echo "Exception while parsing file: '$file'$eol";
throw $e; throw $e;
} }
@ -242,14 +205,11 @@ class TestRunner
} }
echo count($manifests) . " manifest file(s) read.$eol"; echo count($manifests) . " manifest file(s) read.$eol";
return $manifests; return $manifests;
} }
public function run($manifests) public function run($manifests) {
{ /* Manifest format: {
/* Manifest format:
{
name: <optional manifest name>, name: <optional manifest name>,
sequence: [{ sequence: [{
'name': <test name>, 'name': <test name>,
@ -262,63 +222,65 @@ class TestRunner
} }
*/ */
global $eol; global $eol;
foreach($manifests as $manifest) {
foreach($manifests as $manifest)
{
$this->group($manifest->name); $this->group($manifest->name);
$filepath = $manifest->filepath; $filepath = $manifest->filepath;
foreach($manifest->sequence as $test) {
foreach($manifest->sequence as $test)
{
// read test input files // read test input files
$indent = 2;
$type = $test->{'@type'}; $type = $test->{'@type'};
if(in_array('jld:NormalizeTest', $type)) $options = array(
{ 'base' => 'http://json-ld.org/test-suite/tests/' . $test->input);
$indent = 0; if(in_array('jld:NormalizeTest', $type)) {
$input = _readTestJson($test->input, $filepath); $this->test($test->name);
$test->expect = _readTestJson($test->expect, $filepath); $input = read_test_json($test->input, $filepath);
$result = jsonld_normalize($input); $test->expect = read_test_json($test->expect, $filepath);
$result = jsonld_normalize($input, $options);
} }
else if(in_array('jld:ExpandTest', $type)) else if(in_array('jld:ExpandTest', $type)) {
{ $this->test($test->name);
$input = _readTestJson($test->input, $filepath); $input = read_test_json($test->input, $filepath);
$test->expect = _readTestJson($test->expect, $filepath); $test->expect = read_test_json($test->expect, $filepath);
$result = jsonld_expand($input); $result = jsonld_expand($input, $options);
} }
else if(in_array('jld:CompactTest', $type)) else if(in_array('jld:CompactTest', $type)) {
{ $this->test($test->name);
$input = _readTestJson($test->input, $filepath); $input = read_test_json($test->input, $filepath);
$test->context = _readTestJson($test->context, $filepath); $test->context = read_test_json($test->context, $filepath);
$test->expect = _readTestJson($test->expect, $filepath); $test->expect = read_test_json($test->expect, $filepath);
$result = jsonld_compact($test->context->{'@context'}, $input); $result = jsonld_compact($input, $test->context, $options);
} }
else if(in_array('jld:FrameTest', $type)) else if(in_array('jld:FrameTest', $type)) {
{ $this->test($test->name);
$input = _readTestJson($test->input, $filepath); $input = read_test_json($test->input, $filepath);
$test->frame = _readTestJson($test->frame, $filepath); $test->frame = read_test_json($test->frame, $filepath);
$test->expect = _readTestJson($test->expect, $filepath); $test->expect = read_test_json($test->expect, $filepath);
$result = jsonld_frame($input, $test->frame); $result = jsonld_frame($input, $test->frame, $options);
} }
else else {
{ echo "Skipping test \"{$test->name}\" of type: " .
echo 'Skipping test "' . $test->name . '" of type: ' .
json_encode($type) . $eol; json_encode($type) . $eol;
continue; continue;
} }
// check results (only indent output on non-normalize tests) // check results
$this->test($test->name); $this->check($test, $test->expect, $result);
$this->check($test->expect, $result, $indent);
} }
} }
} }
} }
// get command line options
$options = getopt('d:');
if($options === false || !array_key_exists('d', $options)) {
$var = 'path to json-ld.org/test-suite/tests';
echo "Usage: php jsonld-tests.php -d <$var>$eol";
exit(0);
}
// load and run tests // load and run tests
$tr = new TestRunner(); $tr = new TestRunner();
$tr->group('JSON-LD'); $tr->group('JSON-LD');
$tr->run($tr->load('tests')); $tr->run($tr->load($options['d']));
$tr->ungroup(); $tr->ungroup();
echo "All tests complete.$eol"; echo "All tests complete.$eol";

5877
jsonld.php

File diff suppressed because it is too large Load diff