Proyectos de Subversion Moodle

Rev

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