jenkins-bot has submitted this change and it was merged.
Change subject: mediawiki.jqueryMsg: Refactor "Match PHP parser" test suite
......................................................................
mediawiki.jqueryMsg: Refactor "Match PHP parser" test suite
Previously it was doing quite a few things wrong:
* Tests could potentially run in parallel. This was somewhat
obscured by the asynchronous getMwLanguage() call being inside
the synchronous each() loop. As such it basically first fired off
the requests, and then handled them as they came back. They
pretty much always come back in order (lucky) so the tests pass,
but it was fragile.
* By default, jQuery.ajax() appends a cache buster ("&_{random}" query string)
to requests with dataType 'script'. Disable this by setting cache=true.
Also:
* Store Promise objects instead of a low-level Callbacks list so that we don't
have to wrap it. Instead, we simply chain from the $.ajax() promise, and use
then() to feed the value instead of calling resolve() or fire().
* Use hasOwn() as extra sanity check (in case a random browser's non-standard
Object.prototype methods match one of our non-standard language codes).
* Remove dead code "mw.messages.set( test.message )". This object has no message
property (or anything else that it could be mistaken for). It just performs
15 no-op in a loop. Follows-up 261aac63ec0777d6.
While the requests happen to (almost) always arrive in order, them running in
parallel put a lot of pressure on slow VMs using SQLite databases (which are
I/O bound). This causes a lock when queries from different processes overlap.
Change-Id: I0c5064780f80e1ddcc58ce32c390b2639b1f1ab6
---
M tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
1 file changed, 90 insertions(+), 62 deletions(-)
Approvals:
Fomafix: Looks good to me, but someone else must approve
Bartosz Dziewoński: Looks good to me, approved
jenkins-bot: Verified
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
b/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
index 28d6d92..1fb1723 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.jqueryMsg.test.js
@@ -1,6 +1,7 @@
( function ( mw, $ ) {
- var mwLanguageCache = {}, formatText, formatParse, formatnumTests,
specialCharactersPageName,
- expectedListUsers, expectedEntrypoints;
+ var formatText, formatParse, formatnumTests, specialCharactersPageName,
expectedListUsers, expectedEntrypoints,
+ mwLanguageCache = {},
+ hasOwn = Object.hasOwnProperty;
// When the expected result is the same in both modes
function assertBothModes( assert, parserArguments, expectedResult,
assertMessage ) {
@@ -60,31 +61,52 @@
}
} ) );
- function getMwLanguage( langCode, cb ) {
- if ( mwLanguageCache[langCode] !== undefined ) {
- mwLanguageCache[langCode].add( cb );
- return;
- }
- mwLanguageCache[langCode] = $.Callbacks( 'once memory' );
- mwLanguageCache[langCode].add( cb );
- $.ajax( {
- url: mw.util.wikiScript( 'load' ),
- data: {
- skin: mw.config.get( 'skin' ),
- lang: langCode,
- debug: mw.config.get( 'debug' ),
- modules: [
- 'mediawiki.language.data',
- 'mediawiki.language'
- ].join( '|' ),
- only: 'scripts'
- },
- dataType: 'script'
- } ).done( function () {
- mwLanguageCache[langCode].fire( mw.language );
- } ).fail( function () {
- mwLanguageCache[langCode].fire( false );
+ /**
+ * Be careful to no run this in parallel as it uses a global identifier
(mw.language)
+ * to transport the module back to the test. It musn't be overwritten
concurrentely.
+ *
+ * This function caches the mw.language data to avoid having to request
the same module
+ * multiple times. There is more than one test case for any given
language.
+ */
+ function getMwLanguage( langCode ) {
+ if ( !hasOwn.call( mwLanguageCache, langCode ) ) {
+ mwLanguageCache[langCode] = $.ajax( {
+ url: mw.util.wikiScript( 'load' ),
+ data: {
+ skin: mw.config.get( 'skin' ),
+ lang: langCode,
+ debug: mw.config.get( 'debug' ),
+ modules: [
+ 'mediawiki.language.data',
+ 'mediawiki.language'
+ ].join( '|' ),
+ only: 'scripts'
+ },
+ dataType: 'script',
+ cache: true
+ } ).then( function () {
+ return mw.language;
} );
+ }
+ return mwLanguageCache[langCode];
+ }
+
+ /**
+ * @param {Function[]} tasks List of functions that perform tasks
+ * that may be asynchronous. Invoke the callback parameter when done.
+ * @param {Function} done When all tasks are done.
+ * @return
+ */
+ function process( tasks, done ) {
+ function run() {
+ var task = tasks.shift();
+ if ( task ) {
+ task( run );
+ } else {
+ done();
+ }
+ }
+ run();
}
QUnit.test( 'Replace', 16, function ( assert ) {
@@ -283,23 +305,27 @@
QUnit.test( 'Match PHP parser', mw.libs.phpParserData.tests.length,
function ( assert ) {
mw.messages.set( mw.libs.phpParserData.messages );
- $.each( mw.libs.phpParserData.tests, function ( i, test ) {
- QUnit.stop();
- getMwLanguage( test.lang, function ( langClass ) {
- QUnit.start();
- if ( !langClass ) {
- assert.ok( false, 'Language "' +
test.lang + '" failed to load' );
- return;
- }
- mw.config.set( 'wgUserLanguage', test.lang );
- var parser = new mw.jqueryMsg.parser( {
language: langClass } );
- assert.equal(
- parser.parse( test.key, test.args
).html(),
- test.result,
- test.name
- );
- } );
+ var tasks = $.map( mw.libs.phpParserData.tests, function ( test
) {
+ return function ( next ) {
+ getMwLanguage( test.lang )
+ .done( function ( langClass ) {
+ mw.config.set(
'wgUserLanguage', test.lang );
+ var parser = new
mw.jqueryMsg.parser( { language: langClass } );
+ assert.equal(
+ parser.parse( test.key,
test.args ).html(),
+ test.result,
+ test.name
+ );
+ } )
+ .fail( function () {
+ assert.ok( false, 'Language "'
+ test.lang + '" failed to load.' );
+ } )
+ .always( next );
+ };
} );
+
+ QUnit.stop();
+ process( tasks, QUnit.start );
} );
QUnit.test( 'Links', 6, function ( assert ) {
@@ -466,8 +492,8 @@
);
} );
-// Tests that getMessageFunction is used for non-plain messages with curly
braces or
-// square brackets, but not otherwise.
+ // Tests that getMessageFunction is used for non-plain messages with
curly braces or
+ // square brackets, but not otherwise.
QUnit.test( 'mw.Message.prototype.parser monkey-patch', 22, function (
assert ) {
var oldGMF, outerCalled, innerCalled;
@@ -618,25 +644,27 @@
QUnit.test( 'formatnum', formatnumTests.length, function ( assert ) {
mw.messages.set( 'formatnum-msg', '{{formatnum:$1}}' );
mw.messages.set( 'formatnum-msg-int', '{{formatnum:$1|R}}' );
- $.each( formatnumTests, function ( i, test ) {
- QUnit.stop();
- getMwLanguage( test.lang, function ( langClass ) {
- QUnit.start();
- if ( !langClass ) {
- assert.ok( false, 'Language "' + test.lang + '"
failed to load' );
- return;
- }
- mw.messages.set(test.message );
- mw.config.set( 'wgUserLanguage', test.lang );
- var parser = new mw.jqueryMsg.parser( { language:
langClass } );
- assert.equal(
- parser.parse( test.integer ?
'formatnum-msg-int' : 'formatnum-msg',
- [ test.number ] ).html(),
- test.result,
- test.description
- );
- } );
+ var queue = $.map( formatnumTests, function ( test ) {
+ return function ( next ) {
+ getMwLanguage( test.lang )
+ .done( function ( langClass ) {
+ mw.config.set( 'wgUserLanguage',
test.lang );
+ var parser = new mw.jqueryMsg.parser( {
language: langClass } );
+ assert.equal(
+ parser.parse( test.integer ?
'formatnum-msg-int' : 'formatnum-msg',
+ [ test.number ]
).html(),
+ test.result,
+ test.description
+ );
+ } )
+ .fail( function () {
+ assert.ok( false, 'Language "' +
test.lang + '" failed to load' );
+ } )
+ .always( next );
+ };
} );
+ QUnit.stop();
+ process( queue, QUnit.start );
} );
// HTML in wikitext
--
To view, visit https://gerrit.wikimedia.org/r/190154
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I0c5064780f80e1ddcc58ce32c390b2639b1f1ab6
Gerrit-PatchSet: 3
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Krinkle <[email protected]>
Gerrit-Reviewer: Alex Monk <[email protected]>
Gerrit-Reviewer: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Fomafix
Gerrit-Reviewer: Krinkle <[email protected]>
Gerrit-Reviewer: Mattflaschen <[email protected]>
Gerrit-Reviewer: Ori.livneh <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits