Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * @covers    \tool_usertours\cache
31
 */
32
class cache_test extends \advanced_testcase {
33
    // There are shared helpers for these tests in the helper trait.
34
    use \tool_usertours_helper_trait;
35
 
36
    /**
37
     * Test that get_enabled_tourdata does not return disabled tours.
38
     */
39
    public function test_get_enabled_tourdata_disabled(): void {
40
        $this->resetAfterTest();
41
 
42
        $tour = $this->helper_create_tour((object)['enabled' => false]);
43
        $this->helper_create_step((object) ['tourid' => $tour->get_id()]);
44
 
45
        $matches = \tool_usertours\cache::get_enabled_tourdata();
46
        $this->assertEmpty($matches);
47
    }
48
 
49
    /**
50
     * Test that get_enabled_tourdata does not return an enabled but empty tour.
51
     */
52
    public function test_get_enabled_tourdata_enabled_no_steps(): void {
53
        $this->resetAfterTest();
54
 
55
        $this->helper_create_tour();
56
 
57
        $matches = \tool_usertours\cache::get_enabled_tourdata();
58
        $this->assertEmpty($matches);
59
    }
60
 
61
    /**
62
     * Test that get_enabled_tourdata returns a tour with steps.
63
     */
64
    public function test_get_enabled_tourdata_enabled(): void {
65
        $this->resetAfterTest();
66
 
67
        // Create two tours. Only the second has steps.
68
        $this->helper_create_tour();
69
        $tour2 = $this->helper_create_tour();
70
        $this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
71
 
72
        $matches = \tool_usertours\cache::get_enabled_tourdata();
73
        $this->assertNotEmpty($matches);
74
        $this->assertCount(1, $matches);
75
 
76
        $match = array_shift($matches);
77
        $this->assertEquals($tour2->get_id(), $match->id);
78
    }
79
 
80
    /**
81
     * Test that get_enabled_tourdata returns tours in the correct sortorder
82
     */
83
    public function test_get_enabled_tourdata_enabled_sortorder(): void {
84
        $this->resetAfterTest();
85
 
86
        $tour1 = $this->helper_create_tour();
87
        $this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
88
        $tour2 = $this->helper_create_tour();
89
        $this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
90
 
91
        $matches = \tool_usertours\cache::get_enabled_tourdata();
92
        $this->assertNotEmpty($matches);
93
        $this->assertCount(2, $matches);
94
 
95
        $match = array_shift($matches);
96
        $this->assertEquals($tour1->get_id(), $match->id);
97
        $match = array_shift($matches);
98
        $this->assertEquals($tour2->get_id(), $match->id);
99
    }
100
 
101
    /**
102
     * Test that caching prevents additional DB reads.
103
     */
104
    public function test_get_enabled_tourdata_single_fetch(): void {
105
        global $DB;
106
 
107
        $this->resetAfterTest();
108
 
109
        $tour1 = $this->helper_create_tour();
110
        $this->helper_create_step((object) ['tourid' => $tour1->get_id()]);
111
        $tour2 = $this->helper_create_tour();
112
        $this->helper_create_step((object) ['tourid' => $tour2->get_id()]);
113
 
114
        // Only one read for the first call.
115
        $startreads = $DB->perf_get_reads();
116
        $matches = \tool_usertours\cache::get_enabled_tourdata();
117
        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
118
 
119
        // No subsequent reads for any further calls.
120
        $matches = \tool_usertours\cache::get_enabled_tourdata();
121
        $this->assertEquals(1, $DB->perf_get_reads() - $startreads);
122
    }
123
 
124
    /**
125
     * Data provider for get_matching_tourdata.
126
     *
127
     * @return  array
128
     */
129
    public static function get_matching_tourdata_provider(): array {
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): void {
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(): void {
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(): void {
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(): void {
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(): void {
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(): void {
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(): void {
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
}