comment nous avons vérifié 1 112 064 caractères
· l'équipe lowercase.fr
quand nous avons publié @lowercase-fr/tolower, nous voulions écrire une seule phrase dans le readme : exactement comme l'api de lowercase.fr. pour l'écrire honnêtement, il fallait la prouver. nous avons donc testé tous les caractères qui existent.
combien de caractères ?
unicode définit 1 114 112 points de code, de U+0000 à U+10FFFF. on retire les 2 048 surrogates (U+D800 à U+DFFF), qui ne sont pas des caractères mais des moitiés de caractères en utf-16. il en reste 1 112 064. c'est notre univers.
la méthode
le principe tient en trois étapes.
- côté go, un petit programme parcourt les 1 112 064 points de code. pour chacun, il écrit
strings.ToLowerdans un fichier json, ce qui donne la vérité de référence, celle de l'api. - côté node, un script relit ce fichier et appelle
tolower()sur chaque point de code, puis compare. - en contexte, parce que certaines règles dépendent des voisins (le sigma final, justement), chaque caractère est aussi testé au milieu d'un mot, entouré de lettres.
une seule différence suffit à faire échouer la comparaison.
ce que nous avons trouvé
comparé à un simple toLowerCase(), les différences se rangent en trois familles, pas une de plus :
Σen fin de mot (sigma final), qui n'apparaît qu'en contexte ;İ, qui devient deux caractères en javascript ;- 55 majuscules introduites par unicode 16 et 17, que go 1.26 (unicode 15) ne connaît pas encore.
le paquet traite ces trois familles explicitement. deuxième exécution, entre go 1.26.2 et node 24.15 : 0 différence, seul ou en contexte.
garder la preuve vivante
une vérification faite une fois ne vaut pas grand-chose : go et node évoluent. nous avons donc mis en place trois garde-fous.
- le script est versionné dans le dépôt de lowercase.fr (
packages/tolower/scripts/unicode-sweep), et n'importe qui peut le relancer. - des fixtures partagées : les cas sensibles sont dans un fichier json lu à la fois par les tests javascript du paquet et par un test go du backend. si l'un des deux moteurs change, un test casse.
- un signal de mise à jour : le jour où go adoptera unicode 16, le test go échouera sur les 55 lettres. c'est le moment de raccourcir la liste dans le paquet et de publier une nouvelle version.
ce que nous ne vérifions pas
par honnêteté :
- une chaîne javascript peut contenir un surrogate isolé, une moitié d'emoji.
tolower()le laisse tel quel. envoyé à l'api en json, il devient U+FFFD (�). c'est une limite de json, pas du moteur ; - nous comparons à la version de go qui fait tourner l'api, pas à toutes les versions de go ;
- le balayage tourne sur une version précise de node. sur un moteur javascript plus ancien, les tables unicode diffèrent. c'est précisément pour ça que le paquet existe.
la leçon
« mettre en minuscules » n'est pas une opération universelle : c'est une convention, et chaque langage a la sienne. si deux systèmes doivent être d'accord, ne le supposez pas : mesurez-le.
nous, on a mesuré 1 112 064 fois.