weekly release 3.7dev
[moodle.git] / files / tests / conversion_test.php
CommitLineData
34df779a
AN
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/**
19 * PHPUnit tests for conversion API.
20 *
21 * @package core_files
22 * @copyright 2017 Andrew nicols <andrew@nicols.co.uk>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25defined('MOODLE_INTERNAL') || die();
26
27global $CFG;
28
29use core_files\conversion;
30
31/**
32 * PHPUnit tests for conversion persistent.
33 *
34 * @package core_files
35 * @copyright 2017 Andrew nicols <andrew@nicols.co.uk>
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 */
38class core_files_conversion_testcase extends advanced_testcase {
39
40 /**
41 * Helper to create a stored file object with the given supplied content.
42 *
43 * @param string $filecontent The content of the mocked file
44 * @param string $filename The file name to use in the stored_file
45 * @param string $filerecord Any overrides to the filerecord
46 * @return stored_file
47 */
48 protected function create_stored_file($filecontent = 'content', $filename = 'testfile.txt', $filerecord = []) {
49 $filerecord = array_merge([
50 'contextid' => context_system::instance()->id,
51 'component' => 'core',
52 'filearea' => 'unittest',
53 'itemid' => 0,
54 'filepath' => '/',
55 'filename' => $filename,
56 ], $filerecord);
57
58 $fs = get_file_storage();
59 $file = $fs->create_file_from_string($filerecord, $filecontent);
60
61 return $file;
62 }
63
64 /**
65 * Ensure that get_conversions_for_file returns an existing conversion
66 * record with matching sourcefileid and targetformat.
67 */
68 public function test_get_conversions_for_file_existing_conversion_incomplete() {
69 $this->resetAfterTest();
70
71 $sourcefile = $this->create_stored_file();
72
73 $existing = new conversion(0, (object) [
74 'sourcefileid' => $sourcefile->get_id(),
75 'targetformat' => 'pdf',
76 ]);
77 $existing->create();
78
79 $conversions = conversion::get_conversions_for_file($sourcefile, 'pdf');
80
81 $this->assertCount(1, $conversions);
82
83 $conversion = array_shift($conversions);
84 $conversionfile = $conversion->get_sourcefile();
85
86 $this->assertEquals($sourcefile->get_id(), $conversionfile->get_id());
87 $this->assertFalse($conversion->get_destfile());
88 }
89
90 /**
91 * Ensure that get_conversions_for_file returns an existing conversion
92 * record with matching sourcefileid and targetformat when a second
93 * conversion to a different format exists.
94 */
95 public function test_get_conversions_for_file_existing_conversion_multiple_formats_incomplete() {
96 $this->resetAfterTest();
97
98 $sourcefile = $this->create_stored_file();
99
100 $existing = new conversion(0, (object) [
101 'sourcefileid' => $sourcefile->get_id(),
102 'targetformat' => 'pdf',
103 ]);
104 $existing->create();
105
106 $second = new conversion(0, (object) [
107 'sourcefileid' => $sourcefile->get_id(),
108 'targetformat' => 'doc',
109 ]);
110 $second->create();
111
112 $conversions = conversion::get_conversions_for_file($sourcefile, 'pdf');
113
114 $this->assertCount(1, $conversions);
115
116 $conversion = array_shift($conversions);
117 $conversionfile = $conversion->get_sourcefile();
118
119 $this->assertEquals($sourcefile->get_id(), $conversionfile->get_id());
120 $this->assertFalse($conversion->get_destfile());
121 }
122
123 /**
124 * Ensure that get_conversions_for_file returns an existing conversion
125 * record with matching sourcefileid and targetformat.
126 */
127 public function test_get_conversions_for_file_existing_conversion_complete() {
128 $this->resetAfterTest();
129
130 $sourcefile = $this->create_stored_file();
131 $destfile = $this->create_stored_file(
132 'example content',
133 $sourcefile->get_contenthash(),
134 [
135 'component' => 'core',
136 'filearea' => 'documentconversion',
137 'filepath' => '/pdf/',
138 ]);
139
140 $existing = new conversion(0, (object) [
141 'sourcefileid' => $sourcefile->get_id(),
142 'targetformat' => 'pdf',
143 'destfileid' => $destfile->get_id(),
144 ]);
145 $existing->create();
146
147 $conversions = conversion::get_conversions_for_file($sourcefile, 'pdf');
148
149 // Only one file should be returned.
150 $this->assertCount(1, $conversions);
151
152 $conversion = array_shift($conversions);
153
154 $this->assertEquals($sourcefile->get_id(), $conversion->get_sourcefile()->get_id());
155 $this->assertEquals($destfile->get_id(), $conversion->get_destfile()->get_id());
156 }
157
158 /**
159 * Ensure that get_conversions_for_file returns an existing conversion
160 * record with matching sourcefileid and targetformat.
161 */
162 public function test_get_conversions_for_file_existing_conversion_multiple_formats_complete() {
163 $this->resetAfterTest();
164
165 $sourcefile = $this->create_stored_file();
166 $destfile = $this->create_stored_file(
167 'example content',
168 $sourcefile->get_contenthash(),
169 [
170 'component' => 'core',
171 'filearea' => 'documentconversion',
172 'filepath' => '/pdf/',
173 ]);
174
175 $existing = new conversion(0, (object) [
176 'sourcefileid' => $sourcefile->get_id(),
177 'targetformat' => 'pdf',
178 'destfileid' => $destfile->get_id(),
179 ]);
180 $existing->create();
181
182 $second = new conversion(0, (object) [
183 'sourcefileid' => $sourcefile->get_id(),
184 'targetformat' => 'doc',
185 ]);
186 $second->create();
187
188 $conversions = conversion::get_conversions_for_file($sourcefile, 'pdf');
189
190 // Only one file should be returned.
191 $this->assertCount(1, $conversions);
192
193 $conversion = array_shift($conversions);
194
195 $this->assertEquals($sourcefile->get_id(), $conversion->get_sourcefile()->get_id());
196 $this->assertEquals($destfile->get_id(), $conversion->get_destfile()->get_id());
197 }
198
199 /**
200 * Ensure that get_conversions_for_file returns an existing conversion
201 * record does not exist, but the file has previously been converted.
202 */
203 public function test_get_conversions_for_file_existing_target() {
204 $this->resetAfterTest();
205
206 $sourcefile = $this->create_stored_file();
207 $destfile = $this->create_stored_file(
208 'example content',
209 $sourcefile->get_contenthash(),
210 [
211 'component' => 'core',
212 'filearea' => 'documentconversion',
213 'filepath' => '/pdf/',
214 ]);
215
216 $conversions = conversion::get_conversions_for_file($sourcefile, 'pdf');
217
218 $this->assertCount(1, $conversions);
219
220 $conversion = array_shift($conversions);
221 $conversionsource = $conversion->get_sourcefile();
222 $this->assertEquals($sourcefile->get_id(), $conversionsource->get_id());
223 $conversiondest = $conversion->get_destfile();
224 $this->assertEquals($destfile->get_id(), $conversiondest->get_id());
225 }
226
227 /**
228 * Ensure that set_sourcefile sets the correct fileid.
229 */
230 public function test_set_sourcefile() {
231 $this->resetAfterTest();
232
233 $sourcefile = $this->create_stored_file();
234 $conversion = new conversion(0, (object) []);
235
236 $conversion->set_sourcefile($sourcefile);
237
238 $this->assertEquals($sourcefile->get_id(), $conversion->get('sourcefileid'));
239 $this->assertNull($conversion->get('destfileid'));
240 }
241
242 /**
243 * Ensure that store_destfile_from_path stores the file as expected.
244 */
245 public function test_store_destfile_from_path() {
246 $this->resetAfterTest();
247
248 $sourcefile = $this->create_stored_file();
249 $conversion = new conversion(0, (object) [
250 'sourcefileid' => $sourcefile->get_id(),
251 'targetformat' => 'pdf',
252 ]);
253
254 $fixture = __FILE__;
255 $conversion->store_destfile_from_path($fixture);
256
257 $destfile = $conversion->get_destfile();
258 $this->assertEquals(file_get_contents($fixture), $destfile->get_content());
259 }
260
261 /**
262 * Ensure that store_destfile_from_path stores the file as expected.
263 */
264 public function test_store_destfile_from_path_delete_existing() {
265 $this->resetAfterTest();
266
267 $sourcefile = $this->create_stored_file();
268 $conversion = new conversion(0, (object) [
269 'sourcefileid' => $sourcefile->get_id(),
270 'targetformat' => 'pdf',
271 ]);
272
273 $record = [
274 'contextid' => \context_system::instance()->id,
275 'component' => 'core',
276 'filearea' => 'documentconversion',
277 'itemid' => 0,
278 'filepath' => '/pdf/',
279 ];
280 $existingfile = $this->create_stored_file('foo', $sourcefile->get_contenthash(), $record);
281
282 $fixture = __FILE__;
283 $conversion->store_destfile_from_path($fixture);
284
285 $destfile = $conversion->get_destfile();
286 $this->assertEquals(file_get_contents($fixture), $destfile->get_content());
287 }
288
289 /**
290 * Ensure that store_destfile_from_path stores the file as expected.
291 */
292 public function test_store_destfile_from_string() {
293 $this->resetAfterTest();
294
295 $sourcefile = $this->create_stored_file();
296 $conversion = new conversion(0, (object) [
297 'sourcefileid' => $sourcefile->get_id(),
298 'targetformat' => 'pdf',
299 ]);
300
301 $fixture = 'Example content';
302 $conversion->store_destfile_from_string($fixture);
303
304 $destfile = $conversion->get_destfile();
305 $this->assertEquals($fixture, $destfile->get_content());
306 }
307
308 /**
309 * Ensure that store_destfile_from_string stores the file as expected when
310 * an existing destfile is found.
311 */
312 public function test_store_destfile_from_string_delete_existing() {
313 $this->resetAfterTest();
314
315 $sourcefile = $this->create_stored_file();
316 $conversion = new conversion(0, (object) [
317 'sourcefileid' => $sourcefile->get_id(),
318 'targetformat' => 'pdf',
319 ]);
320
321 $record = [
322 'contextid' => \context_system::instance()->id,
323 'component' => 'core',
324 'filearea' => 'documentconversion',
325 'itemid' => 0,
326 'filepath' => '/pdf/',
327 ];
328 $existingfile = $this->create_stored_file('foo', $sourcefile->get_contenthash(), $record);
329
330 $fixture = 'Example content';
331 $conversion->store_destfile_from_string($fixture);
332
333 $destfile = $conversion->get_destfile();
334 $this->assertEquals($fixture, $destfile->get_content());
335 }
336
337 /**
338 * Ensure that the get_status functions cast the status to integer correctly.
339 */
340 public function test_get_status() {
341 $conversion = new conversion(0, (object) [
342 'status' => (string) 1,
343 ]);
344
345 $this->assertInternalType('integer', $conversion->get('status'));
346 }
347
348 /**
349 * Ensure that get_converter_instance returns false when no converter is set.
350 */
351 public function test_get_converter_instance_none_set() {
352 $conversion = new conversion(0, (object) []);
353 $this->assertFalse($conversion->get_converter_instance());
354 }
355
356 /**
357 * Ensure that get_converter_instance returns false when no valid converter is set.
358 */
359 public function test_get_converter_instance_invalid_set() {
360 $conversion = new conversion(0, (object) [
361 'converter' => '\\fileconverter_not_a_valid_converter\\converter',
362 ]);
363 $this->assertFalse($conversion->get_converter_instance());
364 }
365
366 /**
367 * Ensure that get_converter_instance returns an instance when a valid converter is set.
368 */
369 public function test_get_converter_instance_valid_set() {
370 $conversion = new conversion(0, (object) [
371 'converter' => \fileconverter_unoconv\converter::class,
372 ]);
373 $this->assertInstanceOf(\fileconverter_unoconv\converter::class, $conversion->get_converter_instance());
374 }
375
376 /**
377 * Test that all old conversion records are removed periodically.
378 */
379 public function test_remove_old_conversion_records_old() {
380 $this->resetAfterTest();
381 global $DB;
382
383 $sourcefile = $this->create_stored_file();
384 $conversion = new conversion(0, (object) [
385 'sourcefileid' => $sourcefile->get_id(),
386 'targetformat' => 'pdf',
387 ]);
388 $conversion->create();
389 $DB->set_field(conversion::TABLE, 'timemodified', time() - YEARSECS);
390
391 conversion::remove_old_conversion_records();
392
393 $this->assertEquals(0, $DB->count_records(conversion::TABLE));
394 }
395
396 /**
397 * Test that all old conversion records are removed periodically.
398 */
399 public function test_remove_old_conversion_records_young() {
400 $this->resetAfterTest();
401 global $DB;
402
403 $sourcefile = $this->create_stored_file();
404 $conversion = new conversion(0, (object) [
405 'sourcefileid' => $sourcefile->get_id(),
406 'targetformat' => 'pdf',
407 ]);
408 $conversion->create();
409 $DB->set_field(conversion::TABLE, 'timemodified', time() - DAYSECS);
410
411 conversion::remove_old_conversion_records();
412
413 $this->assertEquals(1, $DB->count_records(conversion::TABLE));
414 }
790c89b3
FM
415
416 /**
417 * Test orphan records are removed.
418 */
419 public function test_remove_orphan_records() {
420 global $DB;
421 $this->resetAfterTest();
422
423 $sf1 = $this->create_stored_file('1', '1');
424 $sf2 = $this->create_stored_file('2', '2');
425 $sf3 = $this->create_stored_file('3', '3');
426 $c1 = new conversion(0, (object) ['sourcefileid' => $sf1->get_id(), 'targetformat' => 'pdf']);
427 $c1->create();
428 $c2 = new conversion(0, (object) ['sourcefileid' => $sf2->get_id(), 'targetformat' => 'pdf']);
429 $c2->create();
430 $c3 = new conversion(0, (object) ['sourcefileid' => $sf3->get_id(), 'targetformat' => 'pdf']);
431 $c3->create();
432
433 $this->assertTrue(conversion::record_exists($c1->get('id')));
434 $this->assertTrue(conversion::record_exists($c2->get('id')));
435 $this->assertTrue(conversion::record_exists($c3->get('id')));
436
437 // Nothing should happen here.
438 conversion::remove_orphan_records();
439 $this->assertTrue(conversion::record_exists($c1->get('id')));
440 $this->assertTrue(conversion::record_exists($c2->get('id')));
441 $this->assertTrue(conversion::record_exists($c3->get('id')));
442
443 // Delete file #2.
444 $sf2->delete();
445 conversion::remove_orphan_records();
446 $this->assertTrue(conversion::record_exists($c1->get('id')));
447 $this->assertFalse(conversion::record_exists($c2->get('id')));
448 $this->assertTrue(conversion::record_exists($c3->get('id')));
449
450 // Delete file #1, #3.
451 $sf1->delete();
452 $sf3->delete();
453 conversion::remove_orphan_records();
454 $this->assertFalse(conversion::record_exists($c1->get('id')));
455 $this->assertFalse(conversion::record_exists($c2->get('id')));
456 $this->assertFalse(conversion::record_exists($c3->get('id')));
457 }
34df779a 458}