gcc/libstdc++-v3/testsuite/std/time
Jonathan Wakely eed7fb1b2f
libstdc++: Support link chains in std::chrono::tzdb::locate_zone [PR114770]
Since 2022 the TZif format defined in the zic(8) man page has said that
links can refer to other links, rather than only referring to a zone.
This isn't supported by the C++20 spec, which assumes that the target()
for a chrono::time_zone_link always names a chrono::time_zone, not
another chrono::time_zone_link.

This hasn't been a problem until now, because there are no entries in
the tzdata file that chain links together. However, Debian Sid has
changed the target of the Asia/Chungking link from the Asia/Shanghai
zone to the Asia/Chongqing link, creating a link chain. The libstdc++
code is unable to handle this, so chrono::locate_zone("Asia/Chungking")
will fail with the tzdata.zi file from Debian Sid.

It seems likely that the C++ spec will need a change to allow link
chains, so that the original structure of the IANA database can be fully
represented by chrono::tzdb. The alternative would be for chrono::tzdb
to flatten all chains when loading the data, so that a link's target is
always a zone, but this means throwing away information present in the
tzdata.zi input file.

In anticipation of a change to the spec, this commit adds support for
chained links to libstdc++. When a name is found to be a link, we try to
find its target in the list of zones as before, but now if the target
isn't the name of a zone we don't fail. Instead we look for another link
with that name, and keep doing that until we reach the end of the chain
of links, and then look up the last target as a zone.

This new logic would get stuck in a loop if the tzdata.zi file is buggy
and defines a link chain that contains a cycle, e.g. two links that
refer to each other. To deal with that unlikely case, we use the
tortoise and hare algorithm to detect cycles in link chains, and throw
an exception if we detect a cycle. Cycles in links should never happen,
and it is expected that link chains will be short (if they occur at all)
and so the code is optimized for short chains without cycles. Longer
chains (four or more links) and cycles will do more work, but won't fail
to resolve a chain or get stuck in a loop.

The new test file checks various forms of broken links and cycles.

Also add a new check in the testsuite that every element in the
get_tzdb().zones and get_tzdb().links sequences can be successfully
found using locate_zone.

libstdc++-v3/ChangeLog:

	PR libstdc++/114770
	* src/c++20/tzdb.cc (do_locate_zone): Support links that have
	another link as their target.
	* testsuite/std/time/tzdb/1.cc: Check that all zones and links
	can be found by locate_zone.
	* testsuite/std/time/tzdb/links.cc: New test.
2024-04-19 21:06:28 +01:00
..
clock libstdc++: Fix check in testsuite/std/time/clock/gps/io.cc 2024-01-30 14:50:07 +00:00
day libstdc++: Implement P2905R2 "Runtime format strings" for C++20 2024-01-08 01:14:50 +00:00
hh_mm_ss libstdc++: Fix std::format for floating-point chrono::time_point [PR113500] 2024-01-21 22:15:06 +00:00
is_am Update copyright years. 2024-01-03 12:19:35 +01:00
is_pm Update copyright years. 2024-01-03 12:19:35 +01:00
make12 Update copyright years. 2024-01-03 12:19:35 +01:00
make24 Update copyright years. 2024-01-03 12:19:35 +01:00
month libstdc++: Implement P2905R2 "Runtime format strings" for C++20 2024-01-08 01:14:50 +00:00
month_day Update copyright years. 2024-01-03 12:19:35 +01:00
month_day_last Update copyright years. 2024-01-03 12:19:35 +01:00
month_weekday Update copyright years. 2024-01-03 12:19:35 +01:00
month_weekday_last Update copyright years. 2024-01-03 12:19:35 +01:00
parse libstdc++: Do not require a time-of-day when parsing sys_days [PR114240] 2024-03-09 00:21:42 +00:00
time_zone libstdc++: Remove dg-options "-std=gnu++20" from std::chrono tests 2023-09-15 21:57:39 +01:00
traits Update copyright years. 2024-01-03 12:19:35 +01:00
tzdb libstdc++: Support link chains in std::chrono::tzdb::locate_zone [PR114770] 2024-04-19 21:06:28 +01:00
tzdb_list libstdc++: Remove dg-options "-std=gnu++20" from std::chrono tests 2023-09-15 21:57:39 +01:00
weekday libstdc++: Implement P2905R2 "Runtime format strings" for C++20 2024-01-08 01:14:50 +00:00
weekday_indexed Update copyright years. 2024-01-03 12:19:35 +01:00
weekday_last Update copyright years. 2024-01-03 12:19:35 +01:00
year libstdc++: Implement P2905R2 "Runtime format strings" for C++20 2024-01-08 01:14:50 +00:00
year_month Update copyright years. 2024-01-03 12:19:35 +01:00
year_month_day libstdc++: Adjust expected locale-dependent date formats in tests 2024-04-10 16:14:25 +01:00
year_month_day_last Update copyright years. 2024-01-03 12:19:35 +01:00
year_month_weekday Update copyright years. 2024-01-03 12:19:35 +01:00
year_month_weekday_last Update copyright years. 2024-01-03 12:19:35 +01:00
zoned_time libstdc++: Add dg-timeout-factor to <chrono> IO tests 2023-10-26 21:10:47 +01:00
exceptions.cc libstdc++: Remove dg-options "-std=gnu++20" from std::chrono tests 2023-09-15 21:57:39 +01:00
format.cc libstdc++: Add dg-timeout-factor to <chrono> IO tests 2023-10-26 21:10:47 +01:00
syn_c++20.cc Update copyright years. 2024-01-03 12:19:35 +01:00
zoned_traits.cc libstdc++: Remove dg-options "-std=gnu++20" from std::chrono tests 2023-09-15 21:57:39 +01:00