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
 * 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
     */
11 efrain 43
    public function test_iterator_all_in_past(): void {
1 efrain 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
     */
11 efrain 58
    public function test_iterator_performance(): void {
1 efrain 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
     */
11 efrain 73
    public function test_iterator_empty(): void {
1 efrain 74
        $this->assertEquals('', self::do_iterator([]));
75
    }
76
 
77
    /**
78
     * Test if some documents are in the future.
79
     */
11 efrain 80
    public function test_iterator_some_in_future(): void {
1 efrain 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
     */
11 efrain 95
    public function test_iterator_all_in_future(): void {
1 efrain 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
     */
11 efrain 108
    public function test_iterator_some_false(): void {
1 efrain 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
     */
11 efrain 122
    public function test_iterator_all_false(): void {
1 efrain 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
     */
11 efrain 135
    public function test_iterator_past_false_and_future(): void {
1 efrain 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
}