Proyectos de Subversion Moodle

Rev

Rev 11 | | Comparar con el anterior | 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
/**
18
 * Unit tests for privacy.
19
 *
20
 * @package   search_simpledb
21
 * @copyright 2018 David Monllaó {@link http://www.davidmonllao.com}
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
namespace search_simpledb\privacy;
25
 
26
use search_simpledb\privacy\provider;
27
use core_privacy\local\request\transform;
28
use core_privacy\local\request\writer;
29
 
30
defined('MOODLE_INTERNAL') || die();
31
 
32
global $CFG;
33
require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
34
require_once($CFG->dirroot . '/search/tests/fixtures/mock_search_area.php');
35
 
36
/**
37
 * Unit tests for privacy.
38
 *
39
 * @package   search_simpledb
40
 * @copyright 2018 David Monllaó {@link http://www.davidmonllao.com}
41
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
42
 */
1441 ariadna 43
final class provider_test extends \core_privacy\tests\provider_testcase {
1 efrain 44
 
45
    /** @var \search_simpledb\engine database engine. */
46
    protected $engine;
47
 
48
    /** @var \testable_core_search core search class adapted to unit test. */
49
    protected $search;
50
 
51
    /** @var \core_search_generator core search generator class adapted to unit test. */
52
    protected $generator = null;
53
 
54
    /** @var \stdClass course record.*/
55
    protected $c1;
56
 
57
    /** @var \stdClass course record.*/
58
    protected $c2;
59
 
60
    /** @var \context_course context instance. */
61
    protected $c1context;
62
 
63
    /** @var \context_course context instance. */
64
    protected $c2context;
65
 
66
    /** @var \stdClass user record. */
67
    protected $u1;
68
 
69
    /** @var \stdClass user record. */
70
    protected $u2;
71
 
72
    public function setUp(): void {
73
        global $DB;
1441 ariadna 74
        parent::setUp();
1 efrain 75
 
76
        if ($this->requires_manual_index_update()) {
77
            // We need to update fulltext index manually, which requires an alter table statement.
78
            $this->preventResetByRollback();
79
        }
80
 
81
        $this->resetAfterTest();
82
        set_config('enableglobalsearch', true);
83
 
84
        // Inject search_simpledb engine into the testable core search as we need to add the mock
85
        // search component to it.
86
 
87
        $this->engine = new \search_simpledb\engine();
88
        $this->search = \testable_core_search::instance($this->engine);
89
        $areaid = \core_search\manager::generate_areaid('core_mocksearch', 'mock_search_area');
90
        $this->search->add_search_area($areaid, new \core_mocksearch\search\mock_search_area());
91
 
92
        $this->generator = self::getDataGenerator()->get_plugin_generator('core_search');
93
        $this->generator->setup();
94
 
95
        $this->c1 = $this->getDataGenerator()->create_course();
96
        $this->c2 = $this->getDataGenerator()->create_course();
97
 
98
        $this->c1context = \context_course::instance($this->c1->id);
99
        $this->c2context = \context_course::instance($this->c2->id);
100
 
101
        $this->u1 = $this->getDataGenerator()->create_user();
102
        $this->u2 = $this->getDataGenerator()->create_user();
103
 
104
        $this->getDataGenerator()->enrol_user($this->u1->id, $this->c1->id, 'student');
105
        $this->getDataGenerator()->enrol_user($this->u1->id, $this->c2->id, 'student');
106
        $this->getDataGenerator()->enrol_user($this->u2->id, $this->c1->id, 'student');
107
        $this->getDataGenerator()->enrol_user($this->u2->id, $this->c2->id, 'student');
108
 
109
        $record = (object)[
110
            'userid' => $this->u1->id,
111
            'contextid' => $this->c1context->id,
112
            'title' => 'vi',
113
            'content' => 'va',
114
            'description1' => 'san',
115
            'description2' => 'jose'
116
        ];
117
        $this->generator->create_record($record);
118
        $this->generator->create_record((object)['userid' => $this->u1->id, 'contextid' => $this->c2context->id]);
119
        $this->generator->create_record((object)['userid' => $this->u2->id, 'contextid' => $this->c2context->id]);
120
        $this->generator->create_record((object)['userid' => $this->u2->id, 'contextid' => $this->c1context->id]);
121
        $this->generator->create_record((object)['owneruserid' => $this->u1->id, 'contextid' => $this->c1context->id]);
122
        $this->generator->create_record((object)['owneruserid' => $this->u1->id, 'contextid' => $this->c2context->id]);
123
        $this->generator->create_record((object)['owneruserid' => $this->u2->id, 'contextid' => $this->c1context->id]);
124
        $this->generator->create_record((object)['owneruserid' => $this->u2->id, 'contextid' => $this->c2context->id]);
125
        $this->search->index();
126
 
127
        $this->setAdminUser();
128
    }
129
 
130
    /**
131
     * tearDown
132
     *
133
     * @return void
134
     */
135
    public function tearDown(): void {
136
        // Call parent tearDown() first.
137
        parent::tearDown();
138
 
139
        // For unit tests before PHP 7, teardown is called even on skip. So only do our teardown if we did setup.
140
        if ($this->generator) {
141
            // Moodle DML freaks out if we don't teardown the temp table after each run.
142
            $this->generator->teardown();
143
            $this->generator = null;
144
        }
145
    }
146
 
147
    /**
148
     * Test fetching contexts for a given user ID.
149
     */
11 efrain 150
    public function test_get_contexts_for_userid(): void {
1 efrain 151
        // Ensure both contexts are found for both users.
152
        $expected = [$this->c1context->id, $this->c2context->id];
153
        sort($expected);
154
 
155
        // User 1.
156
        $contextlist = provider::get_contexts_for_userid($this->u1->id);
157
        $this->assertCount(2, $contextlist);
158
 
159
        $actual = $contextlist->get_contextids();
160
        sort($actual);
161
        $this->assertEquals($expected, $actual);
162
 
163
        // User 2.
164
        $contextlist = provider::get_contexts_for_userid($this->u2->id);
165
        $this->assertCount(2, $contextlist);
166
 
167
        $actual = $contextlist->get_contextids();
168
        sort($actual);
169
        $this->assertEquals($expected, $actual);
170
    }
171
 
172
    /**
173
     * Test fetching user IDs for a given context.
174
     */
11 efrain 175
    public function test_get_users_in_context(): void {
1 efrain 176
        $component = 'search_simpledb';
177
 
178
        // Ensure both users are found for both contexts.
179
        $expected = [$this->u1->id, $this->u2->id];
180
        sort($expected);
181
 
182
        // User 1.
183
        $userlist = new \core_privacy\local\request\userlist($this->c1context, $component);
184
        provider::get_users_in_context($userlist);
185
        $this->assertCount(2, $userlist);
186
 
187
        $actual = $userlist->get_userids();
188
        sort($actual);
189
        $this->assertEquals($expected, $actual);
190
 
191
        // User 2.
192
        $userlist = new \core_privacy\local\request\userlist($this->c2context, $component);
193
        provider::get_users_in_context($userlist);
194
        $this->assertCount(2, $userlist);
195
 
196
        $actual = $userlist->get_userids();
197
        sort($actual);
198
        $this->assertEquals($expected, $actual);
199
    }
200
 
201
    /**
202
     * Test export user data.
203
     *
204
     * @return null
205
     */
11 efrain 206
    public function test_export_user_data(): void {
1 efrain 207
        global $DB;
208
 
209
        $contextlist = new \core_privacy\local\request\approved_contextlist($this->u1, 'search_simpledb',
210
                                                                            [$this->c1context->id]);
211
        provider::export_user_data($contextlist);
212
        $writer = \core_privacy\local\request\writer::with_context($this->c1context);
213
        $this->assertTrue($writer->has_any_data());
214
        $u1c1 = $DB->get_record('search_simpledb_index', ['userid' => $this->u1->id, 'contextid' => $this->c1context->id]);
215
        $data = $writer->get_data([get_string('search', 'search'), $u1c1->docid]);
216
 
217
        $this->assertEquals($this->c1context->get_context_name(true, true), $data->context);
218
        $this->assertEquals('vi', $data->title);
219
        $this->assertEquals('va', $data->content);
220
        $this->assertEquals('san', $data->description1);
221
        $this->assertEquals('jose', $data->description2);
222
    }
223
 
224
    /**
225
     * Test delete search for context.
226
     *
227
     * @return null
228
     */
11 efrain 229
    public function test_delete_data_for_all_users(): void {
1 efrain 230
        global $DB;
231
 
232
        $this->assertEquals(8, $DB->count_records('search_simpledb_index'));
233
 
234
        provider::delete_data_for_all_users_in_context($this->c1context);
235
        $this->assertEquals(0, $DB->count_records('search_simpledb_index', ['contextid' => $this->c1context->id]));
236
        $this->assertEquals(4, $DB->count_records('search_simpledb_index'));
237
 
238
        $u2context = \context_user::instance($this->u2->id);
239
        provider::delete_data_for_all_users_in_context($u2context);
240
        $this->assertEquals(0, $DB->count_records('search_simpledb_index', ['contextid' => $u2context->id]));
241
        $this->assertEquals(2, $DB->count_records('search_simpledb_index'));
242
    }
243
 
244
    /**
245
     * Test delete search for user.
246
     *
247
     * @return null
248
     */
11 efrain 249
    public function test_delete_data_for_user(): void {
1 efrain 250
        global $DB;
251
 
252
        $contextlist = new \core_privacy\local\request\approved_contextlist($this->u1, 'search_simpledb',
253
                                                                            [$this->c1context->id]);
254
        provider::delete_data_for_user($contextlist);
255
        $select = 'contextid = :contextid AND (owneruserid = :owneruserid OR userid = :userid)';
256
        $params = ['contextid' => $this->c1context->id, 'owneruserid' => $this->u1->id, 'userid' => $this->u1->id];
257
        $this->assertEquals(0, $DB->count_records_select('search_simpledb_index', $select, $params));
258
        $this->assertEquals(2, $DB->count_records('search_simpledb_index', ['contextid' => $this->c1context->id]));
259
        $this->assertEquals(6, $DB->count_records('search_simpledb_index'));
260
 
261
        $contextlist = new \core_privacy\local\request\approved_contextlist($this->u2, 'search_simpledb',
262
                                                                            [$this->c2context->id]);
263
        provider::delete_data_for_user($contextlist);
264
        $select = 'contextid = :contextid AND (owneruserid = :owneruserid OR userid = :userid)';
265
        $params = ['contextid' => $this->c2context->id, 'owneruserid' => $this->u2->id, 'userid' => $this->u2->id];
266
        $this->assertEquals(0, $DB->count_records_select('search_simpledb_index', $select, $params));
267
        $this->assertEquals(2, $DB->count_records('search_simpledb_index', ['contextid' => $this->c2context->id]));
268
        $this->assertEquals(4, $DB->count_records('search_simpledb_index'));
269
    }
270
 
271
    /**
272
     * Test deleting data for an approved userlist.
273
     */
11 efrain 274
    public function test_delete_data_for_users(): void {
1 efrain 275
        global $DB;
276
        $component = 'search_simpledb';
277
        $select = 'contextid = :contextid AND (owneruserid = :owneruserid OR userid = :userid)';
278
 
279
        // Ensure expected amount of data for both users exists in each context.
280
        $this->assertEquals(4, $DB->count_records('search_simpledb_index', ['contextid' => $this->c1context->id]));
281
        $this->assertEquals(4, $DB->count_records('search_simpledb_index', ['contextid' => $this->c2context->id]));
282
 
283
        // Delete user 1's data in context 1.
284
        $approveduserids = [$this->u1->id];
285
        $approvedlist = new \core_privacy\local\request\approved_userlist($this->c1context, $component, $approveduserids);
286
        provider::delete_data_for_users($approvedlist);
287
 
288
        $params = ['contextid' => $this->c1context->id, 'owneruserid' => $this->u1->id, 'userid' => $this->u1->id];
289
        $this->assertEquals(0, $DB->count_records_select('search_simpledb_index', $select, $params));
290
 
291
        // Ensure user 2's data in context 1 is retained.
292
        $params = ['contextid' => $this->c1context->id, 'owneruserid' => $this->u2->id, 'userid' => $this->u2->id];
293
        $this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params));
294
 
295
        // Ensure both users' data in context 2 is retained.
296
        $params = ['contextid' => $this->c2context->id, 'owneruserid' => $this->u1->id, 'userid' => $this->u1->id];
297
        $this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params));
298
        $params = ['contextid' => $this->c2context->id, 'owneruserid' => $this->u2->id, 'userid' => $this->u2->id];
299
        $this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params));
300
    }
301
 
302
    /**
303
     * Mssql with fulltext support requires manual updates.
304
     *
305
     * @return bool
306
     */
307
    private function requires_manual_index_update() {
308
        global $DB;
309
        return ($DB->get_dbfamily() === 'mssql' && $DB->is_fulltext_search_supported());
310
    }
311
}