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