You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
12 KiB
358 lines
12 KiB
<?php
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
/**
|
|
* Tests for cache.
|
|
*
|
|
* @package tool_usertours
|
|
* @copyright 2016 Andrew Nicols <andrew@nicols.co.uk>
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
global $CFG;
|
|
require_once(__DIR__ . '/helper_trait.php');
|
|
|
|
/**
|
|
* Tests for cache.
|
|
*
|
|
* @package tool_usertours
|
|
* @copyright 2016 Andrew Nicols <andrew@nicols.co.uk>
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class cache_testcase extends advanced_testcase {
|
|
// There are shared helpers for these tests in the helper trait.
|
|
use tool_usertours_helper_trait;
|
|
|
|
/**
|
|
* Test that get_enabled_tourdata does not return disabled tours.
|
|
*/
|
|
public function test_get_enabled_tourdata_disabled() {
|
|
$this->resetAfterTest();
|
|
|
|
$tour = $this->helper_create_tour((object)['enabled' => false]);
|
|
$this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
|
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertEmpty($matches);
|
|
}
|
|
|
|
/**
|
|
* Test that get_enabled_tourdata does not return an enabled but empty tour.
|
|
*/
|
|
public function test_get_enabled_tourdata_enabled_no_steps() {
|
|
$this->resetAfterTest();
|
|
|
|
$this->helper_create_tour();
|
|
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertEmpty($matches);
|
|
}
|
|
|
|
/**
|
|
* Test that get_enabled_tourdata returns a tour with steps.
|
|
*/
|
|
public function test_get_enabled_tourdata_enabled() {
|
|
$this->resetAfterTest();
|
|
|
|
// Create two tours. Only the second has steps.
|
|
$this->helper_create_tour();
|
|
$tour2 = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
|
|
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertNotEmpty($matches);
|
|
$this->assertCount(1, $matches);
|
|
|
|
$match = array_shift($matches);
|
|
$this->assertEquals($tour2->get_id(), $match->id);
|
|
}
|
|
|
|
/**
|
|
* Test that get_enabled_tourdata returns tours in the correct sortorder
|
|
*/
|
|
public function test_get_enabled_tourdata_enabled_sortorder() {
|
|
$this->resetAfterTest();
|
|
|
|
$tour1 = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
|
|
$tour2 = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
|
|
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertNotEmpty($matches);
|
|
$this->assertCount(2, $matches);
|
|
|
|
$match = array_shift($matches);
|
|
$this->assertEquals($tour1->get_id(), $match->id);
|
|
$match = array_shift($matches);
|
|
$this->assertEquals($tour2->get_id(), $match->id);
|
|
}
|
|
|
|
/**
|
|
* Test that caching prevents additional DB reads.
|
|
*/
|
|
public function test_get_enabled_tourdata_single_fetch() {
|
|
global $DB;
|
|
|
|
$this->resetAfterTest();
|
|
|
|
$tour1 = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
|
|
$tour2 = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
|
|
|
|
// Only one read for the first call.
|
|
$startreads = $DB->perf_get_reads();
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
|
|
// No subsequent reads for any further calls.
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
|
|
}
|
|
|
|
/**
|
|
* Data provider for get_matching_tourdata.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_matching_tourdata_provider() {
|
|
$tourconfigs = [
|
|
(object) [
|
|
'name' => 'my_exact_1',
|
|
'pathmatch' => '/my/view.php'
|
|
],
|
|
(object) [
|
|
'name' => 'my_failed_regex',
|
|
'pathmatch' => '/my/*.php'
|
|
],
|
|
(object) [
|
|
'name' => 'my_glob_1',
|
|
'pathmatch' => '/my/%'
|
|
],
|
|
(object) [
|
|
'name' => 'my_glob_2',
|
|
'pathmatch' => '/my/%'
|
|
],
|
|
(object) [
|
|
'name' => 'frontpage_only',
|
|
'pathmatch' => 'FRONTPAGE'
|
|
],
|
|
(object) [
|
|
'name' => 'frontpage_match',
|
|
'pathmatch' => '/?%'
|
|
],
|
|
];
|
|
|
|
return [
|
|
'Matches expected glob' => [
|
|
$tourconfigs,
|
|
'/my/index.php',
|
|
['my_glob_1', 'my_glob_2'],
|
|
],
|
|
'Matches expected glob and exact' => [
|
|
$tourconfigs,
|
|
'/my/view.php',
|
|
['my_exact_1', 'my_glob_1', 'my_glob_2'],
|
|
],
|
|
'Special constant FRONTPAGE must match front page only' => [
|
|
$tourconfigs,
|
|
'/',
|
|
['frontpage_only'],
|
|
],
|
|
'Standard frontpage URL matches both the special constant, and a correctly formed pathmatch' => [
|
|
$tourconfigs,
|
|
'/?redirect=0',
|
|
['frontpage_only', 'frontpage_match'],
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Tests for the get_matching_tourdata function.
|
|
*
|
|
* @dataProvider get_matching_tourdata_provider
|
|
* @param array $tourconfigs The configuration for the tours to create
|
|
* @param string $targetmatch The match to be tested
|
|
* @param array $expected An array containing the ordered names of the expected tours
|
|
*/
|
|
public function test_get_matching_tourdata($tourconfigs, $targetmatch, $expected) {
|
|
$this->resetAfterTest();
|
|
foreach ($tourconfigs as $tourconfig) {
|
|
$tour = $this->helper_create_tour($tourconfig);
|
|
$this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
|
}
|
|
|
|
$matches = \tool_usertours\cache::get_matching_tourdata(new moodle_url($targetmatch));
|
|
$this->assertCount(count($expected), $matches);
|
|
|
|
for ($i = 0; $i < count($matches); $i++) {
|
|
$match = array_shift($matches);
|
|
$this->assertEquals($expected[$i], $match->name);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test that notify_tour_change clears the cache.
|
|
*/
|
|
public function test_notify_tour_change() {
|
|
global $DB;
|
|
|
|
$this->resetAfterTest();
|
|
|
|
$tour1 = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
|
|
$tour2 = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
|
|
|
|
// Only one read for the first call.
|
|
$startreads = $DB->perf_get_reads();
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
|
|
// No subsequent reads for any further calls.
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
|
|
// Reset.
|
|
\tool_usertours\cache::notify_tour_change();
|
|
|
|
// An additional DB read now.
|
|
$startreads = $DB->perf_get_reads();
|
|
$matches = \tool_usertours\cache::get_enabled_tourdata();
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
}
|
|
|
|
/**
|
|
* Test that get_stepdata returns an empty array when no steps were found.
|
|
*/
|
|
public function test_get_stepdata_no_steps() {
|
|
$this->resetAfterTest();
|
|
|
|
$tour = $this->helper_create_tour((object)['enabled' => false]);
|
|
|
|
$data = \tool_usertours\cache::get_stepdata($tour->get_id());
|
|
$this->assertInternalType('array', $data);
|
|
$this->assertEmpty($data);
|
|
}
|
|
|
|
/**
|
|
* Test that get_stepdata returns an empty array when no steps were found.
|
|
*/
|
|
public function test_get_stepdata_correct_tour() {
|
|
$this->resetAfterTest();
|
|
|
|
$tour1 = $this->helper_create_tour((object)['enabled' => false]);
|
|
$this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
|
|
$this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
|
|
$this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
|
|
$tour2 = $this->helper_create_tour((object)['enabled' => false]);
|
|
|
|
$data = \tool_usertours\cache::get_stepdata($tour1->get_id());
|
|
$this->assertInternalType('array', $data);
|
|
$this->assertCount(3, $data);
|
|
|
|
$data = \tool_usertours\cache::get_stepdata($tour2->get_id());
|
|
$this->assertInternalType('array', $data);
|
|
$this->assertEmpty($data);
|
|
}
|
|
|
|
/**
|
|
* Test that get_stepdata returns an array containing multiple steps in
|
|
* the same order.
|
|
*
|
|
* This is very difficult to determine because the act of changing the
|
|
* order will likely change the DB natural sorting.
|
|
*/
|
|
public function test_get_stepdata_ordered_steps() {
|
|
$this->resetAfterTest();
|
|
|
|
$tour = $this->helper_create_tour((object)['enabled' => false]);
|
|
$steps = [];
|
|
$steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
|
$steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
|
$steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
|
$steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
|
$steps[0]->set_sortorder(10)->persist();
|
|
|
|
$data = \tool_usertours\cache::get_stepdata($tour->get_id());
|
|
$this->assertInternalType('array', $data);
|
|
$this->assertCount(4, $data);
|
|
|
|
// Re-order the steps.
|
|
usort($steps, function($a, $b) {
|
|
return ($a->get_sortorder() < $b->get_sortorder()) ? -1 : 1;
|
|
});
|
|
|
|
for ($i = 0; $i < count($data); $i++) {
|
|
$step = array_shift($data);
|
|
$this->assertEquals($steps[$i]->get_id(), $step->id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test that caching prevents additional DB reads.
|
|
*/
|
|
public function test_get_stepdata_single_fetch() {
|
|
global $DB;
|
|
|
|
$this->resetAfterTest();
|
|
|
|
$tour = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
|
|
|
// Only one read for the first call.
|
|
$startreads = $DB->perf_get_reads();
|
|
$matches = \tool_usertours\cache::get_stepdata($tour->get_id());
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
|
|
// No subsequent reads for any further calls.
|
|
$matches = \tool_usertours\cache::get_stepdata($tour->get_id());
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
}
|
|
|
|
/**
|
|
* Test that notify_step_change clears the cache.
|
|
*/
|
|
public function test_notify_step_change() {
|
|
global $DB;
|
|
|
|
$this->resetAfterTest();
|
|
|
|
$tour = $this->helper_create_tour();
|
|
$this->helper_create_step((object) ['tourid' => $tour->get_id()]);
|
|
|
|
// Only one read for the first call.
|
|
$startreads = $DB->perf_get_reads();
|
|
$matches = \tool_usertours\cache::get_stepdata($tour->get_id());
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
|
|
// No subsequent reads for any further calls.
|
|
$matches = \tool_usertours\cache::get_stepdata($tour->get_id());
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
|
|
// Reset.
|
|
\tool_usertours\cache::notify_step_change($tour->get_id());
|
|
|
|
// An additional DB read now.
|
|
$startreads = $DB->perf_get_reads();
|
|
$matches = \tool_usertours\cache::get_stepdata($tour->get_id());
|
|
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
|
|
}
|
|
}
|
|
|