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.
250 lines
6.7 KiB
250 lines
6.7 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/>.
|
|
|
|
/**
|
|
* Test iterator that skips future documents
|
|
*
|
|
* @package core_search
|
|
* @category test
|
|
* @copyright 2017 The Open University
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
|
|
namespace core_search;
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
/**
|
|
* Test iterator that skips future documents
|
|
*
|
|
* @package core_search
|
|
* @category test
|
|
* @copyright 2017 The Open University
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class skip_future_documents_iterator_testcase extends \basic_testcase {
|
|
|
|
/**
|
|
* Test normal case with all documents in the past.
|
|
*/
|
|
public function test_iterator_all_in_past() {
|
|
$past = strtotime('2017-11-01');
|
|
$documents = [
|
|
self::make_doc($past, 1),
|
|
self::make_doc($past + 1, 2),
|
|
self::make_doc($past + 2, 3)
|
|
];
|
|
$this->assertEquals('mod_x-frog-1.mod_x-frog-2.mod_x-frog-3.',
|
|
self::do_iterator($documents));
|
|
}
|
|
|
|
/**
|
|
* Confirm that the iterator does not call its parent iterator current() function too many
|
|
* times.
|
|
*/
|
|
public function test_iterator_performance() {
|
|
$counter = new test_counting_iterator();
|
|
$iterator = new skip_future_documents_iterator($counter);
|
|
$items = 0;
|
|
foreach ($iterator as $value) {
|
|
$this->assertEquals(false, $value);
|
|
$items++;
|
|
}
|
|
$this->assertEquals(3, $items);
|
|
$this->assertEquals(3, $counter->get_count());
|
|
}
|
|
|
|
/**
|
|
* Test with no documents at all.
|
|
*/
|
|
public function test_iterator_empty() {
|
|
$this->assertEquals('', self::do_iterator([]));
|
|
}
|
|
|
|
/**
|
|
* Test if some documents are in the future.
|
|
*/
|
|
public function test_iterator_some_in_future() {
|
|
$past = strtotime('2017-11-01');
|
|
$future = time() + 1000;
|
|
$documents = [
|
|
self::make_doc($past, 1),
|
|
self::make_doc($past + 1, 2),
|
|
self::make_doc($future, 3)
|
|
];
|
|
$this->assertEquals('mod_x-frog-1.mod_x-frog-2.',
|
|
self::do_iterator($documents));
|
|
}
|
|
|
|
/**
|
|
* Test if all documents are in the future.
|
|
*/
|
|
public function test_iterator_all_in_future() {
|
|
$future = time() + 1000;
|
|
$documents = [
|
|
self::make_doc($future, 1),
|
|
self::make_doc($future + 1, 2),
|
|
self::make_doc($future + 2, 3)
|
|
];
|
|
$this->assertEquals('', self::do_iterator($documents));
|
|
}
|
|
|
|
/**
|
|
* Test when some documents return error.
|
|
*/
|
|
public function test_iterator_some_false() {
|
|
$past = strtotime('2017-11-01');
|
|
$documents = [
|
|
self::make_doc($past, 1),
|
|
false,
|
|
self::make_doc($past + 2, 3)
|
|
];
|
|
$this->assertEquals('mod_x-frog-1.false.mod_x-frog-3.',
|
|
self::do_iterator($documents));
|
|
}
|
|
|
|
/**
|
|
* Test when all documents return error.
|
|
*/
|
|
public function test_iterator_all_false() {
|
|
$documents = [
|
|
false,
|
|
false,
|
|
false
|
|
];
|
|
$this->assertEquals('false.false.false.',
|
|
self::do_iterator($documents));
|
|
}
|
|
|
|
/**
|
|
* Test iterator with all cases.
|
|
*/
|
|
public function test_iterator_past_false_and_future() {
|
|
$past = strtotime('2017-11-01');
|
|
$future = time() + 1000;
|
|
$documents = [
|
|
false,
|
|
self::make_doc($past, 1),
|
|
false,
|
|
self::make_doc($past + 1, 2),
|
|
false,
|
|
self::make_doc($future, 3),
|
|
false
|
|
];
|
|
$this->assertEquals('false.mod_x-frog-1.false.mod_x-frog-2.false.',
|
|
self::do_iterator($documents));
|
|
}
|
|
|
|
/**
|
|
* Helper function to create a search document.
|
|
*
|
|
* @param int $time Modified time
|
|
* @param int $index Item id
|
|
* @return document Search document
|
|
*/
|
|
protected static function make_doc($time, $index) {
|
|
$doc = new document($index, 'mod_x', 'frog');
|
|
$doc->set('modified', $time);
|
|
return $doc;
|
|
}
|
|
|
|
/**
|
|
* Puts documents through the iterator and returns result as a string for easy testing.
|
|
*
|
|
* @param document[] $documents Array of documents
|
|
* @return string Documents converted to string
|
|
*/
|
|
protected static function do_iterator(array $documents) {
|
|
$parent = new \ArrayIterator($documents);
|
|
$iterator = new skip_future_documents_iterator($parent);
|
|
$result = '';
|
|
foreach ($iterator as $rec) {
|
|
if (!$rec) {
|
|
$result .= 'false.';
|
|
} else {
|
|
$result .= $rec->get('id') . '.';
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fake iterator just for counting how many times current() is called. It returns 'false' 3 times.
|
|
*
|
|
* @package core_search
|
|
* @category test
|
|
* @copyright 2017 The Open University
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class test_counting_iterator implements \Iterator {
|
|
|
|
/** @var int Current position in iterator */
|
|
protected $pos = 0;
|
|
/** @var int Number of calls to current() function */
|
|
protected $count = 0;
|
|
|
|
/**
|
|
* Returns the current element.
|
|
*
|
|
* @return mixed Can return any type.
|
|
*/
|
|
public function current() {
|
|
$this->count++;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Counts iterator usage.
|
|
*
|
|
* @return int Number of times current() was called
|
|
*/
|
|
public function get_count() {
|
|
return $this->count;
|
|
}
|
|
|
|
/**
|
|
* Goes on to the next element.
|
|
*/
|
|
public function next() {
|
|
$this->pos++;
|
|
}
|
|
|
|
/**
|
|
* Gets the key (not supported)
|
|
*
|
|
* @throws \coding_exception Always
|
|
*/
|
|
public function key() {
|
|
throw new \coding_exception('Unsupported');
|
|
}
|
|
|
|
/**
|
|
* Checks if iterato is valid (still has entries).
|
|
*
|
|
* @return bool True if still valid
|
|
*/
|
|
public function valid() {
|
|
return $this->pos < 3;
|
|
}
|
|
|
|
/**
|
|
* Rewinds the iterator.
|
|
*/
|
|
public function rewind() {
|
|
$this->pos = 0;
|
|
}
|
|
}
|
|
|