The current tests in testGetPluralFormat()
do test the plural evaluator. But since the code is fairly complex, it can use some additional test. Below is the code I have used to manually test the code during development. It can be used to create additional test. Take a few complex formula's and compare the evaluatePlural() result with the computed result. Of course instead of eval() the test should use hardcoded formula's
<?php
Drupal::state()->delete('locale.translation.plurals');
$plurals[0] = 'nplurals=1; plural=0;';
$eval_plural[0] = '(0)';
$plurals[1] = 'nplurals=2; plural=(n > 1);';
$eval_plural[1] = '(n > 1)';
$plurals[2] = 'nplurals=2; plural=(n!=1);';
$eval_plural[2] = 'n!=1';
$plurals[3] = 'nplurals=2; plural=(((n==1)||((n%10)==1))?(0):1);';
$eval_plural[3] = '(((n==1)||((n%10)==1))?(0):1)';
$plurals[4] = 'nplurals=3; plural=((((n%10)==1)&&((n%100)!=11))?(0):(((((n%10)>=2)&&((n%10)<=4))&&(((n%100)<10)||((n%100)>=20)))?(1):2));';
$eval_plural[4] = '((((n%10)==1)&&((n%100)!=11))?(0):(((((n%10)>=2)&&((n%10)<=4))&&(((n%100)<10)||((n%100)>=20)))?(1):2))';
$plurals[5] = 'nplurals=3; plural=((n==1)?(0):(((n>=2)&&(n<=4))?(1):2));';
$eval_plural[5] = '((n==1)?(0):(((n>=2)&&(n<=4))?(1):2))';
$plurals[6] = 'nplurals=3; plural=((n==1)?(0):(((n==0)||(((n%100)>0)&&((n%100)<20)))?(1):2));';
$eval_plural[6] = '((n==1)?(0):(((n==0)||(((n%100)>0)&&((n%100)<20)))?(1):2))';
$plurals[7] = 'nplurals=3; plural=((n==1)?(0):(((((n%10)>=2)&&((n%10)<=4))&&(((n%100)<10)||((n%100)>=20)))?(1):2));';
$eval_plural[7] = '((n==1)?(0):(((((n%10)>=2)&&((n%10)<=4))&&(((n%100)<10)||((n%100)>=20)))?(1):2))';
$plurals[8] = 'nplurals=4; plural=(((n==1)||(n==11))?(0):(((n==2)||(n==12))?(1):(((n>2)&&(n<20))?(2):3)));';
$eval_plural[8] = '(((n==1)||(n==11))?(0):(((n==2)||(n==12))?(1):(((n>2)&&(n<20))?(2):3)))';
$plurals[9] = 'nplurals=4; plural=(((n%100)==1)?(0):(((n%100)==2)?(1):((((n%100)==3)||((n%100)==4))?(2):3)));';
$eval_plural[9] = '(((n%100)==1)?(0):(((n%100)==2)?(1):((((n%100)==3)||((n%100)==4))?(2):3)))';
$plurals[10] = 'nplurals=5; plural=((n==1)?(0):((n==2)?(1):((n<7)?(2):((n<11)?(3):4))));';
$eval_plural[10] = '((n==1)?(0):((n==2)?(1):((n<7)?(2):((n<11)?(3):4))))';
$plurals[11] = 'nplurals=6; plural=((n==1)?(0):((n==0)?(1):((n==2)?(2):((((n%100)>=3)&&((n%100)<=10))?(3):((((n%100)>=11)&&((n%100)<=99))?(4):5)))));';
$eval_plural[11] = '((n==1)?(0):((n==0)?(1):((n==2)?(2):((((n%100)>=3)&&((n%100)<=10))?(3):((((n%100)>=11)&&((n%100)<=99))?(4):5)))))';
$fault = FALSE;
for ($i=0; $i < count($eval_plural); $i++) {
if (!isset($plurals[$i])) continue;
$p = new Drupal\Component\Gettext\PoHeader;
$parsed = $p->parsePluralForms($plurals[$i]);
list($nplurals, $new_plural) = $parsed;
for ($n = 0; $n <= 199; $n++) {
$new_plural_n = isset($new_plural[$n]) ? $new_plural[$n] : $new_plural['default'];
$formula = strtr($eval_plural[$i], array('n' => $n));
$old_plural[$n] = @eval('return intval(' . $formula . ');');
if ((int)$old_plural[$n] != (int)$new_plural_n) {
debug('Difference found at ' . $n . ': ' . $old_plural[$n] . ' versus ' . $new_plural_n);
$fault = TRUE;
}
}
}
if (!$fault) {
debug ('All is well that ends well!');
}
Comment | File | Size | Author |
---|---|---|---|
#30 | interdiff_18.txt | 11.55 KB | Mile23 |
#30 | 2031441-30.patch | 8.67 KB | Mile23 |
#18 | interdiff.txt | 1.3 KB | penyaskito |
#18 | plurals-test-2031441-18.patch | 5.89 KB | penyaskito |
#15 | plurals-test-2031441-15.patch | 5.85 KB | DuaelFr |
Comments
Comment #1
penyaskitoCreated a unittest (phpUnit) with the code above. Still using eval().
To run tests, change into the core directory and then run ./vendor/bin/phpunit --group Gettext.
Comment #2
dawehnerOOOH We should add this in other tests as well. That is cool!
It seems to be a perfect candidate for using dataProviders. Have a look at some "@dataProvider" tags in other core tests.
Comment #3
penyaskito@dawehner, Yes, I started this patch because I wanted to play with @dataprovider :_D
I'm curious if anywhere else we are using an external datasource like csv file, and if it would make sense here.
Pending tasks are:
Comment #4
penyaskitoAssign to me.
Comment #5
dawehnerAll our current data providers use just php directly.
Comment #6
penyaskitoAdded dataprovider method, this is fun stuff :-)
For avoiding eval and hardcoding expected values, we must return arrays with 199 elements.
How could we make that legible? No idea.
Comment #7
Sutharsan CreditAttribution: Sutharsan commentedThere is no need to get all 199 values. You can either only test the retured values or use the default as in locale_get_plural().
and/or you can call each function with a number of random values.
Comment #8
penyaskitoChatted about this with chx and dawehner, and I didn't fully understand this, now I think I do.
This patch adds really long lines for the expected array, but I think in this case is acceptable.
This makes 265 assertions instead of 2400.
Comment #9
penyaskitoImproved docblocks per chx suggestion.
Comment #10
penyaskitoTagging.
Comment #11
Gábor HojtsyAdd tag.
Comment #12
dawehnerI really like the new approach!
The first description should just be one line, try to truncate it to below 80 chars.
After that the coding style forces you to make an emptyu line.
Comment #13
dawehner.
Comment #14
penyaskitoUnassigning and tagging with novice, only #12 is pending and I cannot find the time at the moment.
Comment #15
DuaelFrComment #16
dawehnerThis is nearly perfect.
Let's put an empty line here between.
Comment #17
Gábor HojtsyComment #18
penyaskitoI found some other missing blank lines according to our standards. Also corrected one function comment to a single line.
Comment #19
dawehnerThere is wrong indentation in quite some docs (sorry I can't use dreditor at the moment).
Comment #20
Mile23I found that #18 applies cleanly, but then has one error and fails all the tests. This is with PHP 5.3.14 and 5.4.4.
I get this error:
I'd guess that arises out of line 46:
$result = isset($new_plural[$number]) ? $new_plural[$number] : $new_plural['default'];
Comment #21
Mile23Hmm. Tag craziness.
Comment #22
Gábor Hojtsy#18: plurals-test-2031441-18.patch queued for re-testing.
Comment #23
penyaskitoThis fails because depends on #1273968: remove eval from locale.module which was reverted because of the js issue.
Comment #24
Gábor HojtsyRemove from sprint, since that one is not on sprint either. Let's focus on our several outstanding major and critical tasks!
Comment #25
YesCT CreditAttribution: YesCT commentedtag was stuck. trying again to remove sprint tag.
Comment #27
penyaskitoRetesting #18, as the blocker issue was fixed.
Comment #28
penyaskitoComment #29
penyaskitoThere are not novice tasks here anymore.
Comment #30
Mile23Removed getInfo() as per: https://www.drupal.org/node/2301125
A ton of coding standards reformatting.
Renamed dataprovider to providerTestPluralsFormula().
Comment #31
Gábor HojtsyYay thanks! It is always sad to see patches in limbo for code style but then again we like looking at code we can discern :D
Comment #32
alexpottCommitted e665794 and pushed to 8.x. Thanks!
Comment #33
penyaskitoThanks!