AbstractConfig.php 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. /**
  3. * An abstract test class for XML/XSD validation
  4. *
  5. * Copyright © Magento, Inc. All rights reserved.
  6. * See COPYING.txt for license details.
  7. */
  8. namespace Magento\TestFramework\Integrity;
  9. abstract class AbstractConfig extends \PHPUnit\Framework\TestCase
  10. {
  11. public function testXmlFiles()
  12. {
  13. if (null === $this->_getXmlName()) {
  14. $this->markTestSkipped('No XML validation of files requested');
  15. }
  16. $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this);
  17. $invoker(
  18. /**
  19. * @param string $configFile
  20. */
  21. function ($configFile) {
  22. $this->_validateFileExpectSuccess($configFile, $this->_getXsd(), $this->_getFileXsd());
  23. },
  24. \Magento\Framework\App\Utility\Files::init()->getConfigFiles($this->_getXmlName())
  25. );
  26. }
  27. public function testSchemaUsingValidXml()
  28. {
  29. $xmlFile = $this->_getKnownValidXml();
  30. $schema = $this->_getXsd();
  31. $this->_validateFileExpectSuccess($xmlFile, $schema);
  32. }
  33. public function testSchemaUsingInvalidXml($expectedErrors = null)
  34. {
  35. if (!function_exists('libxml_set_external_entity_loader')) {
  36. $this->markTestSkipped('Skipped due to MAGETWO-45033');
  37. }
  38. $xmlFile = $this->_getKnownInvalidXml();
  39. $schema = $this->_getXsd();
  40. $this->_validateFileExpectFailure($xmlFile, $schema, $expectedErrors);
  41. }
  42. public function testFileSchemaUsingPartialXml()
  43. {
  44. if (!function_exists('libxml_set_external_entity_loader')) {
  45. $this->markTestSkipped('Skipped due to MAGETWO-45033');
  46. }
  47. $xmlFile = $this->_getKnownValidPartialXml();
  48. if ($xmlFile === null) {
  49. $this->markTestSkipped('No Partial File');
  50. return;
  51. }
  52. $schema = $this->_getFileXsd();
  53. $this->_validateFileExpectSuccess($xmlFile, $schema);
  54. }
  55. public function testFileSchemaUsingInvalidXml($expectedErrors = null)
  56. {
  57. if (!function_exists('libxml_set_external_entity_loader')) {
  58. $this->markTestSkipped('Skipped due to MAGETWO-45033');
  59. }
  60. $xmlFile = $this->_getKnownInvalidPartialXml();
  61. if ($xmlFile === null) {
  62. $this->markTestSkipped('No Partial File');
  63. return;
  64. }
  65. $schema = $this->_getFileXsd();
  66. $this->_validateFileExpectFailure($xmlFile, $schema, $expectedErrors);
  67. }
  68. public function testSchemaUsingPartialXml($expectedErrors = null)
  69. {
  70. if (!function_exists('libxml_set_external_entity_loader')) {
  71. $this->markTestSkipped('Skipped due to MAGETWO-45033');
  72. }
  73. $xmlFile = $this->_getKnownValidPartialXml();
  74. if ($xmlFile === null) {
  75. $this->markTestSkipped('No Partial File');
  76. return;
  77. }
  78. $schema = $this->_getXsd();
  79. $this->_validateFileExpectFailure($xmlFile, $schema, $expectedErrors);
  80. }
  81. /**
  82. * Run schema validation against a known bad xml file with a provided schema.
  83. *
  84. * This helper expects the validation to fail and will fail a test if no errors are found.
  85. *
  86. * @param $xmlFile string a known bad xml file.
  87. * @param $schemaFile string schema that should find errors in the known bad xml file.
  88. * @param $fileSchemaFile string schema that should find errors in the known bad xml file
  89. */
  90. protected function _validateFileExpectSuccess($xmlFile, $schemaFile, $fileSchemaFile = null)
  91. {
  92. $dom = new \DOMDocument();
  93. $dom->loadXML(file_get_contents($xmlFile));
  94. $errors = \Magento\Framework\Config\Dom::validateDomDocument($dom, $schemaFile);
  95. if ($errors) {
  96. if ($fileSchemaFile !== null) {
  97. $moreErrors = \Magento\Framework\Config\Dom::validateDomDocument($dom, $fileSchemaFile);
  98. if (empty($moreErrors)) {
  99. return;
  100. } else {
  101. $errors = array_merge($errors, $moreErrors);
  102. }
  103. }
  104. $this->fail(
  105. 'There is a problem with the schema. A known good XML file failed validation: ' . PHP_EOL . implode(
  106. PHP_EOL . PHP_EOL,
  107. $errors
  108. )
  109. );
  110. }
  111. }
  112. /**
  113. * Run schema validation against an xml file with a provided schema.
  114. *
  115. * This helper expects the validation to pass and will fail a test if any errors are found.
  116. *
  117. * @param $xmlFile string a known good xml file.
  118. * @param $schemaFile string schema that should find no errors in the known good xml file.
  119. * @param $expectedErrors null|array that may contain a list of expected errors. Each element can be a substring
  120. * of an error, but all errors must be listed.
  121. */
  122. protected function _validateFileExpectFailure($xmlFile, $schemaFile, $expectedErrors = null)
  123. {
  124. $dom = new \DOMDocument();
  125. $dom->loadXML(file_get_contents($xmlFile));
  126. $actualErrors = \Magento\Framework\Config\Dom::validateDomDocument($dom, $schemaFile);
  127. if (isset($expectedErrors)) {
  128. $this->assertNotEmpty(
  129. $actualErrors,
  130. 'No schema validation errors found, expected errors: ' . PHP_EOL . implode(PHP_EOL, $expectedErrors)
  131. );
  132. foreach ($expectedErrors as $expectedError) {
  133. $found = false;
  134. foreach ($actualErrors as $errorKey => $actualError) {
  135. if (!(strpos($actualError, $expectedError) === false)) {
  136. // found expected string
  137. $found = true;
  138. // remove found error from list of actual errors
  139. unset($actualErrors[$errorKey]);
  140. break;
  141. }
  142. }
  143. $this->assertTrue(
  144. $found,
  145. 'Failed asserting that ' . $expectedError . " is in: \n" . implode(PHP_EOL, $actualErrors)
  146. );
  147. }
  148. // list of actual errors should now be empty
  149. $this->assertEmpty($actualErrors, "There were unexpected errors: \n" . implode(PHP_EOL, $actualErrors));
  150. } elseif (!$actualErrors) {
  151. $this->fail('There is a problem with the schema. A known bad XML file passed validation');
  152. }
  153. }
  154. /**
  155. * Returns the name of the XSD file to be used to validate the XML
  156. *
  157. * @return string
  158. */
  159. abstract protected function _getXsd();
  160. /**
  161. * The location of a single valid complete xml file
  162. *
  163. * @return string
  164. */
  165. abstract protected function _getKnownValidXml();
  166. /**
  167. * The location of a single known invalid complete xml file
  168. *
  169. * @return string
  170. */
  171. abstract protected function _getKnownInvalidXml();
  172. /**
  173. * The location of a single known valid partial xml file
  174. *
  175. * @return string
  176. */
  177. abstract protected function _getKnownValidPartialXml();
  178. /**
  179. * Returns the name of the XSD file to be used to validate partial XML
  180. *
  181. * @return string
  182. */
  183. abstract protected function _getFileXsd();
  184. /**
  185. * The location of a single known invalid partial xml file
  186. *
  187. * @return string
  188. */
  189. abstract protected function _getKnownInvalidPartialXml();
  190. /**
  191. * Returns the name of the xml files to validate
  192. *
  193. * @return string
  194. */
  195. abstract protected function _getXmlName();
  196. }