See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]
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 * Test iterator that skips future documents 19 * 20 * @package core_search 21 * @category test 22 * @copyright 2017 The Open University 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 namespace core_search; 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 /** 31 * Test iterator that skips future documents 32 * 33 * @package core_search 34 * @category test 35 * @copyright 2017 The Open University 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class skip_future_documents_iterator_test extends \basic_testcase { 39 40 /** 41 * Test normal case with all documents in the past. 42 */ 43 public function test_iterator_all_in_past() { 44 $past = strtotime('2017-11-01'); 45 $documents = [ 46 self::make_doc($past, 1), 47 self::make_doc($past + 1, 2), 48 self::make_doc($past + 2, 3) 49 ]; 50 $this->assertEquals('mod_x-frog-1.mod_x-frog-2.mod_x-frog-3.', 51 self::do_iterator($documents)); 52 } 53 54 /** 55 * Confirm that the iterator does not call its parent iterator current() function too many 56 * times. 57 */ 58 public function test_iterator_performance() { 59 $counter = new test_counting_iterator(); 60 $iterator = new skip_future_documents_iterator($counter); 61 $items = 0; 62 foreach ($iterator as $value) { 63 $this->assertEquals(false, $value); 64 $items++; 65 } 66 $this->assertEquals(3, $items); 67 $this->assertEquals(3, $counter->get_count()); 68 } 69 70 /** 71 * Test with no documents at all. 72 */ 73 public function test_iterator_empty() { 74 $this->assertEquals('', self::do_iterator([])); 75 } 76 77 /** 78 * Test if some documents are in the future. 79 */ 80 public function test_iterator_some_in_future() { 81 $past = strtotime('2017-11-01'); 82 $future = time() + 1000; 83 $documents = [ 84 self::make_doc($past, 1), 85 self::make_doc($past + 1, 2), 86 self::make_doc($future, 3) 87 ]; 88 $this->assertEquals('mod_x-frog-1.mod_x-frog-2.', 89 self::do_iterator($documents)); 90 } 91 92 /** 93 * Test if all documents are in the future. 94 */ 95 public function test_iterator_all_in_future() { 96 $future = time() + 1000; 97 $documents = [ 98 self::make_doc($future, 1), 99 self::make_doc($future + 1, 2), 100 self::make_doc($future + 2, 3) 101 ]; 102 $this->assertEquals('', self::do_iterator($documents)); 103 } 104 105 /** 106 * Test when some documents return error. 107 */ 108 public function test_iterator_some_false() { 109 $past = strtotime('2017-11-01'); 110 $documents = [ 111 self::make_doc($past, 1), 112 false, 113 self::make_doc($past + 2, 3) 114 ]; 115 $this->assertEquals('mod_x-frog-1.false.mod_x-frog-3.', 116 self::do_iterator($documents)); 117 } 118 119 /** 120 * Test when all documents return error. 121 */ 122 public function test_iterator_all_false() { 123 $documents = [ 124 false, 125 false, 126 false 127 ]; 128 $this->assertEquals('false.false.false.', 129 self::do_iterator($documents)); 130 } 131 132 /** 133 * Test iterator with all cases. 134 */ 135 public function test_iterator_past_false_and_future() { 136 $past = strtotime('2017-11-01'); 137 $future = time() + 1000; 138 $documents = [ 139 false, 140 self::make_doc($past, 1), 141 false, 142 self::make_doc($past + 1, 2), 143 false, 144 self::make_doc($future, 3), 145 false 146 ]; 147 $this->assertEquals('false.mod_x-frog-1.false.mod_x-frog-2.false.', 148 self::do_iterator($documents)); 149 } 150 151 /** 152 * Helper function to create a search document. 153 * 154 * @param int $time Modified time 155 * @param int $index Item id 156 * @return document Search document 157 */ 158 protected static function make_doc($time, $index) { 159 $doc = new document($index, 'mod_x', 'frog'); 160 $doc->set('modified', $time); 161 return $doc; 162 } 163 164 /** 165 * Puts documents through the iterator and returns result as a string for easy testing. 166 * 167 * @param document[] $documents Array of documents 168 * @return string Documents converted to string 169 */ 170 protected static function do_iterator(array $documents) { 171 $parent = new \ArrayIterator($documents); 172 $iterator = new skip_future_documents_iterator($parent); 173 $result = ''; 174 foreach ($iterator as $rec) { 175 if (!$rec) { 176 $result .= 'false.'; 177 } else { 178 $result .= $rec->get('id') . '.'; 179 } 180 } 181 return $result; 182 } 183 } 184 185 /** 186 * Fake iterator just for counting how many times current() is called. It returns 'false' 3 times. 187 * 188 * @package core_search 189 * @category test 190 * @copyright 2017 The Open University 191 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 192 */ 193 class test_counting_iterator implements \Iterator { 194 195 /** @var int Current position in iterator */ 196 protected $pos = 0; 197 /** @var int Number of calls to current() function */ 198 protected $count = 0; 199 200 /** 201 * Returns the current element. 202 * 203 * @return mixed Can return any type. 204 */ 205 #[\ReturnTypeWillChange] 206 public function current() { 207 $this->count++; 208 return false; 209 } 210 211 /** 212 * Counts iterator usage. 213 * 214 * @return int Number of times current() was called 215 */ 216 public function get_count() { 217 return $this->count; 218 } 219 220 /** 221 * Goes on to the next element. 222 */ 223 public function next(): void { 224 $this->pos++; 225 } 226 227 /** 228 * Gets the key (not supported) 229 * 230 * @throws \coding_exception Always 231 */ 232 #[\ReturnTypeWillChange] 233 public function key() { 234 throw new \coding_exception('Unsupported'); 235 } 236 237 /** 238 * Checks if iterato is valid (still has entries). 239 * 240 * @return bool True if still valid 241 */ 242 public function valid(): bool { 243 return $this->pos < 3; 244 } 245 246 /** 247 * Rewinds the iterator. 248 */ 249 public function rewind(): void { 250 $this->pos = 0; 251 } 252 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body