updated-packages

This commit is contained in:
RafficMohammed
2023-01-08 00:13:22 +05:30
parent 3ff7df7487
commit da241bacb6
12659 changed files with 563377 additions and 510538 deletions

View File

@@ -1,5 +0,0 @@
vendor
composer.lock
phpunit.xml
compiled
artifacts/

View File

@@ -1,17 +0,0 @@
language: php
php:
- 5.4
- 5.5
- 5.6
- hhvm
before_script:
- composer install
script: make test
after_script:
- make perf
- JP_PHP_COMPILE=on make perf
- JP_PHP_COMPILE=on CACHE=on make perf

View File

@@ -1,5 +1,15 @@
# CHANGELOG
## 2.6.0 - 2020-07-31
* Support for PHP 8.0.
## 2.5.0 - 2019-12-30
* Full support for PHP 7.0-7.4.
* Fixed autoloading when run from within vendor folder.
* Full multibyte (UTF-8) string support.
## 2.4.0 - 2016-12-03
* Added support for floats when interpreting data.

View File

@@ -1,19 +0,0 @@
all: clean coverage
test:
vendor/bin/phpunit
coverage:
vendor/bin/phpunit --coverage-html=artifacts/coverage
view-coverage:
open artifacts/coverage/index.html
clean:
rm -rf artifacts/*
rm -rf compiled/*
perf:
php bin/perf.php
.PHONY: test coverage perf

11
vendor/mtdowling/jmespath.php/bin/jp.php vendored Normal file → Executable file
View File

@@ -1,6 +1,15 @@
#!/usr/bin/env php
<?php
require __DIR__ . '/../vendor/autoload.php';
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
require __DIR__ . '/../vendor/autoload.php';
} elseif (file_exists(__DIR__ . '/../../../autoload.php')) {
require __DIR__ . '/../../../autoload.php';
} elseif (file_exists(__DIR__ . '/../autoload.php')) {
require __DIR__ . '/../autoload.php';
} else {
throw new RuntimeException('Unable to locate autoload.php file.');
}
use JmesPath\Env;
use JmesPath\DebugRuntime;

13
vendor/mtdowling/jmespath.php/bin/perf.php vendored Normal file → Executable file
View File

@@ -1,6 +1,17 @@
#!/usr/bin/env php
<?php
require __DIR__ . '/../vendor/autoload.php';
if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
require __DIR__ . '/../vendor/autoload.php';
} elseif (file_exists(__DIR__ . '/../../../autoload.php')) {
require __DIR__ . '/../../../autoload.php';
} else {
throw new RuntimeException('Unable to locate autoload.php file.');
}
$xdebug = new \Composer\XdebugHandler\XdebugHandler('perf.php');
$xdebug->check();
unset($xdebug);
$dir = isset($argv[1]) ? $argv[1] : __DIR__ . '/../tests/compliance/perf';
is_dir($dir) or die('Dir not found: ' . $dir);

View File

@@ -13,11 +13,13 @@
],
"require": {
"php": ">=5.4.0"
"php": "^5.4 || ^7.0 || ^8.0",
"symfony/polyfill-mbstring": "^1.17"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
"composer/xdebug-handler": "^1.4 || ^2.0",
"phpunit/phpunit": "^4.8.36 || ^7.5.15"
},
"autoload": {
@@ -31,7 +33,7 @@
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
"dev-master": "2.6-dev"
}
}
}

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./vendor/autoload.php"
colors="true">
<testsuites>
<testsuite>
<directory>tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -29,7 +29,7 @@ class AstRuntime
* is similar to data returned from json_decode
* using associative arrays rather than objects.
*
* @return mixed|null Returns the matching data or null
* @return mixed Returns the matching data or null
*/
public function __invoke($expression, $data)
{

View File

@@ -19,8 +19,8 @@ class CompilerRuntime
private $interpreter;
/**
* @param string $dir Directory used to store compiled PHP files.
* @param Parser $parser JMESPath parser to utilize
* @param string|null $dir Directory used to store compiled PHP files.
* @param Parser|null $parser JMESPath parser to utilize
* @throws \RuntimeException if the cache directory cannot be created
*/
public function __construct($dir = null, Parser $parser = null)
@@ -46,7 +46,7 @@ class CompilerRuntime
* is similar to data returned from json_decode
* using associative arrays rather than objects.
*
* @return mixed|null Returns the matching data or null
* @return mixed Returns the matching data or null
* @throws \RuntimeException
*/
public function __invoke($expression, $data)

View File

@@ -20,14 +20,16 @@ final class Env
* @param string $expression JMESPath expression to evaluate
* @param mixed $data JSON-like data to search
*
* @return mixed|null Returns the matching data or null
* @return mixed Returns the matching data or null
*/
public static function search($expression, $data)
{
static $runtime;
if (!$runtime) {
$runtime = Env::createRuntime();
}
return $runtime($expression, $data);
}
@@ -39,7 +41,7 @@ final class Env
*/
public static function createRuntime()
{
switch ($compileDir = getenv(self::COMPILE_DIR)) {
switch ($compileDir = self::getEnvVariable(self::COMPILE_DIR)) {
case false: return new AstRuntime();
case 'on': return new CompilerRuntime();
default: return new CompilerRuntime($compileDir);
@@ -55,7 +57,8 @@ final class Env
public static function cleanCompileDir()
{
$total = 0;
$compileDir = getenv(self::COMPILE_DIR) ?: sys_get_temp_dir();
$compileDir = self::getEnvVariable(self::COMPILE_DIR) ?: sys_get_temp_dir();
foreach (glob("{$compileDir}/jmespath_*.php") as $file) {
$total++;
unlink($file);
@@ -63,4 +66,26 @@ final class Env
return $total;
}
/**
* Reads an environment variable from $_SERVER, $_ENV or via getenv().
*
* @param string $name
*
* @return string|null
*/
private static function getEnvVariable($name)
{
if (array_key_exists($name, $_SERVER)) {
return $_SERVER[$name];
}
if (array_key_exists($name, $_ENV)) {
return $_ENV[$name];
}
$value = getenv($name);
return $value === false ? null : $value;
}
}

View File

@@ -45,7 +45,7 @@ class FnDispatcher
{
$this->validate('avg', $args, [['array']]);
$sum = $this->reduce('avg:0', $args[0], ['number'], function ($a, $b) {
return $a + $b;
return Utils::add($a, $b);
});
return $args[0] ? ($sum / count($args[0])) : null;
}
@@ -62,7 +62,7 @@ class FnDispatcher
if (is_array($args[0])) {
return in_array($args[1], $args[0]);
} elseif (is_string($args[1])) {
return strpos($args[0], $args[1]) !== false;
return mb_strpos($args[0], $args[1], 0, 'UTF-8') !== false;
} else {
return null;
}
@@ -72,7 +72,7 @@ class FnDispatcher
{
$this->validate('ends_with', $args, [['string'], ['string']]);
list($search, $suffix) = $args;
return $suffix === '' || substr($search, -strlen($suffix)) === $suffix;
return $suffix === '' || mb_substr($search, -mb_strlen($suffix, 'UTF-8'), null, 'UTF-8') === $suffix;
}
private function fn_floor(array $args)
@@ -112,13 +112,15 @@ class FnDispatcher
private function fn_length(array $args)
{
$this->validate('length', $args, [['string', 'array', 'object']]);
return is_string($args[0]) ? strlen($args[0]) : count((array) $args[0]);
return is_string($args[0]) ? mb_strlen($args[0], 'UTF-8') : count((array) $args[0]);
}
private function fn_max(array $args)
{
$this->validate('max', $args, [['array']]);
$fn = function ($a, $b) { return $a >= $b ? $a : $b; };
$fn = function ($a, $b) {
return $a >= $b ? $a : $b;
};
return $this->reduce('max:0', $args[0], ['number', 'string'], $fn);
}
@@ -137,7 +139,9 @@ class FnDispatcher
private function fn_min(array $args)
{
$this->validate('min', $args, [['array']]);
$fn = function ($a, $b, $i) { return $i && $a <= $b ? $a : $b; };
$fn = function ($a, $b, $i) {
return $i && $a <= $b ? $a : $b;
};
return $this->reduce('min:0', $args[0], ['number', 'string'], $fn);
}
@@ -167,7 +171,9 @@ class FnDispatcher
private function fn_sum(array $args)
{
$this->validate('sum', $args, [['array']]);
$fn = function ($a, $b) { return $a + $b; };
$fn = function ($a, $b) {
return Utils::add($a, $b);
};
return $this->reduce('sum:0', $args[0], ['number'], $fn);
}
@@ -201,7 +207,7 @@ class FnDispatcher
{
$this->validate('starts_with', $args, [['string'], ['string']]);
list($search, $prefix) = $args;
return $prefix === '' || strpos($search, $prefix) === 0;
return $prefix === '' || mb_strpos($search, $prefix, 0, 'UTF-8') === 0;
}
private function fn_type(array $args)
@@ -234,7 +240,7 @@ class FnDispatcher
if ($type == 'number') {
return $value;
} elseif ($type == 'string' && is_numeric($value)) {
return strpos($value, '.') ? (float) $value : (int) $value;
return mb_strpos($value, '.', 0, 'UTF-8') ? (float) $value : (int) $value;
} else {
return null;
}
@@ -276,7 +282,7 @@ class FnDispatcher
private function typeError($from, $msg)
{
if (strpos($from, ':')) {
if (mb_strpos($from, ':', 0, 'UTF-8')) {
list($fn, $pos) = explode(':', $from);
throw new \RuntimeException(
sprintf('Argument %d of %s %s', $pos, $fn, $msg)

View File

@@ -7,7 +7,7 @@ namespace JmesPath;
* @param string $expression Expression to search.
* @param mixed $data Data to search.
*
* @return mixed|null
* @return mixed
*/
if (!function_exists(__NAMESPACE__ . '\search')) {
function search($expression, $data)

View File

@@ -340,7 +340,7 @@ class Lexer
eof:
$tokens[] = [
'type' => self::T_EOF,
'pos' => strlen($input),
'pos' => mb_strlen($input, 'UTF-8'),
'value' => null
];

View File

@@ -55,7 +55,7 @@ class Parser
];
/**
* @param Lexer $lexer Lexer used to tokenize expressions
* @param Lexer|null $lexer Lexer used to tokenize expressions
*/
public function __construct(Lexer $lexer = null)
{
@@ -142,7 +142,8 @@ class Parser
return ['type' => T::T_NOT, 'children' => [$this->expr(self::$bp[T::T_NOT])]];
}
private function nud_lparen() {
private function nud_lparen()
{
$this->next();
$result = $this->expr(0);
if ($this->token['type'] !== T::T_RPAREN) {

View File

@@ -17,7 +17,7 @@ class SyntaxErrorException extends \InvalidArgumentException
$expression
) {
$message = "Syntax error at character {$token['pos']}\n"
. $expression . "\n" . str_repeat(' ', $token['pos']) . "^\n";
. $expression . "\n" . str_repeat(' ', max($token['pos'], 0)) . "^\n";
$message .= !is_array($expectedTypesOrMessage)
? $expectedTypesOrMessage
: $this->createTokenMessage($token, $expectedTypesOrMessage);

View File

@@ -23,7 +23,7 @@ class TreeCompiler
$this->source = $this->indentation = '';
$this->write("<?php\n")
->write('use JmesPath\\TreeInterpreter as Ti;')
->write('use JmesPath\\FnDispatcher as Fn;')
->write('use JmesPath\\FnDispatcher as Fd;')
->write('use JmesPath\\Utils;')
->write('')
->write('function %s(Ti $interpreter, $value) {', $fnName)
@@ -257,7 +257,7 @@ class TreeCompiler
}
return $this->write(
'$value = Fn::getInstance()->__invoke("%s", %s);',
'$value = Fd::getInstance()->__invoke("%s", %s);',
$node['value'], $args
);
}

View File

@@ -10,9 +10,9 @@ class TreeInterpreter
private $fnDispatcher;
/**
* @param callable $fnDispatcher Function dispatching function that accepts
* a function name argument and an array of
* function arguments and returns the result.
* @param callable|null $fnDispatcher Function dispatching function that accepts
* a function name argument and an array of
* function arguments and returns the result.
*/
public function __construct(callable $fnDispatcher = null)
{

View File

@@ -3,7 +3,7 @@ namespace JmesPath;
class Utils
{
static $typeMap = [
public static $typeMap = [
'boolean' => 'boolean',
'string' => 'string',
'NULL' => 'null',
@@ -126,6 +126,31 @@ class Utils
}
}
/**
* Safely add together two values.
*
* @param mixed $a First value to add
* @param mixed $b Second value to add
*
* @return int|float
*/
public static function add($a, $b)
{
if (is_numeric($a)) {
if (is_numeric($b)) {
return $a + $b;
} else {
return $a;
}
} else {
if (is_numeric($b)) {
return $b;
} else {
return 0;
}
}
}
/**
* JMESPath requires a stable sorting algorithm, so here we'll implement
* a simple Schwartzian transform that uses array index positions as tie
@@ -140,14 +165,18 @@ class Utils
public static function stableSort(array $data, callable $sortFn)
{
// Decorate each item by creating an array of [value, index]
array_walk($data, function (&$v, $k) { $v = [$v, $k]; });
array_walk($data, function (&$v, $k) {
$v = [$v, $k];
});
// Sort by the sort function and use the index as a tie-breaker
uasort($data, function ($a, $b) use ($sortFn) {
return $sortFn($a[0], $b[0]) ?: ($a[1] < $b[1] ? -1 : 1);
});
// Undecorate each item and return the resulting sorted array
return array_map(function ($v) { return $v[0]; }, array_values($data));
return array_map(function ($v) {
return $v[0];
}, array_values($data));
}
/**
@@ -210,7 +239,7 @@ class Utils
private static function sliceIndices($subject, $start, $stop, $step)
{
$type = gettype($subject);
$len = $type == 'string' ? strlen($subject) : count($subject);
$len = $type == 'string' ? mb_strlen($subject, 'UTF-8') : count($subject);
list($start, $stop, $step) = self::adjustSlice($len, $start, $stop, $step);
$result = [];
@@ -224,6 +253,6 @@ class Utils
}
}
return $type == 'string' ? implode($result, '') : $result;
return $type == 'string' ? implode('', $result) : $result;
}
}

View File

@@ -1,136 +0,0 @@
<?php
namespace JmesPath\Tests;
use JmesPath\AstRuntime;
use JmesPath\CompilerRuntime;
use JmesPath\SyntaxErrorException;
class ComplianceTest extends \PHPUnit_Framework_TestCase
{
private static $path;
public static function setUpBeforeClass()
{
self::$path = __DIR__ . '/../../compiled';
array_map('unlink', glob(self::$path . '/jmespath_*.php'));
}
public static function tearDownAfterClass()
{
array_map('unlink', glob(self::$path . '/jmespath_*.php'));
}
/**
* @dataProvider complianceProvider
*/
public function testPassesCompliance(
$data,
$expression,
$result,
$error,
$file,
$suite,
$case,
$compiled,
$asAssoc
) {
$evalResult = null;
$failed = false;
$failureMsg = '';
$failure = '';
$compiledStr = '';
try {
if ($compiled) {
$compiledStr = \JmesPath\Env::COMPILE_DIR . '=on ';
$runtime = new CompilerRuntime(self::$path);
} else {
$runtime = new AstRuntime();
}
$evalResult = $runtime($expression, $data);
} catch (\Exception $e) {
$failed = $e instanceof SyntaxErrorException ? 'syntax' : 'runtime';
$failureMsg = sprintf(
'%s (%s line %d)',
$e->getMessage(),
$e->getFile(),
$e->getLine()
);
}
$file = __DIR__ . '/compliance/' . $file . '.json';
$failure .= "\n{$compiledStr}php bin/jp.php --file {$file} --suite {$suite} --case {$case}\n\n"
. "Expected: " . $this->prettyJson($result) . "\n\n";
$failure .= 'Associative? ' . var_export($asAssoc, true) . "\n\n";
if (!$error && $failed) {
$this->fail("Should not have failed\n{$failure}=> {$failed} {$failureMsg}");
} elseif ($error && !$failed) {
$this->fail("Should have failed\n{$failure}");
}
$this->assertEquals(
$this->convertAssoc($result),
$this->convertAssoc($evalResult),
$failure
);
}
public function complianceProvider()
{
$cases = [];
$files = array_map(function ($f) {
return basename($f, '.json');
}, glob(__DIR__ . '/compliance/*.json'));
foreach ($files as $name) {
$contents = file_get_contents(__DIR__ . "/compliance/{$name}.json");
foreach ([true, false] as $asAssoc) {
$json = json_decode($contents, true);
$jsonObj = json_decode($contents);
foreach ($json as $suiteNumber => $suite) {
$given = $asAssoc ? $suite['given'] : $jsonObj[$suiteNumber]->given;
foreach ($suite['cases'] as $caseNumber => $case) {
$caseData = [
$given,
$case['expression'],
isset($case['result']) ? $case['result'] : null,
isset($case['error']) ? $case['error'] : false,
$name,
$suiteNumber,
$caseNumber,
false,
$asAssoc
];
$cases[] = $caseData;
$caseData[7] = true;
$cases[] = $caseData;
}
}
}
}
return $cases;
}
private function convertAssoc($data)
{
if ($data instanceof \stdClass) {
return $this->convertAssoc((array) $data);
} elseif (is_array($data)) {
return array_map([$this, 'convertAssoc'], $data);
} else {
return $data;
}
}
private function prettyJson($json)
{
if (defined('JSON_PRETTY_PRINT')) {
return json_encode($json, JSON_PRETTY_PRINT);
}
return json_encode($json);
}
}

View File

@@ -1,31 +0,0 @@
<?php
namespace JmesPath\Tests;
use JmesPath\Env;
use JmesPath\CompilerRuntime;
class EnvTest extends \PHPUnit_Framework_TestCase
{
public function testSearchesInput()
{
$data = array('foo' => 123);
$this->assertEquals(123, Env::search('foo', $data));
$this->assertEquals(123, Env::search('foo', $data));
}
public function testSearchesWithFunction()
{
$data = array('foo' => 123);
$this->assertEquals(123, \JmesPath\search('foo', $data));
}
public function testCleansCompileDir()
{
$dir = sys_get_temp_dir();
$runtime = new CompilerRuntime($dir);
$runtime('@ | @ | @[0][0][0]', []);
$this->assertNotEmpty(glob($dir . '/jmespath_*.php'));
$this->assertGreaterThan(0, Env::cleanCompileDir());
$this->assertEmpty(glob($dir . '/jmespath_*.php'));
}
}

View File

@@ -1,41 +0,0 @@
<?php
namespace JmesPath\Tests;
use JmesPath\FnDispatcher;
class FnDispatcherTest extends \PHPUnit_Framework_TestCase
{
public function testConvertsToString()
{
$fn = new FnDispatcher();
$this->assertEquals('foo', $fn('to_string', ['foo']));
$this->assertEquals('1', $fn('to_string', [1]));
$this->assertEquals('["foo"]', $fn('to_string', [['foo']]));
$std = new \stdClass();
$std->foo = 'bar';
$this->assertEquals('{"foo":"bar"}', $fn('to_string', [$std]));
$this->assertEquals('foo', $fn('to_string', [new _TestStringClass()]));
$this->assertEquals('"foo"', $fn('to_string', [new _TestJsonStringClass()]));
}
}
class _TestStringClass
{
public function __toString()
{
return 'foo';
}
}
class _TestJsonStringClass implements \JsonSerializable
{
public function __toString()
{
return 'no!';
}
public function jsonSerialize()
{
return 'foo';
}
}

View File

@@ -1,88 +0,0 @@
<?php
namespace JmesPath\Tests;
use JmesPath\Lexer;
use JmesPath\SyntaxErrorException;
/**
* @covers JmesPath\Lexer
*/
class LexerTest extends \PHPUnit_Framework_TestCase
{
public function inputProvider()
{
return array(
array('0', 'number'),
array('1', 'number'),
array('2', 'number'),
array('3', 'number'),
array('4', 'number'),
array('5', 'number'),
array('6', 'number'),
array('7', 'number'),
array('8', 'number'),
array('9', 'number'),
array('-1', 'number'),
array('-1.5', 'number'),
array('109.5', 'number'),
array('.', 'dot'),
array('{', 'lbrace'),
array('}', 'rbrace'),
array('[', 'lbracket'),
array(']', 'rbracket'),
array(':', 'colon'),
array(',', 'comma'),
array('||', 'or'),
array('*', 'star'),
array('foo', 'identifier'),
array('"foo"', 'quoted_identifier'),
array('`true`', 'literal'),
array('`false`', 'literal'),
array('`null`', 'literal'),
array('`"true"`', 'literal')
);
}
/**
* @dataProvider inputProvider
*/
public function testTokenizesInput($input, $type)
{
$l = new Lexer();
$tokens = $l->tokenize($input);
$this->assertEquals($tokens[0]['type'], $type);
}
public function testTokenizesJsonLiterals()
{
$l = new Lexer();
$tokens = $l->tokenize('`null`, `false`, `true`, `"abc"`, `"ab\\"c"`,'
. '`0`, `0.45`, `-0.5`');
$this->assertNull($tokens[0]['value']);
$this->assertFalse($tokens[2]['value']);
$this->assertTrue($tokens[4]['value']);
$this->assertEquals('abc', $tokens[6]['value']);
$this->assertEquals('ab"c', $tokens[8]['value']);
$this->assertSame(0, $tokens[10]['value']);
$this->assertSame(0.45, $tokens[12]['value']);
$this->assertSame(-0.5, $tokens[14]['value']);
}
public function testTokenizesJsonNumbers()
{
$l = new Lexer();
$tokens = $l->tokenize('`10`, `1.2`, `-10.20e-10`, `1.2E+2`');
$this->assertEquals(10, $tokens[0]['value']);
$this->assertEquals(1.2, $tokens[2]['value']);
$this->assertEquals(-1.02E-9, $tokens[4]['value']);
$this->assertEquals(120, $tokens[6]['value']);
}
public function testCanWorkWithElidedJsonLiterals()
{
$l = new Lexer();
$tokens = $l->tokenize('`foo`');
$this->assertEquals('foo', $tokens[0]['value']);
$this->assertEquals('literal', $tokens[0]['type']);
}
}

View File

@@ -1,50 +0,0 @@
<?php
namespace JmesPath\Tests;
use JmesPath\Lexer;
use JmesPath\Parser;
/**
* @covers JmesPath\Parser
*/
class ParserTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException \JmesPath\SyntaxErrorException
* @expectedExceptionMessage Syntax error at character 0
*/
public function testMatchesFirstTokens()
{
$p = new Parser(new Lexer());
$p->parse('.bar');
}
/**
* @expectedException \JmesPath\SyntaxErrorException
* @expectedExceptionMessage Syntax error at character 1
*/
public function testThrowsSyntaxErrorForInvalidSequence()
{
$p = new Parser(new Lexer());
$p->parse('a,');
}
/**
* @expectedException \JmesPath\SyntaxErrorException
* @expectedExceptionMessage Syntax error at character 2
*/
public function testMatchesAfterFirstToken()
{
$p = new Parser(new Lexer());
$p->parse('a.,');
}
/**
* @expectedException \JmesPath\SyntaxErrorException
* @expectedExceptionMessage Unexpected "eof" token
*/
public function testHandlesEmptyExpressions()
{
(new Parser(new Lexer()))->parse('');
}
}

View File

@@ -1,42 +0,0 @@
<?php
namespace JmesPath\Tests;
use JmesPath\SyntaxErrorException;
/**
* @covers JmesPath\SyntaxErrorException
*/
class SyntaxErrorExceptionTest extends \PHPUnit_Framework_TestCase
{
public function testCreatesWithNoArray()
{
$e = new SyntaxErrorException(
'Found comma',
['type' => 'comma', 'pos' => 3, 'value' => ','],
'abc,def'
);
$expected = <<<EOT
Syntax error at character 3
abc,def
^
Found comma
EOT;
$this->assertContains($expected, $e->getMessage());
}
public function testCreatesWithArray()
{
$e = new SyntaxErrorException(
['dot' => true, 'eof' => true],
['type' => 'comma', 'pos' => 3, 'value' => ','],
'abc,def'
);
$expected = <<<EOT
Syntax error at character 3
abc,def
^
Expected one of the following: dot, eof; found comma ","
EOT;
$this->assertContains($expected, $e->getMessage());
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace JmesPath\Tests\Tree;
use JmesPath\TreeCompiler;
/**
* @covers JmesPath\Tree\TreeCompiler
*/
class TreeCompilerTest extends \PHPUnit_Framework_TestCase
{
public function testCreatesSourceCode()
{
$t = new TreeCompiler();
$source = $t->visit(
['type' => 'field', 'value' => 'foo'],
'testing',
'foo'
);
$this->assertContains('<?php', $source);
$this->assertContains('$value = isset($value->{\'foo\'}) ? $value->{\'foo\'} : null;', $source);
$this->assertContains('$value = isset($value[\'foo\']) ? $value[\'foo\'] : null;', $source);
}
}

View File

@@ -1,71 +0,0 @@
<?php
namespace JmesPath\Tests\Tree;
use JmesPath\AstRuntime;
use JmesPath\TreeInterpreter;
/**
* @covers JmesPath\Tree\TreeInterpreter
*/
class TreeInterpreterTest extends \PHPUnit_Framework_TestCase
{
public function testReturnsNullWhenMergingNonArray()
{
$t = new TreeInterpreter();
$this->assertNull($t->visit(array(
'type' => 'flatten',
'children' => array(
array('type' => 'literal', 'value' => 1),
array('type' => 'literal', 'value' => 1)
)
), array(), array(
'runtime' => new AstRuntime()
)));
}
public function testWorksWithArrayObjectAsObject()
{
$runtime = new AstRuntime();
$this->assertEquals('baz', $runtime('foo.bar', new \ArrayObject([
'foo' => new \ArrayObject(['bar' => 'baz'])
])));
}
public function testWorksWithArrayObjectAsArray()
{
$runtime = new AstRuntime();
$this->assertEquals('baz', $runtime('foo[0].bar', new \ArrayObject([
'foo' => new \ArrayObject([new \ArrayObject(['bar' => 'baz'])])
])));
}
public function testWorksWithArrayProjections()
{
$runtime = new AstRuntime();
$this->assertEquals(
['baz'],
$runtime('foo[*].bar', new \ArrayObject([
'foo' => new \ArrayObject([
new \ArrayObject([
'bar' => 'baz'
])
])
]))
);
}
public function testWorksWithObjectProjections()
{
$runtime = new AstRuntime();
$this->assertEquals(
['baz'],
$runtime('foo.*.bar', new \ArrayObject([
'foo' => new \ArrayObject([
'abc' => new \ArrayObject([
'bar' => 'baz'
])
])
]))
);
}
}

View File

@@ -1,130 +0,0 @@
<?php
namespace JmesPath\Tests;
use JmesPath\Utils;
class UtilsTest extends \PHPUnit_Framework_TestCase
{
public function typeProvider()
{
return [
['a', 'string'],
[10, 'number'],
[1.0, 'number'],
[true, 'boolean'],
[false, 'boolean'],
[[], 'array'],
[[1, 2], 'array'],
[['a' => 1], 'object'],
[new \stdClass(), 'object'],
[function () {}, 'expression'],
[new \ArrayObject(), 'array'],
[new \ArrayObject([1, 2]), 'array'],
[new \ArrayObject(['foo' => 'bar']), 'object'],
[new _TestStr(), 'string']
];
}
/**
* @dataProvider typeProvider
*/
public function testGetsTypes($given, $type)
{
$this->assertEquals($type, Utils::type($given));
}
/**
* @expectedException \InvalidArgumentException
*/
public function testThrowsForInvalidArg()
{
Utils::type(new _TestClass());
}
public function isArrayProvider()
{
return [
[[], true],
[[1, 2], true],
[['a' => 1], false],
[new _TestClass(), false],
[new \ArrayObject(['a' => 'b']), false],
[new \ArrayObject([1]), true],
[new \stdClass(), false]
];
}
/**
* @dataProvider isArrayProvider
*/
public function testChecksIfArray($given, $result)
{
$this->assertSame($result, Utils::isArray($given));
}
public function isObjectProvider()
{
return [
[[], true],
[[1, 2], false],
[['a' => 1], true],
[new _TestClass(), false],
[new \ArrayObject(['a' => 'b']), true],
[new \ArrayObject([1]), false],
[new \stdClass(), true]
];
}
/**
* @dataProvider isObjectProvider
*/
public function testChecksIfObject($given, $result)
{
$this->assertSame($result, Utils::isObject($given));
}
public function testHasStableSort()
{
$data = [new _TestStr(), new _TestStr(), 0, 10, 2];
$result = Utils::stableSort($data, function ($a, $b) {
$a = (int) (string) $a;
$b = (int) (string) $b;
return $a > $b ? -1 : ($a == $b ? 0 : 1);
});
$this->assertSame($data[0], $result[0]);
$this->assertSame($data[1], $result[1]);
$this->assertEquals(10, $result[2]);
$this->assertEquals(2, $result[3]);
$this->assertEquals(0, $result[4]);
}
public function testSlicesArrays()
{
$this->assertEquals([3, 2, 1], Utils::slice([1, 2, 3], null, null, -1));
$this->assertEquals([1, 3], Utils::slice([1, 2, 3], null, null, 2));
$this->assertEquals([2, 3], Utils::slice([1, 2, 3], 1));
}
public function testSlicesStrings()
{
$this->assertEquals('cba', Utils::slice('abc', null, null, -1));
$this->assertEquals('ac', Utils::slice('abc', null, null, 2));
$this->assertEquals('bc', Utils::slice('abc', 1));
}
}
class _TestClass implements \ArrayAccess
{
public function offsetExists($offset) {}
public function offsetGet($offset) {}
public function offsetSet($offset, $value) {}
public function offsetUnset($offset) {}
}
class _TestStr
{
public function __toString()
{
return '100';
}
}

View File

@@ -1,96 +0,0 @@
[{
"given":
{"foo": {"bar": {"baz": "correct"}}},
"cases": [
{
"expression": "foo",
"result": {"bar": {"baz": "correct"}}
},
{
"expression": "foo.bar",
"result": {"baz": "correct"}
},
{
"expression": "foo.bar.baz",
"result": "correct"
},
{
"expression": "foo\n.\nbar\n.baz",
"result": "correct"
},
{
"expression": "foo.bar.baz.bad",
"result": null
},
{
"expression": "foo.bar.bad",
"result": null
},
{
"expression": "foo.bad",
"result": null
},
{
"expression": "bad",
"result": null
},
{
"expression": "bad.morebad.morebad",
"result": null
}
]
},
{
"given":
{"foo": {"bar": ["one", "two", "three"]}},
"cases": [
{
"expression": "foo",
"result": {"bar": ["one", "two", "three"]}
},
{
"expression": "foo.bar",
"result": ["one", "two", "three"]
}
]
},
{
"given": ["one", "two", "three"],
"cases": [
{
"expression": "one",
"result": null
},
{
"expression": "two",
"result": null
},
{
"expression": "three",
"result": null
},
{
"expression": "one.two",
"result": null
}
]
},
{
"given":
{"foo": {"1": ["one", "two", "three"], "-1": "bar"}},
"cases": [
{
"expression": "foo.\"1\"",
"result": ["one", "two", "three"]
},
{
"expression": "foo.\"1\"[0]",
"result": "one"
},
{
"expression": "foo.\"-1\"",
"result": "bar"
}
]
}
]

View File

@@ -1,257 +0,0 @@
[
{
"given": {
"outer": {
"foo": "foo",
"bar": "bar",
"baz": "baz"
}
},
"cases": [
{
"expression": "outer.foo || outer.bar",
"result": "foo"
},
{
"expression": "outer.foo||outer.bar",
"result": "foo"
},
{
"expression": "outer.bar || outer.baz",
"result": "bar"
},
{
"expression": "outer.bar||outer.baz",
"result": "bar"
},
{
"expression": "outer.bad || outer.foo",
"result": "foo"
},
{
"expression": "outer.bad||outer.foo",
"result": "foo"
},
{
"expression": "outer.foo || outer.bad",
"result": "foo"
},
{
"expression": "outer.foo||outer.bad",
"result": "foo"
},
{
"expression": "outer.bad || outer.alsobad",
"result": null
},
{
"expression": "outer.bad||outer.alsobad",
"result": null
}
]
},
{
"given": {
"outer": {
"foo": "foo",
"bool": false,
"empty_list": [],
"empty_string": ""
}
},
"cases": [
{
"expression": "outer.empty_string || outer.foo",
"result": "foo"
},
{
"expression": "outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo",
"result": "foo"
}
]
},
{
"given": {
"True": true,
"False": false,
"Number": 5,
"EmptyList": [],
"Zero": 0
},
"cases": [
{
"expression": "True && False",
"result": false
},
{
"expression": "False && True",
"result": false
},
{
"expression": "True && True",
"result": true
},
{
"expression": "False && False",
"result": false
},
{
"expression": "True && Number",
"result": 5
},
{
"expression": "Number && True",
"result": true
},
{
"expression": "Number && False",
"result": false
},
{
"expression": "Number && EmptyList",
"result": []
},
{
"expression": "Number && True",
"result": true
},
{
"expression": "EmptyList && True",
"result": []
},
{
"expression": "EmptyList && False",
"result": []
},
{
"expression": "True || False",
"result": true
},
{
"expression": "True || True",
"result": true
},
{
"expression": "False || True",
"result": true
},
{
"expression": "False || False",
"result": false
},
{
"expression": "Number || EmptyList",
"result": 5
},
{
"expression": "Number || True",
"result": 5
},
{
"expression": "Number || True && False",
"result": 5
},
{
"expression": "(Number || True) && False",
"result": false
},
{
"expression": "Number || (True && False)",
"result": 5
},
{
"expression": "!True",
"result": false
},
{
"expression": "!False",
"result": true
},
{
"expression": "!Number",
"result": false
},
{
"expression": "!EmptyList",
"result": true
},
{
"expression": "True && !False",
"result": true
},
{
"expression": "True && !EmptyList",
"result": true
},
{
"expression": "!False && !EmptyList",
"result": true
},
{
"expression": "!(True && False)",
"result": true
},
{
"expression": "!Zero",
"result": false
},
{
"expression": "!!Zero",
"result": true
}
]
},
{
"given": {
"one": 1,
"two": 2,
"three": 3
},
"cases": [
{
"expression": "one < two",
"result": true
},
{
"expression": "one <= two",
"result": true
},
{
"expression": "one == one",
"result": true
},
{
"expression": "one == two",
"result": false
},
{
"expression": "one > two",
"result": false
},
{
"expression": "one >= two",
"result": false
},
{
"expression": "one != two",
"result": true
},
{
"expression": "one < two && three > one",
"result": true
},
{
"expression": "one < two || three > one",
"result": true
},
{
"expression": "one < two || three < one",
"result": true
},
{
"expression": "two < one || three < one",
"result": false
}
]
}
]

View File

@@ -1,25 +0,0 @@
[
{
"given": {
"foo": [{"name": "a"}, {"name": "b"}],
"bar": {"baz": "qux"}
},
"cases": [
{
"expression": "@",
"result": {
"foo": [{"name": "a"}, {"name": "b"}],
"bar": {"baz": "qux"}
}
},
{
"expression": "@.bar",
"result": {"baz": "qux"}
},
{
"expression": "@.foo[0]",
"result": {"name": "a"}
}
]
}
]

View File

@@ -1,46 +0,0 @@
[{
"given": {
"foo.bar": "dot",
"foo bar": "space",
"foo\nbar": "newline",
"foo\"bar": "doublequote",
"c:\\\\windows\\path": "windows",
"/unix/path": "unix",
"\"\"\"": "threequotes",
"bar": {"baz": "qux"}
},
"cases": [
{
"expression": "\"foo.bar\"",
"result": "dot"
},
{
"expression": "\"foo bar\"",
"result": "space"
},
{
"expression": "\"foo\\nbar\"",
"result": "newline"
},
{
"expression": "\"foo\\\"bar\"",
"result": "doublequote"
},
{
"expression": "\"c:\\\\\\\\windows\\\\path\"",
"result": "windows"
},
{
"expression": "\"/unix/path\"",
"result": "unix"
},
{
"expression": "\"\\\"\\\"\\\"\"",
"result": "threequotes"
},
{
"expression": "\"bar\".\"baz\"",
"result": "qux"
}
]
}]

View File

@@ -1,512 +0,0 @@
[
{
"given": {"foo": [{"name": "a"}, {"name": "b"}]},
"cases": [
{
"comment": "Matching a literal",
"expression": "foo[?name == 'a']",
"result": [{"name": "a"}]
}
]
},
{
"given": {"foo": [0, 1], "bar": [2, 3]},
"cases": [
{
"comment": "Matching a literal",
"expression": "*[?[0] == `0`]",
"result": [[], []]
}
]
},
{
"given": {"foo": [{"first": "foo", "last": "bar"},
{"first": "foo", "last": "foo"},
{"first": "foo", "last": "baz"}]},
"cases": [
{
"comment": "Matching an expression",
"expression": "foo[?first == last]",
"result": [{"first": "foo", "last": "foo"}]
},
{
"comment": "Verify projection created from filter",
"expression": "foo[?first == last].first",
"result": ["foo"]
}
]
},
{
"given": {"foo": [{"age": 20},
{"age": 25},
{"age": 30}]},
"cases": [
{
"comment": "Greater than with a number",
"expression": "foo[?age > `25`]",
"result": [{"age": 30}]
},
{
"expression": "foo[?age >= `25`]",
"result": [{"age": 25}, {"age": 30}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?age > `30`]",
"result": []
},
{
"comment": "Greater than with a number",
"expression": "foo[?age < `25`]",
"result": [{"age": 20}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?age <= `25`]",
"result": [{"age": 20}, {"age": 25}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?age < `20`]",
"result": []
},
{
"expression": "foo[?age == `20`]",
"result": [{"age": 20}]
},
{
"expression": "foo[?age != `20`]",
"result": [{"age": 25}, {"age": 30}]
}
]
},
{
"given": {"foo": [{"weight": 33.3},
{"weight": 44.4},
{"weight": 55.5}]},
"cases": [
{
"comment": "Greater than with a number",
"expression": "foo[?weight > `44.4`]",
"result": [{"weight": 55.5}]
},
{
"expression": "foo[?weight >= `44.4`]",
"result": [{"weight": 44.4}, {"weight": 55.5}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?weight > `55.5`]",
"result": []
},
{
"comment": "Greater than with a number",
"expression": "foo[?weight < `44.4`]",
"result": [{"weight": 33.3}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?weight <= `44.4`]",
"result": [{"weight": 33.3}, {"weight": 44.4}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?weight < `33.3`]",
"result": []
},
{
"expression": "foo[?weight == `33.3`]",
"result": [{"weight": 33.3}]
},
{
"expression": "foo[?weight != `33.3`]",
"result": [{"weight": 44.4}, {"weight": 55.5}]
}
]
},
{
"given": {"foo": [{"top": {"name": "a"}},
{"top": {"name": "b"}}]},
"cases": [
{
"comment": "Filter with subexpression",
"expression": "foo[?top.name == 'a']",
"result": [{"top": {"name": "a"}}]
}
]
},
{
"given": {"foo": [{"top": {"first": "foo", "last": "bar"}},
{"top": {"first": "foo", "last": "foo"}},
{"top": {"first": "foo", "last": "baz"}}]},
"cases": [
{
"comment": "Matching an expression",
"expression": "foo[?top.first == top.last]",
"result": [{"top": {"first": "foo", "last": "foo"}}]
},
{
"comment": "Matching a JSON array",
"expression": "foo[?top == `{\"first\": \"foo\", \"last\": \"bar\"}`]",
"result": [{"top": {"first": "foo", "last": "bar"}}]
}
]
},
{
"given": {"foo": [
{"key": true},
{"key": false},
{"key": 0},
{"key": 1},
{"key": [0]},
{"key": {"bar": [0]}},
{"key": null},
{"key": [1]},
{"key": {"a":2}}
]},
"cases": [
{
"expression": "foo[?key == `true`]",
"result": [{"key": true}]
},
{
"expression": "foo[?key == `false`]",
"result": [{"key": false}]
},
{
"expression": "foo[?key == `0`]",
"result": [{"key": 0}]
},
{
"expression": "foo[?key == `1`]",
"result": [{"key": 1}]
},
{
"expression": "foo[?key == `[0]`]",
"result": [{"key": [0]}]
},
{
"expression": "foo[?key == `{\"bar\": [0]}`]",
"result": [{"key": {"bar": [0]}}]
},
{
"expression": "foo[?key == `null`]",
"result": [{"key": null}]
},
{
"expression": "foo[?key == `[1]`]",
"result": [{"key": [1]}]
},
{
"expression": "foo[?key == `{\"a\":2}`]",
"result": [{"key": {"a":2}}]
},
{
"expression": "foo[?`true` == key]",
"result": [{"key": true}]
},
{
"expression": "foo[?`false` == key]",
"result": [{"key": false}]
},
{
"expression": "foo[?`0` == key]",
"result": [{"key": 0}]
},
{
"expression": "foo[?`1` == key]",
"result": [{"key": 1}]
},
{
"expression": "foo[?`[0]` == key]",
"result": [{"key": [0]}]
},
{
"expression": "foo[?`{\"bar\": [0]}` == key]",
"result": [{"key": {"bar": [0]}}]
},
{
"expression": "foo[?`null` == key]",
"result": [{"key": null}]
},
{
"expression": "foo[?`[1]` == key]",
"result": [{"key": [1]}]
},
{
"expression": "foo[?`{\"a\":2}` == key]",
"result": [{"key": {"a":2}}]
},
{
"expression": "foo[?key != `true`]",
"result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `false`]",
"result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `0`]",
"result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `1`]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `null`]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `[1]`]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `{\"a\":2}`]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
},
{
"expression": "foo[?`true` != key]",
"result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`false` != key]",
"result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`0` != key]",
"result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`1` != key]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`null` != key]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`[1]` != key]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
},
{
"expression": "foo[?`{\"a\":2}` != key]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
}
]
},
{
"given": {"reservations": [
{"instances": [
{"foo": 1, "bar": 2}, {"foo": 1, "bar": 3},
{"foo": 1, "bar": 2}, {"foo": 2, "bar": 1}]}]},
"cases": [
{
"expression": "reservations[].instances[?bar==`1`]",
"result": [[{"foo": 2, "bar": 1}]]
},
{
"expression": "reservations[*].instances[?bar==`1`]",
"result": [[{"foo": 2, "bar": 1}]]
},
{
"expression": "reservations[].instances[?bar==`1`][]",
"result": [{"foo": 2, "bar": 1}]
}
]
},
{
"given": {
"baz": "other",
"foo": [
{"bar": 1}, {"bar": 2}, {"bar": 3}, {"bar": 4}, {"bar": 1, "baz": 2}
]
},
"cases": [
{
"expression": "foo[?bar==`1`].bar[0]",
"result": []
}
]
},
{
"given": {
"foo": [
{"a": 1, "b": {"c": "x"}},
{"a": 1, "b": {"c": "y"}},
{"a": 1, "b": {"c": "z"}},
{"a": 2, "b": {"c": "z"}},
{"a": 1, "baz": 2}
]
},
"cases": [
{
"expression": "foo[?a==`1`].b.c",
"result": ["x", "y", "z"]
}
]
},
{
"given": {"foo": [{"name": "a"}, {"name": "b"}, {"name": "c"}]},
"cases": [
{
"comment": "Filter with or expression",
"expression": "foo[?name == 'a' || name == 'b']",
"result": [{"name": "a"}, {"name": "b"}]
},
{
"expression": "foo[?name == 'a' || name == 'e']",
"result": [{"name": "a"}]
},
{
"expression": "foo[?name == 'a' || name == 'b' || name == 'c']",
"result": [{"name": "a"}, {"name": "b"}, {"name": "c"}]
}
]
},
{
"given": {"foo": [{"a": 1, "b": 2}, {"a": 1, "b": 3}]},
"cases": [
{
"comment": "Filter with and expression",
"expression": "foo[?a == `1` && b == `2`]",
"result": [{"a": 1, "b": 2}]
},
{
"expression": "foo[?a == `1` && b == `4`]",
"result": []
}
]
},
{
"given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
"cases": [
{
"comment": "Filter with Or and And expressions",
"expression": "foo[?c == `3` || a == `1` && b == `4`]",
"result": [{"a": 1, "b": 2, "c": 3}]
},
{
"expression": "foo[?b == `2` || a == `3` && b == `4`]",
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
},
{
"expression": "foo[?a == `3` && b == `4` || b == `2`]",
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
},
{
"expression": "foo[?(a == `3` && b == `4`) || b == `2`]",
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
},
{
"expression": "foo[?((a == `3` && b == `4`)) || b == `2`]",
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
},
{
"expression": "foo[?a == `3` && (b == `4` || b == `2`)]",
"result": [{"a": 3, "b": 4}]
},
{
"expression": "foo[?a == `3` && ((b == `4` || b == `2`))]",
"result": [{"a": 3, "b": 4}]
}
]
},
{
"given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
"cases": [
{
"comment": "Verify precedence of or/and expressions",
"expression": "foo[?a == `1` || b ==`2` && c == `5`]",
"result": [{"a": 1, "b": 2, "c": 3}]
},
{
"comment": "Parentheses can alter precedence",
"expression": "foo[?(a == `1` || b ==`2`) && c == `5`]",
"result": []
},
{
"comment": "Not expressions combined with and/or",
"expression": "foo[?!(a == `1` || b ==`2`)]",
"result": [{"a": 3, "b": 4}]
}
]
},
{
"given": {
"foo": [
{"key": true},
{"key": false},
{"key": []},
{"key": {}},
{"key": [0]},
{"key": {"a": "b"}},
{"key": 0},
{"key": 1},
{"key": null},
{"notkey": true}
]
},
"cases": [
{
"comment": "Unary filter expression",
"expression": "foo[?key]",
"result": [
{"key": true}, {"key": [0]}, {"key": {"a": "b"}},
{"key": 0}, {"key": 1}
]
},
{
"comment": "Unary not filter expression",
"expression": "foo[?!key]",
"result": [
{"key": false}, {"key": []}, {"key": {}},
{"key": null}, {"notkey": true}
]
},
{
"comment": "Equality with null RHS",
"expression": "foo[?key == `null`]",
"result": [
{"key": null}, {"notkey": true}
]
}
]
},
{
"given": {
"foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
"cases": [
{
"comment": "Using @ in a filter expression",
"expression": "foo[?@ < `5`]",
"result": [0, 1, 2, 3, 4]
},
{
"comment": "Using @ in a filter expression",
"expression": "foo[?`5` > @]",
"result": [0, 1, 2, 3, 4]
},
{
"comment": "Using @ in a filter expression",
"expression": "foo[?@ == @]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
]
}
]

View File

@@ -1,821 +0,0 @@
[{
"given":
{
"foo": -1,
"zero": 0,
"numbers": [-1, 3, 4, 5],
"array": [-1, 3, 4, 5, "a", "100"],
"strings": ["a", "b", "c"],
"decimals": [1.01, 1.2, -1.5],
"str": "Str",
"false": false,
"empty_list": [],
"empty_hash": {},
"objects": {"foo": "bar", "bar": "baz"},
"null_key": null
},
"cases": [
{
"expression": "abs(foo)",
"result": 1
},
{
"expression": "abs(foo)",
"result": 1
},
{
"expression": "abs(str)",
"error": "invalid-type"
},
{
"expression": "abs(array[1])",
"result": 3
},
{
"expression": "abs(array[1])",
"result": 3
},
{
"expression": "abs(`false`)",
"error": "invalid-type"
},
{
"expression": "abs(`-24`)",
"result": 24
},
{
"expression": "abs(`-24`)",
"result": 24
},
{
"expression": "abs(`1`, `2`)",
"error": "invalid-arity"
},
{
"expression": "abs()",
"error": "invalid-arity"
},
{
"expression": "unknown_function(`1`, `2`)",
"error": "unknown-function"
},
{
"expression": "avg(numbers)",
"result": 2.75
},
{
"expression": "avg(array)",
"error": "invalid-type"
},
{
"expression": "avg('abc')",
"error": "invalid-type"
},
{
"expression": "avg(foo)",
"error": "invalid-type"
},
{
"expression": "avg(@)",
"error": "invalid-type"
},
{
"expression": "avg(strings)",
"error": "invalid-type"
},
{
"expression": "ceil(`1.2`)",
"result": 2
},
{
"expression": "ceil(decimals[0])",
"result": 2
},
{
"expression": "ceil(decimals[1])",
"result": 2
},
{
"expression": "ceil(decimals[2])",
"result": -1
},
{
"expression": "ceil('string')",
"error": "invalid-type"
},
{
"expression": "contains('abc', 'a')",
"result": true
},
{
"expression": "contains('abc', 'd')",
"result": false
},
{
"expression": "contains(`false`, 'd')",
"error": "invalid-type"
},
{
"expression": "contains(strings, 'a')",
"result": true
},
{
"expression": "contains(decimals, `1.2`)",
"result": true
},
{
"expression": "contains(decimals, `false`)",
"result": false
},
{
"expression": "ends_with(str, 'r')",
"result": true
},
{
"expression": "ends_with(str, 'tr')",
"result": true
},
{
"expression": "ends_with(str, 'Str')",
"result": true
},
{
"expression": "ends_with(str, 'SStr')",
"result": false
},
{
"expression": "ends_with(str, 'foo')",
"result": false
},
{
"expression": "ends_with(str, `0`)",
"error": "invalid-type"
},
{
"expression": "floor(`1.2`)",
"result": 1
},
{
"expression": "floor('string')",
"error": "invalid-type"
},
{
"expression": "floor(decimals[0])",
"result": 1
},
{
"expression": "floor(foo)",
"result": -1
},
{
"expression": "floor(str)",
"error": "invalid-type"
},
{
"expression": "length('abc')",
"result": 3
},
{
"expression": "length('')",
"result": 0
},
{
"expression": "length(@)",
"result": 12
},
{
"expression": "length(strings[0])",
"result": 1
},
{
"expression": "length(str)",
"result": 3
},
{
"expression": "length(array)",
"result": 6
},
{
"expression": "length(objects)",
"result": 2
},
{
"expression": "length(`false`)",
"error": "invalid-type"
},
{
"expression": "length(foo)",
"error": "invalid-type"
},
{
"expression": "length(strings[0])",
"result": 1
},
{
"expression": "max(numbers)",
"result": 5
},
{
"expression": "max(decimals)",
"result": 1.2
},
{
"expression": "max(strings)",
"result": "c"
},
{
"expression": "max(abc)",
"error": "invalid-type"
},
{
"expression": "max(array)",
"error": "invalid-type"
},
{
"expression": "max(decimals)",
"result": 1.2
},
{
"expression": "max(empty_list)",
"result": null
},
{
"expression": "merge(`{}`)",
"result": {}
},
{
"expression": "merge(`{}`, `{}`)",
"result": {}
},
{
"expression": "merge(`{\"a\": 1}`, `{\"b\": 2}`)",
"result": {"a": 1, "b": 2}
},
{
"expression": "merge(`{\"a\": 1}`, `{\"a\": 2}`)",
"result": {"a": 2}
},
{
"expression": "merge(`{\"a\": 1, \"b\": 2}`, `{\"a\": 2, \"c\": 3}`, `{\"d\": 4}`)",
"result": {"a": 2, "b": 2, "c": 3, "d": 4}
},
{
"expression": "min(numbers)",
"result": -1
},
{
"expression": "min(decimals)",
"result": -1.5
},
{
"expression": "min(abc)",
"error": "invalid-type"
},
{
"expression": "min(array)",
"error": "invalid-type"
},
{
"expression": "min(empty_list)",
"result": null
},
{
"expression": "min(decimals)",
"result": -1.5
},
{
"expression": "min(strings)",
"result": "a"
},
{
"expression": "type('abc')",
"result": "string"
},
{
"expression": "type(`1.0`)",
"result": "number"
},
{
"expression": "type(`2`)",
"result": "number"
},
{
"expression": "type(`true`)",
"result": "boolean"
},
{
"expression": "type(`false`)",
"result": "boolean"
},
{
"expression": "type(`null`)",
"result": "null"
},
{
"expression": "type(`[0]`)",
"result": "array"
},
{
"expression": "type(`{\"a\": \"b\"}`)",
"result": "object"
},
{
"expression": "type(@)",
"result": "object"
},
{
"expression": "sort(keys(objects))",
"result": ["bar", "foo"]
},
{
"expression": "keys(foo)",
"error": "invalid-type"
},
{
"expression": "keys(strings)",
"error": "invalid-type"
},
{
"expression": "keys(`false`)",
"error": "invalid-type"
},
{
"expression": "sort(values(objects))",
"result": ["bar", "baz"]
},
{
"expression": "keys(empty_hash)",
"result": []
},
{
"expression": "values(foo)",
"error": "invalid-type"
},
{
"expression": "join(', ', strings)",
"result": "a, b, c"
},
{
"expression": "join(', ', strings)",
"result": "a, b, c"
},
{
"expression": "join(',', `[\"a\", \"b\"]`)",
"result": "a,b"
},
{
"expression": "join(',', `[\"a\", 0]`)",
"error": "invalid-type"
},
{
"expression": "join(', ', str)",
"error": "invalid-type"
},
{
"expression": "join('|', strings)",
"result": "a|b|c"
},
{
"expression": "join(`2`, strings)",
"error": "invalid-type"
},
{
"expression": "join('|', decimals)",
"error": "invalid-type"
},
{
"expression": "join('|', decimals[].to_string(@))",
"result": "1.01|1.2|-1.5"
},
{
"expression": "join('|', empty_list)",
"result": ""
},
{
"expression": "reverse(numbers)",
"result": [5, 4, 3, -1]
},
{
"expression": "reverse(array)",
"result": ["100", "a", 5, 4, 3, -1]
},
{
"expression": "reverse(`[]`)",
"result": []
},
{
"expression": "reverse('')",
"result": ""
},
{
"expression": "reverse('hello world')",
"result": "dlrow olleh"
},
{
"expression": "starts_with(str, 'S')",
"result": true
},
{
"expression": "starts_with(str, 'St')",
"result": true
},
{
"expression": "starts_with(str, 'Str')",
"result": true
},
{
"expression": "starts_with(str, 'String')",
"result": false
},
{
"expression": "starts_with(str, `0`)",
"error": "invalid-type"
},
{
"expression": "sum(numbers)",
"result": 11
},
{
"expression": "sum(decimals)",
"result": 0.71
},
{
"expression": "sum(array)",
"error": "invalid-type"
},
{
"expression": "sum(array[].to_number(@))",
"result": 111
},
{
"expression": "sum(`[]`)",
"result": 0
},
{
"expression": "to_array('foo')",
"result": ["foo"]
},
{
"expression": "to_array(`0`)",
"result": [0]
},
{
"expression": "to_array(objects)",
"result": [{"foo": "bar", "bar": "baz"}]
},
{
"expression": "to_array(`[1, 2, 3]`)",
"result": [1, 2, 3]
},
{
"expression": "to_array(false)",
"result": [false]
},
{
"expression": "to_string('foo')",
"result": "foo"
},
{
"expression": "to_string(`1.2`)",
"result": "1.2"
},
{
"expression": "to_string(`[0, 1]`)",
"result": "[0,1]"
},
{
"expression": "to_number('1.0')",
"result": 1.0
},
{
"expression": "to_number('1.1')",
"result": 1.1
},
{
"expression": "to_number('4')",
"result": 4
},
{
"expression": "to_number('notanumber')",
"result": null
},
{
"expression": "to_number(`false`)",
"result": null
},
{
"expression": "to_number(`null`)",
"result": null
},
{
"expression": "to_number(`[0]`)",
"result": null
},
{
"expression": "to_number(`{\"foo\": 0}`)",
"result": null
},
{
"expression": "\"to_string\"(`1.0`)",
"error": "syntax"
},
{
"expression": "sort(numbers)",
"result": [-1, 3, 4, 5]
},
{
"expression": "sort(strings)",
"result": ["a", "b", "c"]
},
{
"expression": "sort(decimals)",
"result": [-1.5, 1.01, 1.2]
},
{
"expression": "sort(array)",
"error": "invalid-type"
},
{
"expression": "sort(abc)",
"error": "invalid-type"
},
{
"expression": "sort(empty_list)",
"result": []
},
{
"expression": "sort(@)",
"error": "invalid-type"
},
{
"expression": "not_null(unknown_key, str)",
"result": "Str"
},
{
"expression": "not_null(unknown_key, foo.bar, empty_list, str)",
"result": []
},
{
"expression": "not_null(unknown_key, null_key, empty_list, str)",
"result": []
},
{
"expression": "not_null(all, expressions, are_null)",
"result": null
},
{
"expression": "not_null()",
"error": "invalid-arity"
},
{
"description": "function projection on single arg function",
"expression": "numbers[].to_string(@)",
"result": ["-1", "3", "4", "5"]
},
{
"description": "function projection on single arg function",
"expression": "array[].to_number(@)",
"result": [-1, 3, 4, 5, 100]
}
]
}, {
"given":
{
"foo": [
{"b": "b", "a": "a"},
{"c": "c", "b": "b"},
{"d": "d", "c": "c"},
{"e": "e", "d": "d"},
{"f": "f", "e": "e"}
]
},
"cases": [
{
"description": "function projection on variadic function",
"expression": "foo[].not_null(f, e, d, c, b, a)",
"result": ["b", "c", "d", "e", "f"]
}
]
}, {
"given":
{
"people": [
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
{"age": 50, "age_str": "50", "bool": false, "name": "d"},
{"age": 10, "age_str": "10", "bool": true, "name": 3}
]
},
"cases": [
{
"description": "sort by field expression",
"expression": "sort_by(people, &age)",
"result": [
{"age": 10, "age_str": "10", "bool": true, "name": 3},
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
]
},
{
"expression": "sort_by(people, &age_str)",
"result": [
{"age": 10, "age_str": "10", "bool": true, "name": 3},
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
]
},
{
"description": "sort by function expression",
"expression": "sort_by(people, &to_number(age_str))",
"result": [
{"age": 10, "age_str": "10", "bool": true, "name": 3},
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
]
},
{
"description": "function projection on sort_by function",
"expression": "sort_by(people, &age)[].name",
"result": [3, "a", "c", "b", "d"]
},
{
"expression": "sort_by(people, &extra)",
"error": "invalid-type"
},
{
"expression": "sort_by(people, &bool)",
"error": "invalid-type"
},
{
"expression": "sort_by(people, &name)",
"error": "invalid-type"
},
{
"expression": "sort_by(people, name)",
"error": "invalid-type"
},
{
"expression": "sort_by(people, &age)[].extra",
"result": ["foo", "bar"]
},
{
"expression": "sort_by(`[]`, &age)",
"result": []
},
{
"expression": "max_by(people, &age)",
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
},
{
"expression": "max_by(people, &age_str)",
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
},
{
"expression": "max_by(people, &bool)",
"error": "invalid-type"
},
{
"expression": "max_by(people, &extra)",
"error": "invalid-type"
},
{
"expression": "max_by(people, &to_number(age_str))",
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
},
{
"expression": "min_by(people, &age)",
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
},
{
"expression": "min_by(people, &age_str)",
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
},
{
"expression": "min_by(people, &bool)",
"error": "invalid-type"
},
{
"expression": "min_by(people, &extra)",
"error": "invalid-type"
},
{
"expression": "min_by(people, &to_number(age_str))",
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
}
]
}, {
"given":
{
"people": [
{"age": 10, "order": "1"},
{"age": 10, "order": "2"},
{"age": 10, "order": "3"},
{"age": 10, "order": "4"},
{"age": 10, "order": "5"},
{"age": 10, "order": "6"},
{"age": 10, "order": "7"},
{"age": 10, "order": "8"},
{"age": 10, "order": "9"},
{"age": 10, "order": "10"},
{"age": 10, "order": "11"}
]
},
"cases": [
{
"description": "stable sort order",
"expression": "sort_by(people, &age)",
"result": [
{"age": 10, "order": "1"},
{"age": 10, "order": "2"},
{"age": 10, "order": "3"},
{"age": 10, "order": "4"},
{"age": 10, "order": "5"},
{"age": 10, "order": "6"},
{"age": 10, "order": "7"},
{"age": 10, "order": "8"},
{"age": 10, "order": "9"},
{"age": 10, "order": "10"},
{"age": 10, "order": "11"}
]
}
]
}, {
"given":
{
"people": [
{"a": 10, "b": 1, "c": "z"},
{"a": 10, "b": 2, "c": null},
{"a": 10, "b": 3},
{"a": 10, "b": 4, "c": "z"},
{"a": 10, "b": 5, "c": null},
{"a": 10, "b": 6},
{"a": 10, "b": 7, "c": "z"},
{"a": 10, "b": 8, "c": null},
{"a": 10, "b": 9}
],
"empty": []
},
"cases": [
{
"expression": "map(&a, people)",
"result": [10, 10, 10, 10, 10, 10, 10, 10, 10]
},
{
"expression": "map(&c, people)",
"result": ["z", null, null, "z", null, null, "z", null, null]
},
{
"expression": "map(&a, badkey)",
"error": "invalid-type"
},
{
"expression": "map(&foo, empty)",
"result": []
}
]
}, {
"given": {
"array": [
{
"foo": {"bar": "yes1"}
},
{
"foo": {"bar": "yes2"}
},
{
"foo1": {"bar": "no"}
}
]},
"cases": [
{
"expression": "map(&foo.bar, array)",
"result": ["yes1", "yes2", null]
},
{
"expression": "map(&foo1.bar, array)",
"result": [null, null, "no"]
},
{
"expression": "map(&foo.bar.baz, array)",
"result": [null, null, null]
}
]
}, {
"given": {
"array": [[1, 2, 3, [4]], [5, 6, 7, [8, 9]]]
},
"cases": [
{
"expression": "map(&[], array)",
"result": [[1, 2, 3, 4], [5, 6, 7, 8, 9]]
}
]
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -1,346 +0,0 @@
[{
"given":
{"foo": {"bar": ["zero", "one", "two"]}},
"cases": [
{
"expression": "foo.bar[0]",
"result": "zero"
},
{
"expression": "foo.bar[1]",
"result": "one"
},
{
"expression": "foo.bar[2]",
"result": "two"
},
{
"expression": "foo.bar[3]",
"result": null
},
{
"expression": "foo.bar[-1]",
"result": "two"
},
{
"expression": "foo.bar[-2]",
"result": "one"
},
{
"expression": "foo.bar[-3]",
"result": "zero"
},
{
"expression": "foo.bar[-4]",
"result": null
}
]
},
{
"given":
{"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
"cases": [
{
"expression": "foo.bar",
"result": null
},
{
"expression": "foo[0].bar",
"result": "one"
},
{
"expression": "foo[1].bar",
"result": "two"
},
{
"expression": "foo[2].bar",
"result": "three"
},
{
"expression": "foo[3].notbar",
"result": "four"
},
{
"expression": "foo[3].bar",
"result": null
},
{
"expression": "foo[0]",
"result": {"bar": "one"}
},
{
"expression": "foo[1]",
"result": {"bar": "two"}
},
{
"expression": "foo[2]",
"result": {"bar": "three"}
},
{
"expression": "foo[3]",
"result": {"notbar": "four"}
},
{
"expression": "foo[4]",
"result": null
}
]
},
{
"given": [
"one", "two", "three"
],
"cases": [
{
"expression": "[0]",
"result": "one"
},
{
"expression": "[1]",
"result": "two"
},
{
"expression": "[2]",
"result": "three"
},
{
"expression": "[-1]",
"result": "three"
},
{
"expression": "[-2]",
"result": "two"
},
{
"expression": "[-3]",
"result": "one"
}
]
},
{
"given": {"reservations": [
{"instances": [{"foo": 1}, {"foo": 2}]}
]},
"cases": [
{
"expression": "reservations[].instances[].foo",
"result": [1, 2]
},
{
"expression": "reservations[].instances[].bar",
"result": []
},
{
"expression": "reservations[].notinstances[].foo",
"result": []
},
{
"expression": "reservations[].notinstances[].foo",
"result": []
}
]
},
{
"given": {"reservations": [{
"instances": [
{"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
{"foo": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
{"foo": "bar"},
{"notfoo": [{"bar": 20}, {"bar": 21}, {"notbar": [7]}, {"bar": 22}]},
{"bar": [{"baz": [1]}, {"baz": [2]}, {"baz": [3]}, {"baz": [4]}]},
{"baz": [{"baz": [1, 2]}, {"baz": []}, {"baz": []}, {"baz": [3, 4]}]},
{"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
],
"otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
}, {
"instances": [
{"a": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
{"b": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
{"c": "bar"},
{"notfoo": [{"bar": 23}, {"bar": 24}, {"notbar": [7]}, {"bar": 25}]},
{"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
],
"otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
}
]},
"cases": [
{
"expression": "reservations[].instances[].foo[].bar",
"result": [1, 2, 4, 5, 6, 8]
},
{
"expression": "reservations[].instances[].foo[].baz",
"result": []
},
{
"expression": "reservations[].instances[].notfoo[].bar",
"result": [20, 21, 22, 23, 24, 25]
},
{
"expression": "reservations[].instances[].notfoo[].notbar",
"result": [[7], [7]]
},
{
"expression": "reservations[].notinstances[].foo",
"result": []
},
{
"expression": "reservations[].instances[].foo[].notbar",
"result": [3, [7]]
},
{
"expression": "reservations[].instances[].bar[].baz",
"result": [[1], [2], [3], [4]]
},
{
"expression": "reservations[].instances[].baz[].baz",
"result": [[1, 2], [], [], [3, 4]]
},
{
"expression": "reservations[].instances[].qux[].baz",
"result": [[], [1, 2, 3], [4], [], [], [1, 2, 3], [4], []]
},
{
"expression": "reservations[].instances[].qux[].baz[]",
"result": [1, 2, 3, 4, 1, 2, 3, 4]
}
]
},
{
"given": {
"foo": [
[["one", "two"], ["three", "four"]],
[["five", "six"], ["seven", "eight"]],
[["nine"], ["ten"]]
]
},
"cases": [
{
"expression": "foo[]",
"result": [["one", "two"], ["three", "four"], ["five", "six"],
["seven", "eight"], ["nine"], ["ten"]]
},
{
"expression": "foo[][0]",
"result": ["one", "three", "five", "seven", "nine", "ten"]
},
{
"expression": "foo[][1]",
"result": ["two", "four", "six", "eight"]
},
{
"expression": "foo[][0][0]",
"result": []
},
{
"expression": "foo[][2][2]",
"result": []
},
{
"expression": "foo[][0][0][100]",
"result": []
}
]
},
{
"given": {
"foo": [{
"bar": [
{
"qux": 2,
"baz": 1
},
{
"qux": 4,
"baz": 3
}
]
},
{
"bar": [
{
"qux": 6,
"baz": 5
},
{
"qux": 8,
"baz": 7
}
]
}
]
},
"cases": [
{
"expression": "foo",
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
},
{
"expression": "foo[]",
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
},
{
"expression": "foo[].bar",
"result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
[{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
},
{
"expression": "foo[].bar[]",
"result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
},
{
"expression": "foo[].bar[].baz",
"result": [1, 3, 5, 7]
}
]
},
{
"given": {
"string": "string",
"hash": {"foo": "bar", "bar": "baz"},
"number": 23,
"nullvalue": null
},
"cases": [
{
"expression": "string[]",
"result": null
},
{
"expression": "hash[]",
"result": null
},
{
"expression": "number[]",
"result": null
},
{
"expression": "nullvalue[]",
"result": null
},
{
"expression": "string[].foo",
"result": null
},
{
"expression": "hash[].foo",
"result": null
},
{
"expression": "number[].foo",
"result": null
},
{
"expression": "nullvalue[].foo",
"result": null
},
{
"expression": "nullvalue[].foo[].bar",
"result": null
}
]
}
]

View File

@@ -1,190 +0,0 @@
[
{
"given": {
"foo": [{"name": "a"}, {"name": "b"}],
"bar": {"baz": "qux"}
},
"cases": [
{
"expression": "`\"foo\"`",
"result": "foo"
},
{
"comment": "Interpret escaped unicode.",
"expression": "`\"\\u03a6\"`",
"result": "Φ"
},
{
"expression": "`\"✓\"`",
"result": "✓"
},
{
"expression": "`[1, 2, 3]`",
"result": [1, 2, 3]
},
{
"expression": "`{\"a\": \"b\"}`",
"result": {"a": "b"}
},
{
"expression": "`true`",
"result": true
},
{
"expression": "`false`",
"result": false
},
{
"expression": "`null`",
"result": null
},
{
"expression": "`0`",
"result": 0
},
{
"expression": "`1`",
"result": 1
},
{
"expression": "`2`",
"result": 2
},
{
"expression": "`3`",
"result": 3
},
{
"expression": "`4`",
"result": 4
},
{
"expression": "`5`",
"result": 5
},
{
"expression": "`6`",
"result": 6
},
{
"expression": "`7`",
"result": 7
},
{
"expression": "`8`",
"result": 8
},
{
"expression": "`9`",
"result": 9
},
{
"comment": "Escaping a backtick in quotes",
"expression": "`\"foo\\`bar\"`",
"result": "foo`bar"
},
{
"comment": "Double quote in literal",
"expression": "`\"foo\\\"bar\"`",
"result": "foo\"bar"
},
{
"expression": "`\"1\\`\"`",
"result": "1`"
},
{
"comment": "Multiple literal expressions with escapes",
"expression": "`\"\\\\\"`.{a:`\"b\"`}",
"result": {"a": "b"}
},
{
"comment": "literal . identifier",
"expression": "`{\"a\": \"b\"}`.a",
"result": "b"
},
{
"comment": "literal . identifier . identifier",
"expression": "`{\"a\": {\"b\": \"c\"}}`.a.b",
"result": "c"
},
{
"comment": "literal . identifier bracket-expr",
"expression": "`[0, 1, 2]`[1]",
"result": 1
}
]
},
{
"comment": "Literals",
"given": {"type": "object"},
"cases": [
{
"comment": "Literal with leading whitespace",
"expression": "` {\"foo\": true}`",
"result": {"foo": true}
},
{
"comment": "Literal with trailing whitespace",
"expression": "`{\"foo\": true} `",
"result": {"foo": true}
},
{
"comment": "Literal on RHS of subexpr not allowed",
"expression": "foo.`\"bar\"`",
"error": "syntax"
}
]
},
{
"comment": "Raw String Literals",
"given": {},
"cases": [
{
"expression": "'foo'",
"result": "foo"
},
{
"expression": "' foo '",
"result": " foo "
},
{
"expression": "'0'",
"result": "0"
},
{
"expression": "'newline\n'",
"result": "newline\n"
},
{
"expression": "'\n'",
"result": "\n"
},
{
"expression": "'✓'",
"result": "✓"
},
{
"expression": "'𝄞'",
"result": "𝄞"
},
{
"expression": "' [foo] '",
"result": " [foo] "
},
{
"expression": "'[foo]'",
"result": "[foo]"
},
{
"comment": "Do not interpret escaped unicode.",
"expression": "'\\u03a6'",
"result": "\\u03a6"
},
{
"comment": "Can escape the single quote",
"expression": "'foo\\'bar'",
"result": "foo'bar"
}
]
}
]

View File

@@ -1,393 +0,0 @@
[{
"given": {
"foo": {
"bar": "bar",
"baz": "baz",
"qux": "qux",
"nested": {
"one": {
"a": "first",
"b": "second",
"c": "third"
},
"two": {
"a": "first",
"b": "second",
"c": "third"
},
"three": {
"a": "first",
"b": "second",
"c": {"inner": "third"}
}
}
},
"bar": 1,
"baz": 2,
"qux\"": 3
},
"cases": [
{
"expression": "foo.{bar: bar}",
"result": {"bar": "bar"}
},
{
"expression": "foo.{\"bar\": bar}",
"result": {"bar": "bar"}
},
{
"expression": "foo.{\"foo.bar\": bar}",
"result": {"foo.bar": "bar"}
},
{
"expression": "foo.{bar: bar, baz: baz}",
"result": {"bar": "bar", "baz": "baz"}
},
{
"expression": "foo.{\"bar\": bar, \"baz\": baz}",
"result": {"bar": "bar", "baz": "baz"}
},
{
"expression": "{\"baz\": baz, \"qux\\\"\": \"qux\\\"\"}",
"result": {"baz": 2, "qux\"": 3}
},
{
"expression": "foo.{bar:bar,baz:baz}",
"result": {"bar": "bar", "baz": "baz"}
},
{
"expression": "foo.{bar: bar,qux: qux}",
"result": {"bar": "bar", "qux": "qux"}
},
{
"expression": "foo.{bar: bar, noexist: noexist}",
"result": {"bar": "bar", "noexist": null}
},
{
"expression": "foo.{noexist: noexist, alsonoexist: alsonoexist}",
"result": {"noexist": null, "alsonoexist": null}
},
{
"expression": "foo.badkey.{nokey: nokey, alsonokey: alsonokey}",
"result": null
},
{
"expression": "foo.nested.*.{a: a,b: b}",
"result": [{"a": "first", "b": "second"},
{"a": "first", "b": "second"},
{"a": "first", "b": "second"}]
},
{
"expression": "foo.nested.three.{a: a, cinner: c.inner}",
"result": {"a": "first", "cinner": "third"}
},
{
"expression": "foo.nested.three.{a: a, c: c.inner.bad.key}",
"result": {"a": "first", "c": null}
},
{
"expression": "foo.{a: nested.one.a, b: nested.two.b}",
"result": {"a": "first", "b": "second"}
},
{
"expression": "{bar: bar, baz: baz}",
"result": {"bar": 1, "baz": 2}
},
{
"expression": "{bar: bar}",
"result": {"bar": 1}
},
{
"expression": "{otherkey: bar}",
"result": {"otherkey": 1}
},
{
"expression": "{no: no, exist: exist}",
"result": {"no": null, "exist": null}
},
{
"expression": "foo.[bar]",
"result": ["bar"]
},
{
"expression": "foo.[bar,baz]",
"result": ["bar", "baz"]
},
{
"expression": "foo.[bar,qux]",
"result": ["bar", "qux"]
},
{
"expression": "foo.[bar,noexist]",
"result": ["bar", null]
},
{
"expression": "foo.[noexist,alsonoexist]",
"result": [null, null]
}
]
}, {
"given": {
"foo": {"bar": 1, "baz": [2, 3, 4]}
},
"cases": [
{
"expression": "foo.{bar:bar,baz:baz}",
"result": {"bar": 1, "baz": [2, 3, 4]}
},
{
"expression": "foo.[bar,baz[0]]",
"result": [1, 2]
},
{
"expression": "foo.[bar,baz[1]]",
"result": [1, 3]
},
{
"expression": "foo.[bar,baz[2]]",
"result": [1, 4]
},
{
"expression": "foo.[bar,baz[3]]",
"result": [1, null]
},
{
"expression": "foo.[bar[0],baz[3]]",
"result": [null, null]
}
]
}, {
"given": {
"foo": {"bar": 1, "baz": 2}
},
"cases": [
{
"expression": "foo.{bar: bar, baz: baz}",
"result": {"bar": 1, "baz": 2}
},
{
"expression": "foo.[bar,baz]",
"result": [1, 2]
}
]
}, {
"given": {
"foo": {
"bar": {"baz": [{"common": "first", "one": 1},
{"common": "second", "two": 2}]},
"ignoreme": 1,
"includeme": true
}
},
"cases": [
{
"expression": "foo.{bar: bar.baz[1],includeme: includeme}",
"result": {"bar": {"common": "second", "two": 2}, "includeme": true}
},
{
"expression": "foo.{\"bar.baz.two\": bar.baz[1].two, includeme: includeme}",
"result": {"bar.baz.two": 2, "includeme": true}
},
{
"expression": "foo.[includeme, bar.baz[*].common]",
"result": [true, ["first", "second"]]
},
{
"expression": "foo.[includeme, bar.baz[*].none]",
"result": [true, []]
},
{
"expression": "foo.[includeme, bar.baz[].common]",
"result": [true, ["first", "second"]]
}
]
}, {
"given": {
"reservations": [{
"instances": [
{"id": "id1",
"name": "first"},
{"id": "id2",
"name": "second"}
]}, {
"instances": [
{"id": "id3",
"name": "third"},
{"id": "id4",
"name": "fourth"}
]}
]},
"cases": [
{
"expression": "reservations[*].instances[*].{id: id, name: name}",
"result": [[{"id": "id1", "name": "first"}, {"id": "id2", "name": "second"}],
[{"id": "id3", "name": "third"}, {"id": "id4", "name": "fourth"}]]
},
{
"expression": "reservations[].instances[].{id: id, name: name}",
"result": [{"id": "id1", "name": "first"},
{"id": "id2", "name": "second"},
{"id": "id3", "name": "third"},
{"id": "id4", "name": "fourth"}]
},
{
"expression": "reservations[].instances[].[id, name]",
"result": [["id1", "first"],
["id2", "second"],
["id3", "third"],
["id4", "fourth"]]
}
]
},
{
"given": {
"foo": [{
"bar": [
{
"qux": 2,
"baz": 1
},
{
"qux": 4,
"baz": 3
}
]
},
{
"bar": [
{
"qux": 6,
"baz": 5
},
{
"qux": 8,
"baz": 7
}
]
}
]
},
"cases": [
{
"expression": "foo",
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
},
{
"expression": "foo[]",
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
},
{
"expression": "foo[].bar",
"result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
[{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
},
{
"expression": "foo[].bar[]",
"result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
},
{
"expression": "foo[].bar[].[baz, qux]",
"result": [[1, 2], [3, 4], [5, 6], [7, 8]]
},
{
"expression": "foo[].bar[].[baz]",
"result": [[1], [3], [5], [7]]
},
{
"expression": "foo[].bar[].[baz, qux][]",
"result": [1, 2, 3, 4, 5, 6, 7, 8]
}
]
},
{
"given": {
"foo": {
"baz": [
{
"bar": "abc"
}, {
"bar": "def"
}
],
"qux": ["zero"]
}
},
"cases": [
{
"expression": "foo.[baz[*].bar, qux[0]]",
"result": [["abc", "def"], "zero"]
}
]
},
{
"given": {
"foo": {
"baz": [
{
"bar": "a",
"bam": "b",
"boo": "c"
}, {
"bar": "d",
"bam": "e",
"boo": "f"
}
],
"qux": ["zero"]
}
},
"cases": [
{
"expression": "foo.[baz[*].[bar, boo], qux[0]]",
"result": [[["a", "c" ], ["d", "f" ]], "zero"]
}
]
},
{
"given": {
"foo": {
"baz": [
{
"bar": "a",
"bam": "b",
"boo": "c"
}, {
"bar": "d",
"bam": "e",
"boo": "f"
}
],
"qux": ["zero"]
}
},
"cases": [
{
"expression": "foo.[baz[*].not_there || baz[*].bar, qux[0]]",
"result": [["a", "d"], "zero"]
}
]
},
{
"given": {"type": "object"},
"cases": [
{
"comment": "Nested multiselect",
"expression": "[[*],*]",
"result": [null, ["object"]]
}
]
},
{
"given": [],
"cases": [
{
"comment": "Nested multiselect",
"expression": "[[*]]",
"result": [[]]
}
]
}
]

View File

@@ -1,27 +0,0 @@
[{
"description": "Basic minimal case",
"given":
{"foo": {"bar": {"baz": "correct"}}},
"cases": [
{
"name": "single_expression",
"expression": "foo",
"result": {"bar": {"baz": "correct"}}
},
{
"name": "single_dot_expression",
"expression": "foo.bar",
"result": {"baz": "correct"}
},
{
"name": "double_dot_expression",
"expression": "foo.bar.baz",
"result": "correct"
},
{
"name": "dot_no_match",
"expression": "foo.bar.baz.bad",
"result": null
}
]
}]

View File

@@ -1,27 +0,0 @@
[{
"description": "Deeply nested dict",
"given":
{"j49": {"j48": {"j47": {"j46": {"j45": {"j44": {"j43": {"j42": {"j41": {"j40": {"j39": {"j38": {"j37": {"j36": {"j35": {"j34": {"j33": {"j32": {"j31": {"j30": {"j29": {"j28": {"j27": {"j26": {"j25": {"j24": {"j23": {"j22": {"j21": {"j20": {"j19": {"j18": {"j17": {"j16": {"j15": {"j14": {"j13": {"j12": {"j11": {"j10": {"j9": {"j8": {"j7": {"j6": {"j5": {"j4": {"j3": {"j2": {"j1": {"j0": {}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},
"cases": [
{
"name": "deep_nesting_10",
"expression": "j49.j48.j47.j46.j45.j44.j43.j42.j41.j40",
"result": {"j39": {"j38": {"j37": {"j36": {"j35": {"j34": {"j33": {"j32": {"j31": {"j30": {"j29": {"j28": {"j27": {"j26": {"j25": {"j24": {"j23": {"j22": {"j21": {"j20": {"j19": {"j18": {"j17": {"j16": {"j15": {"j14": {"j13": {"j12": {"j11": {"j10": {"j9": {"j8": {"j7": {"j6": {"j5": {"j4": {"j3": {"j2": {"j1": {"j0": {}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
},
{
"name": "deep_nesting_50",
"expression": "j49.j48.j47.j46.j45.j44.j43.j42.j41.j40.j39.j38.j37.j36.j35.j34.j33.j32.j31.j30.j29.j28.j27.j26.j25.j24.j23.j22.j21.j20.j19.j18.j17.j16.j15.j14.j13.j12.j11.j10.j9.j8.j7.j6.j5.j4.j3.j2.j1.j0",
"result": {}
},
{
"name": "deep_nesting_50_pipe",
"expression": "j49|j48|j47|j46|j45|j44|j43|j42|j41|j40|j39|j38|j37|j36|j35|j34|j33|j32|j31|j30|j29|j28|j27|j26|j25|j24|j23|j22|j21|j20|j19|j18|j17|j16|j15|j14|j13|j12|j11|j10|j9|j8|j7|j6|j5|j4|j3|j2|j1|j0",
"result": {}
},
{
"name": "deep_nesting_50_index",
"expression": "[49][48][47][46][45][44][43][42][41][40][39][38][37][36][35][34][33][32][31][30][29][28][27][26][25][24][23][22][21][20][19][18][17][16][15][14][13][12][11][10][9][8][7][6][5][4][3][2][1][0]",
"result": null
}
]
}]

View File

@@ -1,12 +0,0 @@
[{
"description": "Deep projections",
"given":
{"a": []},
"cases": [
{
"name": "deep_projection_104",
"expression": "a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*]",
"result": []
}
]
}]

View File

@@ -1,17 +0,0 @@
[{
"description": "Deep projections",
"given":
[749, 222, 102, 148, 869, 848, 326, 644, 402, 150, 361, 827, 741, 60, 842, 943, 214, 519, 134, 866, 621, 851, 59, 580, 760, 576, 951, 989, 266, 259, 809, 643, 292, 731, 129, 970, 589, 430, 690, 715, 901, 491, 276, 88, 738, 282, 547, 349, 236, 879, 403, 557, 554, 23, 649, 720, 531, 2, 601, 152, 530, 477, 568, 122, 811, 75, 181, 203, 683, 152, 794, 155, 54, 314, 957, 468, 740, 532, 504, 806, 927, 827, 840, 100, 519, 357, 536, 398, 417, 543, 599, 383, 144, 772, 988, 184, 118, 921, 497, 193, 320, 919, 583, 346, 575, 143, 866, 907, 570, 255, 539, 164, 764, 256, 315, 305, 960, 587, 804, 577, 667, 869, 563, 956, 677, 469, 934, 52, 323, 933, 398, 305, 138, 133, 443, 419, 717, 838, 287, 177, 192, 210, 892, 319, 470, 76, 643, 737, 135, 425, 586, 882, 844, 113, 268, 323, 938, 569, 374, 295, 648, 27, 703, 530, 667, 118, 176, 972, 611, 60, 47, 19, 500, 344, 332, 452, 647, 388, 188, 235, 151, 353, 219, 766, 626, 885, 456, 182, 363, 617, 236, 285, 152, 87, 666, 429, 599, 762, 13, 778, 634, 43, 199, 361, 300, 370, 957, 488, 359, 354, 972, 368, 482, 88, 766, 709, 804, 637, 368, 950, 752, 932, 638, 291, 177, 739, 740, 357, 928, 964, 621, 472, 813, 36, 271, 642, 3, 771, 397, 670, 324, 244, 827, 194, 693, 846, 351, 668, 911, 600, 682, 735, 26, 876, 581, 915, 184, 263, 857, 960, 5, 523, 932, 694, 457, 739, 897, 28, 794, 885, 77, 768, 39, 763, 748, 792, 60, 582, 667, 909, 820, 898, 569, 252, 583, 237, 677, 613, 914, 956, 541, 297, 853, 581, 118, 888, 368, 156, 582, 183],
"cases": [
{
"name": "min sort with slice",
"expression": "sort(@)[:3]",
"result": [2, 3, 5]
},
{
"name": "max sort with slice",
"expression": "sort(@)[-3:]",
"result": [972, 988, 989]
}
]
}]

View File

@@ -1,22 +0,0 @@
[{
"description": "Multiple wildcards in an expression",
"given": {
"foo": [
{"bar": [{"kind": "basic"}, {"kind": "intermediate"}]},
{"bar": [{"kind": "advanced"}, {"kind": "expert"}]}
]
},
"cases": [
{
"name": "multi_wildcard_field",
"expression": "foo[*].bar[*].kind",
"result": [["basic", "intermediate"], ["advanced", "expert"]]
},
{
"name": "wildcard_with_index",
"expression": "foo[*].bar[0].kind",
"result": ["basic", "advanced"]
}
]
}]

View File

@@ -1,17 +0,0 @@
[{
"description": "Multiple wildcards",
"given":
{"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
"cases": [
{
"name": "wildcard_with_field_match",
"expression": "foo[*].bar",
"result": ["one", "two", "three"]
},
{
"name": "wildcard_with_field_match2",
"expression": "foo[*].notbar",
"result": ["four"]
}
]
}]

View File

@@ -1,131 +0,0 @@
[{
"given": {
"foo": {
"bar": {
"baz": "subkey"
},
"other": {
"baz": "subkey"
},
"other2": {
"baz": "subkey"
},
"other3": {
"notbaz": ["a", "b", "c"]
},
"other4": {
"notbaz": ["a", "b", "c"]
}
}
},
"cases": [
{
"expression": "foo.*.baz | [0]",
"result": "subkey"
},
{
"expression": "foo.*.baz | [1]",
"result": "subkey"
},
{
"expression": "foo.*.baz | [2]",
"result": "subkey"
},
{
"expression": "foo.bar.* | [0]",
"result": "subkey"
},
{
"expression": "foo.*.notbaz | [*]",
"result": [["a", "b", "c"], ["a", "b", "c"]]
},
{
"expression": "{\"a\": foo.bar, \"b\": foo.other} | *.baz",
"result": ["subkey", "subkey"]
}
]
}, {
"given": {
"foo": {
"bar": {
"baz": "one"
},
"other": {
"baz": "two"
},
"other2": {
"baz": "three"
},
"other3": {
"notbaz": ["a", "b", "c"]
},
"other4": {
"notbaz": ["d", "e", "f"]
}
}
},
"cases": [
{
"expression": "foo | bar",
"result": {"baz": "one"}
},
{
"expression": "foo | bar | baz",
"result": "one"
},
{
"expression": "foo|bar| baz",
"result": "one"
},
{
"expression": "not_there | [0]",
"result": null
},
{
"expression": "not_there | [0]",
"result": null
},
{
"expression": "[foo.bar, foo.other] | [0]",
"result": {"baz": "one"}
},
{
"expression": "{\"a\": foo.bar, \"b\": foo.other} | a",
"result": {"baz": "one"}
},
{
"expression": "{\"a\": foo.bar, \"b\": foo.other} | b",
"result": {"baz": "two"}
},
{
"expression": "foo.bam || foo.bar | baz",
"result": "one"
},
{
"expression": "foo | not_there || bar",
"result": {"baz": "one"}
}
]
}, {
"given": {
"foo": [{
"bar": [{
"baz": "one"
}, {
"baz": "two"
}]
}, {
"bar": [{
"baz": "three"
}, {
"baz": "four"
}]
}]
},
"cases": [
{
"expression": "foo[*].bar[*] | [0][0]",
"result": {"baz": "one"}
}
]
}]

View File

@@ -1,187 +0,0 @@
[{
"given": {
"foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
"bar": {
"baz": 1
}
},
"cases": [
{
"expression": "bar[0:10]",
"result": null
},
{
"expression": "foo[0:10:1]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0:10]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0:10:]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0::1]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0::]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0:]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[:10:1]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[::1]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[:10:]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[::]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[:]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[1:9]",
"result": [1, 2, 3, 4, 5, 6, 7, 8]
},
{
"expression": "foo[0:10:2]",
"result": [0, 2, 4, 6, 8]
},
{
"expression": "foo[5:]",
"result": [5, 6, 7, 8, 9]
},
{
"expression": "foo[5::2]",
"result": [5, 7, 9]
},
{
"expression": "foo[::2]",
"result": [0, 2, 4, 6, 8]
},
{
"expression": "foo[::-1]",
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
},
{
"expression": "foo[1::2]",
"result": [1, 3, 5, 7, 9]
},
{
"expression": "foo[10:0:-1]",
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1]
},
{
"expression": "foo[10:5:-1]",
"result": [9, 8, 7, 6]
},
{
"expression": "foo[8:2:-2]",
"result": [8, 6, 4]
},
{
"expression": "foo[0:20]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[10:-20:-1]",
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
},
{
"expression": "foo[10:-20]",
"result": []
},
{
"expression": "foo[-4:-1]",
"result": [6, 7, 8]
},
{
"expression": "foo[:-5:-1]",
"result": [9, 8, 7, 6]
},
{
"expression": "foo[8:2:0]",
"error": "invalid-value"
},
{
"expression": "foo[8:2:0:1]",
"error": "syntax"
},
{
"expression": "foo[8:2&]",
"error": "syntax"
},
{
"expression": "foo[2:a:3]",
"error": "syntax"
}
]
}, {
"given": {
"foo": [{"a": 1}, {"a": 2}, {"a": 3}],
"bar": [{"a": {"b": 1}}, {"a": {"b": 2}},
{"a": {"b": 3}}],
"baz": 50
},
"cases": [
{
"expression": "foo[:2].a",
"result": [1, 2]
},
{
"expression": "foo[:2].b",
"result": []
},
{
"expression": "foo[:2].a.b",
"result": []
},
{
"expression": "bar[::-1].a.b",
"result": [3, 2, 1]
},
{
"expression": "bar[:2].a.b",
"result": [1, 2]
},
{
"expression": "baz[:2].a",
"result": null
}
]
}, {
"given": [{"a": 1}, {"a": 2}, {"a": 3}],
"cases": [
{
"expression": "[:]",
"result": [{"a": 1}, {"a": 2}, {"a": 3}]
},
{
"expression": "[:2].a",
"result": [1, 2]
},
{
"expression": "[::-1].a",
"result": [3, 2, 1]
},
{
"expression": "[:2].b",
"result": []
}
]
}]

View File

@@ -1,616 +0,0 @@
[{
"comment": "Dot syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "foo.bar",
"result": null
},
{
"expression": "foo.1",
"error": "syntax"
},
{
"expression": "foo.-11",
"error": "syntax"
},
{
"expression": "foo",
"result": null
},
{
"expression": "foo.",
"error": "syntax"
},
{
"expression": "foo.",
"error": "syntax"
},
{
"expression": ".foo",
"error": "syntax"
},
{
"expression": "foo..bar",
"error": "syntax"
},
{
"expression": "foo.bar.",
"error": "syntax"
},
{
"expression": "foo[.]",
"error": "syntax"
}
]
},
{
"comment": "Simple token errors",
"given": {"type": "object"},
"cases": [
{
"expression": ".",
"error": "syntax"
},
{
"expression": ":",
"error": "syntax"
},
{
"expression": ",",
"error": "syntax"
},
{
"expression": "]",
"error": "syntax"
},
{
"expression": "[",
"error": "syntax"
},
{
"expression": "}",
"error": "syntax"
},
{
"expression": "{",
"error": "syntax"
},
{
"expression": ")",
"error": "syntax"
},
{
"expression": "(",
"error": "syntax"
},
{
"expression": "((&",
"error": "syntax"
},
{
"expression": "a[",
"error": "syntax"
},
{
"expression": "a]",
"error": "syntax"
},
{
"expression": "a][",
"error": "syntax"
},
{
"expression": "!",
"error": "syntax"
}
]
},
{
"comment": "Boolean syntax errors",
"given": {"type": "object"},
"cases": [
{
"expression": "![!(!",
"error": "syntax"
}
]
},
{
"comment": "Wildcard syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "*",
"result": ["object"]
},
{
"expression": "*.*",
"result": []
},
{
"expression": "*.foo",
"result": []
},
{
"expression": "*[0]",
"result": []
},
{
"expression": ".*",
"error": "syntax"
},
{
"expression": "*foo",
"error": "syntax"
},
{
"expression": "*0",
"error": "syntax"
},
{
"expression": "foo[*]bar",
"error": "syntax"
},
{
"expression": "foo[*]*",
"error": "syntax"
}
]
},
{
"comment": "Flatten syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "[]",
"result": null
}
]
},
{
"comment": "Simple bracket syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "[0]",
"result": null
},
{
"expression": "[*]",
"result": null
},
{
"expression": "*.[0]",
"error": "syntax"
},
{
"expression": "*.[\"0\"]",
"result": [[null]]
},
{
"expression": "[*].bar",
"result": null
},
{
"expression": "[*][0]",
"result": null
},
{
"expression": "foo[#]",
"error": "syntax"
}
]
},
{
"comment": "Multi-select list syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "foo[0]",
"result": null
},
{
"comment": "Valid multi-select of a list",
"expression": "foo[0, 1]",
"error": "syntax"
},
{
"expression": "foo.[0]",
"error": "syntax"
},
{
"expression": "foo.[*]",
"result": null
},
{
"comment": "Multi-select of a list with trailing comma",
"expression": "foo[0, ]",
"error": "syntax"
},
{
"comment": "Multi-select of a list with trailing comma and no close",
"expression": "foo[0,",
"error": "syntax"
},
{
"comment": "Multi-select of a list with trailing comma and no close",
"expression": "foo.[a",
"error": "syntax"
},
{
"comment": "Multi-select of a list with extra comma",
"expression": "foo[0,, 1]",
"error": "syntax"
},
{
"comment": "Multi-select of a list using an identifier index",
"expression": "foo[abc]",
"error": "syntax"
},
{
"comment": "Multi-select of a list using identifier indices",
"expression": "foo[abc, def]",
"error": "syntax"
},
{
"comment": "Multi-select of a list using an identifier index",
"expression": "foo[abc, 1]",
"error": "syntax"
},
{
"comment": "Multi-select of a list using an identifier index with trailing comma",
"expression": "foo[abc, ]",
"error": "syntax"
},
{
"comment": "Valid multi-select of a hash using an identifier index",
"expression": "foo.[abc]",
"result": null
},
{
"comment": "Valid multi-select of a hash",
"expression": "foo.[abc, def]",
"result": null
},
{
"comment": "Multi-select of a hash using a numeric index",
"expression": "foo.[abc, 1]",
"error": "syntax"
},
{
"comment": "Multi-select of a hash with a trailing comma",
"expression": "foo.[abc, ]",
"error": "syntax"
},
{
"comment": "Multi-select of a hash with extra commas",
"expression": "foo.[abc,, def]",
"error": "syntax"
},
{
"comment": "Multi-select of a hash using number indices",
"expression": "foo.[0, 1]",
"error": "syntax"
}
]
},
{
"comment": "Multi-select hash syntax",
"given": {"type": "object"},
"cases": [
{
"comment": "No key or value",
"expression": "a{}",
"error": "syntax"
},
{
"comment": "No closing token",
"expression": "a{",
"error": "syntax"
},
{
"comment": "Not a key value pair",
"expression": "a{foo}",
"error": "syntax"
},
{
"comment": "Missing value and closing character",
"expression": "a{foo:",
"error": "syntax"
},
{
"comment": "Missing closing character",
"expression": "a{foo: 0",
"error": "syntax"
},
{
"comment": "Missing value",
"expression": "a{foo:}",
"error": "syntax"
},
{
"comment": "Trailing comma and no closing character",
"expression": "a{foo: 0, ",
"error": "syntax"
},
{
"comment": "Missing value with trailing comma",
"expression": "a{foo: ,}",
"error": "syntax"
},
{
"comment": "Accessing Array using an identifier",
"expression": "a{foo: bar}",
"error": "syntax"
},
{
"expression": "a{foo: 0}",
"error": "syntax"
},
{
"comment": "Missing key-value pair",
"expression": "a.{}",
"error": "syntax"
},
{
"comment": "Not a key-value pair",
"expression": "a.{foo}",
"error": "syntax"
},
{
"comment": "Missing value",
"expression": "a.{foo:}",
"error": "syntax"
},
{
"comment": "Missing value with trailing comma",
"expression": "a.{foo: ,}",
"error": "syntax"
},
{
"comment": "Valid multi-select hash extraction",
"expression": "a.{foo: bar}",
"result": null
},
{
"comment": "Valid multi-select hash extraction",
"expression": "a.{foo: bar, baz: bam}",
"result": null
},
{
"comment": "Trailing comma",
"expression": "a.{foo: bar, }",
"error": "syntax"
},
{
"comment": "Missing key in second key-value pair",
"expression": "a.{foo: bar, baz}",
"error": "syntax"
},
{
"comment": "Missing value in second key-value pair",
"expression": "a.{foo: bar, baz:}",
"error": "syntax"
},
{
"comment": "Trailing comma",
"expression": "a.{foo: bar, baz: bam, }",
"error": "syntax"
},
{
"comment": "Nested multi select",
"expression": "{\"\\\\\":{\" \":*}}",
"result": {"\\": {" ": ["object"]}}
}
]
},
{
"comment": "Or expressions",
"given": {"type": "object"},
"cases": [
{
"expression": "foo || bar",
"result": null
},
{
"expression": "foo ||",
"error": "syntax"
},
{
"expression": "foo.|| bar",
"error": "syntax"
},
{
"expression": " || foo",
"error": "syntax"
},
{
"expression": "foo || || foo",
"error": "syntax"
},
{
"expression": "foo.[a || b]",
"result": null
},
{
"expression": "foo.[a ||]",
"error": "syntax"
},
{
"expression": "\"foo",
"error": "syntax"
}
]
},
{
"comment": "Filter expressions",
"given": {"type": "object"},
"cases": [
{
"expression": "foo[?bar==`\"baz\"`]",
"result": null
},
{
"expression": "foo[? bar == `\"baz\"` ]",
"result": null
},
{
"expression": "foo[ ?bar==`\"baz\"`]",
"error": "syntax"
},
{
"expression": "foo[?bar==]",
"error": "syntax"
},
{
"expression": "foo[?==]",
"error": "syntax"
},
{
"expression": "foo[?==bar]",
"error": "syntax"
},
{
"expression": "foo[?bar==baz?]",
"error": "syntax"
},
{
"expression": "foo[?a.b.c==d.e.f]",
"result": null
},
{
"expression": "foo[?bar==`[0, 1, 2]`]",
"result": null
},
{
"expression": "foo[?bar==`[\"a\", \"b\", \"c\"]`]",
"result": null
},
{
"comment": "Literal char not escaped",
"expression": "foo[?bar==`[\"foo`bar\"]`]",
"error": "syntax"
},
{
"comment": "Literal char escaped",
"expression": "foo[?bar==`[\"foo\\`bar\"]`]",
"result": null
},
{
"comment": "Unknown comparator",
"expression": "foo[?bar<>baz]",
"error": "syntax"
},
{
"comment": "Unknown comparator",
"expression": "foo[?bar^baz]",
"error": "syntax"
},
{
"expression": "foo[bar==baz]",
"error": "syntax"
},
{
"comment": "Quoted identifier in filter expression no spaces",
"expression": "[?\"\\\\\">`\"foo\"`]",
"result": null
},
{
"comment": "Quoted identifier in filter expression with spaces",
"expression": "[?\"\\\\\" > `\"foo\"`]",
"result": null
}
]
},
{
"comment": "Filter expression errors",
"given": {"type": "object"},
"cases": [
{
"expression": "bar.`\"anything\"`",
"error": "syntax"
},
{
"expression": "bar.baz.noexists.`\"literal\"`",
"error": "syntax"
},
{
"comment": "Literal wildcard projection",
"expression": "foo[*].`\"literal\"`",
"error": "syntax"
},
{
"expression": "foo[*].name.`\"literal\"`",
"error": "syntax"
},
{
"expression": "foo[].name.`\"literal\"`",
"error": "syntax"
},
{
"expression": "foo[].name.`\"literal\"`.`\"subliteral\"`",
"error": "syntax"
},
{
"comment": "Projecting a literal onto an empty list",
"expression": "foo[*].name.noexist.`\"literal\"`",
"error": "syntax"
},
{
"expression": "foo[].name.noexist.`\"literal\"`",
"error": "syntax"
},
{
"expression": "twolen[*].`\"foo\"`",
"error": "syntax"
},
{
"comment": "Two level projection of a literal",
"expression": "twolen[*].threelen[*].`\"bar\"`",
"error": "syntax"
},
{
"comment": "Two level flattened projection of a literal",
"expression": "twolen[].threelen[].`\"bar\"`",
"error": "syntax"
}
]
},
{
"comment": "Identifiers",
"given": {"type": "object"},
"cases": [
{
"expression": "foo",
"result": null
},
{
"expression": "\"foo\"",
"result": null
},
{
"expression": "\"\\\\\"",
"result": null
}
]
},
{
"comment": "Combined syntax",
"given": [],
"cases": [
{
"expression": "*||*|*|*",
"result": []
},
{
"expression": "*[]||[*]",
"result": []
},
{
"expression": "[*.*]",
"result": [[]]
}
]
}
]

View File

@@ -1,38 +0,0 @@
[
{
"given": {"foo": [{"✓": "✓"}, {"✓": "✗"}]},
"cases": [
{
"expression": "foo[].\"✓\"",
"result": ["✓", "✗"]
}
]
},
{
"given": {"☯": true},
"cases": [
{
"expression": "\"☯\"",
"result": true
}
]
},
{
"given": {"♪♫•*¨*•.¸¸❤¸¸.•*¨*•♫♪": true},
"cases": [
{
"expression": "\"♪♫•*¨*•.¸¸❤¸¸.•*¨*•♫♪\"",
"result": true
}
]
},
{
"given": {"☃": true},
"cases": [
{
"expression": "\"☃\"",
"result": true
}
]
}
]

View File

@@ -1,460 +0,0 @@
[{
"given": {
"foo": {
"bar": {
"baz": "val"
},
"other": {
"baz": "val"
},
"other2": {
"baz": "val"
},
"other3": {
"notbaz": ["a", "b", "c"]
},
"other4": {
"notbaz": ["a", "b", "c"]
},
"other5": {
"other": {
"a": 1,
"b": 1,
"c": 1
}
}
}
},
"cases": [
{
"expression": "foo.*.baz",
"result": ["val", "val", "val"]
},
{
"expression": "foo.bar.*",
"result": ["val"]
},
{
"expression": "foo.*.notbaz",
"result": [["a", "b", "c"], ["a", "b", "c"]]
},
{
"expression": "foo.*.notbaz[0]",
"result": ["a", "a"]
},
{
"expression": "foo.*.notbaz[-1]",
"result": ["c", "c"]
}
]
}, {
"given": {
"foo": {
"first-1": {
"second-1": "val"
},
"first-2": {
"second-1": "val"
},
"first-3": {
"second-1": "val"
}
}
},
"cases": [
{
"expression": "foo.*",
"result": [{"second-1": "val"}, {"second-1": "val"},
{"second-1": "val"}]
},
{
"expression": "foo.*.*",
"result": [["val"], ["val"], ["val"]]
},
{
"expression": "foo.*.*.*",
"result": [[], [], []]
},
{
"expression": "foo.*.*.*.*",
"result": [[], [], []]
}
]
}, {
"given": {
"foo": {
"bar": "one"
},
"other": {
"bar": "one"
},
"nomatch": {
"notbar": "three"
}
},
"cases": [
{
"expression": "*.bar",
"result": ["one", "one"]
}
]
}, {
"given": {
"top1": {
"sub1": {"foo": "one"}
},
"top2": {
"sub1": {"foo": "one"}
}
},
"cases": [
{
"expression": "*",
"result": [{"sub1": {"foo": "one"}},
{"sub1": {"foo": "one"}}]
},
{
"expression": "*.sub1",
"result": [{"foo": "one"},
{"foo": "one"}]
},
{
"expression": "*.*",
"result": [[{"foo": "one"}],
[{"foo": "one"}]]
},
{
"expression": "*.*.foo[]",
"result": ["one", "one"]
},
{
"expression": "*.sub1.foo",
"result": ["one", "one"]
}
]
},
{
"given":
{"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
"cases": [
{
"expression": "foo[*].bar",
"result": ["one", "two", "three"]
},
{
"expression": "foo[*].notbar",
"result": ["four"]
}
]
},
{
"given":
[{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}],
"cases": [
{
"expression": "[*]",
"result": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]
},
{
"expression": "[*].bar",
"result": ["one", "two", "three"]
},
{
"expression": "[*].notbar",
"result": ["four"]
}
]
},
{
"given": {
"foo": {
"bar": [
{"baz": ["one", "two", "three"]},
{"baz": ["four", "five", "six"]},
{"baz": ["seven", "eight", "nine"]}
]
}
},
"cases": [
{
"expression": "foo.bar[*].baz",
"result": [["one", "two", "three"], ["four", "five", "six"], ["seven", "eight", "nine"]]
},
{
"expression": "foo.bar[*].baz[0]",
"result": ["one", "four", "seven"]
},
{
"expression": "foo.bar[*].baz[1]",
"result": ["two", "five", "eight"]
},
{
"expression": "foo.bar[*].baz[2]",
"result": ["three", "six", "nine"]
},
{
"expression": "foo.bar[*].baz[3]",
"result": []
}
]
},
{
"given": {
"foo": {
"bar": [["one", "two"], ["three", "four"]]
}
},
"cases": [
{
"expression": "foo.bar[*]",
"result": [["one", "two"], ["three", "four"]]
},
{
"expression": "foo.bar[0]",
"result": ["one", "two"]
},
{
"expression": "foo.bar[0][0]",
"result": "one"
},
{
"expression": "foo.bar[0][0][0]",
"result": null
},
{
"expression": "foo.bar[0][0][0][0]",
"result": null
},
{
"expression": "foo[0][0]",
"result": null
}
]
},
{
"given": {
"foo": [
{"bar": [{"kind": "basic"}, {"kind": "intermediate"}]},
{"bar": [{"kind": "advanced"}, {"kind": "expert"}]},
{"bar": "string"}
]
},
"cases": [
{
"expression": "foo[*].bar[*].kind",
"result": [["basic", "intermediate"], ["advanced", "expert"]]
},
{
"expression": "foo[*].bar[0].kind",
"result": ["basic", "advanced"]
}
]
},
{
"given": {
"foo": [
{"bar": {"kind": "basic"}},
{"bar": {"kind": "intermediate"}},
{"bar": {"kind": "advanced"}},
{"bar": {"kind": "expert"}},
{"bar": "string"}
]
},
"cases": [
{
"expression": "foo[*].bar.kind",
"result": ["basic", "intermediate", "advanced", "expert"]
}
]
},
{
"given": {
"foo": [{"bar": ["one", "two"]}, {"bar": ["three", "four"]}, {"bar": ["five"]}]
},
"cases": [
{
"expression": "foo[*].bar[0]",
"result": ["one", "three", "five"]
},
{
"expression": "foo[*].bar[1]",
"result": ["two", "four"]
},
{
"expression": "foo[*].bar[2]",
"result": []
}
]
},
{
"given": {
"foo": [{"bar": []}, {"bar": []}, {"bar": []}]
},
"cases": [
{
"expression": "foo[*].bar[0]",
"result": []
}
]
},
{
"given": {
"foo": [["one", "two"], ["three", "four"], ["five"]]
},
"cases": [
{
"expression": "foo[*][0]",
"result": ["one", "three", "five"]
},
{
"expression": "foo[*][1]",
"result": ["two", "four"]
}
]
},
{
"given": {
"foo": [
[
["one", "two"], ["three", "four"]
], [
["five", "six"], ["seven", "eight"]
], [
["nine"], ["ten"]
]
]
},
"cases": [
{
"expression": "foo[*][0]",
"result": [["one", "two"], ["five", "six"], ["nine"]]
},
{
"expression": "foo[*][1]",
"result": [["three", "four"], ["seven", "eight"], ["ten"]]
},
{
"expression": "foo[*][0][0]",
"result": ["one", "five", "nine"]
},
{
"expression": "foo[*][1][0]",
"result": ["three", "seven", "ten"]
},
{
"expression": "foo[*][0][1]",
"result": ["two", "six"]
},
{
"expression": "foo[*][1][1]",
"result": ["four", "eight"]
},
{
"expression": "foo[*][2]",
"result": []
},
{
"expression": "foo[*][2][2]",
"result": []
},
{
"expression": "bar[*]",
"result": null
},
{
"expression": "bar[*].baz[*]",
"result": null
}
]
},
{
"given": {
"string": "string",
"hash": {"foo": "bar", "bar": "baz"},
"number": 23,
"nullvalue": null
},
"cases": [
{
"expression": "string[*]",
"result": null
},
{
"expression": "hash[*]",
"result": null
},
{
"expression": "number[*]",
"result": null
},
{
"expression": "nullvalue[*]",
"result": null
},
{
"expression": "string[*].foo",
"result": null
},
{
"expression": "hash[*].foo",
"result": null
},
{
"expression": "number[*].foo",
"result": null
},
{
"expression": "nullvalue[*].foo",
"result": null
},
{
"expression": "nullvalue[*].foo[*].bar",
"result": null
}
]
},
{
"given": {
"string": "string",
"hash": {"foo": "val", "bar": "val"},
"number": 23,
"array": [1, 2, 3],
"nullvalue": null
},
"cases": [
{
"expression": "string.*",
"result": null
},
{
"expression": "hash.*",
"result": ["val", "val"]
},
{
"expression": "number.*",
"result": null
},
{
"expression": "array.*",
"result": null
},
{
"expression": "nullvalue.*",
"result": null
}
]
},
{
"given": {
"a": [0, 1, 2],
"b": [0, 1, 2]
},
"cases": [
{
"expression": "*[0]",
"result": [0, 0]
}
]
}
]