Merge branch 'MDL-69583-master' of git://github.com/ferranrecio/moodle
[moodle.git] / admin / tool / customlang / tests / local / mlang / langstring_test.php
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/>.
17 /**
18  * mlang langstring tests.
19  *
20  * Based on local_amos mlang_langstring tests.
21  *
22  * @package    tool_customlang
23  * @copyright  2020 Ferran Recio <ferran@moodle.com>
24  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25  */
27 namespace tool_customlang\local\mlang;
29 use advanced_testcase;
30 use moodle_exception;
32 /**
33  * Langstring tests.
34  *
35  * @package    tool_customlang
36  * @copyright  2020 Ferran Recio <ferran@moodle.com>
37  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38  */
39 class langstring_testcase extends advanced_testcase {
41     /**
42      * Sanity 1.x string
43      * - all variables but $a placeholders must be escaped because the string is eval'ed
44      * - all ' and " must be escaped
45      * - all single % must be converted into %% for backwards compatibility
46      *
47      * @dataProvider fix_syntax_data
48      * @param string $text the text to test
49      * @param int $version the lang package version (1 or 2)
50      * @param int|null $fromversion the version to convert (null for none)
51      * @param string $expected the expected result
52      *
53      */
54     public function test_fix_syntax(string $text, int $version, ?int $fromversion, string $expected): void {
55         $this->assertEquals(langstring::fix_syntax($text, $version, $fromversion), $expected);
56     }
58     /**
59      * Data provider for the test_parse.
60      *
61      * @return  array
62      */
63     public function fix_syntax_data() : array {
64         return [
65             // Syntax sanity v1 strings.
66             [
67                 'No change', 1, null,
68                 'No change'
69             ],
70             [
71                 'Completed 100% of work', 1, null,
72                 'Completed 100%% of work'
73             ],
74             [
75                 'Completed 100%% of work', 1, null,
76                 'Completed 100%% of work'
77             ],
78             [
79                 "Windows\r\nsucks", 1, null,
80                 "Windows\nsucks"
81             ],
82             [
83                 "Linux\nsucks", 1, null,
84                 "Linux\nsucks"
85             ],
86             [
87                 "Mac\rsucks", 1, null,
88                 "Mac\nsucks"
89             ],
90             [
91                 "LINE TABULATION\x0Bnewline", 1, null,
92                 "LINE TABULATION\nnewline"
93             ],
94             [
95                 "FORM FEED\x0Cnewline", 1, null,
96                 "FORM FEED\nnewline"
97             ],
98             [
99                 "END OF TRANSMISSION BLOCK\x17newline", 1, null,
100                 "END OF TRANSMISSION BLOCK\nnewline"
101             ],
102             [
103                 "END OF MEDIUM\x19newline", 1, null,
104                 "END OF MEDIUM\nnewline"
105             ],
106             [
107                 "SUBSTITUTE\x1Anewline", 1, null,
108                 "SUBSTITUTE\nnewline"
109             ],
110             [
111                 "BREAK PERMITTED HERE\xC2\x82newline", 1, null,
112                 "BREAK PERMITTED HERE\nnewline"
113             ],
114             [
115                 "NEXT LINE\xC2\x85newline", 1, null,
116                 "NEXT LINE\nnewline"
117             ],
118             [
119                 "START OF STRING\xC2\x98newline", 1, null,
120                 "START OF STRING\nnewline"
121             ],
122             [
123                 "STRING TERMINATOR\xC2\x9Cnewline", 1, null,
124                 "STRING TERMINATOR\nnewline"
125             ],
126             [
127                 "Unicode Zl\xE2\x80\xA8newline", 1, null,
128                 "Unicode Zl\nnewline"
129             ],
130             [
131                 "Unicode Zp\xE2\x80\xA9newline", 1, null,
132                 "Unicode Zp\nnewline"
133             ],
134             [
135                 "Empty\n\n\n\n\n\nlines", 1, null,
136                 "Empty\n\nlines"
137             ],
138             [
139                 "Trailing   \n  whitespace \t \nat \nmultilines  ", 1, null,
140                 "Trailing\n  whitespace\nat\nmultilines"
141             ],
142             [
143                 'Escape $variable names', 1, null,
144                 'Escape \$variable names'
145             ],
146             [
147                 'Escape $alike names', 1, null,
148                 'Escape \$alike names'
149             ],
150             [
151                 'String $a placeholder', 1, null,
152                 'String $a placeholder'
153             ],
154             [
155                 'Escaped \$a', 1, null,
156                 'Escaped \$a'
157             ],
158             [
159                 'Wrapped {$a}', 1, null,
160                 'Wrapped {$a}'
161             ],
162             [
163                 'Trailing $a', 1, null,
164                 'Trailing $a'
165             ],
166             [
167                 '$a leading', 1, null,
168                 '$a leading'
169             ],
170             [
171                 'Hit $a-times', 1, null,
172                 'Hit $a-times'
173             ], // This is placeholder.
174             [
175                 'This is $a_book', 1, null,
176                 'This is \$a_book'
177             ], // This is not a place holder.
178             [
179                 'Bye $a, ttyl', 1, null,
180                 'Bye $a, ttyl'
181             ],
182             [
183                 'Object $a->foo placeholder', 1, null,
184                 'Object $a->foo placeholder'
185             ],
186             [
187                 'Trailing $a->bar', 1, null,
188                 'Trailing $a->bar'
189             ],
190             [
191                 '<strong>AMOS</strong>', 1, null,
192                 '<strong>AMOS</strong>'
193             ],
194             [
195                 '<a href="http://localhost">AMOS</a>', 1, null,
196                 '<a href=\"http://localhost\">AMOS</a>'
197             ],
198             [
199                 '<a href=\"http://localhost\">AMOS</a>', 1, null,
200                 '<a href=\"http://localhost\">AMOS</a>'
201             ],
202             [
203                 "'Murder!', she wrote", 1, null,
204                 "'Murder!', she wrote"
205             ], // Will be escaped by var_export().
206             [
207                 "\t  Trim Hunter  \t\t", 1, null,
208                 'Trim Hunter'
209             ],
210             [
211                 'Delete role "$a->role"?', 1, null,
212                 'Delete role \"$a->role\"?'
213             ],
214             [
215                 'Delete role \"$a->role\"?', 1, null,
216                 'Delete role \"$a->role\"?'
217             ],
218             [
219                 "Delete ASCII\0 NULL control character", 1, null,
220                 'Delete ASCII NULL control character'
221             ],
222             [
223                 "Delete ASCII\x05 ENQUIRY control character", 1, null,
224                 'Delete ASCII ENQUIRY control character'
225             ],
226             [
227                 "Delete ASCII\x06 ACKNOWLEDGE control character", 1, null,
228                 'Delete ASCII ACKNOWLEDGE control character'
229             ],
230             [
231                 "Delete ASCII\x07 BELL control character", 1, null,
232                 'Delete ASCII BELL control character'
233             ],
234             [
235                 "Delete ASCII\x0E SHIFT OUT control character", 1, null,
236                 'Delete ASCII SHIFT OUT control character'
237             ],
238             [
239                 "Delete ASCII\x0F SHIFT IN control character", 1, null,
240                 'Delete ASCII SHIFT IN control character'
241             ],
242             [
243                 "Delete ASCII\x10 DATA LINK ESCAPE control character", 1, null,
244                 'Delete ASCII DATA LINK ESCAPE control character'
245             ],
246             [
247                 "Delete ASCII\x11 DEVICE CONTROL ONE control character", 1, null,
248                 'Delete ASCII DEVICE CONTROL ONE control character'
249             ],
250             [
251                 "Delete ASCII\x12 DEVICE CONTROL TWO control character", 1, null,
252                 'Delete ASCII DEVICE CONTROL TWO control character'
253             ],
254             [
255                 "Delete ASCII\x13 DEVICE CONTROL THREE control character", 1, null,
256                 'Delete ASCII DEVICE CONTROL THREE control character'
257             ],
258             [
259                 "Delete ASCII\x14 DEVICE CONTROL FOUR control character", 1, null,
260                 'Delete ASCII DEVICE CONTROL FOUR control character'
261             ],
262             [
263                 "Delete ASCII\x15 NEGATIVE ACKNOWLEDGE control character", 1, null,
264                 'Delete ASCII NEGATIVE ACKNOWLEDGE control character'
265             ],
266             [
267                 "Delete ASCII\x16 SYNCHRONOUS IDLE control character", 1, null,
268                 'Delete ASCII SYNCHRONOUS IDLE control character'
269             ],
270             [
271                 "Delete ASCII\x1B ESCAPE control character", 1, null,
272                 'Delete ASCII ESCAPE control character'
273             ],
274             [
275                 "Delete ASCII\x7F DELETE control character", 1, null,
276                 'Delete ASCII DELETE control character'
277             ],
278             [
279                 "Delete ISO 8859\xC2\x80 PADDING CHARACTER control character", 1, null,
280                 'Delete ISO 8859 PADDING CHARACTER control character'
281             ],
282             [
283                 "Delete ISO 8859\xC2\x81 HIGH OCTET PRESET control character", 1, null,
284                 'Delete ISO 8859 HIGH OCTET PRESET control character'
285             ],
286             [
287                 "Delete ISO 8859\xC2\x83 NO BREAK HERE control character", 1, null,
288                 'Delete ISO 8859 NO BREAK HERE control character'
289             ],
290             [
291                 "Delete ISO 8859\xC2\x84 INDEX control character", 1, null,
292                 'Delete ISO 8859 INDEX control character'
293             ],
294             [
295                 "Delete ISO 8859\xC2\x86 START OF SELECTED AREA control character", 1, null,
296                 'Delete ISO 8859 START OF SELECTED AREA control character'
297             ],
298             [
299                 "Delete ISO 8859\xC2\x87 END OF SELECTED AREA control character", 1, null,
300                 'Delete ISO 8859 END OF SELECTED AREA control character'
301             ],
302             [
303                 "Delete ISO 8859\xC2\x88 CHARACTER TABULATION SET control character", 1, null,
304                 'Delete ISO 8859 CHARACTER TABULATION SET control character'
305             ],
306             [
307                 "Delete ISO 8859\xC2\x89 CHARACTER TABULATION WITH JUSTIFICATION control character", 1, null,
308                 'Delete ISO 8859 CHARACTER TABULATION WITH JUSTIFICATION control character'
309             ],
310             [
311                 "Delete ISO 8859\xC2\x8A LINE TABULATION SET control character", 1, null,
312                 'Delete ISO 8859 LINE TABULATION SET control character'
313             ],
314             [
315                 "Delete ISO 8859\xC2\x8B PARTIAL LINE FORWARD control character", 1, null,
316                 'Delete ISO 8859 PARTIAL LINE FORWARD control character'
317             ],
318             [
319                 "Delete ISO 8859\xC2\x8C PARTIAL LINE BACKWARD control character", 1, null,
320                 'Delete ISO 8859 PARTIAL LINE BACKWARD control character'
321             ],
322             [
323                 "Delete ISO 8859\xC2\x8D REVERSE LINE FEED control character", 1, null,
324                 'Delete ISO 8859 REVERSE LINE FEED control character'
325             ],
326             [
327                 "Delete ISO 8859\xC2\x8E SINGLE SHIFT TWO control character", 1, null,
328                 'Delete ISO 8859 SINGLE SHIFT TWO control character'
329             ],
330             [
331                 "Delete ISO 8859\xC2\x8F SINGLE SHIFT THREE control character", 1, null,
332                 'Delete ISO 8859 SINGLE SHIFT THREE control character'
333             ],
334             [
335                 "Delete ISO 8859\xC2\x90 DEVICE CONTROL STRING control character", 1, null,
336                 'Delete ISO 8859 DEVICE CONTROL STRING control character'
337             ],
338             [
339                 "Delete ISO 8859\xC2\x91 PRIVATE USE ONE control character", 1, null,
340                 'Delete ISO 8859 PRIVATE USE ONE control character'
341             ],
342             [
343                 "Delete ISO 8859\xC2\x92 PRIVATE USE TWO control character", 1, null,
344                 'Delete ISO 8859 PRIVATE USE TWO control character'
345             ],
346             [
347                 "Delete ISO 8859\xC2\x93 SET TRANSMIT STATE control character", 1, null,
348                 'Delete ISO 8859 SET TRANSMIT STATE control character'
349             ],
350             [
351                 "Delete ISO 8859\xC2\x95 MESSAGE WAITING control character", 1, null,
352                 'Delete ISO 8859 MESSAGE WAITING control character'
353             ],
354             [
355                 "Delete ISO 8859\xC2\x96 START OF GUARDED AREA control character", 1, null,
356                 'Delete ISO 8859 START OF GUARDED AREA control character'
357             ],
358             [
359                 "Delete ISO 8859\xC2\x97 END OF GUARDED AREA control character", 1, null,
360                 'Delete ISO 8859 END OF GUARDED AREA control character'
361             ],
362             [
363                 "Delete ISO 8859\xC2\x99 SINGLE GRAPHIC CHARACTER INTRODUCER control character", 1, null,
364                 'Delete ISO 8859 SINGLE GRAPHIC CHARACTER INTRODUCER control character'
365             ],
366             [
367                 "Delete ISO 8859\xC2\x9A SINGLE CHARACTER INTRODUCER control character", 1, null,
368                 'Delete ISO 8859 SINGLE CHARACTER INTRODUCER control character'
369             ],
370             [
371                 "Delete ISO 8859\xC2\x9B CONTROL SEQUENCE INTRODUCER control character", 1, null,
372                 'Delete ISO 8859 CONTROL SEQUENCE INTRODUCER control character'
373             ],
374             [
375                 "Delete ISO 8859\xC2\x9D OPERATING SYSTEM COMMAND control character", 1, null,
376                 'Delete ISO 8859 OPERATING SYSTEM COMMAND control character'
377             ],
378             [
379                 "Delete ISO 8859\xC2\x9E PRIVACY MESSAGE control character", 1, null,
380                 'Delete ISO 8859 PRIVACY MESSAGE control character'
381             ],
382             [
383                 "Delete ISO 8859\xC2\x9F APPLICATION PROGRAM COMMAND control character", 1, null,
384                 'Delete ISO 8859 APPLICATION PROGRAM COMMAND control character'
385             ],
386             [
387                 "Delete Unicode\xE2\x80\x8B ZERO WIDTH SPACE control character", 1, null,
388                 'Delete Unicode ZERO WIDTH SPACE control character'
389             ],
390             [
391                 "Delete Unicode\xEF\xBB\xBF ZERO WIDTH NO-BREAK SPACE control character", 1, null,
392                 'Delete Unicode ZERO WIDTH NO-BREAK SPACE control character'
393             ],
394             [
395                 "Delete Unicode\xEF\xBF\xBD REPLACEMENT CHARACTER control character", 1, null,
396                 'Delete Unicode REPLACEMENT CHARACTER control character'
397             ],
398             // Syntax sanity v2 strings.
399             [
400                 'No change', 2, null,
401                 'No change'
402             ],
403             [
404                 'Completed 100% of work', 2, null,
405                 'Completed 100% of work'
406             ],
407             [
408                 '%%%% HEADER %%%%', 2, null,
409                 '%%%% HEADER %%%%'
410             ], // Was not possible before.
411             [
412                 "Windows\r\nsucks", 2, null,
413                 "Windows\nsucks"
414             ],
415             [
416                 "Linux\nsucks", 2, null,
417                 "Linux\nsucks"
418             ],
419             [
420                 "Mac\rsucks", 2, null,
421                 "Mac\nsucks"
422             ],
423             [
424                 "LINE TABULATION\x0Bnewline", 2, null,
425                 "LINE TABULATION\nnewline"
426             ],
427             [
428                 "FORM FEED\x0Cnewline", 2, null,
429                 "FORM FEED\nnewline"
430             ],
431             [
432                 "END OF TRANSMISSION BLOCK\x17newline", 2, null,
433                 "END OF TRANSMISSION BLOCK\nnewline"
434             ],
435             [
436                 "END OF MEDIUM\x19newline", 2, null,
437                 "END OF MEDIUM\nnewline"
438             ],
439             [
440                 "SUBSTITUTE\x1Anewline", 2, null,
441                 "SUBSTITUTE\nnewline"
442             ],
443             [
444                 "BREAK PERMITTED HERE\xC2\x82newline", 2, null,
445                 "BREAK PERMITTED HERE\nnewline"
446             ],
447             [
448                 "NEXT LINE\xC2\x85newline", 2, null,
449                 "NEXT LINE\nnewline"
450             ],
451             [
452                 "START OF STRING\xC2\x98newline", 2, null,
453                 "START OF STRING\nnewline"
454             ],
455             [
456                 "STRING TERMINATOR\xC2\x9Cnewline", 2, null,
457                 "STRING TERMINATOR\nnewline"
458             ],
459             [
460                 "Unicode Zl\xE2\x80\xA8newline", 2, null,
461                 "Unicode Zl\nnewline"
462             ],
463             [
464                 "Unicode Zp\xE2\x80\xA9newline", 2, null,
465                 "Unicode Zp\nnewline"
466             ],
467             [
468                 "Empty\n\n\n\n\n\nlines", 2, null,
469                 "Empty\n\n\nlines"
470             ], // Now allows up to two empty lines.
471             [
472                 "Trailing   \n  whitespace\t\nat \nmultilines  ", 2, null,
473                 "Trailing\n  whitespace\nat\nmultilines"
474             ],
475             [
476                 'Do not escape $variable names', 2, null,
477                 'Do not escape $variable names'
478             ],
479             [
480                 'Do not escape $alike names', 2, null,
481                 'Do not escape $alike names'
482             ],
483             [
484                 'Not $a placeholder', 2, null,
485                 'Not $a placeholder'
486             ],
487             [
488                 'String {$a} placeholder', 2, null,
489                 'String {$a} placeholder'
490             ],
491             [
492                 'Trailing {$a}', 2, null,
493                 'Trailing {$a}'
494             ],
495             [
496                 '{$a} leading', 2, null,
497                 '{$a} leading'
498             ],
499             [
500                 'Trailing $a', 2, null,
501                 'Trailing $a'
502             ],
503             [
504                 '$a leading', 2, null,
505                 '$a leading'
506             ],
507             [
508                 'Not $a->foo placeholder', 2, null,
509                 'Not $a->foo placeholder'
510             ],
511             [
512                 'Object {$a->foo} placeholder', 2, null,
513                 'Object {$a->foo} placeholder'
514             ],
515             [
516                 'Trailing $a->bar', 2, null,
517                 'Trailing $a->bar'
518             ],
519             [
520                 'Invalid $a-> placeholder', 2, null,
521                 'Invalid $a-> placeholder'
522             ],
523             [
524                 '<strong>AMOS</strong>', 2, null,
525                 '<strong>AMOS</strong>'
526             ],
527             [
528                 "'Murder!', she wrote", 2, null,
529                 "'Murder!', she wrote"
530             ], // Will be escaped by var_export().
531             [
532                 "\t  Trim Hunter  \t\t", 2, null,
533                 'Trim Hunter'
534             ],
535             [
536                 'Delete role "$a->role"?', 2, null,
537                 'Delete role "$a->role"?'
538             ],
539             [
540                 'Delete role \"$a->role\"?', 2, null,
541                 'Delete role \"$a->role\"?'
542             ],
543             [
544                 "Delete ASCII\0 NULL control character", 2, null,
545                 'Delete ASCII NULL control character'
546             ],
547             [
548                 "Delete ASCII\x05 ENQUIRY control character", 2, null,
549                 'Delete ASCII ENQUIRY control character'
550             ],
551             [
552                 "Delete ASCII\x06 ACKNOWLEDGE control character", 2, null,
553                 'Delete ASCII ACKNOWLEDGE control character'
554             ],
555             [
556                 "Delete ASCII\x07 BELL control character", 2, null,
557                 'Delete ASCII BELL control character'
558             ],
559             [
560                 "Delete ASCII\x0E SHIFT OUT control character", 2, null,
561                 'Delete ASCII SHIFT OUT control character'
562             ],
563             [
564                 "Delete ASCII\x0F SHIFT IN control character", 2, null,
565                 'Delete ASCII SHIFT IN control character'
566             ],
567             [
568                 "Delete ASCII\x10 DATA LINK ESCAPE control character", 2, null,
569                 'Delete ASCII DATA LINK ESCAPE control character'
570             ],
571             [
572                 "Delete ASCII\x11 DEVICE CONTROL ONE control character", 2, null,
573                 'Delete ASCII DEVICE CONTROL ONE control character'
574             ],
575             [
576                 "Delete ASCII\x12 DEVICE CONTROL TWO control character", 2, null,
577                 'Delete ASCII DEVICE CONTROL TWO control character'
578             ],
579             [
580                 "Delete ASCII\x13 DEVICE CONTROL THREE control character", 2, null,
581                 'Delete ASCII DEVICE CONTROL THREE control character'
582             ],
583             [
584                 "Delete ASCII\x14 DEVICE CONTROL FOUR control character", 2, null,
585                 'Delete ASCII DEVICE CONTROL FOUR control character'
586             ],
587             [
588                 "Delete ASCII\x15 NEGATIVE ACKNOWLEDGE control character", 2, null,
589                 'Delete ASCII NEGATIVE ACKNOWLEDGE control character'
590             ],
591             [
592                 "Delete ASCII\x16 SYNCHRONOUS IDLE control character", 2, null,
593                 'Delete ASCII SYNCHRONOUS IDLE control character'
594             ],
595             [
596                 "Delete ASCII\x1B ESCAPE control character", 2, null,
597                 'Delete ASCII ESCAPE control character'
598             ],
599             [
600                 "Delete ASCII\x7F DELETE control character", 2, null,
601                 'Delete ASCII DELETE control character'
602             ],
603             [
604                 "Delete ISO 8859\xC2\x80 PADDING CHARACTER control character", 2, null,
605                 'Delete ISO 8859 PADDING CHARACTER control character'
606             ],
607             [
608                 "Delete ISO 8859\xC2\x81 HIGH OCTET PRESET control character", 2, null,
609                 'Delete ISO 8859 HIGH OCTET PRESET control character'
610             ],
611             [
612                 "Delete ISO 8859\xC2\x83 NO BREAK HERE control character", 2, null,
613                 'Delete ISO 8859 NO BREAK HERE control character'
614             ],
615             [
616                 "Delete ISO 8859\xC2\x84 INDEX control character", 2, null,
617                 'Delete ISO 8859 INDEX control character'
618             ],
619             [
620                 "Delete ISO 8859\xC2\x86 START OF SELECTED AREA control character", 2, null,
621                 'Delete ISO 8859 START OF SELECTED AREA control character'
622             ],
623             [
624                 "Delete ISO 8859\xC2\x87 END OF SELECTED AREA control character", 2, null,
625                 'Delete ISO 8859 END OF SELECTED AREA control character'
626             ],
627             [
628                 "Delete ISO 8859\xC2\x88 CHARACTER TABULATION SET control character", 2, null,
629                 'Delete ISO 8859 CHARACTER TABULATION SET control character'
630             ],
631             [
632                 "Delete ISO 8859\xC2\x89 CHARACTER TABULATION WITH JUSTIFICATION control character", 2, null,
633                 'Delete ISO 8859 CHARACTER TABULATION WITH JUSTIFICATION control character'
634             ],
635             [
636                 "Delete ISO 8859\xC2\x8A LINE TABULATION SET control character", 2, null,
637                 'Delete ISO 8859 LINE TABULATION SET control character'
638             ],
639             [
640                 "Delete ISO 8859\xC2\x8B PARTIAL LINE FORWARD control character", 2, null,
641                 'Delete ISO 8859 PARTIAL LINE FORWARD control character'
642             ],
643             [
644                 "Delete ISO 8859\xC2\x8C PARTIAL LINE BACKWARD control character", 2, null,
645                 'Delete ISO 8859 PARTIAL LINE BACKWARD control character'
646             ],
647             [
648                 "Delete ISO 8859\xC2\x8D REVERSE LINE FEED control character", 2, null,
649                 'Delete ISO 8859 REVERSE LINE FEED control character'
650             ],
651             [
652                 "Delete ISO 8859\xC2\x8E SINGLE SHIFT TWO control character", 2, null,
653                 'Delete ISO 8859 SINGLE SHIFT TWO control character'
654             ],
655             [
656                 "Delete ISO 8859\xC2\x8F SINGLE SHIFT THREE control character", 2, null,
657                 'Delete ISO 8859 SINGLE SHIFT THREE control character'
658             ],
659             [
660                 "Delete ISO 8859\xC2\x90 DEVICE CONTROL STRING control character", 2, null,
661                 'Delete ISO 8859 DEVICE CONTROL STRING control character'
662             ],
663             [
664                 "Delete ISO 8859\xC2\x91 PRIVATE USE ONE control character", 2, null,
665                 'Delete ISO 8859 PRIVATE USE ONE control character'
666             ],
667             [
668                 "Delete ISO 8859\xC2\x92 PRIVATE USE TWO control character", 2, null,
669                 'Delete ISO 8859 PRIVATE USE TWO control character'
670             ],
671             [
672                 "Delete ISO 8859\xC2\x93 SET TRANSMIT STATE control character", 2, null,
673                 'Delete ISO 8859 SET TRANSMIT STATE control character'
674             ],
675             [
676                 "Delete ISO 8859\xC2\x95 MESSAGE WAITING control character", 2, null,
677                 'Delete ISO 8859 MESSAGE WAITING control character'
678             ],
679             [
680                 "Delete ISO 8859\xC2\x96 START OF GUARDED AREA control character", 2, null,
681                 'Delete ISO 8859 START OF GUARDED AREA control character'
682             ],
683             [
684                 "Delete ISO 8859\xC2\x97 END OF GUARDED AREA control character", 2, null,
685                 'Delete ISO 8859 END OF GUARDED AREA control character'
686             ],
687             [
688                 "Delete ISO 8859\xC2\x99 SINGLE GRAPHIC CHARACTER INTRODUCER control character", 2, null,
689                 'Delete ISO 8859 SINGLE GRAPHIC CHARACTER INTRODUCER control character'
690             ],
691             [
692                 "Delete ISO 8859\xC2\x9A SINGLE CHARACTER INTRODUCER control character", 2, null,
693                 'Delete ISO 8859 SINGLE CHARACTER INTRODUCER control character'
694             ],
695             [
696                 "Delete ISO 8859\xC2\x9B CONTROL SEQUENCE INTRODUCER control character", 2, null,
697                 'Delete ISO 8859 CONTROL SEQUENCE INTRODUCER control character'
698             ],
699             [
700                 "Delete ISO 8859\xC2\x9D OPERATING SYSTEM COMMAND control character", 2, null,
701                 'Delete ISO 8859 OPERATING SYSTEM COMMAND control character'
702             ],
703             [
704                 "Delete ISO 8859\xC2\x9E PRIVACY MESSAGE control character", 2, null,
705                 'Delete ISO 8859 PRIVACY MESSAGE control character'
706             ],
707             [
708                 "Delete ISO 8859\xC2\x9F APPLICATION PROGRAM COMMAND control character", 2, null,
709                 'Delete ISO 8859 APPLICATION PROGRAM COMMAND control character'
710             ],
711             [
712                 "Delete Unicode\xE2\x80\x8B ZERO WIDTH SPACE control character", 2, null,
713                 'Delete Unicode ZERO WIDTH SPACE control character'
714             ],
715             [
716                 "Delete Unicode\xEF\xBB\xBF ZERO WIDTH NO-BREAK SPACE control character", 2, null,
717                 'Delete Unicode ZERO WIDTH NO-BREAK SPACE control character'
718             ],
719             [
720                 "Delete Unicode\xEF\xBF\xBD REPLACEMENT CHARACTER control character", 2, null,
721                 'Delete Unicode REPLACEMENT CHARACTER control character'
722             ],
723             // Conterting from v1 to v2.
724             [
725                 'No change', 2, 1,
726                 'No change'
727             ],
728             [
729                 'Completed 100% of work', 2, 1,
730                 'Completed 100% of work'
731             ],
732             [
733                 'Completed 100%% of work', 2, 1,
734                 'Completed 100% of work'
735             ],
736             [
737                 "Windows\r\nsucks", 2, 1,
738                 "Windows\nsucks"
739             ],
740             [
741                 "Linux\nsucks", 2, 1,
742                 "Linux\nsucks"
743             ],
744             [
745                 "Mac\rsucks", 2, 1,
746                 "Mac\nsucks"
747             ],
748             [
749                 "LINE TABULATION\x0Bnewline", 2, 1,
750                 "LINE TABULATION\nnewline"
751             ],
752             [
753                 "FORM FEED\x0Cnewline", 2, 1,
754                 "FORM FEED\nnewline"
755             ],
756             [
757                 "END OF TRANSMISSION BLOCK\x17newline", 2, 1,
758                 "END OF TRANSMISSION BLOCK\nnewline"
759             ],
760             [
761                 "END OF MEDIUM\x19newline", 2, 1,
762                 "END OF MEDIUM\nnewline"
763             ],
764             [
765                 "SUBSTITUTE\x1Anewline", 2, 1,
766                 "SUBSTITUTE\nnewline"
767             ],
768             [
769                 "BREAK PERMITTED HERE\xC2\x82newline", 2, 1,
770                 "BREAK PERMITTED HERE\nnewline"
771             ],
772             [
773                 "NEXT LINE\xC2\x85newline", 2, 1,
774                 "NEXT LINE\nnewline"
775             ],
776             [
777                 "START OF STRING\xC2\x98newline", 2, 1,
778                 "START OF STRING\nnewline"
779             ],
780             [
781                 "STRING TERMINATOR\xC2\x9Cnewline", 2, 1,
782                 "STRING TERMINATOR\nnewline"
783             ],
784             [
785                 "Unicode Zl\xE2\x80\xA8newline", 2, 1,
786                 "Unicode Zl\nnewline"
787             ],
788             [
789                 "Unicode Zp\xE2\x80\xA9newline", 2, 1,
790                 "Unicode Zp\nnewline"
791             ],
792             [
793                 "Empty\n\n\n\n\n\nlines", 2, 1,
794                 "Empty\n\n\nlines"
795             ],
796             [
797                 "Trailing   \n  whitespace\t\nat \nmultilines  ", 2, 1,
798                 "Trailing\n  whitespace\nat\nmultilines"
799             ],
800             [
801                 'Do not escape $variable names', 2, 1,
802                 'Do not escape $variable names'
803             ],
804             [
805                 'Do not escape \$variable names', 2, 1,
806                 'Do not escape $variable names'
807             ],
808             [
809                 'Do not escape $alike names', 2, 1,
810                 'Do not escape $alike names'
811             ],
812             [
813                 'Do not escape \$alike names', 2, 1,
814                 'Do not escape $alike names'
815             ],
816             [
817                 'Do not escape \$a names', 2, 1,
818                 'Do not escape $a names'
819             ],
820             [
821                 'String $a placeholder', 2, 1,
822                 'String {$a} placeholder'
823             ],
824             [
825                 'String {$a} placeholder', 2, 1,
826                 'String {$a} placeholder'
827             ],
828             [
829                 'Trailing $a', 2, 1,
830                 'Trailing {$a}'
831             ],
832             [
833                 '$a leading', 2, 1,
834                 '{$a} leading'
835             ],
836             [
837                 '$a', 2, 1,
838                 '{$a}'
839             ],
840             [
841                 '$a->single', 2, 1,
842                 '{$a->single}'
843             ],
844             [
845                 'Trailing $a->foobar', 2, 1,
846                 'Trailing {$a->foobar}'
847             ],
848             [
849                 'Trailing {$a}', 2, 1,
850                 'Trailing {$a}'
851             ],
852             [
853                 'Hit $a-times', 2, 1,
854                 'Hit {$a}-times'
855             ],
856             [
857                 'This is $a_book', 2, 1,
858                 'This is $a_book'
859             ],
860             [
861                 'Object $a->foo placeholder', 2, 1,
862                 'Object {$a->foo} placeholder'
863             ],
864             [
865                 'Object {$a->foo} placeholder', 2, 1,
866                 'Object {$a->foo} placeholder'
867             ],
868             [
869                 'Trailing $a->bar', 2, 1,
870                 'Trailing {$a->bar}'
871             ],
872             [
873                 'Trailing {$a->bar}', 2, 1,
874                 'Trailing {$a->bar}'
875             ],
876             [
877                 'Invalid $a-> placeholder', 2, 1,
878                 'Invalid {$a}-> placeholder'
879                 ], // Weird but BC.
880             [
881                 '<strong>AMOS</strong>', 2, 1,
882                 '<strong>AMOS</strong>'
883             ],
884             [
885                 "'Murder!', she wrote", 2, 1,
886                 "'Murder!', she wrote"
887             ], // Will be escaped by var_export().
888             [
889                 "\'Murder!\', she wrote", 2, 1,
890                 "'Murder!', she wrote"
891             ], // Will be escaped by var_export().
892             [
893                 "\t  Trim Hunter  \t\t", 2, 1,
894                 'Trim Hunter'
895             ],
896             [
897                 'Delete role "$a->role"?', 2, 1,
898                 'Delete role "{$a->role}"?'
899             ],
900             [
901                 'Delete role \"$a->role\"?', 2, 1,
902                 'Delete role "{$a->role}"?'
903             ],
904             [
905                 'See &#36;CFG->foo', 2, 1,
906                 'See $CFG->foo'
907             ],
908             [
909                 "Delete ASCII\0 NULL control character", 2, 1,
910                 'Delete ASCII NULL control character'
911             ],
912             [
913                 "Delete ASCII\x05 ENQUIRY control character", 2, 1,
914                 'Delete ASCII ENQUIRY control character'
915             ],
916             [
917                 "Delete ASCII\x06 ACKNOWLEDGE control character", 2, 1,
918                 'Delete ASCII ACKNOWLEDGE control character'
919             ],
920             [
921                 "Delete ASCII\x07 BELL control character", 2, 1,
922                 'Delete ASCII BELL control character'
923             ],
924             [
925                 "Delete ASCII\x0E SHIFT OUT control character", 2, 1,
926                 'Delete ASCII SHIFT OUT control character'
927             ],
928             [
929                 "Delete ASCII\x0F SHIFT IN control character", 2, 1,
930                 'Delete ASCII SHIFT IN control character'
931             ],
932             [
933                 "Delete ASCII\x10 DATA LINK ESCAPE control character", 2, 1,
934                 'Delete ASCII DATA LINK ESCAPE control character'
935             ],
936             [
937                 "Delete ASCII\x11 DEVICE CONTROL ONE control character", 2, 1,
938                 'Delete ASCII DEVICE CONTROL ONE control character'
939             ],
940             [
941                 "Delete ASCII\x12 DEVICE CONTROL TWO control character", 2, 1,
942                 'Delete ASCII DEVICE CONTROL TWO control character'
943             ],
944             [
945                 "Delete ASCII\x13 DEVICE CONTROL THREE control character", 2, 1,
946                 'Delete ASCII DEVICE CONTROL THREE control character'
947             ],
948             [
949                 "Delete ASCII\x14 DEVICE CONTROL FOUR control character", 2, 1,
950                 'Delete ASCII DEVICE CONTROL FOUR control character'
951             ],
952             [
953                 "Delete ASCII\x15 NEGATIVE ACKNOWLEDGE control character", 2, 1,
954                 'Delete ASCII NEGATIVE ACKNOWLEDGE control character'
955             ],
956             [
957                 "Delete ASCII\x16 SYNCHRONOUS IDLE control character", 2, 1,
958                 'Delete ASCII SYNCHRONOUS IDLE control character'
959             ],
960             [
961                 "Delete ASCII\x1B ESCAPE control character", 2, 1,
962                 'Delete ASCII ESCAPE control character'
963             ],
964             [
965                 "Delete ASCII\x7F DELETE control character", 2, 1,
966                 'Delete ASCII DELETE control character'
967             ],
968             [
969                 "Delete ISO 8859\xC2\x80 PADDING CHARACTER control character", 2, 1,
970                 'Delete ISO 8859 PADDING CHARACTER control character'
971             ],
972             [
973                 "Delete ISO 8859\xC2\x81 HIGH OCTET PRESET control character", 2, 1,
974                 'Delete ISO 8859 HIGH OCTET PRESET control character'
975             ],
976             [
977                 "Delete ISO 8859\xC2\x83 NO BREAK HERE control character", 2, 1,
978                 'Delete ISO 8859 NO BREAK HERE control character'
979             ],
980             [
981                 "Delete ISO 8859\xC2\x84 INDEX control character", 2, 1,
982                 'Delete ISO 8859 INDEX control character'
983             ],
984             [
985                 "Delete ISO 8859\xC2\x86 START OF SELECTED AREA control character", 2, 1,
986                 'Delete ISO 8859 START OF SELECTED AREA control character'
987             ],
988             [
989                 "Delete ISO 8859\xC2\x87 END OF SELECTED AREA control character", 2, 1,
990                 'Delete ISO 8859 END OF SELECTED AREA control character'
991             ],
992             [
993                 "Delete ISO 8859\xC2\x88 CHARACTER TABULATION SET control character", 2, 1,
994                 'Delete ISO 8859 CHARACTER TABULATION SET control character'
995             ],
996             [
997                 "Delete ISO 8859\xC2\x89 CHARACTER TABULATION WITH JUSTIFICATION control character", 2, 1,
998                 'Delete ISO 8859 CHARACTER TABULATION WITH JUSTIFICATION control character'
999             ],
1000             [
1001                 "Delete ISO 8859\xC2\x8A LINE TABULATION SET control character", 2, 1,
1002                 'Delete ISO 8859 LINE TABULATION SET control character'
1003             ],
1004             [
1005                 "Delete ISO 8859\xC2\x8B PARTIAL LINE FORWARD control character", 2, 1,
1006                 'Delete ISO 8859 PARTIAL LINE FORWARD control character'
1007             ],
1008             [
1009                 "Delete ISO 8859\xC2\x8C PARTIAL LINE BACKWARD control character", 2, 1,
1010                 'Delete ISO 8859 PARTIAL LINE BACKWARD control character'
1011             ],
1012             [
1013                 "Delete ISO 8859\xC2\x8D REVERSE LINE FEED control character", 2, 1,
1014                 'Delete ISO 8859 REVERSE LINE FEED control character'
1015             ],
1016             [
1017                 "Delete ISO 8859\xC2\x8E SINGLE SHIFT TWO control character", 2, 1,
1018                 'Delete ISO 8859 SINGLE SHIFT TWO control character'
1019             ],
1020             [
1021                 "Delete ISO 8859\xC2\x8F SINGLE SHIFT THREE control character", 2, 1,
1022                 'Delete ISO 8859 SINGLE SHIFT THREE control character'
1023             ],
1024             [
1025                 "Delete ISO 8859\xC2\x90 DEVICE CONTROL STRING control character", 2, 1,
1026                 'Delete ISO 8859 DEVICE CONTROL STRING control character'
1027             ],
1028             [
1029                 "Delete ISO 8859\xC2\x91 PRIVATE USE ONE control character", 2, 1,
1030                 'Delete ISO 8859 PRIVATE USE ONE control character'
1031             ],
1032             [
1033                 "Delete ISO 8859\xC2\x92 PRIVATE USE TWO control character", 2, 1,
1034                 'Delete ISO 8859 PRIVATE USE TWO control character'
1035             ],
1036             [
1037                 "Delete ISO 8859\xC2\x93 SET TRANSMIT STATE control character", 2, 1,
1038                 'Delete ISO 8859 SET TRANSMIT STATE control character'
1039             ],
1040             [
1041                 "Delete ISO 8859\xC2\x95 MESSAGE WAITING control character", 2, 1,
1042                 'Delete ISO 8859 MESSAGE WAITING control character'
1043             ],
1044             [
1045                 "Delete ISO 8859\xC2\x96 START OF GUARDED AREA control character", 2, 1,
1046                 'Delete ISO 8859 START OF GUARDED AREA control character'
1047             ],
1048             [
1049                 "Delete ISO 8859\xC2\x97 END OF GUARDED AREA control character", 2, 1,
1050                 'Delete ISO 8859 END OF GUARDED AREA control character'
1051             ],
1052             [
1053                 "Delete ISO 8859\xC2\x99 SINGLE GRAPHIC CHARACTER INTRODUCER control character", 2, 1,
1054                 'Delete ISO 8859 SINGLE GRAPHIC CHARACTER INTRODUCER control character'
1055             ],
1056             [
1057                 "Delete ISO 8859\xC2\x9A SINGLE CHARACTER INTRODUCER control character", 2, 1,
1058                 'Delete ISO 8859 SINGLE CHARACTER INTRODUCER control character'
1059             ],
1060             [
1061                 "Delete ISO 8859\xC2\x9B CONTROL SEQUENCE INTRODUCER control character", 2, 1,
1062                 'Delete ISO 8859 CONTROL SEQUENCE INTRODUCER control character'
1063             ],
1064             [
1065                 "Delete ISO 8859\xC2\x9D OPERATING SYSTEM COMMAND control character", 2, 1,
1066                 'Delete ISO 8859 OPERATING SYSTEM COMMAND control character'
1067             ],
1068             [
1069                 "Delete ISO 8859\xC2\x9E PRIVACY MESSAGE control character", 2, 1,
1070                 'Delete ISO 8859 PRIVACY MESSAGE control character'
1071             ],
1072             [
1073                 "Delete ISO 8859\xC2\x9F APPLICATION PROGRAM COMMAND control character", 2, 1,
1074                 'Delete ISO 8859 APPLICATION PROGRAM COMMAND control character'
1075             ],
1076             [
1077                 "Delete Unicode\xE2\x80\x8B ZERO WIDTH SPACE control character", 2, 1,
1078                 'Delete Unicode ZERO WIDTH SPACE control character'
1079             ],
1080             [
1081                 "Delete Unicode\xEF\xBB\xBF ZERO WIDTH NO-BREAK SPACE control character", 2, 1,
1082                 'Delete Unicode ZERO WIDTH NO-BREAK SPACE control character'
1083             ],
1084             [
1085                 "Delete Unicode\xEF\xBF\xBD REPLACEMENT CHARACTER control character", 2, 1,
1086                 'Delete Unicode REPLACEMENT CHARACTER control character'
1087             ],
1088         ];
1089     }