JsonFileTest.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <?php
  2. /*
  3. * This file is part of Composer.
  4. *
  5. * (c) Nils Adermann <naderman@naderman.de>
  6. * Jordi Boggiano <j.boggiano@seld.be>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. namespace Composer\Test\Json;
  12. use Seld\JsonLint\ParsingException;
  13. use Composer\Json\JsonFile;
  14. use Composer\Test\TestCase;
  15. class JsonFileTest extends TestCase
  16. {
  17. public function testParseErrorDetectExtraComma()
  18. {
  19. $json = '{
  20. "foo": "bar",
  21. }';
  22. $this->expectParseException('Parse error on line 2', $json);
  23. }
  24. public function testParseErrorDetectExtraCommaInArray()
  25. {
  26. $json = '{
  27. "foo": [
  28. "bar",
  29. ]
  30. }';
  31. $this->expectParseException('Parse error on line 3', $json);
  32. }
  33. public function testParseErrorDetectUnescapedBackslash()
  34. {
  35. $json = '{
  36. "fo\o": "bar"
  37. }';
  38. $this->expectParseException('Parse error on line 1', $json);
  39. }
  40. public function testParseErrorSkipsEscapedBackslash()
  41. {
  42. $json = '{
  43. "fo\\\\o": "bar"
  44. "a": "b"
  45. }';
  46. $this->expectParseException('Parse error on line 2', $json);
  47. }
  48. public function testParseErrorDetectSingleQuotes()
  49. {
  50. if (defined('JSON_PARSER_NOTSTRICT') && version_compare(phpversion('json'), '1.3.9', '<')) {
  51. $this->markTestSkipped('jsonc issue, see https://github.com/remicollet/pecl-json-c/issues/23');
  52. }
  53. $json = '{
  54. \'foo\': "bar"
  55. }';
  56. $this->expectParseException('Parse error on line 1', $json);
  57. }
  58. public function testParseErrorDetectMissingQuotes()
  59. {
  60. $json = '{
  61. foo: "bar"
  62. }';
  63. $this->expectParseException('Parse error on line 1', $json);
  64. }
  65. public function testParseErrorDetectArrayAsHash()
  66. {
  67. $json = '{
  68. "foo": ["bar": "baz"]
  69. }';
  70. $this->expectParseException('Parse error on line 2', $json);
  71. }
  72. public function testParseErrorDetectMissingComma()
  73. {
  74. $json = '{
  75. "foo": "bar"
  76. "bar": "foo"
  77. }';
  78. $this->expectParseException('Parse error on line 2', $json);
  79. }
  80. public function testSchemaValidation()
  81. {
  82. $json = new JsonFile(__DIR__.'/Fixtures/composer.json');
  83. $this->assertTrue($json->validateSchema());
  84. }
  85. public function testParseErrorDetectMissingCommaMultiline()
  86. {
  87. $json = '{
  88. "foo": "barbar"
  89. "bar": "foo"
  90. }';
  91. $this->expectParseException('Parse error on line 2', $json);
  92. }
  93. public function testParseErrorDetectMissingColon()
  94. {
  95. $json = '{
  96. "foo": "bar",
  97. "bar" "foo"
  98. }';
  99. $this->expectParseException('Parse error on line 3', $json);
  100. }
  101. public function testSimpleJsonString()
  102. {
  103. $data = array('name' => 'composer/composer');
  104. $json = '{
  105. "name": "composer/composer"
  106. }';
  107. $this->assertJsonFormat($json, $data);
  108. }
  109. public function testTrailingBackslash()
  110. {
  111. $data = array('Metadata\\' => 'src/');
  112. $json = '{
  113. "Metadata\\\\": "src/"
  114. }';
  115. $this->assertJsonFormat($json, $data);
  116. }
  117. public function testFormatEmptyArray()
  118. {
  119. $data = array('test' => array(), 'test2' => new \stdClass);
  120. $json = '{
  121. "test": [],
  122. "test2": {}
  123. }';
  124. $this->assertJsonFormat($json, $data);
  125. }
  126. public function testEscape()
  127. {
  128. $data = array("Metadata\\\"" => 'src/');
  129. $json = '{
  130. "Metadata\\\\\\"": "src/"
  131. }';
  132. $this->assertJsonFormat($json, $data);
  133. }
  134. public function testUnicode()
  135. {
  136. if (!function_exists('mb_convert_encoding') && PHP_VERSION_ID < 50400) {
  137. $this->markTestSkipped('Test requires the mbstring extension');
  138. }
  139. $data = array("Žluťoučký \" kůň" => "úpěl ďábelské ódy za €");
  140. $json = '{
  141. "Žluťoučký \" kůň": "úpěl ďábelské ódy za €"
  142. }';
  143. $this->assertJsonFormat($json, $data);
  144. }
  145. public function testOnlyUnicode()
  146. {
  147. if (!function_exists('mb_convert_encoding') && PHP_VERSION_ID < 50400) {
  148. $this->markTestSkipped('Test requires the mbstring extension');
  149. }
  150. $data = "\\/ƌ";
  151. $this->assertJsonFormat('"\\\\\\/ƌ"', $data, JsonFile::JSON_UNESCAPED_UNICODE);
  152. }
  153. public function testEscapedSlashes()
  154. {
  155. $data = "\\/foo";
  156. $this->assertJsonFormat('"\\\\\\/foo"', $data, 0);
  157. }
  158. public function testEscapedBackslashes()
  159. {
  160. $data = "a\\b";
  161. $this->assertJsonFormat('"a\\\\b"', $data, 0);
  162. }
  163. public function testEscapedUnicode()
  164. {
  165. $data = "ƌ";
  166. $this->assertJsonFormat('"\\u018c"', $data, 0);
  167. }
  168. public function testDoubleEscapedUnicode()
  169. {
  170. $jsonFile = new JsonFile('composer.json');
  171. $data = array("Zdjęcia","hjkjhl\\u0119kkjk");
  172. $encodedData = $jsonFile->encode($data);
  173. $doubleEncodedData = $jsonFile->encode(array('t' => $encodedData));
  174. $decodedData = json_decode($doubleEncodedData, true);
  175. $doubleData = json_decode($decodedData['t'], true);
  176. $this->assertEquals($data, $doubleData);
  177. }
  178. private function expectParseException($text, $json)
  179. {
  180. try {
  181. $result = JsonFile::parseJson($json);
  182. $this->fail(sprintf("Parsing should have failed but didn't.\nExpected:\n\"%s\"\nFor:\n\"%s\"\nGot:\n\"%s\"", $text, $json, var_export($result, true)));
  183. } catch (ParsingException $e) {
  184. $this->assertContains($text, $e->getMessage());
  185. }
  186. }
  187. private function assertJsonFormat($json, $data, $options = null)
  188. {
  189. $file = new JsonFile('composer.json');
  190. $json = str_replace("\r", '', $json);
  191. if (null === $options) {
  192. $this->assertEquals($json, $file->encode($data));
  193. } else {
  194. $this->assertEquals($json, $file->encode($data, $options));
  195. }
  196. }
  197. }