MDL-53226 search_simpledb: Adding clumsy search
[moodle.git] / search / engine / simpledb / tests / engine_test.php
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/>.
17 /**
18  * Simple db search engine tests.
19  *
20  * @package     search_simpledb
21  * @category    phpunit
22  * @copyright   2016 David Monllao {@link http://www.davidmonllao.com}
23  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 global $CFG;
29 require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
30 require_once($CFG->dirroot . '/search/tests/fixtures/mock_search_area.php');
32 /**
33  * Simple search engine base unit tests.
34  *
35  * @package     search_simpledb
36  * @category    phpunit
37  * @copyright   2016 David Monllao {@link http://www.davidmonllao.com}
38  * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  */
40 class search_simpledb_engine_testcase extends advanced_testcase {
42     /**
43      * @var \core_search::manager
44      */
45     protected $search = null;
47     public function setUp() {
48         $this->resetAfterTest();
49         set_config('enableglobalsearch', true);
51         // Inject search_simpledb engine into the testable core search as we need to add the mock
52         // search component to it.
53         $searchengine = new \search_simpledb\engine();
54         $this->search = testable_core_search::instance($searchengine);
55         $areaid = \core_search\manager::generate_areaid('core_mocksearch', 'role_capabilities');
56         $this->search->add_search_area($areaid, new core_mocksearch\search\role_capabilities());
57     }
59     public function test_index() {
60         global $DB;
62         $noneditingteacherid = $DB->get_field('role', 'id', array('shortname' => 'teacher'));
64         // Data gets into the search engine.
65         $this->assertTrue($this->search->index());
67         // Not anymore as everything was already added.
68         sleep(1);
69         $this->assertFalse($this->search->index());
71         assign_capability('moodle/course:renameroles', CAP_ALLOW, $noneditingteacherid, context_system::instance()->id);
72         accesslib_clear_all_caches_for_unit_testing();
74         // Indexing again once there is new data.
75         $this->assertTrue($this->search->index());
76     }
78     /**
79      * Test search filters.
80      *
81      * @return void
82      */
83     public function test_search() {
84         global $USER, $DB;
86         $this->setAdminUser();
88         $noneditingteacherid = $DB->get_field('role', 'id', array('shortname' => 'teacher'));
90         $this->search->index();
92         // Check that docid - id is respected.
93         $rolecaps = $DB->get_records('role_capabilities', array('capability' => 'moodle/course:renameroles'));
94         $rolecap = reset($rolecaps);
95         $rolecap->timemodified = time();
96         $DB->update_record('role_capabilities', $rolecap);
98         $this->search->index();
100         $querydata = new stdClass();
101         $querydata->q = 'message';
102         $results = $this->search->search($querydata);
103         $this->assertCount(2, $results);
105         // Based on core_mocksearch\search\indexer.
106         $this->assertEquals($USER->id, $results[0]->get('userid'));
107         $this->assertEquals(\context_system::instance()->id, $results[0]->get('contextid'));
109         // Do a test to make sure we aren't searching non-query fields, like areaid.
110         $querydata->q = \core_search\manager::generate_areaid('core_mocksearch', 'role_capabilities');
111         $this->assertCount(0, $this->search->search($querydata));
112         $querydata->q = 'message';
114         sleep(1);
115         $beforeadding = time();
116         sleep(1);
117         assign_capability('moodle/course:renameroles', CAP_ALLOW, $noneditingteacherid, context_system::instance()->id);
118         accesslib_clear_all_caches_for_unit_testing();
119         $this->search->index();
121         // Timestart.
122         $querydata->timestart = $beforeadding;
123         $this->assertCount(2, $this->search->search($querydata));
125         // Timeend.
126         unset($querydata->timestart);
127         $querydata->timeend = $beforeadding;
128         $this->assertCount(1, $this->search->search($querydata));
130         // Title.
131         unset($querydata->timeend);
132         $querydata->title = 'moodle/course:renameroles roleid 1';
133         $this->assertCount(1, $this->search->search($querydata));
135         // Course IDs.
136         unset($querydata->title);
137         $querydata->courseids = array(SITEID + 1);
138         $this->assertCount(0, $this->search->search($querydata));
140         $querydata->courseids = array(SITEID);
141         $this->assertCount(3, $this->search->search($querydata));
143         // Check that index contents get updated.
144         $DB->delete_records('role_capabilities', array('capability' => 'moodle/course:renameroles'));
145         $this->search->index(true);
146         unset($querydata->title);
147         $querydata->q = '*renameroles*';
148         $this->assertCount(0, $this->search->search($querydata));
149     }
151     public function test_delete() {
152         $this->search->index();
154         $querydata = new stdClass();
155         $querydata->q = 'message';
157         $this->assertCount(2, $this->search->search($querydata));
159         $areaid = \core_search\manager::generate_areaid('core_mocksearch', 'role_capabilities');
160         $this->search->delete_index($areaid);
161         $this->assertCount(0, $this->search->search($querydata));
162     }
164     public function test_alloweduserid() {
165         $engine = $this->search->get_engine();
166         $area = new core_mocksearch\search\role_capabilities();
168         // Get the first record for the recordset.
169         $recordset = $area->get_recordset_by_timestamp();
170         foreach ($recordset as $r) {
171             $record = $r;
172             break;
173         }
174         $recordset->close();
176         // Get the doc and insert the default doc.
177         $doc = $area->get_document($record);
178         $engine->add_document($doc);
180         $users = array();
181         $users[] = $this->getDataGenerator()->create_user();
182         $users[] = $this->getDataGenerator()->create_user();
183         $users[] = $this->getDataGenerator()->create_user();
185         // Add a record that only user 100 can see.
186         $originalid = $doc->get('id');
188         // Now add a custom doc for each user.
189         foreach ($users as $user) {
190             $doc = $area->get_document($record);
191             $doc->set('id', $originalid.'-'.$user->id);
192             $doc->set('owneruserid', $user->id);
193             $engine->add_document($doc);
194         }
196         $engine->area_index_complete($area->get_area_id());
198         $querydata = new stdClass();
199         $querydata->q = 'message';
200         $querydata->title = $doc->get('title');
202         // We are going to go through each user and see if they get the original and the owned doc.
203         foreach ($users as $user) {
204             $this->setUser($user);
206             $results = $this->search->search($querydata);
207             $this->assertCount(2, $results);
209             $owned = 0;
210             $notowned = 0;
212             // We don't know what order we will get the results in, so we are doing this.
213             foreach ($results as $result) {
214                 $owneruserid = $result->get('owneruserid');
215                 if (empty($owneruserid)) {
216                     $notowned++;
217                     $this->assertEquals(0, $owneruserid);
218                     $this->assertEquals($originalid, $result->get('id'));
219                 } else {
220                     $owned++;
221                     $this->assertEquals($user->id, $owneruserid);
222                     $this->assertEquals($originalid.'-'.$user->id, $result->get('id'));
223                 }
224             }
226             $this->assertEquals(1, $owned);
227             $this->assertEquals(1, $notowned);
228         }
230         // Now test a user with no owned results.
231         $otheruser = $this->getDataGenerator()->create_user();
232         $this->setUser($otheruser);
234         $results = $this->search->search($querydata);
235         $this->assertCount(1, $results);
237         $this->assertEquals(0, $results[0]->get('owneruserid'));
238         $this->assertEquals($originalid, $results[0]->get('id'));
239     }
241     public function test_delete_by_id() {
242         // First get files in the index.
243         $this->search->index();
244         $engine = $this->search->get_engine();
246         $querydata = new stdClass();
248         // Then search to make sure they are there.
249         $querydata->q = 'moodle/course:renameroles';
250         $results = $this->search->search($querydata);
251         $this->assertCount(2, $results);
253         $first = reset($results);
254         $deleteid = $first->get('id');
256         $engine->delete_by_id($deleteid);
258         // Check that we don't get a result for it anymore.
259         $results = $this->search->search($querydata);
260         $this->assertCount(1, $results);
261         $result = reset($results);
262         $this->assertNotEquals($deleteid, $result->get('id'));
263     }