OptionsResolver2Dot6Test.php 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495
  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  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 Symfony\Component\OptionsResolver\Tests;
  11. use PHPUnit\Framework\Assert;
  12. use PHPUnit\Framework\TestCase;
  13. use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
  14. use Symfony\Component\OptionsResolver\Options;
  15. use Symfony\Component\OptionsResolver\OptionsResolver;
  16. class OptionsResolver2Dot6Test extends TestCase
  17. {
  18. /**
  19. * @var OptionsResolver
  20. */
  21. private $resolver;
  22. protected function setUp()
  23. {
  24. $this->resolver = new OptionsResolver();
  25. }
  26. /**
  27. * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
  28. * @expectedExceptionMessage The option "foo" does not exist. Defined options are: "a", "z".
  29. */
  30. public function testResolveFailsIfNonExistingOption()
  31. {
  32. $this->resolver->setDefault('z', '1');
  33. $this->resolver->setDefault('a', '2');
  34. $this->resolver->resolve(array('foo' => 'bar'));
  35. }
  36. /**
  37. * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
  38. * @expectedExceptionMessage The options "baz", "foo", "ping" do not exist. Defined options are: "a", "z".
  39. */
  40. public function testResolveFailsIfMultipleNonExistingOptions()
  41. {
  42. $this->resolver->setDefault('z', '1');
  43. $this->resolver->setDefault('a', '2');
  44. $this->resolver->resolve(array('ping' => 'pong', 'foo' => 'bar', 'baz' => 'bam'));
  45. }
  46. /**
  47. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  48. */
  49. public function testResolveFailsFromLazyOption()
  50. {
  51. $this->resolver->setDefault('foo', function (Options $options) {
  52. $options->resolve(array());
  53. });
  54. $this->resolver->resolve();
  55. }
  56. public function testSetDefaultReturnsThis()
  57. {
  58. $this->assertSame($this->resolver, $this->resolver->setDefault('foo', 'bar'));
  59. }
  60. public function testSetDefault()
  61. {
  62. $this->resolver->setDefault('one', '1');
  63. $this->resolver->setDefault('two', '20');
  64. $this->assertEquals(array(
  65. 'one' => '1',
  66. 'two' => '20',
  67. ), $this->resolver->resolve());
  68. }
  69. /**
  70. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  71. */
  72. public function testFailIfSetDefaultFromLazyOption()
  73. {
  74. $this->resolver->setDefault('lazy', function (Options $options) {
  75. $options->setDefault('default', 42);
  76. });
  77. $this->resolver->resolve();
  78. }
  79. public function testHasDefault()
  80. {
  81. $this->assertFalse($this->resolver->hasDefault('foo'));
  82. $this->resolver->setDefault('foo', 42);
  83. $this->assertTrue($this->resolver->hasDefault('foo'));
  84. }
  85. public function testHasDefaultWithNullValue()
  86. {
  87. $this->assertFalse($this->resolver->hasDefault('foo'));
  88. $this->resolver->setDefault('foo', null);
  89. $this->assertTrue($this->resolver->hasDefault('foo'));
  90. }
  91. public function testSetLazyReturnsThis()
  92. {
  93. $this->assertSame($this->resolver, $this->resolver->setDefault('foo', function (Options $options) {}));
  94. }
  95. public function testSetLazyClosure()
  96. {
  97. $this->resolver->setDefault('foo', function (Options $options) {
  98. return 'lazy';
  99. });
  100. $this->assertEquals(array('foo' => 'lazy'), $this->resolver->resolve());
  101. }
  102. public function testClosureWithoutTypeHintNotInvoked()
  103. {
  104. $closure = function ($options) {
  105. Assert::fail('Should not be called');
  106. };
  107. $this->resolver->setDefault('foo', $closure);
  108. $this->assertSame(array('foo' => $closure), $this->resolver->resolve());
  109. }
  110. public function testClosureWithoutParametersNotInvoked()
  111. {
  112. $closure = function () {
  113. Assert::fail('Should not be called');
  114. };
  115. $this->resolver->setDefault('foo', $closure);
  116. $this->assertSame(array('foo' => $closure), $this->resolver->resolve());
  117. }
  118. public function testAccessPreviousDefaultValue()
  119. {
  120. // defined by superclass
  121. $this->resolver->setDefault('foo', 'bar');
  122. // defined by subclass
  123. $this->resolver->setDefault('foo', function (Options $options, $previousValue) {
  124. Assert::assertEquals('bar', $previousValue);
  125. return 'lazy';
  126. });
  127. $this->assertEquals(array('foo' => 'lazy'), $this->resolver->resolve());
  128. }
  129. public function testAccessPreviousLazyDefaultValue()
  130. {
  131. // defined by superclass
  132. $this->resolver->setDefault('foo', function (Options $options) {
  133. return 'bar';
  134. });
  135. // defined by subclass
  136. $this->resolver->setDefault('foo', function (Options $options, $previousValue) {
  137. Assert::assertEquals('bar', $previousValue);
  138. return 'lazy';
  139. });
  140. $this->assertEquals(array('foo' => 'lazy'), $this->resolver->resolve());
  141. }
  142. public function testPreviousValueIsNotEvaluatedIfNoSecondArgument()
  143. {
  144. // defined by superclass
  145. $this->resolver->setDefault('foo', function () {
  146. Assert::fail('Should not be called');
  147. });
  148. // defined by subclass, no $previousValue argument defined!
  149. $this->resolver->setDefault('foo', function (Options $options) {
  150. return 'lazy';
  151. });
  152. $this->assertEquals(array('foo' => 'lazy'), $this->resolver->resolve());
  153. }
  154. public function testOverwrittenLazyOptionNotEvaluated()
  155. {
  156. $this->resolver->setDefault('foo', function (Options $options) {
  157. Assert::fail('Should not be called');
  158. });
  159. $this->resolver->setDefault('foo', 'bar');
  160. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  161. }
  162. public function testInvokeEachLazyOptionOnlyOnce()
  163. {
  164. $calls = 0;
  165. $this->resolver->setDefault('lazy1', function (Options $options) use (&$calls) {
  166. Assert::assertSame(1, ++$calls);
  167. $options['lazy2'];
  168. });
  169. $this->resolver->setDefault('lazy2', function (Options $options) use (&$calls) {
  170. Assert::assertSame(2, ++$calls);
  171. });
  172. $this->resolver->resolve();
  173. $this->assertSame(2, $calls);
  174. }
  175. public function testSetRequiredReturnsThis()
  176. {
  177. $this->assertSame($this->resolver, $this->resolver->setRequired('foo'));
  178. }
  179. /**
  180. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  181. */
  182. public function testFailIfSetRequiredFromLazyOption()
  183. {
  184. $this->resolver->setDefault('foo', function (Options $options) {
  185. $options->setRequired('bar');
  186. });
  187. $this->resolver->resolve();
  188. }
  189. /**
  190. * @expectedException \Symfony\Component\OptionsResolver\Exception\MissingOptionsException
  191. */
  192. public function testResolveFailsIfRequiredOptionMissing()
  193. {
  194. $this->resolver->setRequired('foo');
  195. $this->resolver->resolve();
  196. }
  197. public function testResolveSucceedsIfRequiredOptionSet()
  198. {
  199. $this->resolver->setRequired('foo');
  200. $this->resolver->setDefault('foo', 'bar');
  201. $this->assertNotEmpty($this->resolver->resolve());
  202. }
  203. public function testResolveSucceedsIfRequiredOptionPassed()
  204. {
  205. $this->resolver->setRequired('foo');
  206. $this->assertNotEmpty($this->resolver->resolve(array('foo' => 'bar')));
  207. }
  208. public function testIsRequired()
  209. {
  210. $this->assertFalse($this->resolver->isRequired('foo'));
  211. $this->resolver->setRequired('foo');
  212. $this->assertTrue($this->resolver->isRequired('foo'));
  213. }
  214. public function testRequiredIfSetBefore()
  215. {
  216. $this->assertFalse($this->resolver->isRequired('foo'));
  217. $this->resolver->setDefault('foo', 'bar');
  218. $this->resolver->setRequired('foo');
  219. $this->assertTrue($this->resolver->isRequired('foo'));
  220. }
  221. public function testStillRequiredAfterSet()
  222. {
  223. $this->assertFalse($this->resolver->isRequired('foo'));
  224. $this->resolver->setRequired('foo');
  225. $this->resolver->setDefault('foo', 'bar');
  226. $this->assertTrue($this->resolver->isRequired('foo'));
  227. }
  228. public function testIsNotRequiredAfterRemove()
  229. {
  230. $this->assertFalse($this->resolver->isRequired('foo'));
  231. $this->resolver->setRequired('foo');
  232. $this->resolver->remove('foo');
  233. $this->assertFalse($this->resolver->isRequired('foo'));
  234. }
  235. public function testIsNotRequiredAfterClear()
  236. {
  237. $this->assertFalse($this->resolver->isRequired('foo'));
  238. $this->resolver->setRequired('foo');
  239. $this->resolver->clear();
  240. $this->assertFalse($this->resolver->isRequired('foo'));
  241. }
  242. public function testGetRequiredOptions()
  243. {
  244. $this->resolver->setRequired(array('foo', 'bar'));
  245. $this->resolver->setDefault('bam', 'baz');
  246. $this->resolver->setDefault('foo', 'boo');
  247. $this->assertSame(array('foo', 'bar'), $this->resolver->getRequiredOptions());
  248. }
  249. public function testIsMissingIfNotSet()
  250. {
  251. $this->assertFalse($this->resolver->isMissing('foo'));
  252. $this->resolver->setRequired('foo');
  253. $this->assertTrue($this->resolver->isMissing('foo'));
  254. }
  255. public function testIsNotMissingIfSet()
  256. {
  257. $this->resolver->setDefault('foo', 'bar');
  258. $this->assertFalse($this->resolver->isMissing('foo'));
  259. $this->resolver->setRequired('foo');
  260. $this->assertFalse($this->resolver->isMissing('foo'));
  261. }
  262. public function testIsNotMissingAfterRemove()
  263. {
  264. $this->resolver->setRequired('foo');
  265. $this->resolver->remove('foo');
  266. $this->assertFalse($this->resolver->isMissing('foo'));
  267. }
  268. public function testIsNotMissingAfterClear()
  269. {
  270. $this->resolver->setRequired('foo');
  271. $this->resolver->clear();
  272. $this->assertFalse($this->resolver->isRequired('foo'));
  273. }
  274. public function testGetMissingOptions()
  275. {
  276. $this->resolver->setRequired(array('foo', 'bar'));
  277. $this->resolver->setDefault('bam', 'baz');
  278. $this->resolver->setDefault('foo', 'boo');
  279. $this->assertSame(array('bar'), $this->resolver->getMissingOptions());
  280. }
  281. /**
  282. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  283. */
  284. public function testFailIfSetDefinedFromLazyOption()
  285. {
  286. $this->resolver->setDefault('foo', function (Options $options) {
  287. $options->setDefined('bar');
  288. });
  289. $this->resolver->resolve();
  290. }
  291. public function testDefinedOptionsNotIncludedInResolvedOptions()
  292. {
  293. $this->resolver->setDefined('foo');
  294. $this->assertSame(array(), $this->resolver->resolve());
  295. }
  296. public function testDefinedOptionsIncludedIfDefaultSetBefore()
  297. {
  298. $this->resolver->setDefault('foo', 'bar');
  299. $this->resolver->setDefined('foo');
  300. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  301. }
  302. public function testDefinedOptionsIncludedIfDefaultSetAfter()
  303. {
  304. $this->resolver->setDefined('foo');
  305. $this->resolver->setDefault('foo', 'bar');
  306. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  307. }
  308. public function testDefinedOptionsIncludedIfPassedToResolve()
  309. {
  310. $this->resolver->setDefined('foo');
  311. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve(array('foo' => 'bar')));
  312. }
  313. public function testIsDefined()
  314. {
  315. $this->assertFalse($this->resolver->isDefined('foo'));
  316. $this->resolver->setDefined('foo');
  317. $this->assertTrue($this->resolver->isDefined('foo'));
  318. }
  319. public function testLazyOptionsAreDefined()
  320. {
  321. $this->assertFalse($this->resolver->isDefined('foo'));
  322. $this->resolver->setDefault('foo', function (Options $options) {});
  323. $this->assertTrue($this->resolver->isDefined('foo'));
  324. }
  325. public function testRequiredOptionsAreDefined()
  326. {
  327. $this->assertFalse($this->resolver->isDefined('foo'));
  328. $this->resolver->setRequired('foo');
  329. $this->assertTrue($this->resolver->isDefined('foo'));
  330. }
  331. public function testSetOptionsAreDefined()
  332. {
  333. $this->assertFalse($this->resolver->isDefined('foo'));
  334. $this->resolver->setDefault('foo', 'bar');
  335. $this->assertTrue($this->resolver->isDefined('foo'));
  336. }
  337. public function testGetDefinedOptions()
  338. {
  339. $this->resolver->setDefined(array('foo', 'bar'));
  340. $this->resolver->setDefault('baz', 'bam');
  341. $this->resolver->setRequired('boo');
  342. $this->assertSame(array('foo', 'bar', 'baz', 'boo'), $this->resolver->getDefinedOptions());
  343. }
  344. public function testRemovedOptionsAreNotDefined()
  345. {
  346. $this->assertFalse($this->resolver->isDefined('foo'));
  347. $this->resolver->setDefined('foo');
  348. $this->assertTrue($this->resolver->isDefined('foo'));
  349. $this->resolver->remove('foo');
  350. $this->assertFalse($this->resolver->isDefined('foo'));
  351. }
  352. public function testClearedOptionsAreNotDefined()
  353. {
  354. $this->assertFalse($this->resolver->isDefined('foo'));
  355. $this->resolver->setDefined('foo');
  356. $this->assertTrue($this->resolver->isDefined('foo'));
  357. $this->resolver->clear();
  358. $this->assertFalse($this->resolver->isDefined('foo'));
  359. }
  360. /**
  361. * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
  362. */
  363. public function testSetAllowedTypesFailsIfUnknownOption()
  364. {
  365. $this->resolver->setAllowedTypes('foo', 'string');
  366. }
  367. /**
  368. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  369. */
  370. public function testFailIfSetAllowedTypesFromLazyOption()
  371. {
  372. $this->resolver->setDefault('foo', function (Options $options) {
  373. $options->setAllowedTypes('bar', 'string');
  374. });
  375. $this->resolver->setDefault('bar', 'baz');
  376. $this->resolver->resolve();
  377. }
  378. /**
  379. * @dataProvider provideInvalidTypes
  380. */
  381. public function testResolveFailsIfInvalidType($actualType, $allowedType, $exceptionMessage)
  382. {
  383. $this->resolver->setDefined('option');
  384. $this->resolver->setAllowedTypes('option', $allowedType);
  385. if (method_exists($this, 'expectException')) {
  386. $this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');
  387. $this->expectExceptionMessage($exceptionMessage);
  388. } else {
  389. $this->setExpectedException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException', $exceptionMessage);
  390. }
  391. $this->resolver->resolve(array('option' => $actualType));
  392. }
  393. public function provideInvalidTypes()
  394. {
  395. return array(
  396. array(true, 'string', 'The option "option" with value true is expected to be of type "string", but is of type "boolean".'),
  397. array(false, 'string', 'The option "option" with value false is expected to be of type "string", but is of type "boolean".'),
  398. array(fopen(__FILE__, 'r'), 'string', 'The option "option" with value resource is expected to be of type "string", but is of type "resource".'),
  399. array(array(), 'string', 'The option "option" with value array is expected to be of type "string", but is of type "array".'),
  400. array(new OptionsResolver(), 'string', 'The option "option" with value Symfony\Component\OptionsResolver\OptionsResolver is expected to be of type "string", but is of type "Symfony\Component\OptionsResolver\OptionsResolver".'),
  401. array(42, 'string', 'The option "option" with value 42 is expected to be of type "string", but is of type "integer".'),
  402. array(null, 'string', 'The option "option" with value null is expected to be of type "string", but is of type "NULL".'),
  403. array('bar', '\stdClass', 'The option "option" with value "bar" is expected to be of type "\stdClass", but is of type "string".'),
  404. );
  405. }
  406. public function testResolveSucceedsIfValidType()
  407. {
  408. $this->resolver->setDefault('foo', 'bar');
  409. $this->resolver->setAllowedTypes('foo', 'string');
  410. $this->assertNotEmpty($this->resolver->resolve());
  411. }
  412. /**
  413. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  414. * @expectedExceptionMessage The option "foo" with value 42 is expected to be of type "string" or "bool", but is of type "integer".
  415. */
  416. public function testResolveFailsIfInvalidTypeMultiple()
  417. {
  418. $this->resolver->setDefault('foo', 42);
  419. $this->resolver->setAllowedTypes('foo', array('string', 'bool'));
  420. $this->resolver->resolve();
  421. }
  422. public function testResolveSucceedsIfValidTypeMultiple()
  423. {
  424. $this->resolver->setDefault('foo', true);
  425. $this->resolver->setAllowedTypes('foo', array('string', 'bool'));
  426. $this->assertNotEmpty($this->resolver->resolve());
  427. }
  428. public function testResolveSucceedsIfInstanceOfClass()
  429. {
  430. $this->resolver->setDefault('foo', new \stdClass());
  431. $this->resolver->setAllowedTypes('foo', '\stdClass');
  432. $this->assertNotEmpty($this->resolver->resolve());
  433. }
  434. /**
  435. * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
  436. */
  437. public function testAddAllowedTypesFailsIfUnknownOption()
  438. {
  439. $this->resolver->addAllowedTypes('foo', 'string');
  440. }
  441. /**
  442. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  443. */
  444. public function testFailIfAddAllowedTypesFromLazyOption()
  445. {
  446. $this->resolver->setDefault('foo', function (Options $options) {
  447. $options->addAllowedTypes('bar', 'string');
  448. });
  449. $this->resolver->setDefault('bar', 'baz');
  450. $this->resolver->resolve();
  451. }
  452. /**
  453. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  454. */
  455. public function testResolveFailsIfInvalidAddedType()
  456. {
  457. $this->resolver->setDefault('foo', 42);
  458. $this->resolver->addAllowedTypes('foo', 'string');
  459. $this->resolver->resolve();
  460. }
  461. public function testResolveSucceedsIfValidAddedType()
  462. {
  463. $this->resolver->setDefault('foo', 'bar');
  464. $this->resolver->addAllowedTypes('foo', 'string');
  465. $this->assertNotEmpty($this->resolver->resolve());
  466. }
  467. /**
  468. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  469. */
  470. public function testResolveFailsIfInvalidAddedTypeMultiple()
  471. {
  472. $this->resolver->setDefault('foo', 42);
  473. $this->resolver->addAllowedTypes('foo', array('string', 'bool'));
  474. $this->resolver->resolve();
  475. }
  476. public function testResolveSucceedsIfValidAddedTypeMultiple()
  477. {
  478. $this->resolver->setDefault('foo', 'bar');
  479. $this->resolver->addAllowedTypes('foo', array('string', 'bool'));
  480. $this->assertNotEmpty($this->resolver->resolve());
  481. }
  482. public function testAddAllowedTypesDoesNotOverwrite()
  483. {
  484. $this->resolver->setDefault('foo', 'bar');
  485. $this->resolver->setAllowedTypes('foo', 'string');
  486. $this->resolver->addAllowedTypes('foo', 'bool');
  487. $this->resolver->setDefault('foo', 'bar');
  488. $this->assertNotEmpty($this->resolver->resolve());
  489. }
  490. public function testAddAllowedTypesDoesNotOverwrite2()
  491. {
  492. $this->resolver->setDefault('foo', 'bar');
  493. $this->resolver->setAllowedTypes('foo', 'string');
  494. $this->resolver->addAllowedTypes('foo', 'bool');
  495. $this->resolver->setDefault('foo', false);
  496. $this->assertNotEmpty($this->resolver->resolve());
  497. }
  498. /**
  499. * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
  500. */
  501. public function testSetAllowedValuesFailsIfUnknownOption()
  502. {
  503. $this->resolver->setAllowedValues('foo', 'bar');
  504. }
  505. /**
  506. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  507. */
  508. public function testFailIfSetAllowedValuesFromLazyOption()
  509. {
  510. $this->resolver->setDefault('foo', function (Options $options) {
  511. $options->setAllowedValues('bar', 'baz');
  512. });
  513. $this->resolver->setDefault('bar', 'baz');
  514. $this->resolver->resolve();
  515. }
  516. /**
  517. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  518. * @expectedExceptionMessage The option "foo" with value 42 is invalid. Accepted values are: "bar".
  519. */
  520. public function testResolveFailsIfInvalidValue()
  521. {
  522. $this->resolver->setDefined('foo');
  523. $this->resolver->setAllowedValues('foo', 'bar');
  524. $this->resolver->resolve(array('foo' => 42));
  525. }
  526. /**
  527. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  528. * @expectedExceptionMessage The option "foo" with value null is invalid. Accepted values are: "bar".
  529. */
  530. public function testResolveFailsIfInvalidValueIsNull()
  531. {
  532. $this->resolver->setDefault('foo', null);
  533. $this->resolver->setAllowedValues('foo', 'bar');
  534. $this->resolver->resolve();
  535. }
  536. /**
  537. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  538. */
  539. public function testResolveFailsIfInvalidValueStrict()
  540. {
  541. $this->resolver->setDefault('foo', 42);
  542. $this->resolver->setAllowedValues('foo', '42');
  543. $this->resolver->resolve();
  544. }
  545. public function testResolveSucceedsIfValidValue()
  546. {
  547. $this->resolver->setDefault('foo', 'bar');
  548. $this->resolver->setAllowedValues('foo', 'bar');
  549. $this->assertEquals(array('foo' => 'bar'), $this->resolver->resolve());
  550. }
  551. public function testResolveSucceedsIfValidValueIsNull()
  552. {
  553. $this->resolver->setDefault('foo', null);
  554. $this->resolver->setAllowedValues('foo', null);
  555. $this->assertEquals(array('foo' => null), $this->resolver->resolve());
  556. }
  557. /**
  558. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  559. * @expectedExceptionMessage The option "foo" with value 42 is invalid. Accepted values are: "bar", false, null.
  560. */
  561. public function testResolveFailsIfInvalidValueMultiple()
  562. {
  563. $this->resolver->setDefault('foo', 42);
  564. $this->resolver->setAllowedValues('foo', array('bar', false, null));
  565. $this->resolver->resolve();
  566. }
  567. public function testResolveSucceedsIfValidValueMultiple()
  568. {
  569. $this->resolver->setDefault('foo', 'baz');
  570. $this->resolver->setAllowedValues('foo', array('bar', 'baz'));
  571. $this->assertEquals(array('foo' => 'baz'), $this->resolver->resolve());
  572. }
  573. public function testResolveFailsIfClosureReturnsFalse()
  574. {
  575. $this->resolver->setDefault('foo', 42);
  576. $this->resolver->setAllowedValues('foo', function ($value) use (&$passedValue) {
  577. $passedValue = $value;
  578. return false;
  579. });
  580. try {
  581. $this->resolver->resolve();
  582. $this->fail('Should fail');
  583. } catch (InvalidOptionsException $e) {
  584. }
  585. $this->assertSame(42, $passedValue);
  586. }
  587. public function testResolveSucceedsIfClosureReturnsTrue()
  588. {
  589. $this->resolver->setDefault('foo', 'bar');
  590. $this->resolver->setAllowedValues('foo', function ($value) use (&$passedValue) {
  591. $passedValue = $value;
  592. return true;
  593. });
  594. $this->assertEquals(array('foo' => 'bar'), $this->resolver->resolve());
  595. $this->assertSame('bar', $passedValue);
  596. }
  597. /**
  598. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  599. */
  600. public function testResolveFailsIfAllClosuresReturnFalse()
  601. {
  602. $this->resolver->setDefault('foo', 42);
  603. $this->resolver->setAllowedValues('foo', array(
  604. function () { return false; },
  605. function () { return false; },
  606. function () { return false; },
  607. ));
  608. $this->resolver->resolve();
  609. }
  610. public function testResolveSucceedsIfAnyClosureReturnsTrue()
  611. {
  612. $this->resolver->setDefault('foo', 'bar');
  613. $this->resolver->setAllowedValues('foo', array(
  614. function () { return false; },
  615. function () { return true; },
  616. function () { return false; },
  617. ));
  618. $this->assertEquals(array('foo' => 'bar'), $this->resolver->resolve());
  619. }
  620. /**
  621. * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
  622. */
  623. public function testAddAllowedValuesFailsIfUnknownOption()
  624. {
  625. $this->resolver->addAllowedValues('foo', 'bar');
  626. }
  627. /**
  628. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  629. */
  630. public function testFailIfAddAllowedValuesFromLazyOption()
  631. {
  632. $this->resolver->setDefault('foo', function (Options $options) {
  633. $options->addAllowedValues('bar', 'baz');
  634. });
  635. $this->resolver->setDefault('bar', 'baz');
  636. $this->resolver->resolve();
  637. }
  638. /**
  639. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  640. */
  641. public function testResolveFailsIfInvalidAddedValue()
  642. {
  643. $this->resolver->setDefault('foo', 42);
  644. $this->resolver->addAllowedValues('foo', 'bar');
  645. $this->resolver->resolve();
  646. }
  647. public function testResolveSucceedsIfValidAddedValue()
  648. {
  649. $this->resolver->setDefault('foo', 'bar');
  650. $this->resolver->addAllowedValues('foo', 'bar');
  651. $this->assertEquals(array('foo' => 'bar'), $this->resolver->resolve());
  652. }
  653. public function testResolveSucceedsIfValidAddedValueIsNull()
  654. {
  655. $this->resolver->setDefault('foo', null);
  656. $this->resolver->addAllowedValues('foo', null);
  657. $this->assertEquals(array('foo' => null), $this->resolver->resolve());
  658. }
  659. /**
  660. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  661. */
  662. public function testResolveFailsIfInvalidAddedValueMultiple()
  663. {
  664. $this->resolver->setDefault('foo', 42);
  665. $this->resolver->addAllowedValues('foo', array('bar', 'baz'));
  666. $this->resolver->resolve();
  667. }
  668. public function testResolveSucceedsIfValidAddedValueMultiple()
  669. {
  670. $this->resolver->setDefault('foo', 'bar');
  671. $this->resolver->addAllowedValues('foo', array('bar', 'baz'));
  672. $this->assertEquals(array('foo' => 'bar'), $this->resolver->resolve());
  673. }
  674. public function testAddAllowedValuesDoesNotOverwrite()
  675. {
  676. $this->resolver->setDefault('foo', 'bar');
  677. $this->resolver->setAllowedValues('foo', 'bar');
  678. $this->resolver->addAllowedValues('foo', 'baz');
  679. $this->assertEquals(array('foo' => 'bar'), $this->resolver->resolve());
  680. }
  681. public function testAddAllowedValuesDoesNotOverwrite2()
  682. {
  683. $this->resolver->setDefault('foo', 'baz');
  684. $this->resolver->setAllowedValues('foo', 'bar');
  685. $this->resolver->addAllowedValues('foo', 'baz');
  686. $this->assertEquals(array('foo' => 'baz'), $this->resolver->resolve());
  687. }
  688. /**
  689. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  690. */
  691. public function testResolveFailsIfAllAddedClosuresReturnFalse()
  692. {
  693. $this->resolver->setDefault('foo', 42);
  694. $this->resolver->setAllowedValues('foo', function () { return false; });
  695. $this->resolver->addAllowedValues('foo', function () { return false; });
  696. $this->resolver->resolve();
  697. }
  698. public function testResolveSucceedsIfAnyAddedClosureReturnsTrue()
  699. {
  700. $this->resolver->setDefault('foo', 'bar');
  701. $this->resolver->setAllowedValues('foo', function () { return false; });
  702. $this->resolver->addAllowedValues('foo', function () { return true; });
  703. $this->assertEquals(array('foo' => 'bar'), $this->resolver->resolve());
  704. }
  705. public function testResolveSucceedsIfAnyAddedClosureReturnsTrue2()
  706. {
  707. $this->resolver->setDefault('foo', 'bar');
  708. $this->resolver->setAllowedValues('foo', function () { return true; });
  709. $this->resolver->addAllowedValues('foo', function () { return false; });
  710. $this->assertEquals(array('foo' => 'bar'), $this->resolver->resolve());
  711. }
  712. public function testSetNormalizerReturnsThis()
  713. {
  714. $this->resolver->setDefault('foo', 'bar');
  715. $this->assertSame($this->resolver, $this->resolver->setNormalizer('foo', function () {}));
  716. }
  717. public function testSetNormalizerClosure()
  718. {
  719. $this->resolver->setDefault('foo', 'bar');
  720. $this->resolver->setNormalizer('foo', function () {
  721. return 'normalized';
  722. });
  723. $this->assertEquals(array('foo' => 'normalized'), $this->resolver->resolve());
  724. }
  725. /**
  726. * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException
  727. */
  728. public function testSetNormalizerFailsIfUnknownOption()
  729. {
  730. $this->resolver->setNormalizer('foo', function () {});
  731. }
  732. /**
  733. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  734. */
  735. public function testFailIfSetNormalizerFromLazyOption()
  736. {
  737. $this->resolver->setDefault('foo', function (Options $options) {
  738. $options->setNormalizer('foo', function () {});
  739. });
  740. $this->resolver->setDefault('bar', 'baz');
  741. $this->resolver->resolve();
  742. }
  743. public function testNormalizerReceivesSetOption()
  744. {
  745. $this->resolver->setDefault('foo', 'bar');
  746. $this->resolver->setNormalizer('foo', function (Options $options, $value) {
  747. return 'normalized['.$value.']';
  748. });
  749. $this->assertEquals(array('foo' => 'normalized[bar]'), $this->resolver->resolve());
  750. }
  751. public function testNormalizerReceivesPassedOption()
  752. {
  753. $this->resolver->setDefault('foo', 'bar');
  754. $this->resolver->setNormalizer('foo', function (Options $options, $value) {
  755. return 'normalized['.$value.']';
  756. });
  757. $resolved = $this->resolver->resolve(array('foo' => 'baz'));
  758. $this->assertEquals(array('foo' => 'normalized[baz]'), $resolved);
  759. }
  760. /**
  761. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  762. */
  763. public function testValidateTypeBeforeNormalization()
  764. {
  765. $this->resolver->setDefault('foo', 'bar');
  766. $this->resolver->setAllowedTypes('foo', 'int');
  767. $this->resolver->setNormalizer('foo', function () {
  768. Assert::fail('Should not be called.');
  769. });
  770. $this->resolver->resolve();
  771. }
  772. /**
  773. * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
  774. */
  775. public function testValidateValueBeforeNormalization()
  776. {
  777. $this->resolver->setDefault('foo', 'bar');
  778. $this->resolver->setAllowedValues('foo', 'baz');
  779. $this->resolver->setNormalizer('foo', function () {
  780. Assert::fail('Should not be called.');
  781. });
  782. $this->resolver->resolve();
  783. }
  784. public function testNormalizerCanAccessOtherOptions()
  785. {
  786. $this->resolver->setDefault('default', 'bar');
  787. $this->resolver->setDefault('norm', 'baz');
  788. $this->resolver->setNormalizer('norm', function (Options $options) {
  789. /* @var TestCase $test */
  790. Assert::assertSame('bar', $options['default']);
  791. return 'normalized';
  792. });
  793. $this->assertEquals(array(
  794. 'default' => 'bar',
  795. 'norm' => 'normalized',
  796. ), $this->resolver->resolve());
  797. }
  798. public function testNormalizerCanAccessLazyOptions()
  799. {
  800. $this->resolver->setDefault('lazy', function (Options $options) {
  801. return 'bar';
  802. });
  803. $this->resolver->setDefault('norm', 'baz');
  804. $this->resolver->setNormalizer('norm', function (Options $options) {
  805. /* @var TestCase $test */
  806. Assert::assertEquals('bar', $options['lazy']);
  807. return 'normalized';
  808. });
  809. $this->assertEquals(array(
  810. 'lazy' => 'bar',
  811. 'norm' => 'normalized',
  812. ), $this->resolver->resolve());
  813. }
  814. /**
  815. * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
  816. */
  817. public function testFailIfCyclicDependencyBetweenNormalizers()
  818. {
  819. $this->resolver->setDefault('norm1', 'bar');
  820. $this->resolver->setDefault('norm2', 'baz');
  821. $this->resolver->setNormalizer('norm1', function (Options $options) {
  822. $options['norm2'];
  823. });
  824. $this->resolver->setNormalizer('norm2', function (Options $options) {
  825. $options['norm1'];
  826. });
  827. $this->resolver->resolve();
  828. }
  829. /**
  830. * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
  831. */
  832. public function testFailIfCyclicDependencyBetweenNormalizerAndLazyOption()
  833. {
  834. $this->resolver->setDefault('lazy', function (Options $options) {
  835. $options['norm'];
  836. });
  837. $this->resolver->setDefault('norm', 'baz');
  838. $this->resolver->setNormalizer('norm', function (Options $options) {
  839. $options['lazy'];
  840. });
  841. $this->resolver->resolve();
  842. }
  843. public function testCaughtExceptionFromNormalizerDoesNotCrashOptionResolver()
  844. {
  845. $throw = true;
  846. $this->resolver->setDefaults(array('catcher' => null, 'thrower' => null));
  847. $this->resolver->setNormalizer('catcher', function (Options $options) {
  848. try {
  849. return $options['thrower'];
  850. } catch (\Exception $e) {
  851. return false;
  852. }
  853. });
  854. $this->resolver->setNormalizer('thrower', function () use (&$throw) {
  855. if ($throw) {
  856. $throw = false;
  857. throw new \UnexpectedValueException('throwing');
  858. }
  859. return true;
  860. });
  861. $this->assertSame(array('catcher' => false, 'thrower' => true), $this->resolver->resolve());
  862. }
  863. public function testCaughtExceptionFromLazyDoesNotCrashOptionResolver()
  864. {
  865. $throw = true;
  866. $this->resolver->setDefault('catcher', function (Options $options) {
  867. try {
  868. return $options['thrower'];
  869. } catch (\Exception $e) {
  870. return false;
  871. }
  872. });
  873. $this->resolver->setDefault('thrower', function (Options $options) use (&$throw) {
  874. if ($throw) {
  875. $throw = false;
  876. throw new \UnexpectedValueException('throwing');
  877. }
  878. return true;
  879. });
  880. $this->assertSame(array('catcher' => false, 'thrower' => true), $this->resolver->resolve());
  881. }
  882. public function testInvokeEachNormalizerOnlyOnce()
  883. {
  884. $calls = 0;
  885. $this->resolver->setDefault('norm1', 'bar');
  886. $this->resolver->setDefault('norm2', 'baz');
  887. $this->resolver->setNormalizer('norm1', function ($options) use (&$calls) {
  888. Assert::assertSame(1, ++$calls);
  889. $options['norm2'];
  890. });
  891. $this->resolver->setNormalizer('norm2', function () use (&$calls) {
  892. Assert::assertSame(2, ++$calls);
  893. });
  894. $this->resolver->resolve();
  895. $this->assertSame(2, $calls);
  896. }
  897. public function testNormalizerNotCalledForUnsetOptions()
  898. {
  899. $this->resolver->setDefined('norm');
  900. $this->resolver->setNormalizer('norm', function () {
  901. Assert::fail('Should not be called.');
  902. });
  903. $this->assertEmpty($this->resolver->resolve());
  904. }
  905. public function testSetDefaultsReturnsThis()
  906. {
  907. $this->assertSame($this->resolver, $this->resolver->setDefaults(array('foo', 'bar')));
  908. }
  909. public function testSetDefaults()
  910. {
  911. $this->resolver->setDefault('one', '1');
  912. $this->resolver->setDefault('two', 'bar');
  913. $this->resolver->setDefaults(array(
  914. 'two' => '2',
  915. 'three' => '3',
  916. ));
  917. $this->assertEquals(array(
  918. 'one' => '1',
  919. 'two' => '2',
  920. 'three' => '3',
  921. ), $this->resolver->resolve());
  922. }
  923. /**
  924. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  925. */
  926. public function testFailIfSetDefaultsFromLazyOption()
  927. {
  928. $this->resolver->setDefault('foo', function (Options $options) {
  929. $options->setDefaults(array('two' => '2'));
  930. });
  931. $this->resolver->resolve();
  932. }
  933. public function testRemoveReturnsThis()
  934. {
  935. $this->resolver->setDefault('foo', 'bar');
  936. $this->assertSame($this->resolver, $this->resolver->remove('foo'));
  937. }
  938. public function testRemoveSingleOption()
  939. {
  940. $this->resolver->setDefault('foo', 'bar');
  941. $this->resolver->setDefault('baz', 'boo');
  942. $this->resolver->remove('foo');
  943. $this->assertSame(array('baz' => 'boo'), $this->resolver->resolve());
  944. }
  945. public function testRemoveMultipleOptions()
  946. {
  947. $this->resolver->setDefault('foo', 'bar');
  948. $this->resolver->setDefault('baz', 'boo');
  949. $this->resolver->setDefault('doo', 'dam');
  950. $this->resolver->remove(array('foo', 'doo'));
  951. $this->assertSame(array('baz' => 'boo'), $this->resolver->resolve());
  952. }
  953. public function testRemoveLazyOption()
  954. {
  955. $this->resolver->setDefault('foo', function (Options $options) {
  956. return 'lazy';
  957. });
  958. $this->resolver->remove('foo');
  959. $this->assertSame(array(), $this->resolver->resolve());
  960. }
  961. public function testRemoveNormalizer()
  962. {
  963. $this->resolver->setDefault('foo', 'bar');
  964. $this->resolver->setNormalizer('foo', function (Options $options, $value) {
  965. return 'normalized';
  966. });
  967. $this->resolver->remove('foo');
  968. $this->resolver->setDefault('foo', 'bar');
  969. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  970. }
  971. public function testRemoveAllowedTypes()
  972. {
  973. $this->resolver->setDefault('foo', 'bar');
  974. $this->resolver->setAllowedTypes('foo', 'int');
  975. $this->resolver->remove('foo');
  976. $this->resolver->setDefault('foo', 'bar');
  977. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  978. }
  979. public function testRemoveAllowedValues()
  980. {
  981. $this->resolver->setDefault('foo', 'bar');
  982. $this->resolver->setAllowedValues('foo', array('baz', 'boo'));
  983. $this->resolver->remove('foo');
  984. $this->resolver->setDefault('foo', 'bar');
  985. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  986. }
  987. /**
  988. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  989. */
  990. public function testFailIfRemoveFromLazyOption()
  991. {
  992. $this->resolver->setDefault('foo', function (Options $options) {
  993. $options->remove('bar');
  994. });
  995. $this->resolver->setDefault('bar', 'baz');
  996. $this->resolver->resolve();
  997. }
  998. public function testRemoveUnknownOptionIgnored()
  999. {
  1000. $this->assertNotNull($this->resolver->remove('foo'));
  1001. }
  1002. public function testClearReturnsThis()
  1003. {
  1004. $this->assertSame($this->resolver, $this->resolver->clear());
  1005. }
  1006. public function testClearRemovesAllOptions()
  1007. {
  1008. $this->resolver->setDefault('one', 1);
  1009. $this->resolver->setDefault('two', 2);
  1010. $this->resolver->clear();
  1011. $this->assertEmpty($this->resolver->resolve());
  1012. }
  1013. public function testClearLazyOption()
  1014. {
  1015. $this->resolver->setDefault('foo', function (Options $options) {
  1016. return 'lazy';
  1017. });
  1018. $this->resolver->clear();
  1019. $this->assertSame(array(), $this->resolver->resolve());
  1020. }
  1021. public function testClearNormalizer()
  1022. {
  1023. $this->resolver->setDefault('foo', 'bar');
  1024. $this->resolver->setNormalizer('foo', function (Options $options, $value) {
  1025. return 'normalized';
  1026. });
  1027. $this->resolver->clear();
  1028. $this->resolver->setDefault('foo', 'bar');
  1029. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  1030. }
  1031. public function testClearAllowedTypes()
  1032. {
  1033. $this->resolver->setDefault('foo', 'bar');
  1034. $this->resolver->setAllowedTypes('foo', 'int');
  1035. $this->resolver->clear();
  1036. $this->resolver->setDefault('foo', 'bar');
  1037. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  1038. }
  1039. public function testClearAllowedValues()
  1040. {
  1041. $this->resolver->setDefault('foo', 'bar');
  1042. $this->resolver->setAllowedValues('foo', 'baz');
  1043. $this->resolver->clear();
  1044. $this->resolver->setDefault('foo', 'bar');
  1045. $this->assertSame(array('foo' => 'bar'), $this->resolver->resolve());
  1046. }
  1047. /**
  1048. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  1049. */
  1050. public function testFailIfClearFromLazyption()
  1051. {
  1052. $this->resolver->setDefault('foo', function (Options $options) {
  1053. $options->clear();
  1054. });
  1055. $this->resolver->setDefault('bar', 'baz');
  1056. $this->resolver->resolve();
  1057. }
  1058. public function testClearOptionAndNormalizer()
  1059. {
  1060. $this->resolver->setDefault('foo1', 'bar');
  1061. $this->resolver->setNormalizer('foo1', function (Options $options) {
  1062. return '';
  1063. });
  1064. $this->resolver->setDefault('foo2', 'bar');
  1065. $this->resolver->setNormalizer('foo2', function (Options $options) {
  1066. return '';
  1067. });
  1068. $this->resolver->clear();
  1069. $this->assertEmpty($this->resolver->resolve());
  1070. }
  1071. public function testArrayAccess()
  1072. {
  1073. $this->resolver->setDefault('default1', 0);
  1074. $this->resolver->setDefault('default2', 1);
  1075. $this->resolver->setRequired('required');
  1076. $this->resolver->setDefined('defined');
  1077. $this->resolver->setDefault('lazy1', function (Options $options) {
  1078. return 'lazy';
  1079. });
  1080. $this->resolver->setDefault('lazy2', function (Options $options) {
  1081. Assert::assertArrayHasKey('default1', $options);
  1082. Assert::assertArrayHasKey('default2', $options);
  1083. Assert::assertArrayHasKey('required', $options);
  1084. Assert::assertArrayHasKey('lazy1', $options);
  1085. Assert::assertArrayHasKey('lazy2', $options);
  1086. Assert::assertArrayNotHasKey('defined', $options);
  1087. Assert::assertSame(0, $options['default1']);
  1088. Assert::assertSame(42, $options['default2']);
  1089. Assert::assertSame('value', $options['required']);
  1090. Assert::assertSame('lazy', $options['lazy1']);
  1091. // Obviously $options['lazy'] and $options['defined'] cannot be
  1092. // accessed
  1093. });
  1094. $this->resolver->resolve(array('default2' => 42, 'required' => 'value'));
  1095. }
  1096. /**
  1097. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  1098. */
  1099. public function testArrayAccessGetFailsOutsideResolve()
  1100. {
  1101. $this->resolver->setDefault('default', 0);
  1102. $this->resolver['default'];
  1103. }
  1104. /**
  1105. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  1106. */
  1107. public function testArrayAccessExistsFailsOutsideResolve()
  1108. {
  1109. $this->resolver->setDefault('default', 0);
  1110. isset($this->resolver['default']);
  1111. }
  1112. /**
  1113. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  1114. */
  1115. public function testArrayAccessSetNotSupported()
  1116. {
  1117. $this->resolver['default'] = 0;
  1118. }
  1119. /**
  1120. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  1121. */
  1122. public function testArrayAccessUnsetNotSupported()
  1123. {
  1124. $this->resolver->setDefault('default', 0);
  1125. unset($this->resolver['default']);
  1126. }
  1127. /**
  1128. * @expectedException \Symfony\Component\OptionsResolver\Exception\NoSuchOptionException
  1129. * @expectedExceptionMessage The option "undefined" does not exist. Defined options are: "foo", "lazy".
  1130. */
  1131. public function testFailIfGetNonExisting()
  1132. {
  1133. $this->resolver->setDefault('foo', 'bar');
  1134. $this->resolver->setDefault('lazy', function (Options $options) {
  1135. $options['undefined'];
  1136. });
  1137. $this->resolver->resolve();
  1138. }
  1139. /**
  1140. * @expectedException \Symfony\Component\OptionsResolver\Exception\NoSuchOptionException
  1141. * @expectedExceptionMessage The optional option "defined" has no value set. You should make sure it is set with "isset" before reading it.
  1142. */
  1143. public function testFailIfGetDefinedButUnset()
  1144. {
  1145. $this->resolver->setDefined('defined');
  1146. $this->resolver->setDefault('lazy', function (Options $options) {
  1147. $options['defined'];
  1148. });
  1149. $this->resolver->resolve();
  1150. }
  1151. /**
  1152. * @expectedException \Symfony\Component\OptionsResolver\Exception\OptionDefinitionException
  1153. */
  1154. public function testFailIfCyclicDependency()
  1155. {
  1156. $this->resolver->setDefault('lazy1', function (Options $options) {
  1157. $options['lazy2'];
  1158. });
  1159. $this->resolver->setDefault('lazy2', function (Options $options) {
  1160. $options['lazy1'];
  1161. });
  1162. $this->resolver->resolve();
  1163. }
  1164. public function testCount()
  1165. {
  1166. $this->resolver->setDefault('default', 0);
  1167. $this->resolver->setRequired('required');
  1168. $this->resolver->setDefined('defined');
  1169. $this->resolver->setDefault('lazy1', function () {});
  1170. $this->resolver->setDefault('lazy2', function (Options $options) {
  1171. Assert::assertCount(4, $options);
  1172. });
  1173. $this->assertCount(4, $this->resolver->resolve(array('required' => 'value')));
  1174. }
  1175. /**
  1176. * In resolve() we count the options that are actually set (which may be
  1177. * only a subset of the defined options). Outside of resolve(), it's not
  1178. * clear what is counted.
  1179. *
  1180. * @expectedException \Symfony\Component\OptionsResolver\Exception\AccessException
  1181. */
  1182. public function testCountFailsOutsideResolve()
  1183. {
  1184. $this->resolver->setDefault('foo', 0);
  1185. $this->resolver->setRequired('bar');
  1186. $this->resolver->setDefined('bar');
  1187. $this->resolver->setDefault('lazy1', function () {});
  1188. \count($this->resolver);
  1189. }
  1190. }