Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | 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
namespace core_backup;
18
 
19
use backup;
20
use backup_attribute;
21
use backup_controller_dbops;
22
use backup_final_element;
23
use backup_nested_element;
24
use backup_optigroup;
25
use backup_optigroup_element;
26
use backup_processor_exception;
27
use backup_structure_processor;
28
use base_element_struct_exception;
29
use base_optigroup_exception;
30
use base_processor;
31
use memory_xml_output;
32
use xml_writer;
33
 
34
defined('MOODLE_INTERNAL') || die();
35
 
36
// Include all the needed stuff.
37
require_once(__DIR__.'/fixtures/structure_fixtures.php');
38
 
39
global $CFG;
40
require_once($CFG->dirroot . '/backup/util/xml/output/memory_xml_output.class.php');
41
 
42
/**
43
 * Unit test case the all the backup structure classes. Note: Uses database
44
 *
45
 * @package   core_backup
46
 * @category  test
47
 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
48
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
49
 */
50
class structure_test extends \advanced_testcase {
51
 
52
    /** @var int Store the inserted forum->id for use in test functions */
53
    protected $forumid;
54
    /** @var int Store the inserted discussion1->id for use in test functions */
55
    protected $discussionid1;
56
    /** @var int Store the inserted discussion2->id for use in test functions */
57
    protected $discussionid2;
58
    /** @var int Store the inserted post1->id for use in test functions */
59
    protected $postid1;
60
    /** @var int Store the inserted post2->id for use in test functions */
61
    protected $postid2;
62
    /** @var int Store the inserted post3->id for use in test functions */
63
    protected $postid3;
64
    /** @var int Store the inserted post4->id for use in test functions */
65
    protected $postid4;
66
    /** @var int Official contextid for these tests */
67
    protected $contextid;
68
 
69
 
70
    protected function setUp(): void {
71
        parent::setUp();
72
 
73
        $this->resetAfterTest(true);
74
 
75
        $this->contextid = 666; // Let's assume this is the context for the forum
76
        $this->fill_records(); // Add common stuff needed by various test methods
77
    }
78
 
79
    private function fill_records() {
80
        global $DB;
81
 
82
        // Create one forum
83
        $forum_data = (object)array('course' => 1, 'name' => 'Test forum', 'intro' => 'Intro forum');
84
        $this->forumid = $DB->insert_record('forum', $forum_data);
85
        // With two related file
86
        $f1_forum_data = (object)array(
87
            'contenthash' => 'testf1', 'contextid' => $this->contextid,
88
            'component'=>'mod_forum', 'filearea' => 'intro', 'filename' => 'tf1', 'itemid' => 0,
89
            'filesize' => 123, 'timecreated' => 0, 'timemodified' => 0,
90
            'pathnamehash' => 'testf1'
91
        );
92
        $DB->insert_record('files', $f1_forum_data);
93
        $f2_forum_data = (object)array(
94
            'contenthash' => 'tesft2', 'contextid' => $this->contextid,
95
            'component'=>'mod_forum', 'filearea' => 'intro', 'filename' => 'tf2', 'itemid' => 0,
96
            'filesize' => 123, 'timecreated' => 0, 'timemodified' => 0,
97
            'pathnamehash' => 'testf2'
98
        );
99
        $DB->insert_record('files', $f2_forum_data);
100
 
101
        // Create two discussions
102
        $discussion1 = (object)array('course' => 1, 'forum' => $this->forumid, 'name' => 'd1', 'userid' => 100, 'groupid' => 200);
103
        $this->discussionid1 = $DB->insert_record('forum_discussions', $discussion1);
104
        $discussion2 = (object)array('course' => 1, 'forum' => $this->forumid, 'name' => 'd2', 'userid' => 101, 'groupid' => 201);
105
        $this->discussionid2 = $DB->insert_record('forum_discussions', $discussion2);
106
 
107
        // Create four posts
108
        $post1 = (object)array('discussion' => $this->discussionid1, 'userid' => 100, 'subject' => 'p1', 'message' => 'm1');
109
        $this->postid1 = $DB->insert_record('forum_posts', $post1);
110
        $post2 = (object)array('discussion' => $this->discussionid1, 'parent' => $this->postid1, 'userid' => 102, 'subject' => 'p2', 'message' => 'm2');
111
        $this->postid2 = $DB->insert_record('forum_posts', $post2);
112
        $post3 = (object)array('discussion' => $this->discussionid1, 'parent' => $this->postid2, 'userid' => 103, 'subject' => 'p3', 'message' => 'm3');
113
        $this->postid3 = $DB->insert_record('forum_posts', $post3);
114
        $post4 = (object)array('discussion' => $this->discussionid2, 'userid' => 101, 'subject' => 'p4', 'message' => 'm4');
115
        $this->postid4 = $DB->insert_record('forum_posts', $post4);
116
        // With two related file
117
        $f1_post1 = (object)array(
118
            'contenthash' => 'testp1', 'contextid' => $this->contextid, 'component'=>'mod_forum',
119
            'filearea' => 'post', 'filename' => 'tp1', 'itemid' => $this->postid1,
120
            'filesize' => 123, 'timecreated' => 0, 'timemodified' => 0,
121
            'pathnamehash' => 'testp1'
122
        );
123
        $DB->insert_record('files', $f1_post1);
124
        $f1_post2 = (object)array(
125
            'contenthash' => 'testp2', 'contextid' => $this->contextid, 'component'=>'mod_forum',
126
            'filearea' => 'attachment', 'filename' => 'tp2', 'itemid' => $this->postid2,
127
            'filesize' => 123, 'timecreated' => 0, 'timemodified' => 0,
128
            'pathnamehash' => 'testp2'
129
        );
130
        $DB->insert_record('files', $f1_post2);
131
 
132
        // Create two ratings
133
        $rating1 = (object)array(
134
            'contextid' => $this->contextid, 'userid' => 104, 'itemid' => $this->postid1, 'rating' => 2,
135
            'scaleid' => -1, 'timecreated' => time(), 'timemodified' => time());
136
        $r1id = $DB->insert_record('rating', $rating1);
137
        $rating2 = (object)array(
138
            'contextid' => $this->contextid, 'userid' => 105, 'itemid' => $this->postid1, 'rating' => 3,
139
            'scaleid' => -1, 'timecreated' => time(), 'timemodified' => time());
140
        $r2id = $DB->insert_record('rating', $rating2);
141
 
142
        // Create 1 reads
143
        $read1 = (object)array('userid' => 102, 'forumid' => $this->forumid, 'discussionid' => $this->discussionid2, 'postid' => $this->postid4);
144
        $DB->insert_record('forum_read', $read1);
145
    }
146
 
147
    /**
148
     * Backup structures tests (construction, definition and execution)
149
     */
150
    function test_backup_structure_construct() {
151
        global $DB;
152
 
153
        $backupid = 'Testing Backup ID'; // Official backupid for these tests
154
 
155
        // Create all the elements that will conform the tree
156
        $forum = new backup_nested_element('forum',
157
            array('id'),
158
            array(
159
                'type', 'name', 'intro', 'introformat',
160
                'assessed', 'assesstimestart', 'assesstimefinish', 'scale',
161
                'maxbytes', 'maxattachments', 'forcesubscribe', 'trackingtype',
162
                'rsstype', 'rssarticles', 'timemodified', 'warnafter',
163
                'blockafter',
164
                new backup_final_element('blockperiod'),
165
                new \mock_skip_final_element('completiondiscussions'),
166
                new \mock_modify_final_element('completionreplies'),
167
                new \mock_final_element_interceptor('completionposts'))
168
        );
169
        $discussions = new backup_nested_element('discussions');
170
        $discussion = new backup_nested_element('discussion',
171
            array('id'),
172
            array(
173
                'forum', 'name', 'firstpost', 'userid',
174
                'groupid', 'assessed', 'timemodified', 'usermodified',
175
                'timestart', 'timeend')
176
        );
177
        $posts = new backup_nested_element('posts');
178
        $post = new backup_nested_element('post',
179
            array('id'),
180
            array(
181
                'discussion', 'parent', 'userid', 'created',
182
                'modified', 'mailed', 'subject', 'message',
183
                'messageformat', 'messagetrust', 'attachment', 'totalscore',
184
                'mailnow')
185
        );
186
        $ratings = new backup_nested_element('ratings');
187
        $rating = new backup_nested_element('rating',
188
            array('id'),
189
            array('userid', 'itemid', 'time', 'post_rating')
190
        );
191
        $reads = new backup_nested_element('readposts');
192
        $read = new backup_nested_element('read',
193
            array('id'),
194
            array(
195
                'userid', 'discussionid', 'postid',
196
                'firstread', 'lastread')
197
        );
198
        $inventeds = new backup_nested_element('invented_elements',
199
            array('reason', 'version')
200
        );
201
        $invented = new backup_nested_element('invented',
202
            null,
203
            array('one', 'two', 'three')
204
        );
205
        $one = $invented->get_final_element('one');
206
        $one->add_attributes(array('attr1', 'attr2'));
207
 
208
        // Build the tree
209
        $forum->add_child($discussions);
210
        $discussions->add_child($discussion);
211
 
212
        $discussion->add_child($posts);
213
        $posts->add_child($post);
214
 
215
        $post->add_child($ratings);
216
        $ratings->add_child($rating);
217
 
218
        $forum->add_child($reads);
219
        $reads->add_child($read);
220
 
221
        $forum->add_child($inventeds);
222
        $inventeds->add_child($invented);
223
 
224
        // Let's add 1 optigroup with 4 elements
225
        $alternative1 = new backup_optigroup_element('alternative1',
226
            array('name', 'value'), '../../id', $this->postid1);
227
        $alternative2 = new backup_optigroup_element('alternative2',
228
            array('name', 'value'), backup::VAR_PARENTID, $this->postid2);
229
        $alternative3 = new backup_optigroup_element('alternative3',
230
            array('name', 'value'), '/forum/discussions/discussion/posts/post/id', $this->postid3);
231
        $alternative4 = new backup_optigroup_element('alternative4',
232
            array('forumtype', 'forumname')); // Alternative without conditions
233
        // Create the optigroup, adding one element
234
        $optigroup = new backup_optigroup('alternatives', $alternative1, false);
235
        // Add second opti element
236
        $optigroup->add_child($alternative2);
237
 
238
        // Add optigroup to post element
239
        $post->add_optigroup($optigroup);
240
        // Add third opti element, on purpose after the add_optigroup() line above to check param evaluation works ok
241
        $optigroup->add_child($alternative3);
242
        // Add 4th opti element (the one without conditions, so will be present always)
243
        $optigroup->add_child($alternative4);
244
 
245
        /// Create some new nested elements, both named 'dupetest1', and add them to alternative1 and alternative2
246
        /// (not problem as far as the optigroup in not unique)
247
        $dupetest1 = new backup_nested_element('dupetest1', null, array('field1', 'field2'));
248
        $dupetest2 = new backup_nested_element('dupetest2', null, array('field1', 'field2'));
249
        $dupetest3 = new backup_nested_element('dupetest3', null, array('field1', 'field2'));
250
        $dupetest4 = new backup_nested_element('dupetest1', null, array('field1', 'field2'));
251
        $dupetest1->add_child($dupetest3);
252
        $dupetest2->add_child($dupetest4);
253
        $alternative1->add_child($dupetest1);
254
        $alternative2->add_child($dupetest2);
255
 
256
        // Define sources
257
        $forum->set_source_table('forum', array('id' => backup::VAR_ACTIVITYID));
258
        $discussion->set_source_sql('SELECT *
259
                                       FROM {forum_discussions}
260
                                      WHERE forum = ?',
261
            array('/forum/id')
262
        );
263
        $post->set_source_table('forum_posts', array('discussion' => '/forum/discussions/discussion/id'));
264
        $rating->set_source_sql('SELECT *
265
                                   FROM {rating}
266
                                  WHERE itemid = ?',
267
            array(backup::VAR_PARENTID)
268
        );
269
 
270
        $read->set_source_table('forum_read', array('forumid' => '../../id'));
271
 
272
        $inventeds->set_source_array(array((object)array('reason' => 'I love Moodle', 'version' => '1.0'),
273
            (object)array('reason' => 'I love Moodle', 'version' => '2.0'))); // 2 object array
274
        $invented->set_source_array(array((object)array('one' => 1, 'two' => 2, 'three' => 3),
275
            (object)array('one' => 11, 'two' => 22, 'three' => 33))); // 2 object array
276
 
277
        // Set optigroup_element sources
278
        $alternative1->set_source_array(array((object)array('name' => 'alternative1', 'value' => 1))); // 1 object array
279
        // Skip alternative2 source definition on purpose (will be tested)
280
        // $alternative2->set_source_array(array((object)array('name' => 'alternative2', 'value' => 2))); // 1 object array
281
        $alternative3->set_source_array(array((object)array('name' => 'alternative3', 'value' => 3))); // 1 object array
282
        // Alternative 4 source is the forum type and name, so we'll get that in ALL posts (no conditions) that
283
        // have not another alternative (post4 in our testing data in the only not matching any other alternative)
284
        $alternative4->set_source_sql('SELECT type AS forumtype, name AS forumname
285
                                         FROM {forum}
286
                                        WHERE id = ?',
287
            array('/forum/id')
288
        );
289
        // Set children of optigroup_element source
290
        $dupetest1->set_source_array(array((object)array('field1' => '1', 'field2' => 1))); // 1 object array
291
        $dupetest2->set_source_array(array((object)array('field1' => '2', 'field2' => 2))); // 1 object array
292
        $dupetest3->set_source_array(array((object)array('field1' => '3', 'field2' => 3))); // 1 object array
293
        $dupetest4->set_source_array(array((object)array('field1' => '4', 'field2' => 4))); // 1 object array
294
 
295
        // Define some aliases
296
        $rating->set_source_alias('rating', 'post_rating'); // Map the 'rating' value from DB to 'post_rating' final element
297
 
298
        // Mark to detect files of type 'forum_intro' in forum (and not item id)
299
        $forum->annotate_files('mod_forum', 'intro', null);
300
 
301
        // Mark to detect file of type 'forum_post' and 'forum_attachment' in post (with itemid being post->id)
302
        $post->annotate_files('mod_forum', 'post', 'id');
303
        $post->annotate_files('mod_forum', 'attachment', 'id');
304
 
305
        // Mark various elements to be annotated
306
        $discussion->annotate_ids('user1', 'userid');
307
        $post->annotate_ids('forum_post', 'id');
308
        $rating->annotate_ids('user2', 'userid');
309
        $rating->annotate_ids('forum_post', 'itemid');
310
 
311
        // Create the backup_ids_temp table
312
        backup_controller_dbops::create_backup_ids_temp_table($backupid);
313
 
314
        // Instantiate in memory xml output
315
        $xo = new memory_xml_output();
316
 
317
        // Instantiate xml_writer and start it
318
        $xw = new xml_writer($xo);
319
        $xw->start();
320
 
321
        // Instantiate the backup processor
322
        $processor = new backup_structure_processor($xw);
323
 
324
        // Set some variables
325
        $processor->set_var(backup::VAR_ACTIVITYID, $this->forumid);
326
        $processor->set_var(backup::VAR_BACKUPID, $backupid);
327
        $processor->set_var(backup::VAR_CONTEXTID,$this->contextid);
328
 
329
        // Process the backup structure with the backup processor
330
        $forum->process($processor);
331
 
332
        // Stop the xml_writer
333
        $xw->stop();
334
 
335
        // Check various counters
336
        $this->assertEquals($forum->get_counter(), $DB->count_records('forum'));
337
        $this->assertEquals($discussion->get_counter(), $DB->count_records('forum_discussions'));
338
        $this->assertEquals($rating->get_counter(), $DB->count_records('rating'));
339
        $this->assertEquals($read->get_counter(), $DB->count_records('forum_read'));
340
        $this->assertEquals($inventeds->get_counter(), 2); // Array
341
 
342
        // Perform some validations with the generated XML
343
        $dom = new \DomDocument();
344
        $dom->loadXML($xo->get_allcontents());
345
        $xpath = new \DOMXPath($dom);
346
        // Some more counters
347
        $query = '/forum/discussions/discussion/posts/post';
348
        $posts = $xpath->query($query);
349
        $this->assertEquals($posts->length, $DB->count_records('forum_posts'));
350
        $query = '/forum/invented_elements/invented';
351
        $inventeds = $xpath->query($query);
352
        $this->assertEquals($inventeds->length, 2*2);
353
 
354
        // Check ratings information against DB
355
        $ratings = $dom->getElementsByTagName('rating');
356
        $this->assertEquals($ratings->length, $DB->count_records('rating'));
357
        foreach ($ratings as $rating) {
358
            $ratarr = array();
359
            $ratarr['id'] = $rating->getAttribute('id');
360
            foreach ($rating->childNodes as $node) {
361
                if ($node->nodeType != XML_TEXT_NODE) {
362
                    $ratarr[$node->nodeName] = $node->nodeValue;
363
                }
364
            }
365
            $this->assertEquals($DB->get_field('rating', 'userid', array('id' => $ratarr['id'])), $ratarr['userid']);
366
            $this->assertEquals($DB->get_field('rating', 'itemid', array('id' => $ratarr['id'])), $ratarr['itemid']);
367
            $this->assertEquals($DB->get_field('rating', 'rating', array('id' => $ratarr['id'])), $ratarr['post_rating']);
368
        }
369
 
370
        // Check forum has "blockeperiod" with value 0 (was declared by object instead of name)
371
        $query = '/forum[blockperiod="0"]';
372
        $result = $xpath->query($query);
373
        $this->assertEquals(1, $result->length);
374
 
375
        // Check forum is missing "completiondiscussions" (as we are using mock_skip_final_element)
376
        $query = '/forum/completiondiscussions';
377
        $result = $xpath->query($query);
378
        $this->assertEquals(0, $result->length);
379
 
380
        // Check forum has "completionreplies" with value "original was 0, now changed" (because of mock_modify_final_element)
381
        $query = '/forum[completionreplies="original was 0, now changed"]';
382
        $result = $xpath->query($query);
383
        $this->assertEquals(1, $result->length);
384
 
385
        // Check forum has "completionposts" with value "intercepted!" (because of mock_final_element_interceptor)
386
        $query = '/forum[completionposts="intercepted!"]';
387
        $result = $xpath->query($query);
388
        $this->assertEquals(1, $result->length);
389
 
390
        // Check there isn't any alternative2 tag, as far as it hasn't source defined
391
        $query = '//alternative2';
392
        $result = $xpath->query($query);
393
        $this->assertEquals(0, $result->length);
394
 
395
        // Check there are 4 "field1" elements
396
        $query = '/forum/discussions/discussion/posts/post//field1';
397
        $result = $xpath->query($query);
398
        $this->assertEquals(4, $result->length);
399
 
400
        // Check first post has one name element with value "alternative1"
401
        $query = '/forum/discussions/discussion/posts/post[@id="'.$this->postid1.'"][name="alternative1"]';
402
        $result = $xpath->query($query);
403
        $this->assertEquals(1, $result->length);
404
 
405
        // Check there are two "dupetest1" elements
406
        $query = '/forum/discussions/discussion/posts/post//dupetest1';
407
        $result = $xpath->query($query);
408
        $this->assertEquals(2, $result->length);
409
 
410
        // Check second post has one name element with value "dupetest2"
411
        $query = '/forum/discussions/discussion/posts/post[@id="'.$this->postid2.'"]/dupetest2';
412
        $result = $xpath->query($query);
413
        $this->assertEquals(1, $result->length);
414
 
415
        // Check element "dupetest2" of second post has one field1 element with value "2"
416
        $query = '/forum/discussions/discussion/posts/post[@id="'.$this->postid2.'"]/dupetest2[field1="2"]';
417
        $result = $xpath->query($query);
418
        $this->assertEquals(1, $result->length);
419
 
420
        // Check forth post has no name element
421
        $query = '/forum/discussions/discussion/posts/post[@id="'.$this->postid4.'"]/name';
422
        $result = $xpath->query($query);
423
        $this->assertEquals(0, $result->length);
424
 
425
        // Check 1st, 2nd and 3rd posts have no forumtype element
426
        $query = '/forum/discussions/discussion/posts/post[@id="'.$this->postid1.'"]/forumtype';
427
        $result = $xpath->query($query);
428
        $this->assertEquals(0, $result->length);
429
        $query = '/forum/discussions/discussion/posts/post[@id="'.$this->postid2.'"]/forumtype';
430
        $result = $xpath->query($query);
431
        $this->assertEquals(0, $result->length);
432
        $query = '/forum/discussions/discussion/posts/post[@id="'.$this->postid3.'"]/forumtype';
433
        $result = $xpath->query($query);
434
        $this->assertEquals(0, $result->length);
435
 
436
        // Check 4th post has one forumtype element with value "general"
437
        // (because it doesn't matches alternatives 1, 2, 3, then alternative 4,
438
        // the one without conditions is being applied)
439
        $query = '/forum/discussions/discussion/posts/post[@id="'.$this->postid4.'"][forumtype="general"]';
440
        $result = $xpath->query($query);
441
        $this->assertEquals(1, $result->length);
442
 
443
        // Check annotations information against DB
444
        // Count records in original tables
445
        $c_postsid    = $DB->count_records_sql('SELECT COUNT(DISTINCT id) FROM {forum_posts}');
446
        $c_dissuserid = $DB->count_records_sql('SELECT COUNT(DISTINCT userid) FROM {forum_discussions}');
447
        $c_ratuserid  = $DB->count_records_sql('SELECT COUNT(DISTINCT userid) FROM {rating}');
448
        // Count records in backup_ids_table
449
        $f_forumpost = $DB->count_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => 'forum_post'));
450
        $f_user1     = $DB->count_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => 'user1'));
451
        $f_user2     = $DB->count_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => 'user2'));
452
        $c_notbackupid = $DB->count_records_select('backup_ids_temp', 'backupid != ?', array($backupid));
453
        // Peform tests by comparing counts
454
        $this->assertEquals($c_notbackupid, 0); // there isn't any record with incorrect backupid
455
        $this->assertEquals($c_postsid, $f_forumpost); // All posts have been registered
456
        $this->assertEquals($c_dissuserid, $f_user1); // All users coming from discussions have been registered
457
        $this->assertEquals($c_ratuserid, $f_user2); // All users coming from ratings have been registered
458
 
459
        // Check file annotations against DB
460
        $fannotations = $DB->get_records('backup_ids_temp', array('backupid' => $backupid, 'itemname' => 'file'));
461
        $ffiles       = $DB->get_records('files', array('contextid' => $this->contextid));
462
        $this->assertEquals(count($fannotations), count($ffiles)); // Same number of recs in both (all files have been annotated)
463
        foreach ($fannotations as $annotation) { // Check ids annotated
464
            $this->assertTrue($DB->record_exists('files', array('id' => $annotation->itemid)));
465
        }
466
 
467
        // Drop the backup_ids_temp table
468
        backup_controller_dbops::drop_backup_ids_temp_table('testingid');
469
    }
470
 
471
    /**
472
     * Backup structures wrong tests (trying to do things the wrong way)
473
     */
474
    function test_backup_structure_wrong() {
475
 
476
        // Instantiate the backup processor
477
        $processor = new backup_structure_processor(new xml_writer(new memory_xml_output()));
478
        $this->assertTrue($processor instanceof base_processor);
479
 
480
        // Set one var twice
481
        $processor->set_var('onenewvariable', 999);
482
        try {
483
            $processor->set_var('onenewvariable', 999);
484
            $this->assertTrue(false, 'backup_processor_exception expected');
485
        } catch (\Exception $e) {
486
            $this->assertTrue($e instanceof backup_processor_exception);
487
            $this->assertEquals($e->errorcode, 'processorvariablealreadyset');
488
            $this->assertEquals($e->a, 'onenewvariable');
489
        }
490
 
491
        // Get non-existing var
492
        try {
493
            $var = $processor->get_var('nonexistingvar');
494
            $this->assertTrue(false, 'backup_processor_exception expected');
495
        } catch (\Exception $e) {
496
            $this->assertTrue($e instanceof backup_processor_exception);
497
            $this->assertEquals($e->errorcode, 'processorvariablenotfound');
498
            $this->assertEquals($e->a, 'nonexistingvar');
499
        }
500
 
501
        // Create nested element and try ro get its parent id (doesn't exisit => exception)
502
        $ne = new backup_nested_element('test', 'one', 'two', 'three');
503
        try {
504
            $ne->set_source_table('forum', array('id' => backup::VAR_PARENTID));
505
            $ne->process($processor);
506
            $this->assertTrue(false, 'base_element_struct_exception expected');
507
        } catch (\Exception $e) {
508
            $this->assertTrue($e instanceof base_element_struct_exception);
509
            $this->assertEquals($e->errorcode, 'cannotfindparentidforelement');
510
        }
511
 
512
        // Try to process one nested/final/attribute elements without processor
513
        $ne = new backup_nested_element('test', 'one', 'two', 'three');
514
        try {
515
            $ne->process(new \stdClass());
516
            $this->assertTrue(false, 'base_element_struct_exception expected');
517
        } catch (\Exception $e) {
518
            $this->assertTrue($e instanceof base_element_struct_exception);
519
            $this->assertEquals($e->errorcode, 'incorrect_processor');
520
        }
521
        $fe = new backup_final_element('test');
522
        try {
523
            $fe->process(new \stdClass());
524
            $this->assertTrue(false, 'base_element_struct_exception expected');
525
        } catch (\Exception $e) {
526
            $this->assertTrue($e instanceof base_element_struct_exception);
527
            $this->assertEquals($e->errorcode, 'incorrect_processor');
528
        }
529
        $at = new backup_attribute('test');
530
        try {
531
            $at->process(new \stdClass());
532
            $this->assertTrue(false, 'base_element_struct_exception expected');
533
        } catch (\Exception $e) {
534
            $this->assertTrue($e instanceof base_element_struct_exception);
535
            $this->assertEquals($e->errorcode, 'incorrect_processor');
536
        }
537
 
538
        // Try to put an incorrect alias
539
        $ne = new backup_nested_element('test', 'one', 'two', 'three');
540
        try {
541
            $ne->set_source_alias('last', 'nonexisting');
542
            $this->assertTrue(false, 'base_element_struct_exception expected');
543
        } catch (\Exception $e) {
544
            $this->assertTrue($e instanceof base_element_struct_exception);
545
            $this->assertEquals($e->errorcode, 'incorrectaliasfinalnamenotfound');
546
            $this->assertEquals($e->a, 'nonexisting');
547
        }
548
 
549
        // Try various incorrect paths specifying source
550
        $ne = new backup_nested_element('test', 'one', 'two', 'three');
551
        try {
552
            $ne->set_source_table('forum', array('/test/subtest'));
553
            $this->assertTrue(false, 'base_element_struct_exception expected');
554
        } catch (\Exception $e) {
555
            $this->assertTrue($e instanceof base_element_struct_exception);
556
            $this->assertEquals($e->errorcode, 'baseelementincorrectfinalorattribute');
557
            $this->assertEquals($e->a, 'subtest');
558
        }
559
        try {
560
            $ne->set_source_table('forum', array('/wrongtest'));
561
            $this->assertTrue(false, 'base_element_struct_exception expected');
562
        } catch (\Exception $e) {
563
            $this->assertTrue($e instanceof base_element_struct_exception);
564
            $this->assertEquals($e->errorcode, 'baseelementincorrectgrandparent');
565
            $this->assertEquals($e->a, 'wrongtest');
566
        }
567
        try {
568
            $ne->set_source_table('forum', array('../nonexisting'));
569
            $this->assertTrue(false, 'base_element_struct_exception expected');
570
        } catch (\Exception $e) {
571
            $this->assertTrue($e instanceof base_element_struct_exception);
572
            $this->assertEquals($e->errorcode, 'baseelementincorrectparent');
573
            $this->assertEquals($e->a, '..');
574
        }
575
 
576
        // Try various incorrect file annotations
577
 
578
        $ne = new backup_nested_element('test', 'one', 'two', 'three');
579
        $ne->annotate_files('test', 'filearea', null);
580
        try {
581
            $ne->annotate_files('test', 'filearea', null); // Try to add annotations twice
582
            $this->assertTrue(false, 'base_element_struct_exception expected');
583
        } catch (\Exception $e) {
584
            $this->assertTrue($e instanceof base_element_struct_exception);
585
            $this->assertEquals($e->errorcode, 'annotate_files_duplicate_annotation');
586
            $this->assertEquals($e->a, 'test/filearea/');
587
        }
588
 
589
        $ne = new backup_nested_element('test', 'one', 'two', 'three');
590
        try {
591
            $ne->annotate_files('test', 'filearea', 'four'); // Incorrect element
592
            $this->assertTrue(false, 'base_element_struct_exception expected');
593
        } catch (\Exception $e) {
594
            $this->assertTrue($e instanceof base_element_struct_exception);
595
            $this->assertEquals($e->errorcode, 'baseelementincorrectfinalorattribute');
596
            $this->assertEquals($e->a, 'four');
597
        }
598
 
599
        // Try to add incorrect element to backup_optigroup
600
        $bog = new backup_optigroup('test');
601
        try {
602
            $bog->add_child(new backup_nested_element('test2'));
603
            $this->assertTrue(false, 'base_optigroup_exception expected');
604
        } catch (\Exception $e) {
605
            $this->assertTrue($e instanceof base_optigroup_exception);
606
            $this->assertEquals($e->errorcode, 'optigroup_element_incorrect');
607
            $this->assertEquals($e->a, 'backup_nested_element');
608
        }
609
 
610
        $bog = new backup_optigroup('test');
611
        try {
612
            $bog->add_child('test2');
613
            $this->assertTrue(false, 'base_optigroup_exception expected');
614
        } catch (\Exception $e) {
615
            $this->assertTrue($e instanceof base_optigroup_exception);
616
            $this->assertEquals($e->errorcode, 'optigroup_element_incorrect');
617
            $this->assertEquals($e->a, 'non object');
618
        }
619
 
620
        try {
621
            $bog = new backup_optigroup('test', new \stdClass());
622
            $this->assertTrue(false, 'base_optigroup_exception expected');
623
        } catch (\Exception $e) {
624
            $this->assertTrue($e instanceof base_optigroup_exception);
625
            $this->assertEquals($e->errorcode, 'optigroup_elements_incorrect');
626
        }
627
 
628
        // Try a wrong processor with backup_optigroup
629
        $bog = new backup_optigroup('test');
630
        try {
631
            $bog->process(new \stdClass());
632
            $this->assertTrue(false, 'base_element_struct_exception expected');
633
        } catch (\Exception $e) {
634
            $this->assertTrue($e instanceof base_element_struct_exception);
635
            $this->assertEquals($e->errorcode, 'incorrect_processor');
636
        }
637
 
638
        // Try duplicating used elements with backup_optigroup
639
        // Adding top->down
640
        $bog = new backup_optigroup('test', null, true);
641
        $boge1 = new backup_optigroup_element('boge1');
642
        $boge2 = new backup_optigroup_element('boge2');
643
        $ne1 = new backup_nested_element('ne1');
644
        $ne2 = new backup_nested_element('ne1');
645
        $bog->add_child($boge1);
646
        $bog->add_child($boge2);
647
        $boge1->add_child($ne1);
648
        try {
649
            $boge2->add_child($ne2);
650
            $this->assertTrue(false, 'base_optigroup_exception expected');
651
        } catch (\Exception $e) {
652
            $this->assertTrue($e instanceof base_optigroup_exception);
653
            $this->assertEquals($e->errorcode, 'multiple_optigroup_duplicate_element');
654
            $this->assertEquals($e->a, 'ne1');
655
        }
656
        // Adding down->top
657
        $bog = new backup_optigroup('test', null, true);
658
        $boge1 = new backup_optigroup_element('boge1');
659
        $boge2 = new backup_optigroup_element('boge2');
660
        $ne1 = new backup_nested_element('ne1');
661
        $ne2 = new backup_nested_element('ne1');
662
        $boge1->add_child($ne1);
663
        $boge2->add_child($ne2);
664
        $bog->add_child($boge1);
665
        try {
666
            $bog->add_child($boge2);
667
            $this->assertTrue(false, 'base_element_struct_exception expected');
668
        } catch (\Exception $e) {
669
            $this->assertTrue($e instanceof base_element_struct_exception);
670
            $this->assertEquals($e->errorcode, 'baseelementexisting');
671
            $this->assertEquals($e->a, 'ne1');
672
        }
673
    }
674
}