summaryrefslogtreecommitdiffstats
path: root/debian/test_timezone_conversions
diff options
context:
space:
mode:
Diffstat (limited to 'debian/test_timezone_conversions')
-rwxr-xr-xdebian/test_timezone_conversions50
1 files changed, 42 insertions, 8 deletions
diff --git a/debian/test_timezone_conversions b/debian/test_timezone_conversions
index 768e6fd..ac009a8 100755
--- a/debian/test_timezone_conversions
+++ b/debian/test_timezone_conversions
@@ -5,6 +5,7 @@
"""Check convert_timezone from tzdata.config for consistency."""
import argparse
+import functools
import logging
import pathlib
import re
@@ -40,13 +41,14 @@ EXCLUDE_UNSELECTABLE = {
class ConvertTimezone:
"""Wrap convert_timezone from tzdata.config."""
- def __init__(self, tzdata_config: pathlib.Path):
+ def __init__(self, tzdata_config: pathlib.Path) -> None:
self.tzdata_config = tzdata_config
content = tzdata_config.read_text(encoding="utf-8")
match = re.search(r"convert_timezone\(\).*\n}", content, flags=re.DOTALL)
assert match, f"convert_timezone function not found in {tzdata_config}"
self.convert_timezone = match.group(0)
+ @functools.lru_cache(maxsize=8192)
def __call__(self, timezone: str) -> str:
shell_script = f"{self.convert_timezone}\nconvert_timezone '{timezone}'\n"
shell = subprocess.run(
@@ -57,17 +59,18 @@ class ConvertTimezone:
)
return shell.stdout.strip()
- def filter_converted_timezones(self, timezones: set[str]) -> set[str]:
- """Return set of timezones that will be converted by convert_timezone."""
- converted = set()
+ def filter_converted_timezones(self, timezones: set[str]) -> dict[str, str]:
+ """Return dict of timezones that will be converted by convert_timezone."""
+ converted = {}
for timezone in timezones:
- if self(timezone) != timezone:
- converted.add(timezone)
+ conversion = self(timezone)
+ if conversion != timezone:
+ converted[timezone] = conversion
return converted
def filter_unconverted_timezones(self, timezones: set[str]) -> set[str]:
"""Return set of timezones that will not be converted by convert_timezone."""
- return timezones - self.filter_converted_timezones(timezones)
+ return timezones - set(self.filter_converted_timezones(timezones))
def get_targets(self) -> set[str]:
"""Return set of conversion targets."""
@@ -115,6 +118,27 @@ def get_debconf_choices(template_filename: pathlib.Path) -> set[str]:
return debconf_choices
+def _check_symlink(source: str, target: str) -> bool:
+ """Check if the given timezone source symlinks to the given target."""
+ for tzpath in zoneinfo.TZPATH:
+ timezone = pathlib.Path(tzpath) / source
+ if timezone.exists():
+ expected_target = pathlib.Path(tzpath) / target
+ return timezone.resolve() == expected_target.resolve()
+ return True
+
+
+def check_symlinks(timezones: dict[str, str]) -> set[str]:
+ """Check timezone replacements are identical to the symlinks on disk."""
+ mismatch = set()
+ for source, target in timezones.items():
+ if source.startswith("right/"):
+ continue
+ if not _check_symlink(source, target):
+ mismatch.add(source)
+ return mismatch
+
+
def existing_dir_path(string: str) -> pathlib.Path:
"""Convert string to existing dir path or raise ArgumentTypeError."""
path = pathlib.Path(string)
@@ -160,7 +184,7 @@ def main() -> int:
conversion_targets = convert_timezone.get_targets()
failures = 0
- converted = convert_timezone.filter_converted_timezones(selectable)
+ converted = set(convert_timezone.filter_converted_timezones(selectable))
if converted:
logger.error(
"Following %i timezones can be selected, but will be converted:\n%s",
@@ -206,6 +230,16 @@ def main() -> int:
)
failures += 1
+ mismatch = check_symlinks(convert_timezone.filter_converted_timezones(available))
+ if mismatch:
+ logger.error(
+ "Following %i timezones are converted,"
+ " but they do not match their symlink targets:\n%s",
+ len(mismatch),
+ "\n".join(sorted(mismatch)),
+ )
+ failures += 1
+
return failures