Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add a test to ensure the correctness of timezone upgrades #45299

Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/timezone-update.yml
Expand Up @@ -36,6 +36,9 @@ jobs:

- run: ./tools/update-timezone.mjs

- name: Update the expected timezone version in test
run: echo "${{ env.new_version }}" > test/fixtures/tz-version.txt

- name: Open Pull Request
uses: gr2m/create-or-update-pull-request-action@dc1726cbf4dd3ce766af4ec29cfb660e0125e8ee # Create a PR or update the Action's existing PR
env:
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/tz-version.txt
@@ -0,0 +1 @@
2022e
22 changes: 22 additions & 0 deletions test/parallel/test-tz-version.js
@@ -0,0 +1,22 @@
'use strict';

const common = require('../common');

if (!common.hasIntl) {
common.skip('missing Intl');
}

// Refs: https://github.com/nodejs/node/blob/1af63a90ca3a59ca05b3a12ad7dbea04008db7d9/configure.py#L1694-L1711
if (process.config.variables.icu_path !== 'deps/icu-small') {
common.skip('not using the icu data file present in deps/icu-small/source/data/in/icudt##l.dat.bz2');
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this would work only if node is built with --with-intl=small-icu? Shouldn't we also check that if the value is undefined, we want to also run the test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this would work only if node is built with --with-intl=small-icu?

Looks like that's not true:

node/configure.py

Lines 1703 to 1711 in 7124476

# We can use 'deps/icu-small' - pre-canned ICU *iff*
# - canned_is_full AND
# - with_icu_source is unset (i.e. no other ICU was specified)
#
# This is *roughly* equivalent to
# $ configure --with-intl=full-icu --with-icu-source=deps/icu-small
# .. Except that we avoid copying icu-small over to deps/icu.
# In this default case, deps/icu is ignored, although make clean will
# still harmlessly remove deps/icu.

i.e., it should work if --with-intl is set to full-icu (default case).

Shouldn't we also check that if the value is undefined, we want to also run the test?

I don't think that's necessary because icu_path can never be undefined for the cases we are interested in (the objective is to run the test iff the current build is using deps/icu-small/source/data/in/icudt##l.dat.bz2):

  • icu_path is set here and icu_full_path is never undefined -

    node/configure.py

    Line 1761 in 7124476

    o['variables']['icu_path'] = icu_full_path
  • And this line wouldn't run only if we hit a return statement between

    node/configure.py

    Line 1584 in 7124476

    def configure_intl(o):
    and this assignment. The possible returns are:
    • node/configure.py

      Line 1641 in 7124476

      return
      - this would happen only if we pass --with-icu-path, I'm avoiding this to exclude the case where the pointed gyp file attempts to build icu with a different icudt file, which would result in a different process.versions.tz value
    • node/configure.py

      Line 1646 in 7124476

      return # no Intl
      - this would happen only if we pass --with-intl=none or --without-intl, which is not being considered because process.versions.tz would be undefined in this case
    • node/configure.py

      Line 1682 in 7124476

      return
      - this would happen only if we pass --with-intl=system-icu which we are avoiding because the system icu is not in our control, so it might produce a different version for process.versions.tz

Copy link
Contributor

@aduh95 aduh95 Nov 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On macOS, node installed through brew:

$ node -p '"Intl" in globalThis'
true
$ node -p 'process.config.variables.icu_path'            
undefined

I tested this with Node.js v14.x, v16.x, and v18.x. Maybe it's using system-icu though, I don't know if there's another way to check. In any case, this should probably be explained in a comment why checking for 'deps/icu-small' covers more than small ICU builds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's using system-icu though,

That is correct.

I don't know if there's another way to check.

There is :)

> process.config.variables.icu_gyp_path
'tools/icu/icu-system.gyp'

It relies on the gyp file for the systemwide icu instead of tools/icu/icu-generic.gyp which is for the builtin icu.
Alternatively, otool -L /usr/local/opt/node/bin/node would print a set of shared objects the binary dynamically links against and you'll see the icu dylibs in that list:

	/usr/local/opt/icu4c/lib/libicui18n.71.dylib (compatibility version 71.0.0, current version 71.1.0)
	/usr/local/opt/icu4c/lib/libicuuc.71.dylib (compatibility version 71.0.0, current version 71.1.0)
	/usr/local/opt/icu4c/lib/libicudata.71.dylib (compatibility version 71.0.0, current version 71.1.0)

In any case, this should probably be explained in a comment why checking for 'deps/icu-small' covers more than small ICU builds.

Explained, PTAL.


const fixtures = require('../common/fixtures');

// This test ensures the correctness of the automated timezone upgrade PRs.

const { strictEqual } = require('assert');
const { readFileSync } = require('fs');

const expectedVersion = readFileSync(fixtures.path('tz-version.txt'), 'utf8').trim();
strictEqual(process.versions.tz, expectedVersion);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We support lots of different ways of building Node.js and ICU, including pointing to external ICU source/data files, so this test is going to need guards to work properly if its going to be part of the regular test suite.

node/configure.py

Lines 549 to 590 in 1af63a9

intl_optgroup.add_argument('--with-intl',
action='store',
dest='with_intl',
default='full-icu',
choices=valid_intl_modes,
help='Intl mode (valid choices: {0}) [default: %(default)s]'.format(
', '.join(valid_intl_modes)))
intl_optgroup.add_argument('--without-intl',
action='store_const',
dest='with_intl',
const='none',
help='Disable Intl, same as --with-intl=none (disables inspector)')
intl_optgroup.add_argument('--with-icu-path',
action='store',
dest='with_icu_path',
help='Path to icu.gyp (ICU i18n, Chromium version only.)')
icu_default_locales='root,en'
intl_optgroup.add_argument('--with-icu-locales',
action='store',
dest='with_icu_locales',
default=icu_default_locales,
help='Comma-separated list of locales for "small-icu". "root" is assumed. '
'[default: %(default)s]')
intl_optgroup.add_argument('--with-icu-source',
action='store',
dest='with_icu_source',
help='Intl mode: optional local path to icu/ dir, or path/URL of '
'the icu4c source archive. '
'v%d.x or later recommended.' % icu_versions['minimum_icu'])
intl_optgroup.add_argument('--with-icu-default-data-dir',
action='store',
dest='with_icu_default_data_dir',
help='Path to the icuXXdt{lb}.dat file. If unspecified, ICU data will '
'only be read if the NODE_ICU_DATA environment variable or the '
'--icu-data-dir runtime argument is used. This option has effect '
'only when Node.js is built with --with-intl=small-icu.')

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a guard, hope that's enough?