ComplianceTest.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <?php
  2. namespace JmesPath\Tests;
  3. use JmesPath\AstRuntime;
  4. use JmesPath\CompilerRuntime;
  5. use JmesPath\SyntaxErrorException;
  6. class ComplianceTest extends \PHPUnit_Framework_TestCase
  7. {
  8. private static $path;
  9. public static function setUpBeforeClass()
  10. {
  11. self::$path = __DIR__ . '/../../compiled';
  12. array_map('unlink', glob(self::$path . '/jmespath_*.php'));
  13. }
  14. public static function tearDownAfterClass()
  15. {
  16. array_map('unlink', glob(self::$path . '/jmespath_*.php'));
  17. }
  18. /**
  19. * @dataProvider complianceProvider
  20. */
  21. public function testPassesCompliance(
  22. $data,
  23. $expression,
  24. $result,
  25. $error,
  26. $file,
  27. $suite,
  28. $case,
  29. $compiled,
  30. $asAssoc
  31. ) {
  32. $evalResult = null;
  33. $failed = false;
  34. $failureMsg = '';
  35. $failure = '';
  36. $compiledStr = '';
  37. try {
  38. if ($compiled) {
  39. $compiledStr = \JmesPath\Env::COMPILE_DIR . '=on ';
  40. $runtime = new CompilerRuntime(self::$path);
  41. } else {
  42. $runtime = new AstRuntime();
  43. }
  44. $evalResult = $runtime($expression, $data);
  45. } catch (\Exception $e) {
  46. $failed = $e instanceof SyntaxErrorException ? 'syntax' : 'runtime';
  47. $failureMsg = sprintf(
  48. '%s (%s line %d)',
  49. $e->getMessage(),
  50. $e->getFile(),
  51. $e->getLine()
  52. );
  53. }
  54. $file = __DIR__ . '/compliance/' . $file . '.json';
  55. $failure .= "\n{$compiledStr}php bin/jp.php --file {$file} --suite {$suite} --case {$case}\n\n"
  56. . "Expected: " . $this->prettyJson($result) . "\n\n";
  57. $failure .= 'Associative? ' . var_export($asAssoc, true) . "\n\n";
  58. if (!$error && $failed) {
  59. $this->fail("Should not have failed\n{$failure}=> {$failed} {$failureMsg}");
  60. } elseif ($error && !$failed) {
  61. $this->fail("Should have failed\n{$failure}");
  62. }
  63. $this->assertEquals(
  64. $this->convertAssoc($result),
  65. $this->convertAssoc($evalResult),
  66. $failure
  67. );
  68. }
  69. public function complianceProvider()
  70. {
  71. $cases = [];
  72. $files = array_map(function ($f) {
  73. return basename($f, '.json');
  74. }, glob(__DIR__ . '/compliance/*.json'));
  75. foreach ($files as $name) {
  76. $contents = file_get_contents(__DIR__ . "/compliance/{$name}.json");
  77. foreach ([true, false] as $asAssoc) {
  78. $json = json_decode($contents, true);
  79. $jsonObj = json_decode($contents);
  80. foreach ($json as $suiteNumber => $suite) {
  81. $given = $asAssoc ? $suite['given'] : $jsonObj[$suiteNumber]->given;
  82. foreach ($suite['cases'] as $caseNumber => $case) {
  83. $caseData = [
  84. $given,
  85. $case['expression'],
  86. isset($case['result']) ? $case['result'] : null,
  87. isset($case['error']) ? $case['error'] : false,
  88. $name,
  89. $suiteNumber,
  90. $caseNumber,
  91. false,
  92. $asAssoc
  93. ];
  94. $cases[] = $caseData;
  95. $caseData[7] = true;
  96. $cases[] = $caseData;
  97. }
  98. }
  99. }
  100. }
  101. return $cases;
  102. }
  103. private function convertAssoc($data)
  104. {
  105. if ($data instanceof \stdClass) {
  106. return $this->convertAssoc((array) $data);
  107. } elseif (is_array($data)) {
  108. return array_map([$this, 'convertAssoc'], $data);
  109. } else {
  110. return $data;
  111. }
  112. }
  113. private function prettyJson($json)
  114. {
  115. if (defined('JSON_PRETTY_PRINT')) {
  116. return json_encode($json, JSON_PRETTY_PRINT);
  117. }
  118. return json_encode($json);
  119. }
  120. }