brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.7 KiB · 9b43ca4 Raw
253 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710// UNSUPPORTED: no-filesystem, no-localization, no-tzdb11 12// XFAIL: libcpp-has-no-experimental-tzdb13// XFAIL: availability-tzdb-missing14 15// <chrono>16 17// class utc_clock;18 19// static sys_time<common_type_t<_Duration, seconds>>20// to_sys(const utc_time<_Duration>& __time);21 22#include <chrono>23#include <cmath>24#include <cassert>25 26#include "test_macros.h"27#include "assert_macros.h"28#include "concat_macros.h"29 30template <class Duration>31static void test_leap_seconds(std::chrono::utc_time<Duration> time, std::chrono::sys_time<Duration> expected) {32  auto result = std::chrono::utc_clock::to_sys(time);33  TEST_REQUIRE(34      result == expected,35      TEST_WRITE_CONCATENATED("\tTime: ", time, "\nExpected output ", expected, "\nActual output   ", result, '\n'));36}37 38static std::chrono::sys_seconds get_sys_time(long long seconds_since_1900) {39  // The file leap-seconds.list stores dates since 1 January 1900, 00:00:00, we want40  // seconds since 1 January 1970.41  constexpr auto offset =42      std::chrono::sys_days{std::chrono::January / 1 / 1970} - std::chrono::sys_days{std::chrono::January / 1 / 1900};43  return std::chrono::sys_seconds{std::chrono::seconds{seconds_since_1900} - offset};44}45 46// Tests the set of existing database entries at the time of writing. Since47// the last leap second insertion is several years ago, it's expected all48// systems have the same information. (Adding new entries in the future does49// not affect this test.)50static void test_transitions() {51  using namespace std::literals::chrono_literals;52 53  test_leap_seconds(std::chrono::utc_seconds::min(), std::chrono::sys_seconds::min());54 55  // Epoch transition no transitions.56  test_leap_seconds(std::chrono::utc_seconds{-1s}, std::chrono::sys_seconds{-1s});57  test_leap_seconds(std::chrono::utc_seconds{0s}, std::chrono::sys_seconds{0s});58  test_leap_seconds(std::chrono::utc_seconds{1s}, std::chrono::sys_seconds{1s});59 60  // "sys" is the time of the transition to the next leap second.61  // "elapsed" is the number of leap seconds before the transition.62  // "positive" is the leap second added +1s? If not it's -1s.63  auto test_transition = [](std::chrono::sys_seconds sys, std::chrono::seconds elapsed, bool positive) {64    // Note at the time of writing all leap seconds are positive so the else65    // branch is never executed. The private test for this function tests66    // negative leap seconds and uses the else branch.67 68    std::chrono::utc_seconds utc = std::chrono::utc_seconds{sys.time_since_epoch()} + elapsed;69    if (positive) {70      // Every transition has the following tests71      // - 1ns before the start of the transition no adjustment needed72      // -         at the start of the transition sys is clamped at the time just prior to the moment73      //                                          of the leap second insertion. The exact value depends74      //                                          on the resolution of the result type.75      // - 1ns before the end   of the transition sys is still clamped like before76      // -         at the end   of the transition sys is 1s behind the utc time77      // - 1ns after  the end   of the transition sys is still 1s behind the utc time78      test_leap_seconds(utc - 1ns, sys - 1ns);79      test_leap_seconds(utc, sys - 1s);80      test_leap_seconds(utc + 0ns, sys - 1ns);81      test_leap_seconds(utc + 1s - 1ns, sys - 1ns);82      test_leap_seconds(utc + 1s, sys);83      test_leap_seconds(utc + 1s + 0ns, sys + 0ns);84      test_leap_seconds(utc + 1s + 1ns, sys + 1ns);85    } else {86      // Every transition has the following tests87      // - 1ns before the transition no adjustment needed88      // -         at the transition sys is 1s ahead of the utc time89      // - 1ns after  the transition sys is still 1s ahead of the utc time90      test_leap_seconds(utc - 1ns, sys - 1ns);91      test_leap_seconds(utc, sys + 1s);92      test_leap_seconds(utc + 1ns, sys + 1s + 1ns);93    }94  };95 96  // Transitions from the start of UTC.97  test_transition(get_sys_time(2287785600), 0s, true);  // 1 Jul 197298  test_transition(get_sys_time(2303683200), 1s, true);  // 1 Jan 197399  test_transition(get_sys_time(2335219200), 2s, true);  // 1 Jan 1974100  test_transition(get_sys_time(2366755200), 3s, true);  // 1 Jan 1975101  test_transition(get_sys_time(2398291200), 4s, true);  // 1 Jan 1976102  test_transition(get_sys_time(2429913600), 5s, true);  // 1 Jan 1977103  test_transition(get_sys_time(2461449600), 6s, true);  // 1 Jan 1978104  test_transition(get_sys_time(2492985600), 7s, true);  // 1 Jan 1979105  test_transition(get_sys_time(2524521600), 8s, true);  // 1 Jan 1980106  test_transition(get_sys_time(2571782400), 9s, true);  // 1 Jul 1981107  test_transition(get_sys_time(2603318400), 10s, true); // 1 Jul 1982108  test_transition(get_sys_time(2634854400), 11s, true); // 1 Jul 1983109  test_transition(get_sys_time(2698012800), 12s, true); // 1 Jul 1985110  test_transition(get_sys_time(2776982400), 13s, true); // 1 Jan 1988111  test_transition(get_sys_time(2840140800), 14s, true); // 1 Jan 1990112  test_transition(get_sys_time(2871676800), 15s, true); // 1 Jan 1991113  test_transition(get_sys_time(2918937600), 16s, true); // 1 Jul 1992114  test_transition(get_sys_time(2950473600), 17s, true); // 1 Jul 1993115  test_transition(get_sys_time(2982009600), 18s, true); // 1 Jul 1994116  test_transition(get_sys_time(3029443200), 19s, true); // 1 Jan 1996117  test_transition(get_sys_time(3076704000), 20s, true); // 1 Jul 1997118  test_transition(get_sys_time(3124137600), 21s, true); // 1 Jan 1999119  test_transition(get_sys_time(3345062400), 22s, true); // 1 Jan 2006120  test_transition(get_sys_time(3439756800), 23s, true); // 1 Jan 2009121  test_transition(get_sys_time(3550089600), 24s, true); // 1 Jul 2012122  test_transition(get_sys_time(3644697600), 25s, true); // 1 Jul 2015123  test_transition(get_sys_time(3692217600), 26s, true); // 1 Jan 2017124}125 126// Tests the transition for clocks where the duration's rep is a floating-point type.127static void test_transitions_floating_point() {128  using namespace std::literals::chrono_literals;129 130  // Based on test_transitions but uses a floating-point duration.131  using F = float;132 133  auto test_transition = [](std::chrono::sys_seconds sys, std::chrono::seconds elapsed, bool positive) {134    // Note at the time of writing all leap seconds are positive so the else135    // branch is never executed. The private test for this function tests136    // negative leap seconds and uses the else branch.137 138    std::chrono::utc_seconds utc = std::chrono::utc_seconds{sys.time_since_epoch()} + elapsed;139 140    using D = std::chrono::duration<F>;141    using S = std::chrono ::time_point<std::chrono::system_clock, D>;142    using U = std::chrono ::time_point<std::chrono::utc_clock, D>;143 144    S s{sys.time_since_epoch()};145    bool is_leap_second = s.time_since_epoch().count() == sys.time_since_epoch().count();146    assert(is_leap_second);147 148    U u{utc.time_since_epoch()};149    if (positive) {150      test_leap_seconds(u - 1ns, s - 1ns);151      test_leap_seconds(u, s - 1s);152      test_leap_seconds(u + 0ns, s - 1ns);153      test_leap_seconds(u + 1s - 1ns, s - 1ns);154      test_leap_seconds(u + 1s, s);155      test_leap_seconds(u + 1s + 0ns, s + 0ns);156      test_leap_seconds(u + 1s + 1ns, s + 1ns);157 158      test_leap_seconds(U{D{std::nextafter(u.time_since_epoch().count(), F{0})}},159                        S{D{std::nextafter(s.time_since_epoch().count(), F{0})}});160      test_leap_seconds(u, S{D{s.time_since_epoch().count() - F{1}}});161      test_leap_seconds(U{D{u.time_since_epoch().count() + F{1}}}, s);162      test_leap_seconds(U{D{std::nextafter(u.time_since_epoch().count() + F{1}, std::numeric_limits<F>::max())}},163                        S{D{std::nextafter(s.time_since_epoch().count(), std::numeric_limits<F>::max())}});164    }165  };166 167  // Transitions from the start of UTC.168  test_transition(get_sys_time(2287785600), 0s, true);  // 1 Jul 1972169  test_transition(get_sys_time(2303683200), 1s, true);  // 1 Jan 1973170  test_transition(get_sys_time(2335219200), 2s, true);  // 1 Jan 1974171  test_transition(get_sys_time(2366755200), 3s, true);  // 1 Jan 1975172  test_transition(get_sys_time(2398291200), 4s, true);  // 1 Jan 1976173  test_transition(get_sys_time(2429913600), 5s, true);  // 1 Jan 1977174  test_transition(get_sys_time(2461449600), 6s, true);  // 1 Jan 1978175  test_transition(get_sys_time(2492985600), 7s, true);  // 1 Jan 1979176  test_transition(get_sys_time(2524521600), 8s, true);  // 1 Jan 1980177  test_transition(get_sys_time(2571782400), 9s, true);  // 1 Jul 1981178  test_transition(get_sys_time(2603318400), 10s, true); // 1 Jul 1982179  test_transition(get_sys_time(2634854400), 11s, true); // 1 Jul 1983180  test_transition(get_sys_time(2698012800), 12s, true); // 1 Jul 1985181  test_transition(get_sys_time(2776982400), 13s, true); // 1 Jan 1988182  test_transition(get_sys_time(2840140800), 14s, true); // 1 Jan 1990183  test_transition(get_sys_time(2871676800), 15s, true); // 1 Jan 1991184  test_transition(get_sys_time(2918937600), 16s, true); // 1 Jul 1992185  test_transition(get_sys_time(2950473600), 17s, true); // 1 Jul 1993186  test_transition(get_sys_time(2982009600), 18s, true); // 1 Jul 1994187  test_transition(get_sys_time(3029443200), 19s, true); // 1 Jan 1996188  test_transition(get_sys_time(3076704000), 20s, true); // 1 Jul 1997189  test_transition(get_sys_time(3124137600), 21s, true); // 1 Jan 1999190  test_transition(get_sys_time(3345062400), 22s, true); // 1 Jan 2006191  test_transition(get_sys_time(3439756800), 23s, true); // 1 Jan 2009192  test_transition(get_sys_time(3550089600), 24s, true); // 1 Jul 2012193  test_transition(get_sys_time(3644697600), 25s, true); // 1 Jul 2015194  test_transition(get_sys_time(3692217600), 26s, true); // 1 Jan 2017195}196 197// Tests whether the return type is the expected type.198static void test_return_type() {199  namespace cr = std::chrono;200  using namespace std::literals::chrono_literals;201 202  {203    [[maybe_unused]] std::same_as<cr::sys_time<cr::nanoseconds>> decltype(auto) _ =204        cr::utc_clock::to_sys(cr::utc_time<cr::nanoseconds>{0ns});205  }206  {207    [[maybe_unused]] std::same_as<cr::sys_time<cr::microseconds>> decltype(auto) _ =208        cr::utc_clock::to_sys(cr::utc_time<cr::microseconds>{0us});209  }210  {211    [[maybe_unused]] std::same_as<cr::sys_time<cr::milliseconds>> decltype(auto) _ =212        cr::utc_clock::to_sys(cr::utc_time<cr::milliseconds>{0ms});213  }214 215  {216    [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =217        cr::utc_clock::to_sys(cr::utc_time<cr::seconds>{cr::seconds{0}});218  }219 220  {221    [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =222        cr::utc_clock::to_sys(cr::utc_time<cr::minutes>{cr::minutes{0}});223  }224  {225    [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =226        cr::utc_clock::to_sys(cr::utc_time<cr::hours>{cr::hours{0}});227  }228  {229    [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =230        cr::utc_clock::to_sys(cr::utc_time<cr::days>{cr::days{0}});231  }232  {233    [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =234        cr::utc_clock::to_sys(cr::utc_time<cr::weeks>{cr::weeks{0}});235  }236  {237    [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =238        cr::utc_clock::to_sys(cr::utc_time<cr::months>{cr::months{0}});239  }240  {241    [[maybe_unused]] std::same_as<cr::sys_time<cr::seconds>> decltype(auto) _ =242        cr::utc_clock::to_sys(cr::utc_time<cr::years>{cr::years{0}});243  }244}245 246int main(int, const char**) {247  test_transitions();248  test_transitions_floating_point();249  test_return_type();250 251  return 0;252}253