tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

format_test.cc (16758B)


      1 // Copyright 2017 The Abseil Authors.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //      https://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <cstdint>
     16 #include <limits>
     17 #include <string>
     18 
     19 #include "gmock/gmock.h"
     20 #include "gtest/gtest.h"
     21 #include "absl/time/internal/test_util.h"
     22 #include "absl/time/time.h"
     23 
     24 using testing::HasSubstr;
     25 
     26 namespace {
     27 
     28 // A helper that tests the given format specifier by itself, and with leading
     29 // and trailing characters.  For example: TestFormatSpecifier(t, "%a", "Thu").
     30 void TestFormatSpecifier(absl::Time t, absl::TimeZone tz,
     31                         const std::string& fmt, const std::string& ans) {
     32  EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));
     33  EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz));
     34  EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz));
     35  EXPECT_EQ("xxx " + ans + " yyy",
     36            absl::FormatTime("xxx " + fmt + " yyy", t, tz));
     37 }
     38 
     39 //
     40 // Testing FormatTime()
     41 //
     42 
     43 TEST(FormatTime, Basics) {
     44  absl::TimeZone tz = absl::UTCTimeZone();
     45  absl::Time t = absl::FromTimeT(0);
     46 
     47  // Starts with a couple basic edge cases.
     48  EXPECT_EQ("", absl::FormatTime("", t, tz));
     49  EXPECT_EQ(" ", absl::FormatTime(" ", t, tz));
     50  EXPECT_EQ("  ", absl::FormatTime("  ", t, tz));
     51  EXPECT_EQ("xxx", absl::FormatTime("xxx", t, tz));
     52  std::string big(128, 'x');
     53  EXPECT_EQ(big, absl::FormatTime(big, t, tz));
     54  // Cause the 1024-byte buffer to grow.
     55  std::string bigger(100000, 'x');
     56  EXPECT_EQ(bigger, absl::FormatTime(bigger, t, tz));
     57 
     58  t += absl::Hours(13) + absl::Minutes(4) + absl::Seconds(5);
     59  t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
     60  EXPECT_EQ("1970-01-01", absl::FormatTime("%Y-%m-%d", t, tz));
     61  EXPECT_EQ("13:04:05", absl::FormatTime("%H:%M:%S", t, tz));
     62  EXPECT_EQ("13:04:05.006", absl::FormatTime("%H:%M:%E3S", t, tz));
     63  EXPECT_EQ("13:04:05.006007", absl::FormatTime("%H:%M:%E6S", t, tz));
     64  EXPECT_EQ("13:04:05.006007008", absl::FormatTime("%H:%M:%E9S", t, tz));
     65 }
     66 
     67 TEST(FormatTime, LocaleSpecific) {
     68  const absl::TimeZone tz = absl::UTCTimeZone();
     69  absl::Time t = absl::FromTimeT(0);
     70 
     71  TestFormatSpecifier(t, tz, "%a", "Thu");
     72  TestFormatSpecifier(t, tz, "%A", "Thursday");
     73  TestFormatSpecifier(t, tz, "%b", "Jan");
     74  TestFormatSpecifier(t, tz, "%B", "January");
     75 
     76  // %c should at least produce the numeric year and time-of-day.
     77  const std::string s =
     78      absl::FormatTime("%c", absl::FromTimeT(0), absl::UTCTimeZone());
     79  EXPECT_THAT(s, HasSubstr("1970"));
     80  EXPECT_THAT(s, HasSubstr("00:00:00"));
     81 
     82  TestFormatSpecifier(t, tz, "%p", "AM");
     83  TestFormatSpecifier(t, tz, "%x", "01/01/70");
     84  TestFormatSpecifier(t, tz, "%X", "00:00:00");
     85 }
     86 
     87 TEST(FormatTime, ExtendedSeconds) {
     88  const absl::TimeZone tz = absl::UTCTimeZone();
     89 
     90  // No subseconds.
     91  absl::Time t = absl::FromTimeT(0) + absl::Seconds(5);
     92  EXPECT_EQ("05", absl::FormatTime("%E*S", t, tz));
     93  EXPECT_EQ("05.000000000000000", absl::FormatTime("%E15S", t, tz));
     94 
     95  // With subseconds.
     96  t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
     97  EXPECT_EQ("05.006007008", absl::FormatTime("%E*S", t, tz));
     98  EXPECT_EQ("05", absl::FormatTime("%E0S", t, tz));
     99  EXPECT_EQ("05.006007008000000", absl::FormatTime("%E15S", t, tz));
    100 
    101  // Times before the Unix epoch.
    102  t = absl::FromUnixMicros(-1);
    103  EXPECT_EQ("1969-12-31 23:59:59.999999",
    104            absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
    105 
    106  // Here is a "%E*S" case we got wrong for a while.  While the first
    107  // instant below is correctly rendered as "...:07.333304", the second
    108  // one used to appear as "...:07.33330499999999999".
    109  t = absl::FromUnixMicros(1395024427333304);
    110  EXPECT_EQ("2014-03-17 02:47:07.333304",
    111            absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
    112  t += absl::Microseconds(1);
    113  EXPECT_EQ("2014-03-17 02:47:07.333305",
    114            absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
    115 }
    116 
    117 TEST(FormatTime, RFC1123FormatPadsYear) {  // locale specific
    118  absl::TimeZone tz = absl::UTCTimeZone();
    119 
    120  // A year of 77 should be padded to 0077.
    121  absl::Time t = absl::FromCivil(absl::CivilSecond(77, 6, 28, 9, 8, 7), tz);
    122  EXPECT_EQ("Mon, 28 Jun 0077 09:08:07 +0000",
    123            absl::FormatTime(absl::RFC1123_full, t, tz));
    124  EXPECT_EQ("28 Jun 0077 09:08:07 +0000",
    125            absl::FormatTime(absl::RFC1123_no_wday, t, tz));
    126 }
    127 
    128 TEST(FormatTime, InfiniteTime) {
    129  absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
    130 
    131  // The format and timezone are ignored.
    132  EXPECT_EQ("infinite-future",
    133            absl::FormatTime("%H:%M blah", absl::InfiniteFuture(), tz));
    134  EXPECT_EQ("infinite-past",
    135            absl::FormatTime("%H:%M blah", absl::InfinitePast(), tz));
    136 }
    137 
    138 //
    139 // Testing ParseTime()
    140 //
    141 
    142 TEST(ParseTime, Basics) {
    143  absl::Time t = absl::FromTimeT(1234567890);
    144  std::string err;
    145 
    146  // Simple edge cases.
    147  EXPECT_TRUE(absl::ParseTime("", "", &t, &err)) << err;
    148  EXPECT_EQ(absl::UnixEpoch(), t);  // everything defaulted
    149  EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err;
    150  EXPECT_TRUE(absl::ParseTime("  ", "  ", &t, &err)) << err;
    151  EXPECT_TRUE(absl::ParseTime("x", "x", &t, &err)) << err;
    152  EXPECT_TRUE(absl::ParseTime("xxx", "xxx", &t, &err)) << err;
    153 
    154  EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
    155                              "2013-06-28 19:08:09 -0800", &t, &err))
    156      << err;
    157  const auto ci = absl::FixedTimeZone(-8 * 60 * 60).At(t);
    158  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
    159  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
    160 }
    161 
    162 TEST(ParseTime, NullErrorString) {
    163  absl::Time t;
    164  EXPECT_FALSE(absl::ParseTime("%Q", "invalid format", &t, nullptr));
    165  EXPECT_FALSE(absl::ParseTime("%H", "12 trailing data", &t, nullptr));
    166  EXPECT_FALSE(
    167      absl::ParseTime("%H out of range", "42 out of range", &t, nullptr));
    168 }
    169 
    170 TEST(ParseTime, WithTimeZone) {
    171  const absl::TimeZone tz =
    172      absl::time_internal::LoadTimeZone("America/Los_Angeles");
    173  absl::Time t;
    174  std::string e;
    175 
    176  // We can parse a string without a UTC offset if we supply a timezone.
    177  EXPECT_TRUE(
    178      absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
    179      << e;
    180  auto ci = tz.At(t);
    181  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
    182  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
    183 
    184  // But the timezone is ignored when a UTC offset is present.
    185  EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
    186                              "2013-06-28 19:08:09 +0800", tz, &t, &e))
    187      << e;
    188  ci = absl::FixedTimeZone(8 * 60 * 60).At(t);
    189  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
    190  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
    191 }
    192 
    193 TEST(ParseTime, ErrorCases) {
    194  absl::Time t = absl::FromTimeT(0);
    195  std::string err;
    196 
    197  EXPECT_FALSE(absl::ParseTime("%S", "123", &t, &err)) << err;
    198  EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
    199 
    200  // Can't parse an illegal format specifier.
    201  err.clear();
    202  EXPECT_FALSE(absl::ParseTime("%Q", "x", &t, &err)) << err;
    203  // Exact contents of "err" are platform-dependent because of
    204  // differences in the strptime implementation between macOS and Linux.
    205  EXPECT_FALSE(err.empty());
    206 
    207  // Fails because of trailing, unparsed data "blah".
    208  EXPECT_FALSE(absl::ParseTime("%m-%d", "2-3 blah", &t, &err)) << err;
    209  EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
    210 
    211  // Feb 31 requires normalization.
    212  EXPECT_FALSE(absl::ParseTime("%m-%d", "2-31", &t, &err)) << err;
    213  EXPECT_THAT(err, HasSubstr("Out-of-range"));
    214 
    215  // Check that we cannot have spaces in UTC offsets.
    216  EXPECT_TRUE(absl::ParseTime("%z", "-0203", &t, &err)) << err;
    217  EXPECT_FALSE(absl::ParseTime("%z", "- 2 3", &t, &err)) << err;
    218  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    219  EXPECT_TRUE(absl::ParseTime("%Ez", "-02:03", &t, &err)) << err;
    220  EXPECT_FALSE(absl::ParseTime("%Ez", "- 2: 3", &t, &err)) << err;
    221  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    222 
    223  // Check that we reject other malformed UTC offsets.
    224  EXPECT_FALSE(absl::ParseTime("%Ez", "+-08:00", &t, &err)) << err;
    225  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    226  EXPECT_FALSE(absl::ParseTime("%Ez", "-+08:00", &t, &err)) << err;
    227  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    228 
    229  // Check that we do not accept "-0" in fields that allow zero.
    230  EXPECT_FALSE(absl::ParseTime("%Y", "-0", &t, &err)) << err;
    231  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    232  EXPECT_FALSE(absl::ParseTime("%E4Y", "-0", &t, &err)) << err;
    233  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    234  EXPECT_FALSE(absl::ParseTime("%H", "-0", &t, &err)) << err;
    235  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    236  EXPECT_FALSE(absl::ParseTime("%M", "-0", &t, &err)) << err;
    237  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    238  EXPECT_FALSE(absl::ParseTime("%S", "-0", &t, &err)) << err;
    239  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    240  EXPECT_FALSE(absl::ParseTime("%z", "+-000", &t, &err)) << err;
    241  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    242  EXPECT_FALSE(absl::ParseTime("%Ez", "+-0:00", &t, &err)) << err;
    243  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    244  EXPECT_FALSE(absl::ParseTime("%z", "-00-0", &t, &err)) << err;
    245  EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
    246  EXPECT_FALSE(absl::ParseTime("%Ez", "-00:-0", &t, &err)) << err;
    247  EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
    248 }
    249 
    250 TEST(ParseTime, ExtendedSeconds) {
    251  std::string err;
    252  absl::Time t;
    253 
    254  // Here is a "%E*S" case we got wrong for a while.  The fractional
    255  // part of the first instant is less than 2^31 and was correctly
    256  // parsed, while the second (and any subsecond field >=2^31) failed.
    257  t = absl::UnixEpoch();
    258  EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483647", &t, &err)) << err;
    259  EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
    260                absl::Nanoseconds(1) / 2,
    261            t);
    262  t = absl::UnixEpoch();
    263  EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483648", &t, &err)) << err;
    264  EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
    265                absl::Nanoseconds(3) / 4,
    266            t);
    267 
    268  // We should also be able to specify long strings of digits far
    269  // beyond the current resolution and have them convert the same way.
    270  t = absl::UnixEpoch();
    271  EXPECT_TRUE(absl::ParseTime(
    272      "%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
    273      &t, &err))
    274      << err;
    275  EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
    276                absl::Nanoseconds(3) / 4,
    277            t);
    278 }
    279 
    280 TEST(ParseTime, ExtendedOffsetErrors) {
    281  std::string err;
    282  absl::Time t;
    283 
    284  // %z against +-HHMM.
    285  EXPECT_FALSE(absl::ParseTime("%z", "-123", &t, &err)) << err;
    286  EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
    287 
    288  // %z against +-HH.
    289  EXPECT_FALSE(absl::ParseTime("%z", "-1", &t, &err)) << err;
    290  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    291 
    292  // %Ez against +-HH:MM.
    293  EXPECT_FALSE(absl::ParseTime("%Ez", "-12:3", &t, &err)) << err;
    294  EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
    295 
    296  // %Ez against +-HHMM.
    297  EXPECT_FALSE(absl::ParseTime("%Ez", "-123", &t, &err)) << err;
    298  EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
    299 
    300  // %Ez against +-HH.
    301  EXPECT_FALSE(absl::ParseTime("%Ez", "-1", &t, &err)) << err;
    302  EXPECT_THAT(err, HasSubstr("Failed to parse"));
    303 }
    304 
    305 TEST(ParseTime, InfiniteTime) {
    306  absl::Time t;
    307  std::string err;
    308  EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future", &t, &err));
    309  EXPECT_EQ(absl::InfiniteFuture(), t);
    310 
    311  // Surrounding whitespace.
    312  EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-future", &t, &err));
    313  EXPECT_EQ(absl::InfiniteFuture(), t);
    314  EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future  ", &t, &err));
    315  EXPECT_EQ(absl::InfiniteFuture(), t);
    316  EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-future  ", &t, &err));
    317  EXPECT_EQ(absl::InfiniteFuture(), t);
    318 
    319  EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past", &t, &err));
    320  EXPECT_EQ(absl::InfinitePast(), t);
    321 
    322  // Surrounding whitespace.
    323  EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-past", &t, &err));
    324  EXPECT_EQ(absl::InfinitePast(), t);
    325  EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past  ", &t, &err));
    326  EXPECT_EQ(absl::InfinitePast(), t);
    327  EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-past  ", &t, &err));
    328  EXPECT_EQ(absl::InfinitePast(), t);
    329 
    330  // "infinite-future" as literal string
    331  absl::TimeZone tz = absl::UTCTimeZone();
    332  EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
    333                              &t, &err));
    334  EXPECT_NE(absl::InfiniteFuture(), t);
    335  EXPECT_EQ(3, tz.At(t).cs.hour());
    336  EXPECT_EQ(4, tz.At(t).cs.minute());
    337 
    338  // "infinite-past" as literal string
    339  EXPECT_TRUE(
    340      absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
    341  EXPECT_NE(absl::InfinitePast(), t);
    342  EXPECT_EQ(3, tz.At(t).cs.hour());
    343  EXPECT_EQ(4, tz.At(t).cs.minute());
    344 
    345  // The input doesn't match the format.
    346  EXPECT_FALSE(absl::ParseTime("infinite-future %H:%M", "03:04", &t, &err));
    347  EXPECT_FALSE(absl::ParseTime("infinite-past %H:%M", "03:04", &t, &err));
    348 }
    349 
    350 TEST(ParseTime, FailsOnUnrepresentableTime) {
    351  const absl::TimeZone utc = absl::UTCTimeZone();
    352  absl::Time t;
    353  EXPECT_FALSE(
    354      absl::ParseTime("%Y-%m-%d", "-292277022657-01-27", utc, &t, nullptr));
    355  EXPECT_TRUE(
    356      absl::ParseTime("%Y-%m-%d", "-292277022657-01-28", utc, &t, nullptr));
    357  EXPECT_TRUE(
    358      absl::ParseTime("%Y-%m-%d", "292277026596-12-04", utc, &t, nullptr));
    359  EXPECT_FALSE(
    360      absl::ParseTime("%Y-%m-%d", "292277026596-12-05", utc, &t, nullptr));
    361 }
    362 
    363 //
    364 // Roundtrip test for FormatTime()/ParseTime().
    365 //
    366 
    367 TEST(FormatParse, RoundTrip) {
    368  const absl::TimeZone lax =
    369      absl::time_internal::LoadTimeZone("America/Los_Angeles");
    370  const absl::Time in =
    371      absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax);
    372  const absl::Duration subseconds = absl::Nanoseconds(654321);
    373  std::string err;
    374 
    375  // RFC3339, which renders subseconds.
    376  {
    377    absl::Time out;
    378    const std::string s =
    379        absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);
    380    EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
    381        << s << ": " << err;
    382    EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez
    383  }
    384 
    385  // RFC1123, which only does whole seconds.
    386  {
    387    absl::Time out;
    388    const std::string s = absl::FormatTime(absl::RFC1123_full, in, lax);
    389    EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err))
    390        << s << ": " << err;
    391    EXPECT_EQ(in, out);  // RFC1123_full includes %z
    392  }
    393 
    394  // `absl::FormatTime()` falls back to strftime() for "%c", which appears to
    395  // work. On Windows, `absl::ParseTime()` falls back to std::get_time() which
    396  // appears to fail on "%c" (or at least on the "%c" text produced by
    397  // `strftime()`). This makes it fail the round-trip test.
    398  //
    399  // Under the emscripten compiler `absl::ParseTime() falls back to
    400  // `strptime()`, but that ends up using a different definition for "%c"
    401  // compared to `strftime()`, also causing the round-trip test to fail
    402  // (see https://github.com/kripken/emscripten/pull/7491).
    403 #if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
    404  // Even though we don't know what %c will produce, it should roundtrip,
    405  // but only in the 0-offset timezone.
    406  {
    407    absl::Time out;
    408    const std::string s = absl::FormatTime("%c", in, absl::UTCTimeZone());
    409    EXPECT_TRUE(absl::ParseTime("%c", s, &out, &err)) << s << ": " << err;
    410    EXPECT_EQ(in, out);
    411  }
    412 #endif  // !_MSC_VER && !__EMSCRIPTEN__
    413 }
    414 
    415 TEST(FormatParse, RoundTripDistantFuture) {
    416  const absl::TimeZone tz = absl::UTCTimeZone();
    417  const absl::Time in =
    418      absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());
    419  std::string err;
    420 
    421  absl::Time out;
    422  const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
    423  EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
    424      << s << ": " << err;
    425  EXPECT_EQ(in, out);
    426 }
    427 
    428 TEST(FormatParse, RoundTripDistantPast) {
    429  const absl::TimeZone tz = absl::UTCTimeZone();
    430  const absl::Time in =
    431      absl::FromUnixSeconds(std::numeric_limits<int64_t>::min());
    432  std::string err;
    433 
    434  absl::Time out;
    435  const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
    436  EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
    437      << s << ": " << err;
    438  EXPECT_EQ(in, out);
    439 }
    440 
    441 }  // namespace