Skip to content

Commit dc85bf7

Browse files
committed
Add unit tests for wp_cache_set_last_changed
1 parent 98b851a commit dc85bf7

File tree

1 file changed

+259
-0
lines changed

1 file changed

+259
-0
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
<?php
2+
3+
/**
4+
* Tests for the wp_cache_set_posts_last_changed() function.
5+
*
6+
* @group post
7+
* @group cache
8+
*
9+
* @covers ::wp_cache_set_posts_last_changed
10+
*/
11+
class Tests_Post_wpCacheSetPostsLastChanged extends WP_UnitTestCase {
12+
13+
protected static $post_id;
14+
15+
public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
16+
self::$post_id = $factory->post->create();
17+
}
18+
19+
public static function wpTearDownAfterClass() {
20+
wp_delete_post( self::$post_id, true );
21+
}
22+
23+
public function tear_down() {
24+
unset( $GLOBALS['__suspend_posts_last_changed_update'] );
25+
parent::tear_down();
26+
}
27+
28+
/**
29+
* Verifies that the function updates the 'posts' cache group.
30+
*/
31+
public function test_sets_last_changed_for_posts_group() {
32+
wp_cache_delete( 'last_changed', 'posts' );
33+
34+
wp_cache_set_posts_last_changed();
35+
36+
$this->assertNotFalse( wp_cache_get( 'last_changed', 'posts' ) );
37+
}
38+
39+
/**
40+
* Verifies that the function is suspended when the global counter is set.
41+
*/
42+
public function test_suspended_when_global_is_set() {
43+
wp_cache_delete( 'last_changed', 'posts' );
44+
45+
$GLOBALS['__suspend_posts_last_changed_update'] = 1;
46+
47+
wp_cache_set_posts_last_changed();
48+
49+
$this->assertFalse( wp_cache_get( 'last_changed', 'posts' ) );
50+
}
51+
52+
/**
53+
* Verifies that the function resumes after the global counter reaches zero.
54+
*/
55+
public function test_resumes_when_global_reaches_zero() {
56+
wp_cache_delete( 'last_changed', 'posts' );
57+
58+
$GLOBALS['__suspend_posts_last_changed_update'] = 0;
59+
60+
wp_cache_set_posts_last_changed();
61+
62+
$this->assertNotFalse( wp_cache_get( 'last_changed', 'posts' ) );
63+
}
64+
65+
/**
66+
* Verifies that add_post_meta updates last_changed when not suspended.
67+
*/
68+
public function test_add_post_meta_updates_last_changed() {
69+
wp_cache_set_posts_last_changed();
70+
$before = wp_cache_get( 'last_changed', 'posts' );
71+
72+
// Ensure the microtime value changes.
73+
usleep( 1 );
74+
75+
add_post_meta( self::$post_id, '_test_meta_add', 'value' );
76+
77+
$after = wp_cache_get( 'last_changed', 'posts' );
78+
$this->assertNotSame( $before, $after, 'add_post_meta should update last_changed.' );
79+
}
80+
81+
/**
82+
* Verifies that add_post_meta does not update last_changed when suspended.
83+
*/
84+
public function test_add_post_meta_suspended() {
85+
wp_cache_set_posts_last_changed();
86+
$before = wp_cache_get( 'last_changed', 'posts' );
87+
88+
// Ensure the microtime value changes.
89+
usleep( 1 );
90+
91+
$GLOBALS['__suspend_posts_last_changed_update'] = 1;
92+
add_post_meta( self::$post_id, '_test_meta_add_suspended', 'value' );
93+
$GLOBALS['__suspend_posts_last_changed_update'] = 0;
94+
95+
$after = wp_cache_get( 'last_changed', 'posts' );
96+
$this->assertSame( $before, $after, 'add_post_meta should not update last_changed when suspended.' );
97+
}
98+
99+
/**
100+
* Verifies that update_post_meta updates last_changed when not suspended.
101+
*/
102+
public function test_update_post_meta_updates_last_changed() {
103+
add_post_meta( self::$post_id, '_test_meta_update', 'old' );
104+
105+
wp_cache_set_posts_last_changed();
106+
$before = wp_cache_get( 'last_changed', 'posts' );
107+
108+
// Ensure the microtime value changes.
109+
usleep( 1 );
110+
111+
update_post_meta( self::$post_id, '_test_meta_update', 'new' );
112+
113+
$after = wp_cache_get( 'last_changed', 'posts' );
114+
$this->assertNotSame( $before, $after, 'update_post_meta should update last_changed.' );
115+
}
116+
117+
/**
118+
* Verifies that update_post_meta does not update last_changed when suspended.
119+
*/
120+
public function test_update_post_meta_suspended() {
121+
add_post_meta( self::$post_id, '_test_meta_update_suspended', 'old' );
122+
123+
wp_cache_set_posts_last_changed();
124+
$before = wp_cache_get( 'last_changed', 'posts' );
125+
126+
// Ensure the microtime value changes.
127+
usleep( 1 );
128+
129+
$GLOBALS['__suspend_posts_last_changed_update'] = 1;
130+
update_post_meta( self::$post_id, '_test_meta_update_suspended', 'new' );
131+
$GLOBALS['__suspend_posts_last_changed_update'] = 0;
132+
133+
$after = wp_cache_get( 'last_changed', 'posts' );
134+
$this->assertSame( $before, $after, 'update_post_meta should not update last_changed when suspended.' );
135+
}
136+
137+
/**
138+
* Verifies that delete_post_meta updates last_changed when not suspended.
139+
*/
140+
public function test_delete_post_meta_updates_last_changed() {
141+
add_post_meta( self::$post_id, '_test_meta_delete', 'value' );
142+
143+
wp_cache_set_posts_last_changed();
144+
$before = wp_cache_get( 'last_changed', 'posts' );
145+
146+
// Ensure the microtime value changes.
147+
usleep( 1 );
148+
149+
delete_post_meta( self::$post_id, '_test_meta_delete' );
150+
151+
$after = wp_cache_get( 'last_changed', 'posts' );
152+
$this->assertNotSame( $before, $after, 'delete_post_meta should update last_changed.' );
153+
}
154+
155+
/**
156+
* Verifies that delete_post_meta does not update last_changed when suspended.
157+
*/
158+
public function test_delete_post_meta_suspended() {
159+
add_post_meta( self::$post_id, '_test_meta_delete_suspended', 'value' );
160+
161+
wp_cache_set_posts_last_changed();
162+
$before = wp_cache_get( 'last_changed', 'posts' );
163+
164+
// Ensure the microtime value changes.
165+
usleep( 1 );
166+
167+
$GLOBALS['__suspend_posts_last_changed_update'] = 1;
168+
delete_post_meta( self::$post_id, '_test_meta_delete_suspended' );
169+
$GLOBALS['__suspend_posts_last_changed_update'] = 0;
170+
171+
$after = wp_cache_get( 'last_changed', 'posts' );
172+
$this->assertSame( $before, $after, 'delete_post_meta should not update last_changed when suspended.' );
173+
}
174+
175+
/**
176+
* Verifies that an embedded post meta operation triggered by a hook during
177+
* a suspended call does not prematurely unsuspend the counter.
178+
*
179+
* Simulates: outer add_post_meta (suspended) triggers a hook that calls
180+
* update_post_meta internally. The inner operation should not reset the
181+
* counter, and last_changed should remain unchanged after both complete.
182+
*/
183+
public function test_nested_post_meta_via_hook_respects_suspension_counter() {
184+
// When the outer add_post_meta fires 'added_post_meta', this hook
185+
// performs its own update_post_meta while the counter is still active.
186+
$nested_callback = function ( $meta_id, $post_id, $meta_key ) {
187+
if ( '_test_outer_meta' !== $meta_key ) {
188+
return;
189+
}
190+
191+
// Increment the counter to simulate a nested suspended operation.
192+
++$GLOBALS['__suspend_posts_last_changed_update'];
193+
try {
194+
update_post_meta( $post_id, '_test_inner_meta', 'inner_value' );
195+
} finally {
196+
--$GLOBALS['__suspend_posts_last_changed_update'];
197+
}
198+
};
199+
200+
add_action( 'added_post_meta', $nested_callback, 10, 3 );
201+
202+
wp_cache_set_posts_last_changed();
203+
$before = wp_cache_get( 'last_changed', 'posts' );
204+
205+
// Ensure the microtime value changes.
206+
usleep( 1 );
207+
208+
// Outer suspended operation.
209+
$GLOBALS['__suspend_posts_last_changed_update'] = 1;
210+
add_post_meta( self::$post_id, '_test_outer_meta', 'outer_value' );
211+
$GLOBALS['__suspend_posts_last_changed_update'] = 0;
212+
213+
$after = wp_cache_get( 'last_changed', 'posts' );
214+
215+
remove_action( 'added_post_meta', $nested_callback, 10 );
216+
217+
$this->assertSame( $before, $after, 'Nested post meta via hook should not update last_changed while suspended.' );
218+
$this->assertSame( 'inner_value', get_post_meta( self::$post_id, '_test_inner_meta', true ), 'Inner meta should still be written.' );
219+
}
220+
221+
/**
222+
* Verifies that last_changed is updated normally after suspension ends,
223+
* even when a nested operation occurred during the suspended window.
224+
*/
225+
public function test_last_changed_updates_after_nested_suspension_ends() {
226+
$nested_callback = function ( $mid, $post_id, $meta_key ) {
227+
if ( '_test_outer_meta_2' !== $meta_key ) {
228+
return;
229+
}
230+
++$GLOBALS['__suspend_posts_last_changed_update'];
231+
try {
232+
update_post_meta( $post_id, '_test_inner_meta_2', 'inner' );
233+
} finally {
234+
--$GLOBALS['__suspend_posts_last_changed_update'];
235+
}
236+
};
237+
238+
add_action( 'added_post_meta', $nested_callback, 10, 3 );
239+
240+
// Suspended operation with nested hook.
241+
$GLOBALS['__suspend_posts_last_changed_update'] = 1;
242+
add_post_meta( self::$post_id, '_test_outer_meta_2', 'outer' );
243+
$GLOBALS['__suspend_posts_last_changed_update'] = 0;
244+
245+
remove_action( 'added_post_meta', $nested_callback, 10 );
246+
247+
// Record the cache value after the suspended window.
248+
wp_cache_set_posts_last_changed();
249+
$before = wp_cache_get( 'last_changed', 'posts' );
250+
251+
// A normal (unsuspended) meta operation should update last_changed.
252+
usleep( 1 );
253+
254+
add_post_meta( self::$post_id, '_test_after_nested', 'value' );
255+
256+
$after = wp_cache_get( 'last_changed', 'posts' );
257+
$this->assertNotSame( $before, $after, 'last_changed should update normally after suspension ends.' );
258+
}
259+
}

0 commit comments

Comments
 (0)