3 use Wikimedia\TestingAccessWrapper
;
6 * @covers DeprecationHelper
8 class DeprecationHelperTest
extends MediaWikiTestCase
{
10 /** @var TestDeprecatedClass */
13 /** @var TestDeprecatedSubclass */
14 private $testSubclass;
16 public function setUp() {
18 $this->testClass
= new TestDeprecatedClass();
19 $this->testSubclass
= new TestDeprecatedSubclass();
20 $this->setMwGlobals( 'wgDevelopmentWarnings', false );
23 public function tearDown() {
29 * @dataProvider provideGet
31 public function testGet( $propName, $expectedLevel, $expectedMessage ) {
32 if ( $expectedLevel ) {
33 $this->assertErrorTriggered( function () use ( $propName ) {
34 $this->assertSame( null, $this->testClass
->$propName );
35 }, $expectedLevel, $expectedMessage );
37 $this->assertDeprecationWarningIssued( function () use ( $propName ) {
38 $this->assertSame( 1, $this->testClass
->$propName );
43 public function provideGet() {
45 [ 'protectedDeprecated', null, null ],
46 [ 'protectedNonDeprecated', E_USER_ERROR
,
47 'Cannot access non-public property TestDeprecatedClass::$protectedNonDeprecated' ],
48 [ 'privateDeprecated', null, null ],
49 [ 'privateNonDeprecated', E_USER_ERROR
,
50 'Cannot access non-public property TestDeprecatedClass::$privateNonDeprecated' ],
51 [ 'nonExistent', E_USER_NOTICE
, 'Undefined property: TestDeprecatedClass::$nonExistent' ],
56 * @dataProvider provideSet
58 public function testSet( $propName, $expectedLevel, $expectedMessage ) {
59 $this->assertPropertySame( 1, $this->testClass
, $propName );
60 if ( $expectedLevel ) {
61 $this->assertErrorTriggered( function () use ( $propName ) {
62 $this->testClass
->$propName = 0;
63 $this->assertPropertySame( 1, $this->testClass
, $propName );
64 }, $expectedLevel, $expectedMessage );
66 if ( $propName === 'nonExistent' ) {
67 $this->testClass
->$propName = 0;
69 $this->assertDeprecationWarningIssued( function () use ( $propName ) {
70 $this->testClass
->$propName = 0;
73 $this->assertPropertySame( 0, $this->testClass
, $propName );
77 public function provideSet() {
79 [ 'protectedDeprecated', null, null ],
80 [ 'protectedNonDeprecated', E_USER_ERROR
,
81 'Cannot access non-public property TestDeprecatedClass::$protectedNonDeprecated' ],
82 [ 'privateDeprecated', null, null ],
83 [ 'privateNonDeprecated', E_USER_ERROR
,
84 'Cannot access non-public property TestDeprecatedClass::$privateNonDeprecated' ],
85 [ 'nonExistent', null, null ],
89 public function testInternalGet() {
95 ], $this->testClass
->getThings() );
98 public function testInternalSet() {
99 $this->testClass
->setThings( 2, 2, 2, 2 );
100 $wrapper = TestingAccessWrapper
::newFromObject( $this->testClass
);
101 $this->assertSame( 2, $wrapper->protectedDeprecated
);
102 $this->assertSame( 2, $wrapper->protectedNonDeprecated
);
103 $this->assertSame( 2, $wrapper->privateDeprecated
);
104 $this->assertSame( 2, $wrapper->privateNonDeprecated
);
107 public function testSubclassGetSet() {
108 $this->assertDeprecationWarningIssued( function () {
109 $this->assertSame( 1, $this->testSubclass
->getDeprecatedPrivateParentProperty() );
111 $this->assertDeprecationWarningIssued( function () {
112 $this->testSubclass
->setDeprecatedPrivateParentProperty( 0 );
114 $wrapper = TestingAccessWrapper
::newFromObject( $this->testSubclass
);
115 $this->assertSame( 0, $wrapper->privateDeprecated
);
117 $fullName = 'TestDeprecatedClass::$privateNonDeprecated';
118 $this->assertErrorTriggered( function () {
119 $this->assertSame( null, $this->testSubclass
->getNonDeprecatedPrivateParentProperty() );
120 }, E_USER_ERROR
, "Cannot access non-public property $fullName" );
121 $this->assertErrorTriggered( function () {
122 $this->testSubclass
->setNonDeprecatedPrivateParentProperty( 0 );
123 $wrapper = TestingAccessWrapper
::newFromObject( $this->testSubclass
);
124 $this->assertSame( 1, $wrapper->privateNonDeprecated
);
125 }, E_USER_ERROR
, "Cannot access non-public property $fullName" );
128 protected function assertErrorTriggered( callable
$callback, $level, $message ) {
129 $actualLevel = $actualMessage = null;
130 set_error_handler( function ( $errorCode, $errorStr ) use ( &$actualLevel, &$actualMessage ) {
131 $actualLevel = $errorCode;
132 $actualMessage = $errorStr;
135 restore_error_handler();
136 $this->assertSame( $level, $actualLevel );
137 $this->assertSame( $message, $actualMessage );
140 protected function assertPropertySame( $expected, $object, $propName ) {
142 $this->assertSame( $expected, TestingAccessWrapper
::newFromObject( $object )->$propName );
143 } catch ( ReflectionException
$e ) {
144 if ( !preg_match( "/Property (TestDeprecated(Class|Subclass)::)?$propName does not exist/",
149 // property_exists accepts monkey-patching, Reflection / TestingAccessWrapper doesn't
150 if ( property_exists( $object, $propName ) ) {
151 $this->assertSame( $expected, $object->$propName );
156 protected function assertDeprecationWarningIssued( callable
$callback ) {
159 $wrapper = TestingAccessWrapper
::newFromClass( MWDebug
::class );
160 $this->assertNotEmpty( $wrapper->deprecationWarnings
);