2011-01-15 08:35:56 +00:00
< ? php
2018-07-29 12:24:54 +00:00
use MediaWiki\MediaWikiServices ;
2016-08-26 01:01:07 +00:00
/**
* @ covers Preprocessor
*
* @ covers Preprocessor_Hash
* @ covers PPDStack_Hash
* @ covers PPDStackElement_Hash
* @ covers PPDPart_Hash
* @ covers PPFrame_Hash
* @ covers PPTemplateFrame_Hash
* @ covers PPCustomFrame_Hash
* @ covers PPNode_Hash_Tree
* @ covers PPNode_Hash_Text
* @ covers PPNode_Hash_Array
* @ covers PPNode_Hash_Attr
*/
2020-06-30 15:09:24 +00:00
class PreprocessorTest extends MediaWikiIntegrationTestCase {
2013-10-22 23:50:38 +00:00
protected $mTitle = 'Page title' ;
protected $mPPNodeCount = 0 ;
2020-04-07 23:52:41 +00:00
/** @var ParserOptions */
2013-10-22 23:50:38 +00:00
protected $mOptions ;
2020-04-07 23:52:41 +00:00
/** @var Preprocessor */
protected $preprocessor ;
2011-01-15 08:35:56 +00:00
2021-07-22 03:11:47 +00:00
protected function setUp () : void {
2012-10-23 17:02:36 +00:00
parent :: setUp ();
2018-07-29 12:24:54 +00:00
$this -> mOptions = ParserOptions :: newFromUserAndLang ( new User ,
MediaWikiServices :: getInstance () -> getContentLanguage () );
2011-01-15 08:35:56 +00:00
2020-04-07 23:52:41 +00:00
$wanCache = new WANObjectCache ( [ 'cache' => new HashBagOStuff () ] );
$parser = $this -> getMockBuilder ( Parser :: class )
-> disableOriginalConstructor ()
-> getMock ();
$parser -> method ( 'getStripList' ) -> willReturn ( [
'gallery' , 'display map' /* Used by Maps, see r80025 CR */ , '/foo'
] );
2011-01-15 08:35:56 +00:00
2020-04-07 23:52:41 +00:00
$this -> preprocessor = new Preprocessor_Hash (
$parser ,
$wanCache ,
[ 'cacheThreshold' => 1000 ]
);
2016-08-25 03:17:13 +00:00
}
2013-03-22 02:12:37 +00:00
public static function provideCases () {
2018-01-01 13:10:16 +00:00
// phpcs:disable Generic.Files.LineLength
2020-04-07 23:52:41 +00:00
return [
2016-03-19 01:05:19 +00:00
[ " Foo " , " <root>Foo</root> " ],
[ " <!-- Foo --> " , " <root><comment><!-- Foo --></comment></root> " ],
[ " <!-- Foo --><!-- Bar --> " , " <root><comment><!-- Foo --></comment><comment><!-- Bar --></comment></root> " ],
[ " <!-- Foo --> <!-- Bar --> " , " <root><comment><!-- Foo --></comment> <comment><!-- Bar --></comment></root> " ],
[ " <!-- Foo --> \n <!-- Bar --> " , " <root><comment><!-- Foo --></comment> \n <comment><!-- Bar --></comment></root> " ],
[ " <!-- Foo --> \n <!-- Bar --> \n " , " <root><comment><!-- Foo --></comment> \n <comment> <!-- Bar --> \n </comment></root> " ],
[ " <!-- Foo --> <!-- Bar --> \n " , " <root><comment><!-- Foo --></comment> <comment><!-- Bar --></comment> \n </root> " ],
[ " <!-->Bar " , " <root><comment><!-->Bar</comment></root> " ],
[ " <!-- Comment -- comment " , " <root><comment><!-- Comment -- comment</comment></root> " ],
[ " == Foo == \n <!-- Bar --> \n == Baz == \n " , " <root><h level= \" 2 \" i= \" 1 \" >== Foo ==</h> \n <comment> <!-- Bar --> \n </comment><h level= \" 2 \" i= \" 2 \" >== Baz ==</h> \n </root> " ],
[ " <gallery/> " , " <root><ext><name>gallery</name><attr></attr></ext></root> " ],
[ " Foo <gallery/> Bar " , " <root>Foo <ext><name>gallery</name><attr></attr></ext> Bar</root> " ],
[ " <gallery></gallery> " , " <root><ext><name>gallery</name><attr></attr><inner></inner><close></gallery></close></ext></root> " ],
[ " <foo> <gallery></gallery> " , " <root><foo> <ext><name>gallery</name><attr></attr><inner></inner><close></gallery></close></ext></root> " ],
[ " <foo> <gallery><gallery></gallery> " , " <root><foo> <ext><name>gallery</name><attr></attr><inner><gallery></inner><close></gallery></close></ext></root> " ],
[ " <noinclude> Foo bar </noinclude> " , " <root><ignore><noinclude></ignore> Foo bar <ignore></noinclude></ignore></root> " ],
[ " <noinclude> \n { { Foo}} \n </noinclude> " , " <root><ignore><noinclude></ignore> \n <template lineStart= \" 1 \" ><title>Foo</title></template> \n <ignore></noinclude></ignore></root> " ],
[ " <noinclude> \n { { Foo}} \n </noinclude> \n " , " <root><ignore><noinclude></ignore> \n <template lineStart= \" 1 \" ><title>Foo</title></template> \n <ignore></noinclude></ignore> \n </root> " ],
Preprocessor: Don't allow unclosed extension tags (matching until end of input)
(Previously done in f51d0d9a819f8f1c181350ced2f015ce97985fcc and
reverted in 543f46e9c08e0ff8c5e8b4e917fcc045730ef1bc.)
I think it's saner to treat this as invalid syntax, and output the
mismatched tag code verbatim. The current behavior is particularly
annoying for <ref> tags, which often swallow everything afterwards.
This does not affect HTML tags, though. Assuming Tidy is enabled, they
are still auto-closed at the end of the page content. (For tags that
"shadow" a HTML tag name, this results in the tag being treated as a
HTML tag. This currently only affects <pre> tags: if unclosed, they
are still displayed as preformatted text, but without suppressing
wikitext formatting.)
It also does not affect <includeonly>, <noinclude> and <onlyinclude>
tags. Changing this behavior now would be too disruptive to existing
content, and is the reason why previous attempt was reverted. (They
are already special-cased enough that this isn't too weird, for example
mismatched closing tags are hidden.)
Related to T17712 and T58306. I think this brings the PHP parser closer
to Parsoid's interpretation.
It reduces performance somewhat in the worst case, though. Testing with
https://phabricator.wikimedia.org/F3245989 (a 1 MB page starting with
3000 opening tags of 15 different types), parsing time rises from
~0.2 seconds to ~1.1 seconds on my setup. We go from O(N) to O(kN),
where N is bytes of input and k is the number of types of tags present
on the page. Maximum k shouldn't exceed 30 or so in reasonable setups
(depends on installed extensions, it's 20 on English Wikipedia).
Change-Id: Ide8b034e464eefb1b7c9e2a48ed06e21a7f8d434
2016-02-04 01:13:24 +00:00
[ " <gallery>foo bar " , " <root><gallery>foo bar</root> " ],
2016-03-19 01:05:19 +00:00
[ " < { { foo}}> " , " <root><<template><title>foo</title></template>></root> " ],
[ " < { { { foo}}}> " , " <root><<tplarg><title>foo</title></tplarg>></root> " ],
[ " <gallery></gallery</gallery> " , " <root><ext><name>gallery</name><attr></attr><inner></gallery</inner><close></gallery></close></ext></root> " ],
[ " === Foo === " , " <root><h level= \" 3 \" i= \" 1 \" >=== Foo === </h></root> " ],
[ " ==<!-- -->= Foo === " , " <root><h level= \" 2 \" i= \" 1 \" >==<comment><!-- --></comment>= Foo === </h></root> " ],
[ " === Foo ==<!-- -->= " , " <root><h level= \" 1 \" i= \" 1 \" >=== Foo ==<comment><!-- --></comment>= </h></root> " ],
[ " === Foo ===<!-- --> \n " , " <root><h level= \" 3 \" i= \" 1 \" >=== Foo ===<comment><!-- --></comment></h> \n </root> " ],
[ " === Foo ===<!-- --> <!-- --> \n " , " <root><h level= \" 3 \" i= \" 1 \" >=== Foo ===<comment><!-- --></comment> <comment><!-- --></comment></h> \n </root> " ],
[ " == Foo == \n == Bar == \n " , " <root><h level= \" 2 \" i= \" 1 \" >== Foo ==</h> \n <h level= \" 2 \" i= \" 2 \" >== Bar == </h> \n </root> " ],
[ " =========== " , " <root><h level= \" 5 \" i= \" 1 \" >===========</h></root> " ],
[ " Foo \n = \n == \n = \n " , " <root>Foo \n = \n == \n = \n </root> " ],
[ " { { Foo}} " , " <root><template><title>Foo</title></template></root> " ],
[ " \n { { Foo}} " , " <root> \n <template lineStart= \" 1 \" ><title>Foo</title></template></root> " ],
[ " { { Foo|bar}} " , " <root><template><title>Foo</title><part><name index= \" 1 \" /><value>bar</value></part></template></root> " ],
[ " { { Foo|bar}}a " , " <root><template><title>Foo</title><part><name index= \" 1 \" /><value>bar</value></part></template>a</root> " ],
[ " { { Foo|bar|baz}} " , " <root><template><title>Foo</title><part><name index= \" 1 \" /><value>bar</value></part><part><name index= \" 2 \" /><value>baz</value></part></template></root> " ],
[ " { { Foo|1=bar}} " , " <root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part></template></root> " ],
[ " { { Foo|=bar}} " , " <root><template><title>Foo</title><part><name></name>=<value>bar</value></part></template></root> " ],
[ " { { Foo|bar=baz}} " , " <root><template><title>Foo</title><part><name>bar</name>=<value>baz</value></part></template></root> " ],
[ " { { Foo| { { bar}}=baz}} " , " <root><template><title>Foo</title><part><name><template><title>bar</title></template></name>=<value>baz</value></part></template></root> " ],
[ " { { Foo|1=bar|baz}} " , " <root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name index= \" 1 \" /><value>baz</value></part></template></root> " ],
[ " { { Foo|1=bar|2=baz}} " , " <root><template><title>Foo</title><part><name>1</name>=<value>bar</value></part><part><name>2</name>=<value>baz</value></part></template></root> " ],
[ " { { Foo|bar|foo=baz}} " , " <root><template><title>Foo</title><part><name index= \" 1 \" /><value>bar</value></part><part><name>foo</name>=<value>baz</value></part></template></root> " ],
[ " { { { 1}}} " , " <root><tplarg><title>1</title></tplarg></root> " ],
[ " { { { 1|}}} " , " <root><tplarg><title>1</title><part><name index= \" 1 \" /><value></value></part></tplarg></root> " ],
[ " { { { Foo}}} " , " <root><tplarg><title>Foo</title></tplarg></root> " ],
[ " { { { Foo|}}} " , " <root><tplarg><title>Foo</title><part><name index= \" 1 \" /><value></value></part></tplarg></root> " ],
[ " { { { Foo|bar|baz}}} " , " <root><tplarg><title>Foo</title><part><name index= \" 1 \" /><value>bar</value></part><part><name index= \" 2 \" /><value>baz</value></part></tplarg></root> " ],
[ " { <!-- --> { Foo}} " , " <root> { <comment><!-- --></comment> { Foo}}</root> " ],
[ " { { { { Foobar}}}} " , " <root> { <tplarg><title>Foobar</title></tplarg>}</root> " ],
[ " { { { { { Foo}} }}} " , " <root><tplarg><title> <template><title>Foo</title></template> </title></tplarg></root> " ],
[ " { { { { { Foo}}} }} " , " <root><template><title> <tplarg><title>Foo</title></tplarg> </title></template></root> " ],
[ " { { { { { Foo}}}}} " , " <root><template><title><tplarg><title>Foo</title></tplarg></title></template></root> " ],
[ " { { { { { Foo}} }}} " , " <root><tplarg><title><template><title>Foo</title></template> </title></tplarg></root> " ],
[ " { { { { { { Foo}}}}}} " , " <root><tplarg><title><tplarg><title>Foo</title></tplarg></title></tplarg></root> " ],
[ " { { { { { { Foo}}}}} " , " <root> { <template><title><tplarg><title>Foo</title></tplarg></title></template></root> " ],
[ " [[[Foo]] " , " <root>[[[Foo]]</root> " ],
[ " { { Foo|[[[[bar]]|baz]]}} " , " <root><template><title>Foo</title><part><name index= \" 1 \" /><value>[[[[bar]]|baz]]</value></part></template></root> " ], // This test is important, since it means the difference between having the [[ rule stacked or not
[ " { { Foo|[[[[bar]|baz]]}} " , " <root> { { Foo|[[[[bar]|baz]]}}</root> " ],
[ " { { Foo|Foo [[[[bar]|baz]]}} " , " <root> { { Foo|Foo [[[[bar]|baz]]}}</root> " ],
[ " Foo <display map>Bar</display map >Baz " , " <root>Foo <ext><name>display map</name><attr></attr><inner>Bar</inner><close></display map ></close></ext>Baz</root> " ],
[ " Foo <display map foo>Bar</display map >Baz " , " <root>Foo <ext><name>display map</name><attr> foo</attr><inner>Bar</inner><close></display map ></close></ext>Baz</root> " ],
[ " Foo <gallery bar= \" baz \" /> " , " <root>Foo <ext><name>gallery</name><attr> bar="baz" </attr></ext></root> " ],
[ " Foo <gallery bar= \" 1 \" baz=2 /> " , " <root>Foo <ext><name>gallery</name><attr> bar="1" baz=2 </attr></ext></root> " ],
2021-03-29 04:21:28 +00:00
[ " </foo>Foo<//foo> " , " <root><ext><name>/foo</name><attr></attr><inner>Foo</inner><close><//foo></close></ext></root> " ], # Worth prohibiting IMHO
2016-03-19 01:05:19 +00:00
[ " { { #ifexpr: ( { { { 1|1}}} = 2) | Foo | Bar }} " , " <root><template><title>#ifexpr: (<tplarg><title>1</title><part><name index= \" 1 \" /><value>1</value></part></tplarg> = 2) </title><part><name index= \" 1 \" /><value> Foo </value></part><part><name index= \" 2 \" /><value> Bar </value></part></template></root> " ],
[ " { { #if: { { { 1|}}} | Foo | { { Bar}} }} " , " <root><template><title>#if: <tplarg><title>1</title><part><name index= \" 1 \" /><value></value></part></tplarg> </title><part><name index= \" 1 \" /><value> Foo </value></part><part><name index= \" 2 \" /><value> <template><title>Bar</title></template> </value></part></template></root> " ],
[ " { { #if: { { { 1|}}} | Foo | [[Bar]] }} " , " <root><template><title>#if: <tplarg><title>1</title><part><name index= \" 1 \" /><value></value></part></tplarg> </title><part><name index= \" 1 \" /><value> Foo </value></part><part><name index= \" 2 \" /><value> [[Bar]] </value></part></template></root> " ],
[ " { { #if: { { { 1|}}} | [[Foo]] | Bar }} " , " <root><template><title>#if: <tplarg><title>1</title><part><name index= \" 1 \" /><value></value></part></tplarg> </title><part><name index= \" 1 \" /><value> [[Foo]] </value></part><part><name index= \" 2 \" /><value> Bar </value></part></template></root> " ],
[ " { { #if: { { { 1|}}} | 1 | { { #if: { { { 1|}}} | 2 | 3 }} }} " , " <root><template><title>#if: <tplarg><title>1</title><part><name index= \" 1 \" /><value></value></part></tplarg> </title><part><name index= \" 1 \" /><value> 1 </value></part><part><name index= \" 2 \" /><value> <template><title>#if: <tplarg><title>1</title><part><name index= \" 1 \" /><value></value></part></tplarg> </title><part><name index= \" 1 \" /><value> 2 </value></part><part><name index= \" 2 \" /><value> 3 </value></part></template> </value></part></template></root> " ],
[ " { { { { Foo}} " , " <root> { { <template><title>Foo</title></template></root> " ],
[ " { { Foobar { { Foo}} { { Bar}} { { Baz}} " , " <root> { { Foobar <template><title>Foo</title></template> <template><title>Bar</title></template> <template><title>Baz</title></template> </root> " ],
[ " [[Foo]] | " , " <root>[[Foo]] |</root> " ],
[ " { { Foo|Bar| " , " <root> { { Foo|Bar|</root> " ],
[ " [[Foo] " , " <root>[[Foo]</root> " ],
[ " [[Foo|Bar] " , " <root>[[Foo|Bar]</root> " ],
[ " { { Foo| [[Bar] }} " , " <root> { { Foo| [[Bar] }}</root> " ],
[ " { { Foo| [[Bar|Baz] }} " , " <root> { { Foo| [[Bar|Baz] }}</root> " ],
[ " { { Foo|bar=[[baz]}} " , " <root> { { Foo|bar=[[baz]}}</root> " ],
[ " { { foo| " , " <root> { { foo|</root> " ],
[ " { { foo|} " , " <root> { { foo|}</root> " ],
[ " { { foo|} }} " , " <root><template><title>foo</title><part><name index= \" 1 \" /><value>} </value></part></template></root> " ],
[ " { { foo|bar=|} " , " <root> { { foo|bar=|}</root> " ],
[ " { { Foo|} Bar= " , " <root> { { Foo|} Bar=</root> " ],
[ " { { Foo|} Bar=}} " , " <root><template><title>Foo</title><part><name>} Bar</name>=<value></value></part></template></root> " ],
/* [ file_get_contents( __DIR__ . '/QuoteQuran.txt' ], file_get_contents( __DIR__ . '/QuoteQuranExpanded.txt' ) ], */
2020-04-07 23:52:41 +00:00
];
2018-01-01 13:10:16 +00:00
// phpcs:enable
2011-01-15 08:35:56 +00:00
}
2011-10-15 20:21:52 +00:00
/**
* Get XML preprocessor tree from the preprocessor ( which may not be the
* native XML - based one ) .
*
* @ param string $wikiText
* @ return string
*/
2020-04-07 23:52:41 +00:00
protected function preprocessToXml ( $wikiText ) {
$preprocessor = $this -> preprocessor ;
2016-08-25 03:17:13 +00:00
if ( method_exists ( $preprocessor , 'preprocessToXml' ) ) {
return $this -> normalizeXml ( $preprocessor -> preprocessToXml ( $wikiText ) );
2011-10-28 15:02:10 +00:00
}
2012-12-09 02:37:10 +00:00
2016-08-25 03:17:13 +00:00
$dom = $preprocessor -> preprocessToObj ( $wikiText );
2016-02-17 09:09:32 +00:00
if ( is_callable ( [ $dom , 'saveXML' ] ) ) {
2011-10-15 20:21:52 +00:00
return $dom -> saveXML ();
} else {
return $this -> normalizeXml ( $dom -> __toString () );
}
}
/**
* Normalize XML string to the form that a DOMDocument saves out .
*
* @ param string $xml
* @ return string
*/
2013-10-22 23:50:38 +00:00
protected function normalizeXml ( $xml ) {
2016-08-25 03:17:13 +00:00
// Normalize self-closing tags
$xml = preg_replace ( '!<([a-z]+)/>!' , '<$1></$1>' , str_replace ( ' />' , '/>' , $xml ) );
// Remove <equals> tags, which only occur in Preprocessor_Hash and
// have no semantic value
$xml = preg_replace ( '!</?equals>!' , '' , $xml );
return $xml ;
2011-10-15 20:21:52 +00:00
}
2011-01-15 08:35:56 +00:00
/**
* @ dataProvider provideCases
*/
2020-04-07 23:52:41 +00:00
public function testPreprocessorOutput ( $wikiText , $expectedXml ) {
$this -> assertEquals (
$this -> normalizeXml ( $expectedXml ),
$this -> preprocessToXml ( $wikiText )
);
2011-01-15 08:35:56 +00:00
}
2011-01-21 23:03:33 +00:00
/**
* These are more complex test cases taken out of wiki articles .
*/
2013-03-22 02:12:37 +00:00
public static function provideFiles () {
2018-01-01 13:10:16 +00:00
// phpcs:disable Generic.Files.LineLength
2020-04-07 23:52:41 +00:00
return [
2016-10-09 17:48:14 +00:00
[ " QuoteQuran " ], # https://en.wikipedia.org/w/index.php?title=Template:QuoteQuran/sandbox&oldid=237348988 GFDL + CC BY-SA by Striver
[ " Factorial " ], # https://en.wikipedia.org/w/index.php?title=Template:Factorial&oldid=98548758 GFDL + CC BY-SA by Polonium
[ " All_system_messages " ], # https://tl.wiktionary.org/w/index.php?title=Suleras:All_system_messages&oldid=2765 GPL text generated by MediaWiki
[ " Fundraising " ], # https://tl.wiktionary.org/w/index.php?title=MediaWiki:Sitenotice&oldid=5716 GFDL + CC BY-SA, copied there by Sky Harbor.
2017-02-20 23:45:58 +00:00
[ " NestedTemplates " ], # T29936
2020-04-07 23:52:41 +00:00
];
2018-01-01 13:10:16 +00:00
// phpcs:enable
2011-01-21 23:03:33 +00:00
}
/**
* @ dataProvider provideFiles
*/
2020-04-07 23:52:41 +00:00
public function testPreprocessorOutputFiles ( $filename ) {
2019-06-13 23:00:08 +00:00
$folder = __DIR__ . " /../../../parser/preprocess " ;
2011-01-21 23:03:33 +00:00
$wikiText = file_get_contents ( " $folder / $filename .txt " );
2020-04-07 23:52:41 +00:00
$output = $this -> preprocessToXml ( $wikiText );
2011-01-21 23:03:33 +00:00
$expectedFilename = " $folder / $filename .expected " ;
if ( file_exists ( $expectedFilename ) ) {
2011-10-15 20:21:52 +00:00
$expectedXml = $this -> normalizeXml ( file_get_contents ( $expectedFilename ) );
$this -> assertEquals ( $expectedXml , $output );
2011-01-21 23:03:33 +00:00
} else {
2011-04-23 21:18:50 +00:00
$tempFilename = tempnam ( $folder , " $filename . " );
file_put_contents ( $tempFilename , $output );
$this -> markTestIncomplete ( " File $expectedFilename missing. Output stored as $tempFilename " );
2011-01-21 23:03:33 +00:00
}
}
2011-05-01 21:33:16 +00:00
/**
2015-09-12 13:54:13 +00:00
* Tests from T30642 · https :// phabricator . wikimedia . org / T30642
2011-05-01 21:33:16 +00:00
*/
2013-03-22 02:12:37 +00:00
public static function provideHeadings () {
2018-01-01 13:10:16 +00:00
// phpcs:disable Generic.Files.LineLength
2020-04-07 23:52:41 +00:00
return [
2016-08-25 03:17:13 +00:00
/* These should become headings: */
2016-03-19 01:05:19 +00:00
[ " == h ==<!--c1--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment></h></root> " ],
[ " == h == <!--c1--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment></h></root> " ],
[ " == h ==<!--c1--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment> </h></root> " ],
[ " == h == <!--c1--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment> </h></root> " ],
[ " == h ==<!--c1--><!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment><comment><!--c2--></comment></h></root> " ],
[ " == h == <!--c1--><!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment><comment><!--c2--></comment></h></root> " ],
[ " == h ==<!--c1--><!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment><comment><!--c2--></comment> </h></root> " ],
[ " == h == <!--c1--><!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment><comment><!--c2--></comment> </h></root> " ],
[ " == h == <!--c1--> <!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment> <comment><!--c2--></comment></h></root> " ],
[ " == h ==<!--c1--> <!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment> <comment><!--c2--></comment> </h></root> " ],
[ " == h == <!--c1--> <!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment> <comment><!--c2--></comment> </h></root> " ],
[ " == h ==<!--c1--><!--c2--><!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment><comment><!--c2--></comment><comment><!--c3--></comment></h></root> " ],
[ " == h ==<!--c1--> <!--c2--><!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment> <comment><!--c2--></comment><comment><!--c3--></comment></h></root> " ],
[ " == h ==<!--c1--><!--c2--> <!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment><comment><!--c2--></comment> <comment><!--c3--></comment></h></root> " ],
[ " == h ==<!--c1--> <!--c2--> <!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment> <comment><!--c2--></comment> <comment><!--c3--></comment></h></root> " ],
[ " == h == <!--c1--><!--c2--><!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment><comment><!--c2--></comment><comment><!--c3--></comment></h></root> " ],
[ " == h == <!--c1--> <!--c2--><!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment> <comment><!--c2--></comment><comment><!--c3--></comment></h></root> " ],
[ " == h == <!--c1--><!--c2--> <!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment><comment><!--c2--></comment> <comment><!--c3--></comment></h></root> " ],
[ " == h == <!--c1--> <!--c2--> <!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment> <comment><!--c2--></comment> <comment><!--c3--></comment></h></root> " ],
[ " == h ==<!--c1--><!--c2--><!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment><comment><!--c2--></comment><comment><!--c3--></comment> </h></root> " ],
[ " == h ==<!--c1--> <!--c2--><!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment> <comment><!--c2--></comment><comment><!--c3--></comment> </h></root> " ],
[ " == h ==<!--c1--><!--c2--> <!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment><comment><!--c2--></comment> <comment><!--c3--></comment> </h></root> " ],
[ " == h ==<!--c1--> <!--c2--> <!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment> <comment><!--c2--></comment> <comment><!--c3--></comment> </h></root> " ],
[ " == h == <!--c1--><!--c2--><!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment><comment><!--c2--></comment><comment><!--c3--></comment> </h></root> " ],
[ " == h == <!--c1--> <!--c2--><!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment> <comment><!--c2--></comment><comment><!--c3--></comment> </h></root> " ],
[ " == h == <!--c1--><!--c2--> <!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment><comment><!--c2--></comment> <comment><!--c3--></comment> </h></root> " ],
[ " == h == <!--c1--> <!--c2--> <!--c3--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment> <comment><!--c2--></comment> <comment><!--c3--></comment> </h></root> " ],
[ " == h ==<!--c1--> <!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment> <comment><!--c2--></comment></h></root> " ],
[ " == h == <!--c1--> <!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h == <comment><!--c1--></comment> <comment><!--c2--></comment></h></root> " ],
[ " == h ==<!--c1--> <!--c2--> " , " <root><h level= \" 2 \" i= \" 1 \" >== h ==<comment><!--c1--></comment> <comment><!--c2--></comment> </h></root> " ],
2011-05-01 21:33:16 +00:00
/* These are not working: */
2016-03-19 01:05:19 +00:00
[ " == h == x <!--c1--><!--c2--><!--c3--> " , " <root>== h == x <comment><!--c1--></comment><comment><!--c2--></comment><comment><!--c3--></comment> </root> " ],
[ " == h ==<!--c1--> x <!--c2--><!--c3--> " , " <root>== h ==<comment><!--c1--></comment> x <comment><!--c2--></comment><comment><!--c3--></comment> </root> " ],
[ " == h ==<!--c1--><!--c2--><!--c3--> x " , " <root>== h ==<comment><!--c1--></comment><comment><!--c2--></comment><comment><!--c3--></comment> x </root> " ],
2020-04-07 23:52:41 +00:00
];
2018-01-01 13:10:16 +00:00
// phpcs:enable
2011-05-01 21:33:16 +00:00
}
/**
* @ dataProvider provideHeadings
*/
2020-04-07 23:52:41 +00:00
public function testHeadings ( $wikiText , $expectedXml ) {
$this -> assertEquals (
$this -> normalizeXml ( $expectedXml ),
$this -> preprocessToXml ( $wikiText )
);
2011-05-01 21:33:16 +00:00
}
2011-01-15 08:35:56 +00:00
}