cache.php 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <?php
  2. /**
  3. * @group cache
  4. */
  5. class Tests_Cache extends WP_UnitTestCase {
  6. public $cache = null;
  7. function setUp() {
  8. parent::setUp();
  9. // Create two cache objects with a shared cache directory.
  10. // This simulates a typical cache situation, two separate requests interacting.
  11. $this->cache =& $this->init_cache();
  12. }
  13. function tearDown() {
  14. $this->flush_cache();
  15. parent::tearDown();
  16. }
  17. function &init_cache() {
  18. global $wp_object_cache;
  19. $cache_class = get_class( $wp_object_cache );
  20. $cache = new $cache_class();
  21. $cache->add_global_groups( array( 'global-cache-test', 'users', 'userlogins', 'usermeta', 'user_meta', 'useremail', 'userslugs', 'site-transient', 'site-options', 'blog-lookup', 'blog-details', 'rss', 'global-posts', 'blog-id-cache', 'networks', 'sites', 'site-details' ) );
  22. return $cache;
  23. }
  24. function test_miss() {
  25. $this->assertFalse( $this->cache->get( 'test_miss' ) );
  26. }
  27. function test_add_get() {
  28. $key = __FUNCTION__;
  29. $val = 'val';
  30. $this->cache->add( $key, $val );
  31. $this->assertSame( $val, $this->cache->get( $key ) );
  32. }
  33. function test_add_get_0() {
  34. $key = __FUNCTION__;
  35. $val = 0;
  36. // You can store zero in the cache.
  37. $this->assertTrue( $this->cache->add( $key, $val ) );
  38. $this->assertSame( $val, $this->cache->get( $key ) );
  39. }
  40. /**
  41. * @ticket 20004
  42. */
  43. function test_add_get_null() {
  44. $key = __FUNCTION__;
  45. $val = null;
  46. // You can store `null` in the cache.
  47. $this->assertTrue( $this->cache->add( $key, $val ) );
  48. $this->assertSame( $val, $this->cache->get( $key ) );
  49. }
  50. /**
  51. * @ticket 20004
  52. */
  53. function test_add_get_false() {
  54. $key = __FUNCTION__;
  55. $val = false;
  56. // You can store `false` in the cache.
  57. $this->assertTrue( $this->cache->add( $key, $val ) );
  58. $this->assertSame( $val, $this->cache->get( $key ) );
  59. }
  60. function test_add() {
  61. $key = __FUNCTION__;
  62. $val1 = 'val1';
  63. $val2 = 'val2';
  64. // Add $key to the cache.
  65. $this->assertTrue( $this->cache->add( $key, $val1 ) );
  66. $this->assertSame( $val1, $this->cache->get( $key ) );
  67. // $key is in the cache, so reject new calls to add().
  68. $this->assertFalse( $this->cache->add( $key, $val2 ) );
  69. $this->assertSame( $val1, $this->cache->get( $key ) );
  70. }
  71. function test_replace() {
  72. $key = __FUNCTION__;
  73. $val = 'val1';
  74. $val2 = 'val2';
  75. // memcached rejects replace() if the key does not exist.
  76. $this->assertFalse( $this->cache->replace( $key, $val ) );
  77. $this->assertFalse( $this->cache->get( $key ) );
  78. $this->assertTrue( $this->cache->add( $key, $val ) );
  79. $this->assertSame( $val, $this->cache->get( $key ) );
  80. $this->assertTrue( $this->cache->replace( $key, $val2 ) );
  81. $this->assertSame( $val2, $this->cache->get( $key ) );
  82. }
  83. function test_set() {
  84. $key = __FUNCTION__;
  85. $val1 = 'val1';
  86. $val2 = 'val2';
  87. // memcached accepts set() if the key does not exist.
  88. $this->assertTrue( $this->cache->set( $key, $val1 ) );
  89. $this->assertSame( $val1, $this->cache->get( $key ) );
  90. // Second set() with same key should be allowed.
  91. $this->assertTrue( $this->cache->set( $key, $val2 ) );
  92. $this->assertSame( $val2, $this->cache->get( $key ) );
  93. }
  94. function test_flush() {
  95. global $_wp_using_ext_object_cache;
  96. if ( $_wp_using_ext_object_cache ) {
  97. $this->markTestSkipped( 'This test requires that an external object cache is not in use.' );
  98. }
  99. $key = __FUNCTION__;
  100. $val = 'val';
  101. $this->cache->add( $key, $val );
  102. // Item is visible to both cache objects.
  103. $this->assertSame( $val, $this->cache->get( $key ) );
  104. $this->cache->flush();
  105. // If there is no value get returns false.
  106. $this->assertFalse( $this->cache->get( $key ) );
  107. }
  108. // Make sure objects are cloned going to and from the cache.
  109. function test_object_refs() {
  110. $key = __FUNCTION__ . '_1';
  111. $object_a = new stdClass;
  112. $object_a->foo = 'alpha';
  113. $this->cache->set( $key, $object_a );
  114. $object_a->foo = 'bravo';
  115. $object_b = $this->cache->get( $key );
  116. $this->assertSame( 'alpha', $object_b->foo );
  117. $object_b->foo = 'charlie';
  118. $this->assertSame( 'bravo', $object_a->foo );
  119. $key = __FUNCTION__ . '_2';
  120. $object_a = new stdClass;
  121. $object_a->foo = 'alpha';
  122. $this->cache->add( $key, $object_a );
  123. $object_a->foo = 'bravo';
  124. $object_b = $this->cache->get( $key );
  125. $this->assertSame( 'alpha', $object_b->foo );
  126. $object_b->foo = 'charlie';
  127. $this->assertSame( 'bravo', $object_a->foo );
  128. }
  129. function test_incr() {
  130. $key = __FUNCTION__;
  131. $this->assertFalse( $this->cache->incr( $key ) );
  132. $this->cache->set( $key, 0 );
  133. $this->cache->incr( $key );
  134. $this->assertSame( 1, $this->cache->get( $key ) );
  135. $this->cache->incr( $key, 2 );
  136. $this->assertSame( 3, $this->cache->get( $key ) );
  137. }
  138. function test_wp_cache_incr() {
  139. $key = __FUNCTION__;
  140. $this->assertFalse( wp_cache_incr( $key ) );
  141. wp_cache_set( $key, 0 );
  142. wp_cache_incr( $key );
  143. $this->assertSame( 1, wp_cache_get( $key ) );
  144. wp_cache_incr( $key, 2 );
  145. $this->assertSame( 3, wp_cache_get( $key ) );
  146. }
  147. function test_decr() {
  148. $key = __FUNCTION__;
  149. $this->assertFalse( $this->cache->decr( $key ) );
  150. $this->cache->set( $key, 0 );
  151. $this->cache->decr( $key );
  152. $this->assertSame( 0, $this->cache->get( $key ) );
  153. $this->cache->set( $key, 3 );
  154. $this->cache->decr( $key );
  155. $this->assertSame( 2, $this->cache->get( $key ) );
  156. $this->cache->decr( $key, 2 );
  157. $this->assertSame( 0, $this->cache->get( $key ) );
  158. }
  159. /**
  160. * @ticket 21327
  161. */
  162. function test_wp_cache_decr() {
  163. $key = __FUNCTION__;
  164. $this->assertFalse( wp_cache_decr( $key ) );
  165. wp_cache_set( $key, 0 );
  166. wp_cache_decr( $key );
  167. $this->assertSame( 0, wp_cache_get( $key ) );
  168. wp_cache_set( $key, 3 );
  169. wp_cache_decr( $key );
  170. $this->assertSame( 2, wp_cache_get( $key ) );
  171. wp_cache_decr( $key, 2 );
  172. $this->assertSame( 0, wp_cache_get( $key ) );
  173. }
  174. function test_delete() {
  175. $key = __FUNCTION__;
  176. $val = 'val';
  177. // Verify set.
  178. $this->assertTrue( $this->cache->set( $key, $val ) );
  179. $this->assertSame( $val, $this->cache->get( $key ) );
  180. // Verify successful delete.
  181. $this->assertTrue( $this->cache->delete( $key ) );
  182. $this->assertFalse( $this->cache->get( $key ) );
  183. $this->assertFalse( $this->cache->delete( $key, 'default' ) );
  184. }
  185. function test_wp_cache_delete() {
  186. $key = __FUNCTION__;
  187. $val = 'val';
  188. // Verify set.
  189. $this->assertTrue( wp_cache_set( $key, $val ) );
  190. $this->assertSame( $val, wp_cache_get( $key ) );
  191. // Verify successful delete.
  192. $this->assertTrue( wp_cache_delete( $key ) );
  193. $this->assertFalse( wp_cache_get( $key ) );
  194. // wp_cache_delete() does not have a $force method.
  195. // Delete returns (bool) true when key is not set and $force is true.
  196. // $this->assertTrue( wp_cache_delete( $key, 'default', true ) );
  197. $this->assertFalse( wp_cache_delete( $key, 'default' ) );
  198. }
  199. function test_switch_to_blog() {
  200. if ( ! method_exists( $this->cache, 'switch_to_blog' ) ) {
  201. return;
  202. }
  203. $key = __FUNCTION__;
  204. $val = 'val1';
  205. $val2 = 'val2';
  206. if ( ! is_multisite() ) {
  207. // Single site ingnores switch_to_blog().
  208. $this->assertTrue( $this->cache->set( $key, $val ) );
  209. $this->assertSame( $val, $this->cache->get( $key ) );
  210. $this->cache->switch_to_blog( 999 );
  211. $this->assertSame( $val, $this->cache->get( $key ) );
  212. $this->assertTrue( $this->cache->set( $key, $val2 ) );
  213. $this->assertSame( $val2, $this->cache->get( $key ) );
  214. $this->cache->switch_to_blog( get_current_blog_id() );
  215. $this->assertSame( $val2, $this->cache->get( $key ) );
  216. } else {
  217. // Multisite should have separate per-blog caches.
  218. $this->assertTrue( $this->cache->set( $key, $val ) );
  219. $this->assertSame( $val, $this->cache->get( $key ) );
  220. $this->cache->switch_to_blog( 999 );
  221. $this->assertFalse( $this->cache->get( $key ) );
  222. $this->assertTrue( $this->cache->set( $key, $val2 ) );
  223. $this->assertSame( $val2, $this->cache->get( $key ) );
  224. $this->cache->switch_to_blog( get_current_blog_id() );
  225. $this->assertSame( $val, $this->cache->get( $key ) );
  226. $this->cache->switch_to_blog( 999 );
  227. $this->assertSame( $val2, $this->cache->get( $key ) );
  228. $this->cache->switch_to_blog( get_current_blog_id() );
  229. $this->assertSame( $val, $this->cache->get( $key ) );
  230. }
  231. // Global group.
  232. $this->assertTrue( $this->cache->set( $key, $val, 'global-cache-test' ) );
  233. $this->assertSame( $val, $this->cache->get( $key, 'global-cache-test' ) );
  234. $this->cache->switch_to_blog( 999 );
  235. $this->assertSame( $val, $this->cache->get( $key, 'global-cache-test' ) );
  236. $this->assertTrue( $this->cache->set( $key, $val2, 'global-cache-test' ) );
  237. $this->assertSame( $val2, $this->cache->get( $key, 'global-cache-test' ) );
  238. $this->cache->switch_to_blog( get_current_blog_id() );
  239. $this->assertSame( $val2, $this->cache->get( $key, 'global-cache-test' ) );
  240. }
  241. function test_wp_cache_init() {
  242. $new_blank_cache_object = new WP_Object_Cache();
  243. wp_cache_init();
  244. global $wp_object_cache;
  245. if ( wp_using_ext_object_cache() ) {
  246. // External caches will contain property values that contain non-matching resource IDs.
  247. $this->assertInstanceOf( 'WP_Object_Cache', $wp_object_cache );
  248. } else {
  249. $this->assertEquals( $wp_object_cache, $new_blank_cache_object );
  250. }
  251. }
  252. function test_wp_cache_replace() {
  253. $key = 'my-key';
  254. $val1 = 'first-val';
  255. $val2 = 'second-val';
  256. $fake_key = 'my-fake-key';
  257. // Save the first value to cache and verify.
  258. wp_cache_set( $key, $val1 );
  259. $this->assertSame( $val1, wp_cache_get( $key ) );
  260. // Replace the value and verify.
  261. wp_cache_replace( $key, $val2 );
  262. $this->assertSame( $val2, wp_cache_get( $key ) );
  263. // Non-existant key should fail.
  264. $this->assertFalse( wp_cache_replace( $fake_key, $val1 ) );
  265. // Make sure $fake_key is not stored.
  266. $this->assertFalse( wp_cache_get( $fake_key ) );
  267. }
  268. /**
  269. * @ticket 20875
  270. */
  271. public function test_get_multiple() {
  272. wp_cache_set( 'foo1', 'bar', 'group1' );
  273. wp_cache_set( 'foo2', 'bar', 'group1' );
  274. wp_cache_set( 'foo1', 'bar', 'group2' );
  275. $found = wp_cache_get_multiple( array( 'foo1', 'foo2', 'foo3' ), 'group1' );
  276. $expected = array(
  277. 'foo1' => 'bar',
  278. 'foo2' => 'bar',
  279. 'foo3' => false,
  280. );
  281. $this->assertSame( $expected, $found );
  282. }
  283. }