diff options
Diffstat (limited to 'libstdc++-v3/testsuite/std')
-rw-r--r-- | libstdc++-v3/testsuite/std/format/functions/format.cc | 8 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/ranges/concat/1.cc | 74 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/ranges/range.cc | 6 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/time/leap_seconds/io.cc | 56 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/time/tzdb/1.cc | 12 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/time/tzdb/links.cc | 215 |
6 files changed, 371 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc index 4499397aaf9..78cc1ab482a 100644 --- a/libstdc++-v3/testsuite/std/format/functions/format.cc +++ b/libstdc++-v3/testsuite/std/format/functions/format.cc @@ -248,6 +248,14 @@ test_locale() s = std::format(cloc, "{:05L}", -1.0); // PR libstdc++/110968 VERIFY( s == "-0001" ); + // PR libstdc++/114863 grouping applied to nan and inf + double inf = std::numeric_limits<double>::infinity(); + s = std::format(eloc, "{0:Le} {0:Lf} {0:Lg}", -inf); + VERIFY( s == "-inf -inf -inf" ); + double nan = std::numeric_limits<double>::quiet_NaN(); + s = std::format(eloc, "{0:Le} {0:Lf} {0:Lg}", -nan); + VERIFY( s == "-nan -nan -nan" ); + // Restore std::locale::global(cloc); } diff --git a/libstdc++-v3/testsuite/std/ranges/concat/1.cc b/libstdc++-v3/testsuite/std/ranges/concat/1.cc new file mode 100644 index 00000000000..6ffe28ece51 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/concat/1.cc @@ -0,0 +1,74 @@ +// { dg-do run { target c++26 } } +// { dg-add-options no_pch } + +#include <ranges> + +#if __cpp_lib_ranges_concat != 202403L +# error "Feature-test macro __cpp_lib_ranges_concat has wrong value in <ranges>" +#endif + +#include <algorithm> +#include <vector> +#include <array> +#include <utility> +#include <testsuite_hooks.h> +#include <testsuite_iterators.h> + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + std::vector<int> v1{1, 2, 3}, v2{4, 5}, v3{}; + std::array a{6, 7, 8}; + auto s = views::single(9); + + auto v = views::concat(v1, v2, v3, a, s); + VERIFY( ranges::size(v) == 9 ); + VERIFY( ranges::size(std::as_const(v)) == 9 ); + VERIFY( ranges::equal(v, views::iota(1, 10)) ); + VERIFY( ranges::equal(v | views::reverse, + views::iota(1, 10) | views::reverse) ); + + auto it0 = v.begin(); + auto cit = std::as_const(v).begin(); + VERIFY( it0 == it0 ); + VERIFY( cit == cit ); + VERIFY( it0 == cit ); + for (int i = 0; i < 10; i++) + { + VERIFY( it0 + i - it0 == i ); + VERIFY( it0 + i - (it0 + 1) == i - 1 ); + VERIFY( it0 + i - (it0 + 3) == i - 3 ); + VERIFY( it0 + i - (it0 + 5) == i - 5 ); + VERIFY( it0 + i - i + i == it0 + i ); + VERIFY( it0 + i - (it0 + i) == 0 ); + } + VERIFY( std::default_sentinel - it0 == 9 ); + VERIFY( it0 + 9 == std::default_sentinel ); + + auto it5 = it0+5; + ranges::iter_swap(it0, it5); + VERIFY( *it0 == 6 && *it5 == 1 ); + ranges::iter_swap(it0, it5); + *it0 = ranges::iter_move(it0); + return true; +} + +void +test02() +{ + int x[] = {1, 2, 3, 4, 5}; + __gnu_test::test_input_range rx(x); + auto v = views::concat(views::single(0), rx, views::empty<int>); + static_assert(!ranges::forward_range<decltype(v)>); + VERIFY( ranges::equal(v | views::drop(1), x) ); +} + +int +main() +{ + static_assert(test01()); + test02(); +} diff --git a/libstdc++-v3/testsuite/std/ranges/range.cc b/libstdc++-v3/testsuite/std/ranges/range.cc index 18435659137..760f6ffacfd 100644 --- a/libstdc++-v3/testsuite/std/ranges/range.cc +++ b/libstdc++-v3/testsuite/std/ranges/range.cc @@ -83,3 +83,9 @@ static_assert( same_as<std::ranges::range_rvalue_reference_t<I>, char&&> ); static_assert( same_as<std::ranges::range_rvalue_reference_t<O>, WritableObject<char>> ); + +// LWG 3860. range_common_reference_t is missing +static_assert( same_as<std::ranges::range_common_reference_t<C>, + char&> ); +static_assert( same_as<std::ranges::range_common_reference_t<I>, + char&> ); diff --git a/libstdc++-v3/testsuite/std/time/leap_seconds/io.cc b/libstdc++-v3/testsuite/std/time/leap_seconds/io.cc new file mode 100644 index 00000000000..511fafdd1a0 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/leap_seconds/io.cc @@ -0,0 +1,56 @@ +// { dg-do run { target c++20 } } +// { dg-require-effective-target tzdb } +// { dg-require-effective-target cxx11_abi } + +#include <chrono> +#include <sstream> +#include <format> +#include <testsuite_hooks.h> + +void +test_output() +{ + using namespace std::chrono; + + std::ostringstream out; + out << '\n'; + + for (auto& l : get_tzdb().leap_seconds) + if (l <= sys_days{2018y/March/17d}) + out << l.date() << ": " << l.value() << '\n'; + + VERIFY( out.str() == R"( +1972-07-01 00:00:00: 1s +1973-01-01 00:00:00: 1s +1974-01-01 00:00:00: 1s +1975-01-01 00:00:00: 1s +1976-01-01 00:00:00: 1s +1977-01-01 00:00:00: 1s +1978-01-01 00:00:00: 1s +1979-01-01 00:00:00: 1s +1980-01-01 00:00:00: 1s +1981-07-01 00:00:00: 1s +1982-07-01 00:00:00: 1s +1983-07-01 00:00:00: 1s +1985-07-01 00:00:00: 1s +1988-01-01 00:00:00: 1s +1990-01-01 00:00:00: 1s +1991-01-01 00:00:00: 1s +1992-07-01 00:00:00: 1s +1993-07-01 00:00:00: 1s +1994-07-01 00:00:00: 1s +1996-01-01 00:00:00: 1s +1997-07-01 00:00:00: 1s +1999-01-01 00:00:00: 1s +2006-01-01 00:00:00: 1s +2009-01-01 00:00:00: 1s +2012-07-01 00:00:00: 1s +2015-07-01 00:00:00: 1s +2017-01-01 00:00:00: 1s +)" ); +} + +int main() +{ + test_output(); +} diff --git a/libstdc++-v3/testsuite/std/time/tzdb/1.cc b/libstdc++-v3/testsuite/std/time/tzdb/1.cc index cf9df952577..796f3a8b425 100644 --- a/libstdc++-v3/testsuite/std/time/tzdb/1.cc +++ b/libstdc++-v3/testsuite/std/time/tzdb/1.cc @@ -47,6 +47,18 @@ test_locate() VERIFY( db.locate_zone(db.current_zone()->name()) == db.current_zone() ); } +void +test_all_zones() +{ + const tzdb& db = get_tzdb(); + + for (const auto& zone : db.zones) + VERIFY( locate_zone(zone.name())->name() == zone.name() ); + + for (const auto& link : db.links) + VERIFY( locate_zone(link.name()) == locate_zone(link.target()) ); +} + int main() { test_version(); diff --git a/libstdc++-v3/testsuite/std/time/tzdb/links.cc b/libstdc++-v3/testsuite/std/time/tzdb/links.cc new file mode 100644 index 00000000000..0ba214846c6 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/tzdb/links.cc @@ -0,0 +1,215 @@ +// { dg-do run { target c++20 } } +// { dg-require-effective-target tzdb } +// { dg-require-effective-target cxx11_abi } +// { dg-xfail-run-if "no weak override on AIX" { powerpc-ibm-aix* } } + +#include <chrono> +#include <fstream> +#include <testsuite_hooks.h> + +static bool override_used = false; + +namespace __gnu_cxx +{ + const char* zoneinfo_dir_override() { + override_used = true; + return "./"; + } +} + +using namespace std::chrono; + +void +test_link_chains() +{ + std::ofstream("tzdata.zi") << R"(# version test_1 +Link Greenwich G_M_T +Link Etc/GMT Greenwich +Zone Etc/GMT 0 - GMT +Zone A_Zone 1 - ZON +Link A_Zone L1 +Link L1 L2 +Link L2 L3 +Link L3 L4 +Link L4 L5 +Link L5 L6 +Link L3 L7 +)"; + + const auto& db = reload_tzdb(); + VERIFY( override_used ); // If this fails then XFAIL for the target. + VERIFY( db.version == "test_1" ); + + // Simple case of a link with a zone as its target. + VERIFY( locate_zone("Greenwich")->name() == "Etc/GMT" ); + // Chains of links, where the target may be another link. + VERIFY( locate_zone("G_M_T")->name() == "Etc/GMT" ); + VERIFY( locate_zone("L1")->name() == "A_Zone" ); + VERIFY( locate_zone("L2")->name() == "A_Zone" ); + VERIFY( locate_zone("L3")->name() == "A_Zone" ); + VERIFY( locate_zone("L4")->name() == "A_Zone" ); + VERIFY( locate_zone("L5")->name() == "A_Zone" ); + VERIFY( locate_zone("L6")->name() == "A_Zone" ); + VERIFY( locate_zone("L7")->name() == "A_Zone" ); +} + +void +test_bad_links() +{ + // The zic(8) man page says + // > the behavior is unspecified if multiple zone or link lines + // > define the same name" + // For libstdc++ the expected behaviour is described and tested below. + std::ofstream("tzdata.zi") << R"(# version test_2 +Zone A_Zone 1 - ZA +Zone B_Zone 2 - ZB +Link A_Zone B_Zone +Link B_Zone C_Link +Link C_Link D_Link +Link D_Link E_Link +)"; + + const auto& db2 = reload_tzdb(); + VERIFY( override_used ); // If this fails then XFAIL for the target. + VERIFY( db2.version == "test_2" ); + + // The standard requires locate_zone(name) to search for a zone first, + // so this finds the zone B_Zone, not the link that points to zone A_Zone. + VERIFY( locate_zone("B_Zone")->name() == "B_Zone" ); + // And libstdc++ does the same at every step when following chained links: + VERIFY( locate_zone("C_Link")->name() == "B_Zone" ); + VERIFY( locate_zone("D_Link")->name() == "B_Zone" ); + VERIFY( locate_zone("E_Link")->name() == "B_Zone" ); + + // The zic(8) man page says + // > the behavior is unspecified if a chain of one or more links + // > does not terminate in a Zone name. + // For libstdc++ we throw std::runtime_error if locate_zone finds an + // unterminated chain, including the case of a chain that includes a cycle. + std::ofstream("tzdata.zi") << R"(# version test_3 +Zone A_Zone 1 - ZON +Link A_Zone GoodLink +Link No_Zone BadLink +Link LinkSelf LinkSelf +Link LinkSelf Link1 +Link Link1 Link2 +Link Cycle2_A Cycle2_B +Link Cycle2_B Cycle2_A +Link Cycle3_A Cycle3_B +Link Cycle3_B Cycle3_C +Link Cycle3_C Cycle3_A +Link Cycle3_C Cycle3_D +Link Cycle4_A Cycle4_B +Link Cycle4_B Cycle4_C +Link Cycle4_C Cycle4_D +Link Cycle4_D Cycle4_A +)"; + + const auto& db3 = reload_tzdb(); + VERIFY( db3.version == "test_3" ); + + // Lookup for valid links should still work even if other links are bad. + VERIFY( locate_zone("GoodLink")->name() == "A_Zone" ); + +#if __cpp_exceptions + try { + locate_zone("BadLink"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("cannot locate zone: BadLink") ); + } + + // LinkSelf forms a link cycle with itself. + try { + locate_zone("LinkSelf"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: LinkSelf") ); + } + + // Any chain that leads to LinkSelf reaches a cycle. + try { + locate_zone("Link1"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Link1") ); + } + + try { + locate_zone("Link2"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Link2") ); + } + + // Cycle2_A and Cycle2_B form a cycle of length two. + try { + locate_zone("Cycle2_A"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Cycle2_A") ); + } + + try { + locate_zone("Cycle2_B"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Cycle2_B") ); + } + + // Cycle3_A, Cycle3_B and Cycle3_C form a cycle of length three. + try { + locate_zone("Cycle3_A"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Cycle3_A") ); + } + + try { + locate_zone("Cycle3_B"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Cycle3_B") ); + } + + try { + locate_zone("Cycle3_C"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Cycle3_C") ); + } + + // Cycle3_D isn't part of the cycle, but it leads to it. + try { + locate_zone("Cycle3_D"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Cycle3_D") ); + } + + // Cycle4_* links form a cycle of length four. + try { + locate_zone("Cycle4_A"); + VERIFY( false ); + } catch (const std::runtime_error& e) { + std::string_view what(e.what()); + VERIFY( what.ends_with("link cycle: Cycle4_A") ); + } +#endif +} + +int main() +{ + test_link_chains(); + test_bad_links(); +} |