See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Tests for cache. 19 * 20 * @package tool_usertours 21 * @copyright 2016 Andrew Nicols <andrew@nicols.co.uk> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 global $CFG; 28 require_once (__DIR__ . '/helper_trait.php'); 29 30 /** 31 * Tests for cache. 32 * 33 * @package tool_usertours 34 * @copyright 2016 Andrew Nicols <andrew@nicols.co.uk> 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class cache_testcase extends advanced_testcase { 38 // There are shared helpers for these tests in the helper trait. 39 use tool_usertours_helper_trait; 40 41 /** 42 * Test that get_enabled_tourdata does not return disabled tours. 43 */ 44 public function test_get_enabled_tourdata_disabled() { 45 $this->resetAfterTest(); 46 47 $tour = $this->helper_create_tour((object)['enabled' => false]); 48 $this->helper_create_step((object) ['tourid' => $tour->get_id()]); 49 50 $matches = \tool_usertours\cache::get_enabled_tourdata(); 51 $this->assertEmpty($matches); 52 } 53 54 /** 55 * Test that get_enabled_tourdata does not return an enabled but empty tour. 56 */ 57 public function test_get_enabled_tourdata_enabled_no_steps() { 58 $this->resetAfterTest(); 59 60 $this->helper_create_tour(); 61 62 $matches = \tool_usertours\cache::get_enabled_tourdata(); 63 $this->assertEmpty($matches); 64 } 65 66 /** 67 * Test that get_enabled_tourdata returns a tour with steps. 68 */ 69 public function test_get_enabled_tourdata_enabled() { 70 $this->resetAfterTest(); 71 72 // Create two tours. Only the second has steps. 73 $this->helper_create_tour(); 74 $tour2 = $this->helper_create_tour(); 75 $this->helper_create_step((object) ['tourid' => $tour2->get_id()]); 76 77 $matches = \tool_usertours\cache::get_enabled_tourdata(); 78 $this->assertNotEmpty($matches); 79 $this->assertCount(1, $matches); 80 81 $match = array_shift($matches); 82 $this->assertEquals($tour2->get_id(), $match->id); 83 } 84 85 /** 86 * Test that get_enabled_tourdata returns tours in the correct sortorder 87 */ 88 public function test_get_enabled_tourdata_enabled_sortorder() { 89 $this->resetAfterTest(); 90 91 $tour1 = $this->helper_create_tour(); 92 $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); 93 $tour2 = $this->helper_create_tour(); 94 $this->helper_create_step((object) ['tourid' => $tour2->get_id()]); 95 96 $matches = \tool_usertours\cache::get_enabled_tourdata(); 97 $this->assertNotEmpty($matches); 98 $this->assertCount(2, $matches); 99 100 $match = array_shift($matches); 101 $this->assertEquals($tour1->get_id(), $match->id); 102 $match = array_shift($matches); 103 $this->assertEquals($tour2->get_id(), $match->id); 104 } 105 106 /** 107 * Test that caching prevents additional DB reads. 108 */ 109 public function test_get_enabled_tourdata_single_fetch() { 110 global $DB; 111 112 $this->resetAfterTest(); 113 114 $tour1 = $this->helper_create_tour(); 115 $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); 116 $tour2 = $this->helper_create_tour(); 117 $this->helper_create_step((object) ['tourid' => $tour2->get_id()]); 118 119 // Only one read for the first call. 120 $startreads = $DB->perf_get_reads(); 121 $matches = \tool_usertours\cache::get_enabled_tourdata(); 122 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 123 124 // No subsequent reads for any further calls. 125 $matches = \tool_usertours\cache::get_enabled_tourdata(); 126 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 127 128 } 129 130 /** 131 * Data provider for get_matching_tourdata. 132 * 133 * @return array 134 */ 135 public function get_matching_tourdata_provider() { 136 $tourconfigs = [ 137 (object) [ 138 'name' => 'my_exact_1', 139 'pathmatch' => '/my/view.php' 140 ], 141 (object) [ 142 'name' => 'my_failed_regex', 143 'pathmatch' => '/my/*.php' 144 ], 145 (object) [ 146 'name' => 'my_glob_1', 147 'pathmatch' => '/my/%' 148 ], 149 (object) [ 150 'name' => 'my_glob_2', 151 'pathmatch' => '/my/%' 152 ], 153 (object) [ 154 'name' => 'frontpage_only', 155 'pathmatch' => 'FRONTPAGE' 156 ], 157 (object) [ 158 'name' => 'frontpage_match', 159 'pathmatch' => '/?%' 160 ], 161 ]; 162 163 return [ 164 'Matches expected glob' => [ 165 $tourconfigs, 166 '/my/index.php', 167 ['my_glob_1', 'my_glob_2'], 168 ], 169 'Matches expected glob and exact' => [ 170 $tourconfigs, 171 '/my/view.php', 172 ['my_exact_1', 'my_glob_1', 'my_glob_2'], 173 ], 174 'Special constant FRONTPAGE must match front page only' => [ 175 $tourconfigs, 176 '/', 177 ['frontpage_only'], 178 ], 179 'Standard frontpage URL matches both the special constant, and a correctly formed pathmatch' => [ 180 $tourconfigs, 181 '/?redirect=0', 182 ['frontpage_only', 'frontpage_match'], 183 ], 184 ]; 185 } 186 187 /** 188 * Tests for the get_matching_tourdata function. 189 * 190 * @dataProvider get_matching_tourdata_provider 191 * @param array $tourconfigs The configuration for the tours to create 192 * @param string $targetmatch The match to be tested 193 * @param array $expected An array containing the ordered names of the expected tours 194 */ 195 public function test_get_matching_tourdata($tourconfigs, $targetmatch, $expected) { 196 $this->resetAfterTest(); 197 foreach ($tourconfigs as $tourconfig) { 198 $tour = $this->helper_create_tour($tourconfig); 199 $this->helper_create_step((object) ['tourid' => $tour->get_id()]); 200 } 201 202 $matches = \tool_usertours\cache::get_matching_tourdata(new moodle_url($targetmatch)); 203 $this->assertCount(count($expected), $matches); 204 205 for ($i = 0; $i < count($matches); $i++) { 206 $match = array_shift($matches); 207 $this->assertEquals($expected[$i], $match->name); 208 } 209 } 210 211 /** 212 * Test that notify_tour_change clears the cache. 213 */ 214 public function test_notify_tour_change() { 215 global $DB; 216 217 $this->resetAfterTest(); 218 219 $tour1 = $this->helper_create_tour(); 220 $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); 221 $tour2 = $this->helper_create_tour(); 222 $this->helper_create_step((object) ['tourid' => $tour2->get_id()]); 223 224 // Only one read for the first call. 225 $startreads = $DB->perf_get_reads(); 226 $matches = \tool_usertours\cache::get_enabled_tourdata(); 227 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 228 229 // No subsequent reads for any further calls. 230 $matches = \tool_usertours\cache::get_enabled_tourdata(); 231 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 232 233 // Reset. 234 \tool_usertours\cache::notify_tour_change(); 235 236 // An additional DB read now. 237 $startreads = $DB->perf_get_reads(); 238 $matches = \tool_usertours\cache::get_enabled_tourdata(); 239 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 240 } 241 242 /** 243 * Test that get_stepdata returns an empty array when no steps were found. 244 */ 245 public function test_get_stepdata_no_steps() { 246 $this->resetAfterTest(); 247 248 $tour = $this->helper_create_tour((object)['enabled' => false]); 249 250 $data = \tool_usertours\cache::get_stepdata($tour->get_id()); 251 $this->assertInternalType('array', $data); 252 $this->assertEmpty($data); 253 } 254 255 /** 256 * Test that get_stepdata returns an empty array when no steps were found. 257 */ 258 public function test_get_stepdata_correct_tour() { 259 $this->resetAfterTest(); 260 261 $tour1 = $this->helper_create_tour((object)['enabled' => false]); 262 $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); 263 $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); 264 $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); 265 $tour2 = $this->helper_create_tour((object)['enabled' => false]); 266 267 $data = \tool_usertours\cache::get_stepdata($tour1->get_id()); 268 $this->assertInternalType('array', $data); 269 $this->assertCount(3, $data); 270 271 $data = \tool_usertours\cache::get_stepdata($tour2->get_id()); 272 $this->assertInternalType('array', $data); 273 $this->assertEmpty($data); 274 } 275 276 /** 277 * Test that get_stepdata returns an array containing multiple steps in 278 * the same order. 279 * 280 * This is very difficult to determine because the act of changing the 281 * order will likely change the DB natural sorting. 282 */ 283 public function test_get_stepdata_ordered_steps() { 284 $this->resetAfterTest(); 285 286 $tour = $this->helper_create_tour((object)['enabled' => false]); 287 $steps = []; 288 $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]); 289 $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]); 290 $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]); 291 $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]); 292 $steps[0]->set_sortorder(10)->persist(); 293 294 $data = \tool_usertours\cache::get_stepdata($tour->get_id()); 295 $this->assertInternalType('array', $data); 296 $this->assertCount(4, $data); 297 298 // Re-order the steps. 299 usort($steps, function($a, $b) { 300 return ($a->get_sortorder() < $b->get_sortorder()) ? -1 : 1; 301 }); 302 303 for ($i = 0; $i < count($data); $i++) { 304 $step = array_shift($data); 305 $this->assertEquals($steps[$i]->get_id(), $step->id); 306 } 307 } 308 309 /** 310 * Test that caching prevents additional DB reads. 311 */ 312 public function test_get_stepdata_single_fetch() { 313 global $DB; 314 315 $this->resetAfterTest(); 316 317 $tour = $this->helper_create_tour(); 318 $this->helper_create_step((object) ['tourid' => $tour->get_id()]); 319 320 // Only one read for the first call. 321 $startreads = $DB->perf_get_reads(); 322 $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); 323 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 324 325 // No subsequent reads for any further calls. 326 $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); 327 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 328 } 329 330 /** 331 * Test that notify_step_change clears the cache. 332 */ 333 public function test_notify_step_change() { 334 global $DB; 335 336 $this->resetAfterTest(); 337 338 $tour = $this->helper_create_tour(); 339 $this->helper_create_step((object) ['tourid' => $tour->get_id()]); 340 341 // Only one read for the first call. 342 $startreads = $DB->perf_get_reads(); 343 $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); 344 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 345 346 // No subsequent reads for any further calls. 347 $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); 348 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 349 350 // Reset. 351 \tool_usertours\cache::notify_step_change($tour->get_id()); 352 353 // An additional DB read now. 354 $startreads = $DB->perf_get_reads(); 355 $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); 356 $this->assertEquals(1, $DB->perf_get_reads() - $startreads); 357 } 358 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body