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.
279 lines
12 KiB
279 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/>.
|
|
|
|
/**
|
|
* Unit tests for privacy.
|
|
*
|
|
* @package search_simpledb
|
|
* @copyright 2018 David Monllaó {@link http://www.davidmonllao.com}
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
use \search_simpledb\privacy\provider;
|
|
use core_privacy\local\request\transform;
|
|
use core_privacy\local\request\writer;
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
global $CFG;
|
|
require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
|
|
require_once($CFG->dirroot . '/search/tests/fixtures/mock_search_area.php');
|
|
|
|
/**
|
|
* Unit tests for privacy.
|
|
*
|
|
* @package search_simpledb
|
|
* @copyright 2018 David Monllaó {@link http://www.davidmonllao.com}
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class privacy_model_testcase extends \core_privacy\tests\provider_testcase {
|
|
|
|
public function setUp() {
|
|
global $DB;
|
|
|
|
if ($this->requires_manual_index_update()) {
|
|
// We need to update fulltext index manually, which requires an alter table statement.
|
|
$this->preventResetByRollback();
|
|
}
|
|
|
|
$this->resetAfterTest();
|
|
set_config('enableglobalsearch', true);
|
|
|
|
// Inject search_simpledb engine into the testable core search as we need to add the mock
|
|
// search component to it.
|
|
|
|
$this->engine = new \search_simpledb\engine();
|
|
$this->search = testable_core_search::instance($this->engine);
|
|
$areaid = \core_search\manager::generate_areaid('core_mocksearch', 'mock_search_area');
|
|
$this->search->add_search_area($areaid, new core_mocksearch\search\mock_search_area());
|
|
|
|
$this->generator = self::getDataGenerator()->get_plugin_generator('core_search');
|
|
$this->generator->setup();
|
|
|
|
$this->c1 = $this->getDataGenerator()->create_course();
|
|
$this->c2 = $this->getDataGenerator()->create_course();
|
|
|
|
$this->c1context = \context_course::instance($this->c1->id);
|
|
$this->c2context = \context_course::instance($this->c2->id);
|
|
|
|
$this->u1 = $this->getDataGenerator()->create_user();
|
|
$this->u2 = $this->getDataGenerator()->create_user();
|
|
|
|
$this->getDataGenerator()->enrol_user($this->u1->id, $this->c1->id, 'student');
|
|
$this->getDataGenerator()->enrol_user($this->u1->id, $this->c2->id, 'student');
|
|
$this->getDataGenerator()->enrol_user($this->u2->id, $this->c1->id, 'student');
|
|
$this->getDataGenerator()->enrol_user($this->u2->id, $this->c2->id, 'student');
|
|
|
|
$record = (object)[
|
|
'userid' => $this->u1->id,
|
|
'contextid' => $this->c1context->id,
|
|
'title' => 'vi',
|
|
'content' => 'va',
|
|
'description1' => 'san',
|
|
'description2' => 'jose'
|
|
];
|
|
$this->generator->create_record($record);
|
|
$this->generator->create_record((object)['userid' => $this->u1->id, 'contextid' => $this->c2context->id]);
|
|
$this->generator->create_record((object)['userid' => $this->u2->id, 'contextid' => $this->c2context->id]);
|
|
$this->generator->create_record((object)['userid' => $this->u2->id, 'contextid' => $this->c1context->id]);
|
|
$this->generator->create_record((object)['owneruserid' => $this->u1->id, 'contextid' => $this->c1context->id]);
|
|
$this->generator->create_record((object)['owneruserid' => $this->u1->id, 'contextid' => $this->c2context->id]);
|
|
$this->generator->create_record((object)['owneruserid' => $this->u2->id, 'contextid' => $this->c1context->id]);
|
|
$this->generator->create_record((object)['owneruserid' => $this->u2->id, 'contextid' => $this->c2context->id]);
|
|
$this->search->index();
|
|
|
|
$this->setAdminUser();
|
|
}
|
|
|
|
/**
|
|
* tearDown
|
|
*
|
|
* @return void
|
|
*/
|
|
public function tearDown() {
|
|
// For unit tests before PHP 7, teardown is called even on skip. So only do our teardown if we did setup.
|
|
if ($this->generator) {
|
|
// Moodle DML freaks out if we don't teardown the temp table after each run.
|
|
$this->generator->teardown();
|
|
$this->generator = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test fetching contexts for a given user ID.
|
|
*/
|
|
public function test_get_contexts_for_userid() {
|
|
// Ensure both contexts are found for both users.
|
|
$expected = [$this->c1context->id, $this->c2context->id];
|
|
sort($expected);
|
|
|
|
// User 1.
|
|
$contextlist = provider::get_contexts_for_userid($this->u1->id);
|
|
$this->assertCount(2, $contextlist);
|
|
|
|
$actual = $contextlist->get_contextids();
|
|
sort($actual);
|
|
$this->assertEquals($expected, $actual);
|
|
|
|
// User 2.
|
|
$contextlist = provider::get_contexts_for_userid($this->u2->id);
|
|
$this->assertCount(2, $contextlist);
|
|
|
|
$actual = $contextlist->get_contextids();
|
|
sort($actual);
|
|
$this->assertEquals($expected, $actual);
|
|
}
|
|
|
|
/**
|
|
* Test fetching user IDs for a given context.
|
|
*/
|
|
public function test_get_users_in_context() {
|
|
$component = 'search_simpledb';
|
|
|
|
// Ensure both users are found for both contexts.
|
|
$expected = [$this->u1->id, $this->u2->id];
|
|
sort($expected);
|
|
|
|
// User 1.
|
|
$userlist = new \core_privacy\local\request\userlist($this->c1context, $component);
|
|
provider::get_users_in_context($userlist);
|
|
$this->assertCount(2, $userlist);
|
|
|
|
$actual = $userlist->get_userids();
|
|
sort($actual);
|
|
$this->assertEquals($expected, $actual);
|
|
|
|
// User 2.
|
|
$userlist = new \core_privacy\local\request\userlist($this->c2context, $component);
|
|
provider::get_users_in_context($userlist);
|
|
$this->assertCount(2, $userlist);
|
|
|
|
$actual = $userlist->get_userids();
|
|
sort($actual);
|
|
$this->assertEquals($expected, $actual);
|
|
}
|
|
|
|
/**
|
|
* Test export user data.
|
|
*
|
|
* @return null
|
|
*/
|
|
public function test_export_user_data() {
|
|
global $DB;
|
|
|
|
$contextlist = new \core_privacy\local\request\approved_contextlist($this->u1, 'search_simpledb',
|
|
[$this->c1context->id]);
|
|
provider::export_user_data($contextlist);
|
|
$writer = \core_privacy\local\request\writer::with_context($this->c1context);
|
|
$this->assertTrue($writer->has_any_data());
|
|
$u1c1 = $DB->get_record('search_simpledb_index', ['userid' => $this->u1->id, 'contextid' => $this->c1context->id]);
|
|
$data = $writer->get_data([get_string('search', 'search'), $u1c1->docid]);
|
|
|
|
$this->assertEquals($this->c1context->get_context_name(true, true), $data->context);
|
|
$this->assertEquals('vi', $data->title);
|
|
$this->assertEquals('va', $data->content);
|
|
$this->assertEquals('san', $data->description1);
|
|
$this->assertEquals('jose', $data->description2);
|
|
}
|
|
|
|
/**
|
|
* Test delete search for context.
|
|
*
|
|
* @return null
|
|
*/
|
|
public function test_delete_data_for_all_users() {
|
|
global $DB;
|
|
|
|
$this->assertEquals(8, $DB->count_records('search_simpledb_index'));
|
|
|
|
provider::delete_data_for_all_users_in_context($this->c1context);
|
|
$this->assertEquals(0, $DB->count_records('search_simpledb_index', ['contextid' => $this->c1context->id]));
|
|
$this->assertEquals(4, $DB->count_records('search_simpledb_index'));
|
|
|
|
$u2context = \context_user::instance($this->u2->id);
|
|
provider::delete_data_for_all_users_in_context($u2context);
|
|
$this->assertEquals(0, $DB->count_records('search_simpledb_index', ['contextid' => $u2context->id]));
|
|
$this->assertEquals(2, $DB->count_records('search_simpledb_index'));
|
|
}
|
|
|
|
/**
|
|
* Test delete search for user.
|
|
*
|
|
* @return null
|
|
*/
|
|
public function test_delete_data_for_user() {
|
|
global $DB;
|
|
|
|
$contextlist = new \core_privacy\local\request\approved_contextlist($this->u1, 'search_simpledb',
|
|
[$this->c1context->id]);
|
|
provider::delete_data_for_user($contextlist);
|
|
$select = 'contextid = :contextid AND (owneruserid = :owneruserid OR userid = :userid)';
|
|
$params = ['contextid' => $this->c1context->id, 'owneruserid' => $this->u1->id, 'userid' => $this->u1->id];
|
|
$this->assertEquals(0, $DB->count_records_select('search_simpledb_index', $select, $params));
|
|
$this->assertEquals(2, $DB->count_records('search_simpledb_index', ['contextid' => $this->c1context->id]));
|
|
$this->assertEquals(6, $DB->count_records('search_simpledb_index'));
|
|
|
|
$contextlist = new \core_privacy\local\request\approved_contextlist($this->u2, 'search_simpledb',
|
|
[$this->c2context->id]);
|
|
provider::delete_data_for_user($contextlist);
|
|
$select = 'contextid = :contextid AND (owneruserid = :owneruserid OR userid = :userid)';
|
|
$params = ['contextid' => $this->c2context->id, 'owneruserid' => $this->u2->id, 'userid' => $this->u2->id];
|
|
$this->assertEquals(0, $DB->count_records_select('search_simpledb_index', $select, $params));
|
|
$this->assertEquals(2, $DB->count_records('search_simpledb_index', ['contextid' => $this->c2context->id]));
|
|
$this->assertEquals(4, $DB->count_records('search_simpledb_index'));
|
|
}
|
|
|
|
/**
|
|
* Test deleting data for an approved userlist.
|
|
*/
|
|
public function test_delete_data_for_users() {
|
|
global $DB;
|
|
$component = 'search_simpledb';
|
|
$select = 'contextid = :contextid AND (owneruserid = :owneruserid OR userid = :userid)';
|
|
|
|
// Ensure expected amount of data for both users exists in each context.
|
|
$this->assertEquals(4, $DB->count_records('search_simpledb_index', ['contextid' => $this->c1context->id]));
|
|
$this->assertEquals(4, $DB->count_records('search_simpledb_index', ['contextid' => $this->c2context->id]));
|
|
|
|
// Delete user 1's data in context 1.
|
|
$approveduserids = [$this->u1->id];
|
|
$approvedlist = new \core_privacy\local\request\approved_userlist($this->c1context, $component, $approveduserids);
|
|
provider::delete_data_for_users($approvedlist);
|
|
|
|
$params = ['contextid' => $this->c1context->id, 'owneruserid' => $this->u1->id, 'userid' => $this->u1->id];
|
|
$this->assertEquals(0, $DB->count_records_select('search_simpledb_index', $select, $params));
|
|
|
|
// Ensure user 2's data in context 1 is retained.
|
|
$params = ['contextid' => $this->c1context->id, 'owneruserid' => $this->u2->id, 'userid' => $this->u2->id];
|
|
$this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params));
|
|
|
|
// Ensure both users' data in context 2 is retained.
|
|
$params = ['contextid' => $this->c2context->id, 'owneruserid' => $this->u1->id, 'userid' => $this->u1->id];
|
|
$this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params));
|
|
$params = ['contextid' => $this->c2context->id, 'owneruserid' => $this->u2->id, 'userid' => $this->u2->id];
|
|
$this->assertEquals(2, $DB->count_records_select('search_simpledb_index', $select, $params));
|
|
}
|
|
|
|
/**
|
|
* Mssql with fulltext support requires manual updates.
|
|
*
|
|
* @return bool
|
|
*/
|
|
private function requires_manual_index_update() {
|
|
global $DB;
|
|
return ($DB->get_dbfamily() === 'mssql' && $DB->is_fulltext_search_supported());
|
|
}
|
|
}
|
|
|