11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst assert = require('assert');
41cb0ef41Sopenharmony_ciconst { execFileSync } = require('child_process');
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci// system-icu should not be tested
71cb0ef41Sopenharmony_ciconst hasBuiltinICU = process.config.variables.icu_gyp_path === 'tools/icu/icu-generic.gyp';
81cb0ef41Sopenharmony_ciif (!hasBuiltinICU)
91cb0ef41Sopenharmony_ci  common.skip('system ICU');
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci// small-icu doesn't support non-English locales
121cb0ef41Sopenharmony_ciconst hasFullICU = (() => {
131cb0ef41Sopenharmony_ci  try {
141cb0ef41Sopenharmony_ci    const january = new Date(9e8);
151cb0ef41Sopenharmony_ci    const spanish = new Intl.DateTimeFormat('es', { month: 'long' });
161cb0ef41Sopenharmony_ci    return spanish.format(january) === 'enero';
171cb0ef41Sopenharmony_ci  } catch {
181cb0ef41Sopenharmony_ci    return false;
191cb0ef41Sopenharmony_ci  }
201cb0ef41Sopenharmony_ci})();
211cb0ef41Sopenharmony_ciif (!hasFullICU)
221cb0ef41Sopenharmony_ci  common.skip('small ICU');
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ciconst icuVersionMajor = Number(process.config.variables.icu_ver_major ?? 0);
251cb0ef41Sopenharmony_ciif (icuVersionMajor < 71)
261cb0ef41Sopenharmony_ci  common.skip('ICU too old');
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cifunction runEnvOutside(addEnv, code, ...args) {
301cb0ef41Sopenharmony_ci  return execFileSync(
311cb0ef41Sopenharmony_ci    process.execPath,
321cb0ef41Sopenharmony_ci    ['-e', `process.stdout.write(String(${code}));`],
331cb0ef41Sopenharmony_ci    { env: { ...process.env, ...addEnv }, encoding: 'utf8' }
341cb0ef41Sopenharmony_ci  );
351cb0ef41Sopenharmony_ci}
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_cifunction runEnvInside(addEnv, func, ...args) {
381cb0ef41Sopenharmony_ci  Object.assign(process.env, addEnv); // side effects!
391cb0ef41Sopenharmony_ci  return func(...args);
401cb0ef41Sopenharmony_ci}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cifunction isPack(array) {
431cb0ef41Sopenharmony_ci  const firstItem = array[0];
441cb0ef41Sopenharmony_ci  return array.every((item) => item === firstItem);
451cb0ef41Sopenharmony_ci}
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_cifunction isSet(array) {
481cb0ef41Sopenharmony_ci  const deduped = new Set(array);
491cb0ef41Sopenharmony_ci  return array.length === deduped.size;
501cb0ef41Sopenharmony_ci}
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ciconst localesISO639 = [
541cb0ef41Sopenharmony_ci  'eng', 'cmn', 'hin', 'spa',
551cb0ef41Sopenharmony_ci  'fra', 'arb', 'ben', 'rus',
561cb0ef41Sopenharmony_ci  'por', 'urd', 'ind', 'deu',
571cb0ef41Sopenharmony_ci  'jpn', 'pcm', 'mar', 'tel',
581cb0ef41Sopenharmony_ci];
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ciconst locales = [
611cb0ef41Sopenharmony_ci  'en', 'zh', 'hi', 'es',
621cb0ef41Sopenharmony_ci  'fr', 'ar', 'bn', 'ru',
631cb0ef41Sopenharmony_ci  'pt', 'ur', 'id', 'de',
641cb0ef41Sopenharmony_ci  'ja', 'pcm', 'mr', 'te',
651cb0ef41Sopenharmony_ci];
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci// These must not overlap
681cb0ef41Sopenharmony_ciconst zones = [
691cb0ef41Sopenharmony_ci  'America/New_York',
701cb0ef41Sopenharmony_ci  'UTC',
711cb0ef41Sopenharmony_ci  'Asia/Irkutsk',
721cb0ef41Sopenharmony_ci  'Australia/North',
731cb0ef41Sopenharmony_ci  'Antarctica/South_Pole',
741cb0ef41Sopenharmony_ci];
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ciassert.deepStrictEqual(Intl.getCanonicalLocales(localesISO639), locales);
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci// On some platforms these keep original locale (for example, 'January')
811cb0ef41Sopenharmony_ciconst enero = runEnvOutside(
821cb0ef41Sopenharmony_ci  { LANG: 'es' },
831cb0ef41Sopenharmony_ci  'new Intl.DateTimeFormat(undefined, { month: "long" } ).format(new Date(9e8))'
841cb0ef41Sopenharmony_ci);
851cb0ef41Sopenharmony_ciconst janvier = runEnvOutside(
861cb0ef41Sopenharmony_ci  { LANG: 'fr' },
871cb0ef41Sopenharmony_ci  'new Intl.DateTimeFormat(undefined, { month: "long" } ).format(new Date(9e8))'
881cb0ef41Sopenharmony_ci);
891cb0ef41Sopenharmony_ciconst isMockable = enero !== janvier;
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci// Tests with mocked env
921cb0ef41Sopenharmony_ciif (isMockable) {
931cb0ef41Sopenharmony_ci  assert.strictEqual(
941cb0ef41Sopenharmony_ci    isSet(zones.map((TZ) => runEnvOutside({ TZ }, 'new Date(333333333333).toString()'))),
951cb0ef41Sopenharmony_ci    true
961cb0ef41Sopenharmony_ci  );
971cb0ef41Sopenharmony_ci  assert.strictEqual(
981cb0ef41Sopenharmony_ci    isSet(zones.map((TZ) => runEnvOutside({ TZ }, 'new Date(333333333333).toLocaleString()'))),
991cb0ef41Sopenharmony_ci    true
1001cb0ef41Sopenharmony_ci  );
1011cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
1021cb0ef41Sopenharmony_ci    locales.map((LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Date(333333333333).toString()')),
1031cb0ef41Sopenharmony_ci    [
1041cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (Central European Standard Time)',
1051cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (中欧标准时间)',
1061cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (मध्य यूरोपीय मानक समय)',
1071cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (hora estándar de Europa central)',
1081cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (heure normale d’Europe centrale)',
1091cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (توقيت وسط أوروبا الرسمي)',
1101cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (মধ্য ইউরোপীয় মানক সময়)',
1111cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (Центральная Европа, стандартное время)',
1121cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (Horário Padrão da Europa Central)',
1131cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (وسطی یورپ کا معیاری وقت)',
1141cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (Waktu Standar Eropa Tengah)',
1151cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (Mitteleuropäische Normalzeit)',
1161cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (中央ヨーロッパ標準時)',
1171cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (Mídúl Yúrop Fíksd Taim)',
1181cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (मध्‍य युरोपियन प्रमाण वेळ)',
1191cb0ef41Sopenharmony_ci      'Fri Jul 25 1980 01:35:33 GMT+0100 (సెంట్రల్ యూరోపియన్ ప్రామాణిక సమయం)',
1201cb0ef41Sopenharmony_ci    ]
1211cb0ef41Sopenharmony_ci  );
1221cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
1231cb0ef41Sopenharmony_ci    locales.map((LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Date(333333333333).toLocaleString()')),
1241cb0ef41Sopenharmony_ci    [
1251cb0ef41Sopenharmony_ci      '7/25/1980, 1:35:33 AM',
1261cb0ef41Sopenharmony_ci      '1980/7/25 01:35:33',
1271cb0ef41Sopenharmony_ci      '25/7/1980, 1:35:33 am',
1281cb0ef41Sopenharmony_ci      '25/7/1980, 1:35:33',
1291cb0ef41Sopenharmony_ci      '25/07/1980 01:35:33',
1301cb0ef41Sopenharmony_ci      '٢٥‏/٧‏/١٩٨٠، ١:٣٥:٣٣ ص',
1311cb0ef41Sopenharmony_ci      '২৫/৭/১৯৮০, ১:৩৫:৩৩ AM',
1321cb0ef41Sopenharmony_ci      '25.07.1980, 01:35:33',
1331cb0ef41Sopenharmony_ci      '25/07/1980, 01:35:33',
1341cb0ef41Sopenharmony_ci      '25/7/1980، 1:35:33 AM',
1351cb0ef41Sopenharmony_ci      '25/7/1980, 01.35.33',
1361cb0ef41Sopenharmony_ci      '25.7.1980, 01:35:33',
1371cb0ef41Sopenharmony_ci      '1980/7/25 1:35:33',
1381cb0ef41Sopenharmony_ci      '25/7/1980 01:35:33',
1391cb0ef41Sopenharmony_ci      '२५/७/१९८०, १:३५:३३ AM',
1401cb0ef41Sopenharmony_ci      '25/7/1980 1:35:33 AM',
1411cb0ef41Sopenharmony_ci    ]
1421cb0ef41Sopenharmony_ci  );
1431cb0ef41Sopenharmony_ci  assert.strictEqual(
1441cb0ef41Sopenharmony_ci    runEnvOutside({ LANG: 'en' }, '["z", "ä"].sort(new Intl.Collator().compare)'),
1451cb0ef41Sopenharmony_ci    'ä,z'
1461cb0ef41Sopenharmony_ci  );
1471cb0ef41Sopenharmony_ci  assert.strictEqual(
1481cb0ef41Sopenharmony_ci    runEnvOutside({ LANG: 'sv' }, '["z", "ä"].sort(new Intl.Collator().compare)'),
1491cb0ef41Sopenharmony_ci    'z,ä'
1501cb0ef41Sopenharmony_ci  );
1511cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
1521cb0ef41Sopenharmony_ci    locales.map(
1531cb0ef41Sopenharmony_ci      (LANG) => runEnvOutside({ LANG, TZ: 'Europe/Zurich' }, 'new Intl.DateTimeFormat().format(333333333333)')
1541cb0ef41Sopenharmony_ci    ),
1551cb0ef41Sopenharmony_ci    [
1561cb0ef41Sopenharmony_ci      '7/25/1980', '1980/7/25',
1571cb0ef41Sopenharmony_ci      '25/7/1980', '25/7/1980',
1581cb0ef41Sopenharmony_ci      '25/07/1980', '٢٥‏/٧‏/١٩٨٠',
1591cb0ef41Sopenharmony_ci      '২৫/৭/১৯৮০', '25.07.1980',
1601cb0ef41Sopenharmony_ci      '25/07/1980', '25/7/1980',
1611cb0ef41Sopenharmony_ci      '25/7/1980', '25.7.1980',
1621cb0ef41Sopenharmony_ci      '1980/7/25', '25/7/1980',
1631cb0ef41Sopenharmony_ci      '२५/७/१९८०', '25/7/1980',
1641cb0ef41Sopenharmony_ci    ]
1651cb0ef41Sopenharmony_ci  );
1661cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
1671cb0ef41Sopenharmony_ci    locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.DisplayNames(undefined, { type: "region" }).of("CH")')),
1681cb0ef41Sopenharmony_ci    [
1691cb0ef41Sopenharmony_ci      'Switzerland', '瑞士',
1701cb0ef41Sopenharmony_ci      'स्विट्ज़रलैंड', 'Suiza',
1711cb0ef41Sopenharmony_ci      'Suisse', 'سويسرا',
1721cb0ef41Sopenharmony_ci      'সুইজারল্যান্ড', 'Швейцария',
1731cb0ef41Sopenharmony_ci      'Suíça', 'سوئٹزر لینڈ',
1741cb0ef41Sopenharmony_ci      'Swiss', 'Schweiz',
1751cb0ef41Sopenharmony_ci      'スイス', 'Swítsaland',
1761cb0ef41Sopenharmony_ci      'स्वित्झर्लंड', 'స్విట్జర్లాండ్',
1771cb0ef41Sopenharmony_ci    ]
1781cb0ef41Sopenharmony_ci  );
1791cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
1801cb0ef41Sopenharmony_ci    locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.NumberFormat().format(275760.913)')),
1811cb0ef41Sopenharmony_ci    [
1821cb0ef41Sopenharmony_ci      '275,760.913', '275,760.913',
1831cb0ef41Sopenharmony_ci      '2,75,760.913', '275.760,913',
1841cb0ef41Sopenharmony_ci      '275 760,913', '٢٧٥٬٧٦٠٫٩١٣',
1851cb0ef41Sopenharmony_ci      '২,৭৫,৭৬০.৯১৩', '275 760,913',
1861cb0ef41Sopenharmony_ci      '275.760,913', '275,760.913',
1871cb0ef41Sopenharmony_ci      '275.760,913', '275.760,913',
1881cb0ef41Sopenharmony_ci      '275,760.913', '275,760.913',
1891cb0ef41Sopenharmony_ci      '२,७५,७६०.९१३', '2,75,760.913',
1901cb0ef41Sopenharmony_ci    ]
1911cb0ef41Sopenharmony_ci  );
1921cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
1931cb0ef41Sopenharmony_ci    locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.PluralRules().select(0)')),
1941cb0ef41Sopenharmony_ci    [
1951cb0ef41Sopenharmony_ci      'other', 'other', 'one', 'other',
1961cb0ef41Sopenharmony_ci      'one', 'zero', 'one', 'many',
1971cb0ef41Sopenharmony_ci      'one', 'other', 'other', 'other',
1981cb0ef41Sopenharmony_ci      'other', 'one', 'other', 'other',
1991cb0ef41Sopenharmony_ci    ]
2001cb0ef41Sopenharmony_ci  );
2011cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
2021cb0ef41Sopenharmony_ci    locales.map((LANG) => runEnvOutside({ LANG }, 'new Intl.RelativeTimeFormat().format(-586920.617, "hour")')),
2031cb0ef41Sopenharmony_ci    [
2041cb0ef41Sopenharmony_ci      '586,920.617 hours ago',
2051cb0ef41Sopenharmony_ci      '586,920.617小时前',
2061cb0ef41Sopenharmony_ci      '5,86,920.617 घंटे पहले',
2071cb0ef41Sopenharmony_ci      'hace 586.920,617 horas',
2081cb0ef41Sopenharmony_ci      'il y a 586 920,617 heures',
2091cb0ef41Sopenharmony_ci      'قبل ٥٨٦٬٩٢٠٫٦١٧ ساعة',
2101cb0ef41Sopenharmony_ci      '৫,৮৬,৯২০.৬১৭ ঘন্টা আগে',
2111cb0ef41Sopenharmony_ci      '586 920,617 часа назад',
2121cb0ef41Sopenharmony_ci      'há 586.920,617 horas',
2131cb0ef41Sopenharmony_ci      '586,920.617 گھنٹے پہلے',
2141cb0ef41Sopenharmony_ci      '586.920,617 jam yang lalu',
2151cb0ef41Sopenharmony_ci      'vor 586.920,617 Stunden',
2161cb0ef41Sopenharmony_ci      '586,920.617 時間前',
2171cb0ef41Sopenharmony_ci      '586,920.617 áwa wé dọ́n pas',
2181cb0ef41Sopenharmony_ci      '५,८६,९२०.६१७ तासांपूर्वी',
2191cb0ef41Sopenharmony_ci      '5,86,920.617 గంటల క్రితం',
2201cb0ef41Sopenharmony_ci    ]
2211cb0ef41Sopenharmony_ci  );
2221cb0ef41Sopenharmony_ci}
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci// Tests with process.env mutated inside
2261cb0ef41Sopenharmony_ci{
2271cb0ef41Sopenharmony_ci  // process.env.TZ is not intercepted in Workers
2281cb0ef41Sopenharmony_ci  if (common.isMainThread) {
2291cb0ef41Sopenharmony_ci    assert.strictEqual(
2301cb0ef41Sopenharmony_ci      isSet(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toString()))),
2311cb0ef41Sopenharmony_ci      true
2321cb0ef41Sopenharmony_ci    );
2331cb0ef41Sopenharmony_ci    assert.strictEqual(
2341cb0ef41Sopenharmony_ci      isSet(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toLocaleString()))),
2351cb0ef41Sopenharmony_ci      true
2361cb0ef41Sopenharmony_ci    );
2371cb0ef41Sopenharmony_ci  } else {
2381cb0ef41Sopenharmony_ci    assert.strictEqual(
2391cb0ef41Sopenharmony_ci      isPack(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toString()))),
2401cb0ef41Sopenharmony_ci      true
2411cb0ef41Sopenharmony_ci    );
2421cb0ef41Sopenharmony_ci    assert.strictEqual(
2431cb0ef41Sopenharmony_ci      isPack(zones.map((TZ) => runEnvInside({ TZ }, () => new Date(333333333333).toLocaleString()))),
2441cb0ef41Sopenharmony_ci      true
2451cb0ef41Sopenharmony_ci    );
2461cb0ef41Sopenharmony_ci  }
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  assert.strictEqual(
2491cb0ef41Sopenharmony_ci    isPack(locales.map((LANG) => runEnvInside({ LANG, TZ: 'Europe/Zurich' }, () => new Date(333333333333).toString()))),
2501cb0ef41Sopenharmony_ci    true
2511cb0ef41Sopenharmony_ci  );
2521cb0ef41Sopenharmony_ci  assert.strictEqual(
2531cb0ef41Sopenharmony_ci    isPack(locales.map(
2541cb0ef41Sopenharmony_ci      (LANG) => runEnvInside({ LANG, TZ: 'Europe/Zurich' }, () => new Date(333333333333).toLocaleString())
2551cb0ef41Sopenharmony_ci    )),
2561cb0ef41Sopenharmony_ci    true
2571cb0ef41Sopenharmony_ci  );
2581cb0ef41Sopenharmony_ci  assert.deepStrictEqual(
2591cb0ef41Sopenharmony_ci    runEnvInside({ LANG: 'en' }, () => ['z', 'ä'].sort(new Intl.Collator().compare)),
2601cb0ef41Sopenharmony_ci    runEnvInside({ LANG: 'sv' }, () => ['z', 'ä'].sort(new Intl.Collator().compare))
2611cb0ef41Sopenharmony_ci  );
2621cb0ef41Sopenharmony_ci  assert.strictEqual(
2631cb0ef41Sopenharmony_ci    isPack(locales.map(
2641cb0ef41Sopenharmony_ci      (LANG) => runEnvInside({ LANG, TZ: 'Europe/Zurich' }, () => new Intl.DateTimeFormat().format(333333333333))
2651cb0ef41Sopenharmony_ci    )),
2661cb0ef41Sopenharmony_ci    true
2671cb0ef41Sopenharmony_ci  );
2681cb0ef41Sopenharmony_ci  assert.strictEqual(
2691cb0ef41Sopenharmony_ci    isPack(locales.map(
2701cb0ef41Sopenharmony_ci      (LANG) => runEnvInside({ LANG }, () => new Intl.DisplayNames(undefined, { type: 'region' }).of('CH'))
2711cb0ef41Sopenharmony_ci    )),
2721cb0ef41Sopenharmony_ci    true
2731cb0ef41Sopenharmony_ci  );
2741cb0ef41Sopenharmony_ci  assert.strictEqual(
2751cb0ef41Sopenharmony_ci    isPack(locales.map((LANG) => runEnvInside({ LANG }, () => new Intl.NumberFormat().format(275760.913)))),
2761cb0ef41Sopenharmony_ci    true
2771cb0ef41Sopenharmony_ci  );
2781cb0ef41Sopenharmony_ci  assert.strictEqual(
2791cb0ef41Sopenharmony_ci    isPack(locales.map((LANG) => runEnvInside({ LANG }, () => new Intl.PluralRules().select(0)))),
2801cb0ef41Sopenharmony_ci    true
2811cb0ef41Sopenharmony_ci  );
2821cb0ef41Sopenharmony_ci  assert.strictEqual(
2831cb0ef41Sopenharmony_ci    isPack(locales.map(
2841cb0ef41Sopenharmony_ci      (LANG) => runEnvInside({ LANG }, () => new Intl.RelativeTimeFormat().format(-586920.617, 'hour'))
2851cb0ef41Sopenharmony_ci    )),
2861cb0ef41Sopenharmony_ci    true
2871cb0ef41Sopenharmony_ci  );
2881cb0ef41Sopenharmony_ci}
289