PageRenderTime 374ms CodeModel.GetById 81ms RepoModel.GetById 1ms app.codeStats 0ms

/PHPUnit/Util/Configuration.php

https://github.com/jakoch/phpunit
PHP | 1026 lines | 607 code | 137 blank | 282 comment | 115 complexity | 20b32a410ebb54ba3e3f7dc5ffa16a1f MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * PHPUnit
  4. *
  5. * Copyright (c) 2001-2012, Sebastian Bergmann <sebastian@phpunit.de>.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * * Neither the name of Sebastian Bergmann nor the names of his
  21. * contributors may be used to endorse or promote products derived
  22. * from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  27. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  28. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  29. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  30. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  31. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  32. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  34. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. * @package PHPUnit
  38. * @subpackage Util
  39. * @author Sebastian Bergmann <sebastian@phpunit.de>
  40. * @copyright 2001-2012 Sebastian Bergmann <sebastian@phpunit.de>
  41. * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
  42. * @link http://www.phpunit.de/
  43. * @since File available since Release 3.2.0
  44. */
  45. /**
  46. * Wrapper for the PHPUnit XML configuration file.
  47. *
  48. * Example XML configuration file:
  49. * <code>
  50. * <?xml version="1.0" encoding="utf-8" ?>
  51. *
  52. * <phpunit backupGlobals="true"
  53. * backupStaticAttributes="false"
  54. * bootstrap="/path/to/bootstrap.php"
  55. * cacheTokens="false"
  56. * colors="false"
  57. * convertErrorsToExceptions="true"
  58. * convertNoticesToExceptions="true"
  59. * convertWarningsToExceptions="true"
  60. * forceCoversAnnotation="false"
  61. * mapTestClassNameToCoveredClassName="false"
  62. * printerClass="PHPUnit_TextUI_ResultPrinter"
  63. * processIsolation="false"
  64. * stopOnError="false"
  65. * stopOnFailure="false"
  66. * stopOnIncomplete="false"
  67. * stopOnSkipped="false"
  68. * testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
  69. * timeoutForSmallTests="1"
  70. * timeoutForMediumTests="10"
  71. * timeoutForLargeTests="60"
  72. * strict="false"
  73. * verbose="false">
  74. * <testsuites>
  75. * <testsuite name="My Test Suite">
  76. * <directory suffix="Test.php" phpVersion="5.3.0" phpVersionOperator=">=">/path/to/files</directory>
  77. * <file phpVersion="5.3.0" phpVersionOperator=">=">/path/to/MyTest.php</file>
  78. * <exclude>/path/to/files/exclude</exclude>
  79. * </testsuite>
  80. * </testsuites>
  81. *
  82. * <groups>
  83. * <include>
  84. * <group>name</group>
  85. * </include>
  86. * <exclude>
  87. * <group>name</group>
  88. * </exclude>
  89. * </groups>
  90. *
  91. * <filter>
  92. * <blacklist>
  93. * <directory suffix=".php">/path/to/files</directory>
  94. * <file>/path/to/file</file>
  95. * <exclude>
  96. * <directory suffix=".php">/path/to/files</directory>
  97. * <file>/path/to/file</file>
  98. * </exclude>
  99. * </blacklist>
  100. * <whitelist addUncoveredFilesFromWhitelist="true"
  101. * processUncoveredFilesFromWhitelist="false">
  102. * <directory suffix=".php">/path/to/files</directory>
  103. * <file>/path/to/file</file>
  104. * <exclude>
  105. * <directory suffix=".php">/path/to/files</directory>
  106. * <file>/path/to/file</file>
  107. * </exclude>
  108. * </whitelist>
  109. * </filter>
  110. *
  111. * <listeners>
  112. * <listener class="MyListener" file="/optional/path/to/MyListener.php">
  113. * <arguments>
  114. * <array>
  115. * <element key="0">
  116. * <string>Sebastian</string>
  117. * </element>
  118. * </array>
  119. * <integer>22</integer>
  120. * <string>April</string>
  121. * <double>19.78</double>
  122. * <null/>
  123. * <object class="stdClass"/>
  124. * <file>MyRelativeFile.php</file>
  125. * <directory>MyRelativeDir</directory>
  126. * </arguments>
  127. * </listener>
  128. * </listeners>
  129. *
  130. * <logging>
  131. * <log type="coverage-html" target="/tmp/report"
  132. charset="UTF-8" highlight="false"
  133. * lowUpperBound="35" highLowerBound="70"/>
  134. * <log type="coverage-clover" target="/tmp/clover.xml"/>
  135. * <log type="json" target="/tmp/logfile.json"/>
  136. * <log type="plain" target="/tmp/logfile.txt"/>
  137. * <log type="tap" target="/tmp/logfile.tap"/>
  138. * <log type="junit" target="/tmp/logfile.xml" logIncompleteSkipped="false"/>
  139. * <log type="testdox-html" target="/tmp/testdox.html"/>
  140. * <log type="testdox-text" target="/tmp/testdox.txt"/>
  141. * </logging>
  142. *
  143. * <php>
  144. * <includePath>.</includePath>
  145. * <ini name="foo" value="bar"/>
  146. * <const name="foo" value="bar"/>
  147. * <var name="foo" value="bar"/>
  148. * <env name="foo" value="bar"/>
  149. * <post name="foo" value="bar"/>
  150. * <get name="foo" value="bar"/>
  151. * <cookie name="foo" value="bar"/>
  152. * <server name="foo" value="bar"/>
  153. * <files name="foo" value="bar"/>
  154. * <request name="foo" value="bar"/>
  155. * </php>
  156. *
  157. * <selenium>
  158. * <browser name="Firefox on Linux"
  159. * browser="*firefox /usr/lib/firefox/firefox-bin"
  160. * host="my.linux.box"
  161. * port="4444"
  162. * timeout="30000"/>
  163. * </selenium>
  164. * </phpunit>
  165. * </code>
  166. *
  167. * @package PHPUnit
  168. * @subpackage Util
  169. * @author Sebastian Bergmann <sebastian@phpunit.de>
  170. * @copyright 2001-2012 Sebastian Bergmann <sebastian@phpunit.de>
  171. * @license http://www.opensource.org/licenses/BSD-3-Clause The BSD 3-Clause License
  172. * @link http://www.phpunit.de/
  173. * @since Class available since Release 3.2.0
  174. */
  175. class PHPUnit_Util_Configuration
  176. {
  177. private static $instances = array();
  178. protected $document;
  179. protected $xpath;
  180. protected $filename;
  181. /**
  182. * Loads a PHPUnit configuration file.
  183. *
  184. * @param string $filename
  185. */
  186. protected function __construct($filename)
  187. {
  188. $this->filename = $filename;
  189. $this->document = PHPUnit_Util_XML::loadFile($filename, FALSE, TRUE);
  190. $this->xpath = new DOMXPath($this->document);
  191. }
  192. /**
  193. * @since Method available since Release 3.4.0
  194. */
  195. private final function __clone()
  196. {
  197. }
  198. /**
  199. * Returns a PHPUnit configuration object.
  200. *
  201. * @param string $filename
  202. * @return PHPUnit_Util_Configuration
  203. * @since Method available since Release 3.4.0
  204. */
  205. public static function getInstance($filename)
  206. {
  207. $realpath = realpath($filename);
  208. if ($realpath === FALSE) {
  209. throw new PHPUnit_Framework_Exception(
  210. sprintf(
  211. 'Could not read "%s".',
  212. $filename
  213. )
  214. );
  215. }
  216. if (!isset(self::$instances[$realpath])) {
  217. self::$instances[$realpath] = new PHPUnit_Util_Configuration($realpath);
  218. }
  219. return self::$instances[$realpath];
  220. }
  221. /**
  222. * Returns the realpath to the configuration file.
  223. *
  224. * @return string
  225. * @since Method available since Release 3.6.0
  226. */
  227. public function getFilename()
  228. {
  229. return $this->filename;
  230. }
  231. /**
  232. * Returns the configuration for SUT filtering.
  233. *
  234. * @return array
  235. * @since Method available since Release 3.2.1
  236. */
  237. public function getFilterConfiguration()
  238. {
  239. $addUncoveredFilesFromWhitelist = TRUE;
  240. $processUncoveredFilesFromWhitelist = FALSE;
  241. $tmp = $this->xpath->query('filter/whitelist');
  242. if ($tmp->length == 1) {
  243. if ($tmp->item(0)->hasAttribute('addUncoveredFilesFromWhitelist')) {
  244. $addUncoveredFilesFromWhitelist = $this->getBoolean(
  245. (string)$tmp->item(0)->getAttribute(
  246. 'addUncoveredFilesFromWhitelist'
  247. ),
  248. TRUE
  249. );
  250. }
  251. if ($tmp->item(0)->hasAttribute('processUncoveredFilesFromWhitelist')) {
  252. $processUncoveredFilesFromWhitelist = $this->getBoolean(
  253. (string)$tmp->item(0)->getAttribute(
  254. 'processUncoveredFilesFromWhitelist'
  255. ),
  256. FALSE
  257. );
  258. }
  259. }
  260. return array(
  261. 'blacklist' => array(
  262. 'include' => array(
  263. 'directory' => $this->readFilterDirectories(
  264. 'filter/blacklist/directory'
  265. ),
  266. 'file' => $this->readFilterFiles(
  267. 'filter/blacklist/file'
  268. )
  269. ),
  270. 'exclude' => array(
  271. 'directory' => $this->readFilterDirectories(
  272. 'filter/blacklist/exclude/directory'
  273. ),
  274. 'file' => $this->readFilterFiles(
  275. 'filter/blacklist/exclude/file'
  276. )
  277. )
  278. ),
  279. 'whitelist' => array(
  280. 'addUncoveredFilesFromWhitelist' => $addUncoveredFilesFromWhitelist,
  281. 'processUncoveredFilesFromWhitelist' => $processUncoveredFilesFromWhitelist,
  282. 'include' => array(
  283. 'directory' => $this->readFilterDirectories(
  284. 'filter/whitelist/directory'
  285. ),
  286. 'file' => $this->readFilterFiles(
  287. 'filter/whitelist/file'
  288. )
  289. ),
  290. 'exclude' => array(
  291. 'directory' => $this->readFilterDirectories(
  292. 'filter/whitelist/exclude/directory'
  293. ),
  294. 'file' => $this->readFilterFiles(
  295. 'filter/whitelist/exclude/file'
  296. )
  297. )
  298. )
  299. );
  300. }
  301. /**
  302. * Returns the configuration for groups.
  303. *
  304. * @return array
  305. * @since Method available since Release 3.2.1
  306. */
  307. public function getGroupConfiguration()
  308. {
  309. $groups = array(
  310. 'include' => array(),
  311. 'exclude' => array()
  312. );
  313. foreach ($this->xpath->query('groups/include/group') as $group) {
  314. $groups['include'][] = (string)$group->nodeValue;
  315. }
  316. foreach ($this->xpath->query('groups/exclude/group') as $group) {
  317. $groups['exclude'][] = (string)$group->nodeValue;
  318. }
  319. return $groups;
  320. }
  321. /**
  322. * Returns the configuration for listeners.
  323. *
  324. * @return array
  325. * @since Method available since Release 3.4.0
  326. */
  327. public function getListenerConfiguration()
  328. {
  329. $result = array();
  330. foreach ($this->xpath->query('listeners/listener') as $listener) {
  331. $class = (string)$listener->getAttribute('class');
  332. $file = '';
  333. $arguments = array();
  334. if ($listener->hasAttribute('file')) {
  335. $file = $this->toAbsolutePath(
  336. (string)$listener->getAttribute('file'), TRUE
  337. );
  338. }
  339. foreach ($listener->childNodes as $node) {
  340. if ($node instanceof DOMElement && $node->tagName == 'arguments') {
  341. foreach ($node->childNodes as $argument) {
  342. if ($argument instanceof DOMElement) {
  343. if ($argument->tagName == 'file' ||
  344. $argument->tagName == 'directory') {
  345. $arguments[] = $this->toAbsolutePath((string)$argument->nodeValue);
  346. } else {
  347. $arguments[] = PHPUnit_Util_XML::xmlToVariable($argument);
  348. }
  349. }
  350. }
  351. }
  352. }
  353. $result[] = array(
  354. 'class' => $class,
  355. 'file' => $file,
  356. 'arguments' => $arguments
  357. );
  358. }
  359. return $result;
  360. }
  361. /**
  362. * Returns the logging configuration.
  363. *
  364. * @return array
  365. */
  366. public function getLoggingConfiguration()
  367. {
  368. $result = array();
  369. foreach ($this->xpath->query('logging/log') as $log) {
  370. $type = (string)$log->getAttribute('type');
  371. $target = $this->toAbsolutePath(
  372. (string)$log->getAttribute('target')
  373. );
  374. if ($type == 'coverage-html') {
  375. if ($log->hasAttribute('title')) {
  376. $result['title'] = (string)$log->getAttribute('title');
  377. }
  378. if ($log->hasAttribute('charset')) {
  379. $result['charset'] = (string)$log->getAttribute('charset');
  380. }
  381. if ($log->hasAttribute('lowUpperBound')) {
  382. $result['lowUpperBound'] = (string)$log->getAttribute('lowUpperBound');
  383. }
  384. if ($log->hasAttribute('highLowerBound')) {
  385. $result['highLowerBound'] = (string)$log->getAttribute('highLowerBound');
  386. }
  387. if ($log->hasAttribute('highlight')) {
  388. $result['highlight'] = $this->getBoolean(
  389. (string)$log->getAttribute('highlight'),
  390. FALSE
  391. );
  392. }
  393. }
  394. else if ($type == 'junit') {
  395. if ($log->hasAttribute('logIncompleteSkipped')) {
  396. $result['logIncompleteSkipped'] = $this->getBoolean(
  397. (string)$log->getAttribute('logIncompleteSkipped'),
  398. FALSE
  399. );
  400. }
  401. }
  402. else if ($type == 'coverage-text') {
  403. if ($log->hasAttribute('showUncoveredFiles')) {
  404. $result['coverageTextShowUncoveredFiles'] = $this->getBoolean(
  405. (string)$log->getAttribute('showUncoveredFiles'),
  406. FALSE
  407. );
  408. }
  409. }
  410. $result[$type] = $target;
  411. }
  412. return $result;
  413. }
  414. /**
  415. * Returns the PHP configuration.
  416. *
  417. * @return array
  418. * @since Method available since Release 3.2.1
  419. */
  420. public function getPHPConfiguration()
  421. {
  422. $result = array(
  423. 'include_path' => array(),
  424. 'ini' => array(),
  425. 'const' => array(),
  426. 'var' => array(),
  427. 'env' => array(),
  428. 'post' => array(),
  429. 'get' => array(),
  430. 'cookie' => array(),
  431. 'server' => array(),
  432. 'files' => array(),
  433. 'request' => array()
  434. );
  435. foreach ($this->xpath->query('php/includePath') as $includePath) {
  436. $path = (string)$includePath->nodeValue;
  437. $result['include_path'][] = $this->toAbsolutePath($path);
  438. }
  439. foreach ($this->xpath->query('php/ini') as $ini) {
  440. $name = (string)$ini->getAttribute('name');
  441. $value = (string)$ini->getAttribute('value');
  442. $result['ini'][$name] = $value;
  443. }
  444. foreach ($this->xpath->query('php/const') as $const) {
  445. $name = (string)$const->getAttribute('name');
  446. $value = (string)$const->getAttribute('value');
  447. $result['const'][$name] = $this->getBoolean($value, $value);
  448. }
  449. foreach (array('var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request') as $array) {
  450. foreach ($this->xpath->query('php/' . $array) as $var) {
  451. $name = (string)$var->getAttribute('name');
  452. $value = (string)$var->getAttribute('value');
  453. $result[$array][$name] = $this->getBoolean($value, $value);
  454. }
  455. }
  456. return $result;
  457. }
  458. /**
  459. * Handles the PHP configuration.
  460. *
  461. * @since Method available since Release 3.2.20
  462. */
  463. public function handlePHPConfiguration()
  464. {
  465. $configuration = $this->getPHPConfiguration();
  466. if (! empty($configuration['include_path'])) {
  467. ini_set(
  468. 'include_path',
  469. implode(PATH_SEPARATOR, $configuration['include_path']) .
  470. PATH_SEPARATOR .
  471. ini_get('include_path')
  472. );
  473. }
  474. foreach ($configuration['ini'] as $name => $value) {
  475. if (defined($value)) {
  476. $value = constant($value);
  477. }
  478. ini_set($name, $value);
  479. }
  480. foreach ($configuration['const'] as $name => $value) {
  481. if (!defined($name)) {
  482. define($name, $value);
  483. }
  484. }
  485. foreach (array('var', 'env', 'post', 'get', 'cookie', 'server', 'files', 'request') as $array) {
  486. if ($array == 'var') {
  487. $target = &$GLOBALS;
  488. } else {
  489. $target = &$GLOBALS['_' . strtoupper($array)];
  490. }
  491. foreach ($configuration[$array] as $name => $value) {
  492. $target[$name] = $value;
  493. }
  494. }
  495. foreach ($configuration['env'] as $name => $value) {
  496. putenv("$name=$value");
  497. }
  498. }
  499. /**
  500. * Returns the PHPUnit configuration.
  501. *
  502. * @return array
  503. * @since Method available since Release 3.2.14
  504. */
  505. public function getPHPUnitConfiguration()
  506. {
  507. $result = array();
  508. $root = $this->document->documentElement;
  509. if ($root->hasAttribute('cacheTokens')) {
  510. $result['cacheTokens'] = $this->getBoolean(
  511. (string)$root->getAttribute('cacheTokens'), FALSE
  512. );
  513. }
  514. if ($root->hasAttribute('colors')) {
  515. $result['colors'] = $this->getBoolean(
  516. (string)$root->getAttribute('colors'), FALSE
  517. );
  518. }
  519. if ($root->hasAttribute('backupGlobals')) {
  520. $result['backupGlobals'] = $this->getBoolean(
  521. (string)$root->getAttribute('backupGlobals'), TRUE
  522. );
  523. }
  524. if ($root->hasAttribute('backupStaticAttributes')) {
  525. $result['backupStaticAttributes'] = $this->getBoolean(
  526. (string)$root->getAttribute('backupStaticAttributes'), FALSE
  527. );
  528. }
  529. if ($root->hasAttribute('bootstrap')) {
  530. $result['bootstrap'] = $this->toAbsolutePath(
  531. (string)$root->getAttribute('bootstrap')
  532. );
  533. }
  534. if ($root->hasAttribute('convertErrorsToExceptions')) {
  535. $result['convertErrorsToExceptions'] = $this->getBoolean(
  536. (string)$root->getAttribute('convertErrorsToExceptions'), TRUE
  537. );
  538. }
  539. if ($root->hasAttribute('convertNoticesToExceptions')) {
  540. $result['convertNoticesToExceptions'] = $this->getBoolean(
  541. (string)$root->getAttribute('convertNoticesToExceptions'), TRUE
  542. );
  543. }
  544. if ($root->hasAttribute('convertWarningsToExceptions')) {
  545. $result['convertWarningsToExceptions'] = $this->getBoolean(
  546. (string)$root->getAttribute('convertWarningsToExceptions'), TRUE
  547. );
  548. }
  549. if ($root->hasAttribute('forceCoversAnnotation')) {
  550. $result['forceCoversAnnotation'] = $this->getBoolean(
  551. (string)$root->getAttribute('forceCoversAnnotation'), FALSE
  552. );
  553. }
  554. if ($root->hasAttribute('mapTestClassNameToCoveredClassName')) {
  555. $result['mapTestClassNameToCoveredClassName'] = $this->getBoolean(
  556. (string)$root->getAttribute('mapTestClassNameToCoveredClassName'),
  557. FALSE
  558. );
  559. }
  560. if ($root->hasAttribute('processIsolation')) {
  561. $result['processIsolation'] = $this->getBoolean(
  562. (string)$root->getAttribute('processIsolation'), FALSE
  563. );
  564. }
  565. if ($root->hasAttribute('stopOnError')) {
  566. $result['stopOnError'] = $this->getBoolean(
  567. (string)$root->getAttribute('stopOnError'), FALSE
  568. );
  569. }
  570. if ($root->hasAttribute('stopOnFailure')) {
  571. $result['stopOnFailure'] = $this->getBoolean(
  572. (string)$root->getAttribute('stopOnFailure'), FALSE
  573. );
  574. }
  575. if ($root->hasAttribute('stopOnIncomplete')) {
  576. $result['stopOnIncomplete'] = $this->getBoolean(
  577. (string)$root->getAttribute('stopOnIncomplete'), FALSE
  578. );
  579. }
  580. if ($root->hasAttribute('stopOnSkipped')) {
  581. $result['stopOnSkipped'] = $this->getBoolean(
  582. (string)$root->getAttribute('stopOnSkipped'), FALSE
  583. );
  584. }
  585. if ($root->hasAttribute('testSuiteLoaderClass')) {
  586. $result['testSuiteLoaderClass'] = (string)$root->getAttribute(
  587. 'testSuiteLoaderClass'
  588. );
  589. }
  590. if ($root->hasAttribute('testSuiteLoaderFile')) {
  591. $result['testSuiteLoaderFile'] = (string)$root->getAttribute(
  592. 'testSuiteLoaderFile'
  593. );
  594. }
  595. if ($root->hasAttribute('printerClass')) {
  596. $result['printerClass'] = (string)$root->getAttribute(
  597. 'printerClass'
  598. );
  599. }
  600. if ($root->hasAttribute('printerFile')) {
  601. $result['printerFile'] = (string)$root->getAttribute(
  602. 'printerFile'
  603. );
  604. }
  605. if ($root->hasAttribute('timeoutForSmallTests')) {
  606. $result['timeoutForSmallTests'] = $this->getInteger(
  607. (string)$root->getAttribute('timeoutForSmallTests'), 1
  608. );
  609. }
  610. if ($root->hasAttribute('timeoutForMediumTests')) {
  611. $result['timeoutForMediumTests'] = $this->getInteger(
  612. (string)$root->getAttribute('timeoutForMediumTests'), 10
  613. );
  614. }
  615. if ($root->hasAttribute('timeoutForLargeTests')) {
  616. $result['timeoutForLargeTests'] = $this->getInteger(
  617. (string)$root->getAttribute('timeoutForLargeTests'), 60
  618. );
  619. }
  620. if ($root->hasAttribute('strict')) {
  621. $result['strict'] = $this->getBoolean(
  622. (string)$root->getAttribute('strict'), FALSE
  623. );
  624. }
  625. if ($root->hasAttribute('verbose')) {
  626. $result['verbose'] = $this->getBoolean(
  627. (string)$root->getAttribute('verbose'), FALSE
  628. );
  629. }
  630. return $result;
  631. }
  632. /**
  633. * Returns the SeleniumTestCase browser configuration.
  634. *
  635. * @return array
  636. * @since Method available since Release 3.2.9
  637. */
  638. public function getSeleniumBrowserConfiguration()
  639. {
  640. $result = array();
  641. foreach ($this->xpath->query('selenium/browser') as $config) {
  642. $name = (string)$config->getAttribute('name');
  643. $browser = (string)$config->getAttribute('browser');
  644. if ($config->hasAttribute('host')) {
  645. $host = (string)$config->getAttribute('host');
  646. } else {
  647. $host = 'localhost';
  648. }
  649. if ($config->hasAttribute('port')) {
  650. $port = $this->getInteger(
  651. (string)$config->getAttribute('port'), 4444
  652. );
  653. } else {
  654. $port = 4444;
  655. }
  656. if ($config->hasAttribute('timeout')) {
  657. $timeout = $this->getInteger(
  658. (string)$config->getAttribute('timeout'), 30000
  659. );
  660. } else {
  661. $timeout = 30000;
  662. }
  663. $result[] = array(
  664. 'name' => $name,
  665. 'browser' => $browser,
  666. 'host' => $host,
  667. 'port' => $port,
  668. 'timeout' => $timeout
  669. );
  670. }
  671. return $result;
  672. }
  673. /**
  674. * Returns the test suite configuration.
  675. *
  676. * @return PHPUnit_Framework_TestSuite
  677. * @since Method available since Release 3.2.1
  678. */
  679. public function getTestSuiteConfiguration($testSuiteFilter=null)
  680. {
  681. $testSuiteNodes = $this->xpath->query('testsuites/testsuite');
  682. if ($testSuiteNodes->length == 0) {
  683. $testSuiteNodes = $this->xpath->query('testsuite');
  684. }
  685. if ($testSuiteNodes->length == 1) {
  686. return $this->getTestSuite($testSuiteNodes->item(0), $testSuiteFilter);
  687. }
  688. if ($testSuiteNodes->length > 1) {
  689. $suite = new PHPUnit_Framework_TestSuite;
  690. foreach ($testSuiteNodes as $testSuiteNode) {
  691. $suite->addTestSuite(
  692. $this->getTestSuite($testSuiteNode, $testSuiteFilter)
  693. );
  694. }
  695. return $suite;
  696. }
  697. }
  698. /**
  699. * @param DOMElement $testSuiteNode
  700. * @return PHPUnit_Framework_TestSuite
  701. * @since Method available since Release 3.4.0
  702. */
  703. protected function getTestSuite(DOMElement $testSuiteNode, $testSuiteFilter=null)
  704. {
  705. if ($testSuiteNode->hasAttribute('name')) {
  706. $suite = new PHPUnit_Framework_TestSuite(
  707. (string)$testSuiteNode->getAttribute('name')
  708. );
  709. } else {
  710. $suite = new PHPUnit_Framework_TestSuite;
  711. }
  712. $exclude = array();
  713. foreach ($testSuiteNode->getElementsByTagName('exclude') as $excludeNode) {
  714. $exclude[] = (string)$excludeNode->nodeValue;
  715. }
  716. $fileIteratorFacade = new File_Iterator_Facade;
  717. foreach ($testSuiteNode->getElementsByTagName('directory') as $directoryNode) {
  718. if ($testSuiteFilter && $directoryNode->parentNode->getAttribute('name') != $testSuiteFilter) {
  719. continue;
  720. }
  721. $directory = (string)$directoryNode->nodeValue;
  722. if (empty($directory)) {
  723. continue;
  724. }
  725. if ($directoryNode->hasAttribute('phpVersion')) {
  726. $phpVersion = (string)$directoryNode->getAttribute('phpVersion');
  727. } else {
  728. $phpVersion = PHP_VERSION;
  729. }
  730. if ($directoryNode->hasAttribute('phpVersionOperator')) {
  731. $phpVersionOperator = (string)$directoryNode->getAttribute('phpVersionOperator');
  732. } else {
  733. $phpVersionOperator = '>=';
  734. }
  735. if (!version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) {
  736. continue;
  737. }
  738. if ($directoryNode->hasAttribute('prefix')) {
  739. $prefix = (string)$directoryNode->getAttribute('prefix');
  740. } else {
  741. $prefix = '';
  742. }
  743. if ($directoryNode->hasAttribute('suffix')) {
  744. $suffix = (string)$directoryNode->getAttribute('suffix');
  745. } else {
  746. $suffix = 'Test.php';
  747. }
  748. $files = $fileIteratorFacade->getFilesAsArray(
  749. $this->toAbsolutePath($directory),
  750. $suffix,
  751. $prefix,
  752. $exclude
  753. );
  754. $suite->addTestFiles($files);
  755. }
  756. foreach ($testSuiteNode->getElementsByTagName('file') as $fileNode) {
  757. if ($testSuiteFilter && $fileNode->parentNode->getAttribute('name') != $testSuiteFilter) {
  758. continue;
  759. }
  760. $file = (string)$fileNode->nodeValue;
  761. if (empty($file)) {
  762. continue;
  763. }
  764. // Get the absolute path to the file
  765. $file = $fileIteratorFacade->getFilesAsArray($file);
  766. if (!isset($file[0])) {
  767. continue;
  768. }
  769. $file = $file[0];
  770. if ($fileNode->hasAttribute('phpVersion')) {
  771. $phpVersion = (string)$fileNode->getAttribute('phpVersion');
  772. } else {
  773. $phpVersion = PHP_VERSION;
  774. }
  775. if ($fileNode->hasAttribute('phpVersionOperator')) {
  776. $phpVersionOperator = (string)$fileNode->getAttribute('phpVersionOperator');
  777. } else {
  778. $phpVersionOperator = '>=';
  779. }
  780. if (!version_compare(PHP_VERSION, $phpVersion, $phpVersionOperator)) {
  781. continue;
  782. }
  783. $suite->addTestFile($file);
  784. }
  785. return $suite;
  786. }
  787. /**
  788. * @param string $value
  789. * @param boolean $default
  790. * @return boolean
  791. * @since Method available since Release 3.2.3
  792. */
  793. protected function getBoolean($value, $default)
  794. {
  795. if (strtolower($value) == 'false') {
  796. return FALSE;
  797. }
  798. else if (strtolower($value) == 'true') {
  799. return TRUE;
  800. }
  801. return $default;
  802. }
  803. /**
  804. * @param string $value
  805. * @param boolean $default
  806. * @return boolean
  807. * @since Method available since Release 3.6.0
  808. */
  809. protected function getInteger($value, $default)
  810. {
  811. if (is_numeric($value)) {
  812. return (int)$value;
  813. }
  814. return $default;
  815. }
  816. /**
  817. * @param string $query
  818. * @return array
  819. * @since Method available since Release 3.2.3
  820. */
  821. protected function readFilterDirectories($query)
  822. {
  823. $directories = array();
  824. foreach ($this->xpath->query($query) as $directory) {
  825. if ($directory->hasAttribute('prefix')) {
  826. $prefix = (string)$directory->getAttribute('prefix');
  827. } else {
  828. $prefix = '';
  829. }
  830. if ($directory->hasAttribute('suffix')) {
  831. $suffix = (string)$directory->getAttribute('suffix');
  832. } else {
  833. $suffix = '.php';
  834. }
  835. if ($directory->hasAttribute('group')) {
  836. $group = (string)$directory->getAttribute('group');
  837. } else {
  838. $group = 'DEFAULT';
  839. }
  840. $directories[] = array(
  841. 'path' => $this->toAbsolutePath((string)$directory->nodeValue),
  842. 'prefix' => $prefix,
  843. 'suffix' => $suffix,
  844. 'group' => $group
  845. );
  846. }
  847. return $directories;
  848. }
  849. /**
  850. * @param string $query
  851. * @return array
  852. * @since Method available since Release 3.2.3
  853. */
  854. protected function readFilterFiles($query)
  855. {
  856. $files = array();
  857. foreach ($this->xpath->query($query) as $file) {
  858. $files[] = $this->toAbsolutePath((string)$file->nodeValue);
  859. }
  860. return $files;
  861. }
  862. /**
  863. * @param string $path
  864. * @param boolean $useIncludePath
  865. * @return string
  866. * @since Method available since Release 3.5.0
  867. */
  868. protected function toAbsolutePath($path, $useIncludePath = FALSE)
  869. {
  870. // Check whether the path is already absolute.
  871. if ($path[0] === '/' || $path[0] === '\\' ||
  872. (strlen($path) > 3 && ctype_alpha($path[0]) &&
  873. $path[1] === ':' && ($path[2] === '\\' || $path[2] === '/'))) {
  874. return $path;
  875. }
  876. // Check whether a stream is used.
  877. if (strpos($path, '://') !== FALSE) {
  878. return $path;
  879. }
  880. $file = dirname($this->filename) . DIRECTORY_SEPARATOR . $path;
  881. if ($useIncludePath && !file_exists($file)) {
  882. $includePathFile = stream_resolve_include_path($path);
  883. if ($includePathFile) {
  884. $file = $includePathFile;
  885. }
  886. }
  887. return $file;
  888. }
  889. }