4e47f77fe59866ea45328f79afc5f1347dcb72ca
[yaffs-website] / web / core / tests / Drupal / Tests / Traits / ExpectDeprecationTrait.php
1 <?php
2
3 namespace Drupal\Tests\Traits;
4
5 use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener as LegacySymfonyTestsListener;
6 use Symfony\Bridge\PhpUnit\SymfonyTestsListener;
7 use PHPUnit\Framework\TestCase;
8
9 /**
10  * Adds the ability to dynamically set expected deprecation messages in tests.
11  *
12  * @internal
13  *   This class should only be used by Drupal core and will be removed once
14  *   https://github.com/symfony/symfony/pull/25757 is resolved.
15  *
16  * @todo Remove once https://github.com/symfony/symfony/pull/25757 is resolved.
17  */
18 trait ExpectDeprecationTrait {
19
20   /**
21    * Sets an expected deprecation message.
22    *
23    * @param string $message
24    *   The expected deprecation message.
25    */
26   protected function expectDeprecation($message) {
27     $this->expectedDeprecations([$message]);
28   }
29
30   /**
31    * Sets expected deprecation messages.
32    *
33    * @param string[] $messages
34    *   The expected deprecation messages.
35    */
36   public function expectedDeprecations(array $messages) {
37     if (class_exists('PHPUnit_Util_Test', FALSE)) {
38       $test_util = 'PHPUnit_Util_Test';
39       $assertion_failed_error = 'PHPUnit_Framework_AssertionFailedError';
40     }
41     else {
42       $test_util = 'PHPUnit\Util\Test';
43       $assertion_failed_error = 'PHPUnit\Framework\AssertionFailedError';
44     }
45     if ($this instanceof \PHPUnit_Framework_TestCase || $this instanceof TestCase) {
46       // Ensure the class or method is in the legacy group.
47       $groups = $test_util::getGroups(get_class($this), $this->getName(FALSE));
48       if (!in_array('legacy', $groups, TRUE)) {
49         throw new $assertion_failed_error('Only tests with the `@group legacy` annotation can call `setExpectedDeprecation()`.');
50       }
51
52       // If setting an expected deprecation there is no need to be strict about
53       // testing nothing as this is an assertion.
54       $this->getTestResultObject()
55         ->beStrictAboutTestsThatDoNotTestAnything(FALSE);
56
57       if ($trait = $this->getSymfonyTestListenerTrait()) {
58         // Add the expected deprecation message to the class property.
59         $reflection_class = new \ReflectionClass($trait);
60         $expected_deprecations_property = $reflection_class->getProperty('expectedDeprecations');
61         $expected_deprecations_property->setAccessible(TRUE);
62         $expected_deprecations = $expected_deprecations_property->getValue($trait);
63         $expected_deprecations = array_merge($expected_deprecations, $messages);
64         $expected_deprecations_property->setValue($trait, $expected_deprecations);
65
66         // Register the error handler if necessary.
67         $previous_error_handler_property = $reflection_class->getProperty('previousErrorHandler');
68         $previous_error_handler_property->setAccessible(TRUE);
69         $previous_error_handler = $previous_error_handler_property->getValue($trait);
70         if (!$previous_error_handler) {
71           $previous_error_handler = set_error_handler([$trait, 'handleError']);
72           $previous_error_handler_property->setValue($trait, $previous_error_handler);
73         }
74         return;
75       }
76     }
77
78     // Expected deprecations set by isolated tests need to be written to a file
79     // so that the test running process can take account of them.
80     if ($file = getenv('DRUPAL_EXPECTED_DEPRECATIONS_SERIALIZE')) {
81       $expected_deprecations = file_get_contents($file);
82       if ($expected_deprecations) {
83         $expected_deprecations = array_merge(unserialize($expected_deprecations), $messages);
84       }
85       else {
86         $expected_deprecations = $messages;
87       }
88       file_put_contents($file, serialize($expected_deprecations));
89       return;
90     }
91
92     throw new $assertion_failed_error('Can not set an expected deprecation message because the Symfony\Bridge\PhpUnit\SymfonyTestsListener is not registered as a PHPUnit test listener.');
93   }
94
95   /**
96    * Gets the SymfonyTestsListenerTrait.
97    *
98    * @return \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait|null
99    *   The SymfonyTestsListenerTrait object or NULL is a Symfony test listener
100    *   is not present.
101    */
102   private function getSymfonyTestListenerTrait() {
103     $test_result_object = $this->getTestResultObject();
104     $reflection_class = new \ReflectionClass($test_result_object);
105     $reflection_property = $reflection_class->getProperty('listeners');
106     $reflection_property->setAccessible(TRUE);
107     $listeners = $reflection_property->getValue($test_result_object);
108     foreach ($listeners as $listener) {
109       if ($listener instanceof SymfonyTestsListener || $listener instanceof LegacySymfonyTestsListener) {
110         $reflection_class = new \ReflectionClass($listener);
111         $reflection_property = $reflection_class->getProperty('trait');
112         $reflection_property->setAccessible(TRUE);
113         return $reflection_property->getValue($listener);
114       }
115     }
116   }
117
118 }