Add Full-Coverage Test TexVC-MMLGeneration for Mathoid-LateXML

* Implemented multiple-column generation for the HTML-Generator
* Items can be skipped in test by defining index

Bug: T327386
Change-Id: I13148d58246ddcc1f2e6dcd14fa5b4255a1fb8e7
This commit is contained in:
Stegmujo 2023-01-20 15:48:41 +01:00
parent 8ca418578c
commit ada1d6e3db
No known key found for this signature in database
GPG key ID: BB616B7CC84186BE
6 changed files with 4437 additions and 66 deletions

View file

@ -0,0 +1,123 @@
<?php
namespace MediaWiki\Extension\Math\TexVC;
use InvalidArgumentException;
use MediaWiki\Extension\Math\TexVC\MMLmappings\Util\MMLTestUtil;
use MediaWiki\Extension\Math\TexVC\MMLmappings\Util\MMLTestUtilHTML;
use MediaWikiUnitTestCase;
/**
* This is a test which checks the TexVC (LaTeX to MathML) converter capabilities
* It uses the Full-Coverage definition of tests from:
* https://www.mediawiki.org/wiki/Extension:Math/CoverageTest
*
* The json test-files for this can be updated with:
* 'MathSearch-Extension/maintenance/UpdateMath.php --mode mathml --exportmml /var/www/html/extensions/MathSearch'
*
* WIP:
* Currently this is just checking that texVC can generate MathML
* for the specified tests, not how the MathML looks like.
*
* @covers \MediaWiki\Extension\Math\TexVC\TexVC
* @group stub
*/
final class MMLFullCoverageTest extends MediaWikiUnitTestCase {
private static $FILENAMELATEXML = __DIR__ . "/mmlRes-latexml-FullCoverage.json";
private static $FILENAMEMATHOID = __DIR__ . "/mmlRes-mathml-FullCoverage.json";
private static $APPLYFILTER = false;
private static $FILTERSTART = 0;
private static $FILTERLENGTH = 60;
private static $GENERATEHTML = true;
private static $GENERATEDHTMLFILE = __DIR__ . "/MMLFullCoverageTest-Output.html";
private static $SKIPPEDINDICES = [ 0,58, 380, 388 ];
private static $FILTERMML = true;
public static function setUpBeforeClass(): void {
MMLTestUtilHTML::generateHTMLstart( self::$GENERATEDHTMLFILE, [ "name","TeX-Input","MathML(LaTeXML)",
"MathML(Mathoid)", "MathML(TexVC)" ], self::$GENERATEHTML );
}
public static function tearDownAfterClass(): void {
MMLTestUtilHTML::generateHTMLEnd( self::$GENERATEDHTMLFILE, self::$GENERATEHTML );
}
/**
* @dataProvider provideTestCases
*/
public function testTexVC( $title, $tc ) {
$texVC = new TexVC();
if ( in_array( $tc->ctr, self::$SKIPPEDINDICES ) ) {
MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, [ $tc->ctr, $tc->tex,
"skipped", "skipped", "skipped" ], false, self::$GENERATEHTML );
$this->assertTrue( true );
return;
}
# Fetch result from TexVC(PHP)
$resultT = $texVC->check( $tc->tex, [
'debug' => false,
'usemathrm' => $tc->usemathrm ?? false,
'oldtexvc' => $tc->oldtexvc ?? false
] );
$mml_latexml = self::$FILTERMML ? self::loadXMLandDeleteAttrs( $tc->mml_latexml ) : $tc->mml_latexml;
$mathMLtexVC = MMLTestUtil::getMMLwrapped( $resultT["input"] );
MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, [ $tc->ctr, $tc->tex, $mml_latexml,
$tc->mml_mathoid, $mathMLtexVC ], false, self::$GENERATEHTML );
$this->assertTrue( true );
}
/**
* Deletes some attributes from the mathml which are not necessary for comparisons.
* @param string $mml mathml as string
* @return bool|string false if problem, mathml as xml string without the specified attributes if ok
*/
public static function loadXMLandDeleteAttrs( $mml ) {
$xml = simplexml_load_string( $mml );
self::unsetAttrs( $xml );
// Recursive call deleting attributes
self::deleteAttributes( $xml );
return $xml->asXML();
}
public static function deleteAttributes( &$xml ) {
foreach ( $xml as $node ) {
self::unsetAttrs( $node );
self::deleteAttributes( $node );
}
}
public static function unsetAttrs( $node ): void {
$attrs = $node->attributes();
unset( $attrs['id'] );
unset( $attrs['xref'] );
}
public static function provideTestCases() {
$resMathoid = MMLTestUtil::getJSON( self::$FILENAMEMATHOID );
$resLaTeXML = MMLTestUtil::getJSON( self::$FILENAMELATEXML );
if ( count( $resMathoid ) != count( $resLaTeXML ) ) {
throw new InvalidArgumentException( "Test files dont have the same number of entries." );
}
$f = [];
// Adding running indices for location of tests.
foreach ( $resMathoid as $index => $tcMathoid ) {
$tcLaTeXML = $resLaTeXML[$index];
$tc = [
"ctr" => $index,
"tex" => $tcMathoid->tex,
"type" => $tcMathoid->type,
"mml_mathoid" => $tcMathoid->mml,
"mml_latexml" => $tcLaTeXML->mml,
];
array_push( $f, [ "title N/A", (object)$tc ] );
}
// Filtering results by index if necessary
if ( self::$APPLYFILTER ) {
$f = array_slice( $f, self::$FILTERSTART, self::$FILTERLENGTH );
}
return $f;
}
}

View file

@ -156,12 +156,12 @@ class MMLGenerationTest extends MediaWikiUnitTestCase {
$resMML3latexml = $mmlLatexML[$input] ?? "merror"; $resMML3latexml = $mmlLatexML[$input] ?? "merror";
if ( str_contains( $resMML3latexml, "merror" ) ) { if ( str_contains( $resMML3latexml, "merror" ) ) {
$errorMessage = "Error Rendering in MathJax"; $errorMessage = "Error Rendering in MathJax";
MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, $title, $input, $errorMessage, MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, [ $title, $input, $errorMessage,
$mathMLtexVC, false, self::$GENERATEHTML ); $mathMLtexVC ], false, self::$GENERATEHTML );
$this->assertTrue( true ); $this->assertTrue( true );
} else { } else {
MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, $title, $input, $resMML3latexml, MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, [ $title, $input, $resMML3latexml,
$mathMLtexVC, false, self::$GENERATEHTML ); $mathMLtexVC ], false, self::$GENERATEHTML );
$resMML3latexml = $resMML3latexml ?: "<math> no MML3 from Lookup </math>"; $resMML3latexml = $resMML3latexml ?: "<math> no MML3 from Lookup </math>";
if ( !self::$SKIPXMLVALIDATION ) { if ( !self::$SKIPXMLVALIDATION ) {
$this->assertXmlStringEqualsXmlString( $resMML3latexml, $mathMLtexVC ); $this->assertXmlStringEqualsXmlString( $resMML3latexml, $mathMLtexVC );
@ -172,7 +172,8 @@ class MMLGenerationTest extends MediaWikiUnitTestCase {
} }
public static function setUpBeforeClass(): void { public static function setUpBeforeClass(): void {
MMLTestUtilHTML::generateHTMLstart( self::$GENERATEDHTMLFILE, "MathML(MathJax3)", self::$GENERATEHTML ); MMLTestUtilHTML::generateHTMLstart( self::$GENERATEDHTMLFILE, [ "name","Tex-Input",
"MathML(MathJax3)","MathML(TexVC)" ], self::$GENERATEHTML );
} }
public static function tearDownAfterClass(): void { public static function tearDownAfterClass(): void {

View file

@ -22,7 +22,7 @@ final class MMLGenerationTest2 extends MediaWikiUnitTestCase {
private static $FILTERSTART = 0; private static $FILTERSTART = 0;
private static $FILTERLENGTH = 1; private static $FILTERLENGTH = 1;
private static $GENERATEHTML = true; private static $GENERATEHTML = false;
private static $GENERATEDHTMLFILE = __DIR__ . "/MMLGenerationTest2-Output.html"; private static $GENERATEDHTMLFILE = __DIR__ . "/MMLGenerationTest2-Output.html";
protected function setUp(): void { protected function setUp(): void {
@ -34,7 +34,8 @@ final class MMLGenerationTest2 extends MediaWikiUnitTestCase {
} }
public static function setUpBeforeClass(): void { public static function setUpBeforeClass(): void {
MMLTestUtilHTML::generateHTMLstart( self::$GENERATEDHTMLFILE, self::$GENERATEHTML ); MMLTestUtilHTML::generateHTMLstart( self::$GENERATEDHTMLFILE, [ "name","Tex-Input",
"MathML(MathJax3)","MathML(TexVC)" ], self::$GENERATEHTML );
} }
public static function tearDownAfterClass(): void { public static function tearDownAfterClass(): void {
@ -48,8 +49,8 @@ final class MMLGenerationTest2 extends MediaWikiUnitTestCase {
$texVC = new TexVC(); $texVC = new TexVC();
if ( $tc->skipped ?? false ) { if ( $tc->skipped ?? false ) {
MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, $tc->ctr, $tc->input, MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, [ $tc->ctr, $tc->input,
"skipped", "skipped", false, self::$GENERATEHTML ); "skipped", "skipped" ], false, self::$GENERATEHTML );
$this->assertTrue( true ); $this->assertTrue( true );
return; return;
} }
@ -60,8 +61,8 @@ final class MMLGenerationTest2 extends MediaWikiUnitTestCase {
'oldtexvc' => $tc->oldtexvc ?? false 'oldtexvc' => $tc->oldtexvc ?? false
] ); ] );
$mathMLtexVC = MMLTestUtil::getMMLwrapped( $resultT["input"] ); $mathMLtexVC = MMLTestUtil::getMMLwrapped( $resultT["input"] );
MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, $tc->ctr, $tc->input, "tbd", MMLTestUtilHTML::generateHTMLtableRow( self::$GENERATEDHTMLFILE, [ $tc->ctr, $tc->input, "tbd",
$mathMLtexVC, false, self::$GENERATEHTML ); $mathMLtexVC ], false, self::$GENERATEHTML );
$this->assertTrue( true ); $this->assertTrue( true );
} }

View file

@ -27,78 +27,80 @@ class MMLTestUtilHTML {
fclose( $file ); fclose( $file );
} }
public static function generateHTMLtableRow( $filePath, $id, $inputTex, $mmlMj3, $mmlGen, public static function generateHTMLtableRow( $filePath, $rows, $bold = false, $active = true ) {
$bold = false, $active = true ) {
if ( !$active ) { if ( !$active ) {
return; return;
} }
$file = fopen( $filePath, 'a' ); $file = fopen( $filePath, 'a' );
$stringData = "<tr>" $stringData = "<tr>";
. self::generateHTMLtableItem( $id, $bold ) foreach ( $rows as $row ) {
. self::generateHTMLtableItem( $inputTex, $bold ) $stringData .= self::generateHTMLtableItem( $row, $bold );
. self::generateHTMLtableItem( $mmlMj3, $bold ) }
. self::generateHTMLtableItem( $mmlGen, $bold ) . $stringData .= "</tr>";
"</tr>";
fwrite( $file, $stringData ); fwrite( $file, $stringData );
fclose( $file ); // tbd only open close once for all tests fclose( $file ); // tbd only open close once for all tests
} }
public static function generateHTMLstart( $filePath, $name, $active = true ) { public static function generateHTMLstart( $filePath, $headrows = [ "name","Tex-Input",
"MathML(MathJax3)","MathML(TexVC)" ], $active = true ) {
if ( !$active ) { if ( !$active ) {
return; return;
} }
$htmlRows = "";
foreach ( $headrows as $header ) {
$htmlRows .= "<th class=\"tg-0lax\"><b>" . $header . "</b></th>";
}
$file = fopen( $filePath, 'w' ); // or die("error"); $file = fopen( $filePath, 'w' ); // or die("error");
$stringData = /** @lang HTML */ $stringData = /** @lang HTML */
<<<HTML <<<HTML
<style> <!DOCTYPE html>
.tg { <html lang="en">
border-collapse: collapse; <head>
border-spacing: 0; <meta charset="utf-8">
} </head>
<style>
.tg td { .tg {
border-color: black; border-collapse: collapse;
border-style: solid; border-spacing: 0;
border-width: 1px; }
font-family: Arial, sans-serif; .tg td {
font-size: 14px; border-color: black;
overflow: hidden; border-style: solid;
padding: 10px 5px; border-width: 1px;
word-break: normal; font-family: Arial, sans-serif;
} font-size: 14px;
overflow: hidden;
.tg th { padding: 10px 5px;
border-color: black; word-break: normal;
border-style: solid; }
border-width: 1px; .tg th {
font-family: Arial, border-color: black;
sans-serif; border-style: solid;
font-size: 14px; border-width: 1px;
font-weight: normal; font-family: Arial,
overflow: hidden; sans-serif;
padding: 10px 5px; font-size: 14px;
word-break: normal; font-weight: normal;
} overflow: hidden;
padding: 10px 5px;
.tg .tg-0lax { word-break: normal;
text-align: left; }
vertical-align: top .tg .tg-0lax {
} text-align: left;
</style> vertical-align: top
<table class="tg"> }
<thead> </style>
<tr> <table class="tg">
<th class="tg-0lax"><b>name</b></th> <thead>
<th class="tg-0lax"><b>Tex-Input</b></th> <tr>{$htmlRows}</tr>
<th class="tg-0lax"><b>MathML(MathJax3)</b></th> </thead>
<th class="tg-0lax"><b>MathML(TexVC)</b></th> <tbody>
</tr> HTML;
</thead>
<tbody>
HTML;
fwrite( $file, $stringData ); fwrite( $file, $stringData );
fclose( $file ); fclose( $file );
} }

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff