OptionsResolver2Dot6Test.php 49 KB

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