ExporterTest.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. <?php
  2. /*
  3. * This file is part of the Exporter package.
  4. *
  5. * (c) Sebastian Bergmann <sebastian@phpunit.de>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace SebastianBergmann\Exporter;
  11. /**
  12. * @covers SebastianBergmann\Exporter\Exporter
  13. */
  14. class ExporterTest extends \PHPUnit_Framework_TestCase
  15. {
  16. /**
  17. * @var Exporter
  18. */
  19. private $exporter;
  20. protected function setUp()
  21. {
  22. $this->exporter = new Exporter;
  23. }
  24. public function exportProvider()
  25. {
  26. $obj2 = new \stdClass;
  27. $obj2->foo = 'bar';
  28. $obj3 = (object)array(1,2,"Test\r\n",4,5,6,7,8);
  29. $obj = new \stdClass;
  30. //@codingStandardsIgnoreStart
  31. $obj->null = null;
  32. //@codingStandardsIgnoreEnd
  33. $obj->boolean = true;
  34. $obj->integer = 1;
  35. $obj->double = 1.2;
  36. $obj->string = '1';
  37. $obj->text = "this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext";
  38. $obj->object = $obj2;
  39. $obj->objectagain = $obj2;
  40. $obj->array = array('foo' => 'bar');
  41. $obj->self = $obj;
  42. $storage = new \SplObjectStorage;
  43. $storage->attach($obj2);
  44. $storage->foo = $obj2;
  45. return array(
  46. array(null, 'null'),
  47. array(true, 'true'),
  48. array(false, 'false'),
  49. array(1, '1'),
  50. array(1.0, '1.0'),
  51. array(1.2, '1.2'),
  52. array(fopen('php://memory', 'r'), 'resource(%d) of type (stream)'),
  53. array('1', "'1'"),
  54. array(array(array(1,2,3), array(3,4,5)),
  55. <<<EOF
  56. Array &0 (
  57. 0 => Array &1 (
  58. 0 => 1
  59. 1 => 2
  60. 2 => 3
  61. )
  62. 1 => Array &2 (
  63. 0 => 3
  64. 1 => 4
  65. 2 => 5
  66. )
  67. )
  68. EOF
  69. ),
  70. // \n\r and \r is converted to \n
  71. array("this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext",
  72. <<<EOF
  73. 'this
  74. is
  75. a
  76. very
  77. very
  78. very
  79. very
  80. very
  81. very
  82. long
  83. text'
  84. EOF
  85. ),
  86. array(new \stdClass, 'stdClass Object &%x ()'),
  87. array($obj,
  88. <<<EOF
  89. stdClass Object &%x (
  90. 'null' => null
  91. 'boolean' => true
  92. 'integer' => 1
  93. 'double' => 1.2
  94. 'string' => '1'
  95. 'text' => 'this
  96. is
  97. a
  98. very
  99. very
  100. very
  101. very
  102. very
  103. very
  104. long
  105. text'
  106. 'object' => stdClass Object &%x (
  107. 'foo' => 'bar'
  108. )
  109. 'objectagain' => stdClass Object &%x
  110. 'array' => Array &%d (
  111. 'foo' => 'bar'
  112. )
  113. 'self' => stdClass Object &%x
  114. )
  115. EOF
  116. ),
  117. array(array(), 'Array &%d ()'),
  118. array($storage,
  119. <<<EOF
  120. SplObjectStorage Object &%x (
  121. 'foo' => stdClass Object &%x (
  122. 'foo' => 'bar'
  123. )
  124. '%x' => Array &0 (
  125. 'obj' => stdClass Object &%x
  126. 'inf' => null
  127. )
  128. )
  129. EOF
  130. ),
  131. array($obj3,
  132. <<<EOF
  133. stdClass Object &%x (
  134. 0 => 1
  135. 1 => 2
  136. 2 => 'Test\n'
  137. 3 => 4
  138. 4 => 5
  139. 5 => 6
  140. 6 => 7
  141. 7 => 8
  142. )
  143. EOF
  144. ),
  145. array(
  146. chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5),
  147. 'Binary String: 0x000102030405'
  148. ),
  149. array(
  150. implode('', array_map('chr', range(0x0e, 0x1f))),
  151. 'Binary String: 0x0e0f101112131415161718191a1b1c1d1e1f'
  152. ),
  153. array(
  154. chr(0x00) . chr(0x09),
  155. 'Binary String: 0x0009'
  156. ),
  157. array(
  158. '',
  159. "''"
  160. ),
  161. );
  162. }
  163. /**
  164. * @dataProvider exportProvider
  165. */
  166. public function testExport($value, $expected)
  167. {
  168. $this->assertStringMatchesFormat(
  169. $expected,
  170. $this->trimNewline($this->exporter->export($value))
  171. );
  172. }
  173. public function testExport2()
  174. {
  175. if (PHP_VERSION === '5.3.3') {
  176. $this->markTestSkipped('Skipped due to "Nesting level too deep - recursive dependency?" fatal error');
  177. }
  178. $obj = new \stdClass;
  179. $obj->foo = 'bar';
  180. $array = array(
  181. 0 => 0,
  182. 'null' => null,
  183. 'boolean' => true,
  184. 'integer' => 1,
  185. 'double' => 1.2,
  186. 'string' => '1',
  187. 'text' => "this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext",
  188. 'object' => $obj,
  189. 'objectagain' => $obj,
  190. 'array' => array('foo' => 'bar'),
  191. );
  192. $array['self'] = &$array;
  193. $expected = <<<EOF
  194. Array &%d (
  195. 0 => 0
  196. 'null' => null
  197. 'boolean' => true
  198. 'integer' => 1
  199. 'double' => 1.2
  200. 'string' => '1'
  201. 'text' => 'this
  202. is
  203. a
  204. very
  205. very
  206. very
  207. very
  208. very
  209. very
  210. long
  211. text'
  212. 'object' => stdClass Object &%x (
  213. 'foo' => 'bar'
  214. )
  215. 'objectagain' => stdClass Object &%x
  216. 'array' => Array &%d (
  217. 'foo' => 'bar'
  218. )
  219. 'self' => Array &%d (
  220. 0 => 0
  221. 'null' => null
  222. 'boolean' => true
  223. 'integer' => 1
  224. 'double' => 1.2
  225. 'string' => '1'
  226. 'text' => 'this
  227. is
  228. a
  229. very
  230. very
  231. very
  232. very
  233. very
  234. very
  235. long
  236. text'
  237. 'object' => stdClass Object &%x
  238. 'objectagain' => stdClass Object &%x
  239. 'array' => Array &%d (
  240. 'foo' => 'bar'
  241. )
  242. 'self' => Array &%d
  243. )
  244. )
  245. EOF;
  246. $this->assertStringMatchesFormat(
  247. $expected,
  248. $this->trimNewline($this->exporter->export($array))
  249. );
  250. }
  251. public function shortenedExportProvider()
  252. {
  253. $obj = new \stdClass;
  254. $obj->foo = 'bar';
  255. $array = array(
  256. 'foo' => 'bar',
  257. );
  258. return array(
  259. array(null, 'null'),
  260. array(true, 'true'),
  261. array(1, '1'),
  262. array(1.0, '1.0'),
  263. array(1.2, '1.2'),
  264. array('1', "'1'"),
  265. // \n\r and \r is converted to \n
  266. array("this\nis\na\nvery\nvery\nvery\nvery\nvery\nvery\rlong\n\rtext", "'this\\nis\\na\\nvery\\nvery\\nvery\\nvery...g\\ntext'"),
  267. array(new \stdClass, 'stdClass Object ()'),
  268. array($obj, 'stdClass Object (...)'),
  269. array(array(), 'Array ()'),
  270. array($array, 'Array (...)'),
  271. );
  272. }
  273. /**
  274. * @dataProvider shortenedExportProvider
  275. */
  276. public function testShortenedExport($value, $expected)
  277. {
  278. $this->assertSame(
  279. $expected,
  280. $this->trimNewline($this->exporter->shortenedExport($value))
  281. );
  282. }
  283. /**
  284. * @requires extension mbstring
  285. */
  286. public function testShortenedExportForMultibyteCharacters()
  287. {
  288. $oldMbLanguage = mb_language();
  289. mb_language('Japanese');
  290. $oldMbInternalEncoding = mb_internal_encoding();
  291. mb_internal_encoding('UTF-8');
  292. try {
  293. $this->assertSame(
  294. "'いろはにほへとちりぬるをわかよたれそつねならむうゐのおくや...しゑひもせす'",
  295. $this->trimNewline($this->exporter->shortenedExport('いろはにほへとちりぬるをわかよたれそつねならむうゐのおくやまけふこえてあさきゆめみしゑひもせす'))
  296. );
  297. } catch (\Exception $e) {
  298. mb_internal_encoding($oldMbInternalEncoding);
  299. mb_language($oldMbLanguage);
  300. throw $e;
  301. }
  302. mb_internal_encoding($oldMbInternalEncoding);
  303. mb_language($oldMbLanguage);
  304. }
  305. public function provideNonBinaryMultibyteStrings()
  306. {
  307. return array(
  308. array(implode('', array_map('chr', range(0x09, 0x0d))), 5),
  309. array(implode('', array_map('chr', range(0x20, 0x7f))), 96),
  310. array(implode('', array_map('chr', range(0x80, 0xff))), 128),
  311. );
  312. }
  313. /**
  314. * @dataProvider provideNonBinaryMultibyteStrings
  315. */
  316. public function testNonBinaryStringExport($value, $expectedLength)
  317. {
  318. $this->assertRegExp(
  319. "~'.{{$expectedLength}}'\$~s",
  320. $this->exporter->export($value)
  321. );
  322. }
  323. public function testNonObjectCanBeReturnedAsArray()
  324. {
  325. $this->assertEquals(array(true), $this->exporter->toArray(true));
  326. }
  327. private function trimNewline($string)
  328. {
  329. return preg_replace('/[ ]*\n/', "\n", $string);
  330. }
  331. }