format_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include <cstdint>
00016 #include <limits>
00017 #include <string>
00018 
00019 #include "gmock/gmock.h"
00020 #include "gtest/gtest.h"
00021 #include "absl/time/internal/test_util.h"
00022 #include "absl/time/time.h"
00023 
00024 using testing::HasSubstr;
00025 
00026 namespace {
00027 
00028 // A helper that tests the given format specifier by itself, and with leading
00029 // and trailing characters.  For example: TestFormatSpecifier(t, "%a", "Thu").
00030 void TestFormatSpecifier(absl::Time t, absl::TimeZone tz,
00031                          const std::string& fmt, const std::string& ans) {
00032   EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));
00033   EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz));
00034   EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz));
00035   EXPECT_EQ("xxx " + ans + " yyy",
00036             absl::FormatTime("xxx " + fmt + " yyy", t, tz));
00037 }
00038 
00039 //
00040 // Testing FormatTime()
00041 //
00042 
00043 TEST(FormatTime, Basics) {
00044   absl::TimeZone tz = absl::UTCTimeZone();
00045   absl::Time t = absl::FromTimeT(0);
00046 
00047   // Starts with a couple basic edge cases.
00048   EXPECT_EQ("", absl::FormatTime("", t, tz));
00049   EXPECT_EQ(" ", absl::FormatTime(" ", t, tz));
00050   EXPECT_EQ("  ", absl::FormatTime("  ", t, tz));
00051   EXPECT_EQ("xxx", absl::FormatTime("xxx", t, tz));
00052   std::string big(128, 'x');
00053   EXPECT_EQ(big, absl::FormatTime(big, t, tz));
00054   // Cause the 1024-byte buffer to grow.
00055   std::string bigger(100000, 'x');
00056   EXPECT_EQ(bigger, absl::FormatTime(bigger, t, tz));
00057 
00058   t += absl::Hours(13) + absl::Minutes(4) + absl::Seconds(5);
00059   t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
00060   EXPECT_EQ("1970-01-01", absl::FormatTime("%Y-%m-%d", t, tz));
00061   EXPECT_EQ("13:04:05", absl::FormatTime("%H:%M:%S", t, tz));
00062   EXPECT_EQ("13:04:05.006", absl::FormatTime("%H:%M:%E3S", t, tz));
00063   EXPECT_EQ("13:04:05.006007", absl::FormatTime("%H:%M:%E6S", t, tz));
00064   EXPECT_EQ("13:04:05.006007008", absl::FormatTime("%H:%M:%E9S", t, tz));
00065 }
00066 
00067 TEST(FormatTime, LocaleSpecific) {
00068   const absl::TimeZone tz = absl::UTCTimeZone();
00069   absl::Time t = absl::FromTimeT(0);
00070 
00071   TestFormatSpecifier(t, tz, "%a", "Thu");
00072   TestFormatSpecifier(t, tz, "%A", "Thursday");
00073   TestFormatSpecifier(t, tz, "%b", "Jan");
00074   TestFormatSpecifier(t, tz, "%B", "January");
00075 
00076   // %c should at least produce the numeric year and time-of-day.
00077   const std::string s =
00078       absl::FormatTime("%c", absl::FromTimeT(0), absl::UTCTimeZone());
00079   EXPECT_THAT(s, HasSubstr("1970"));
00080   EXPECT_THAT(s, HasSubstr("00:00:00"));
00081 
00082   TestFormatSpecifier(t, tz, "%p", "AM");
00083   TestFormatSpecifier(t, tz, "%x", "01/01/70");
00084   TestFormatSpecifier(t, tz, "%X", "00:00:00");
00085 }
00086 
00087 TEST(FormatTime, ExtendedSeconds) {
00088   const absl::TimeZone tz = absl::UTCTimeZone();
00089 
00090   // No subseconds.
00091   absl::Time t = absl::FromTimeT(0) + absl::Seconds(5);
00092   EXPECT_EQ("05", absl::FormatTime("%E*S", t, tz));
00093   EXPECT_EQ("05.000000000000000", absl::FormatTime("%E15S", t, tz));
00094 
00095   // With subseconds.
00096   t += absl::Milliseconds(6) + absl::Microseconds(7) + absl::Nanoseconds(8);
00097   EXPECT_EQ("05.006007008", absl::FormatTime("%E*S", t, tz));
00098   EXPECT_EQ("05", absl::FormatTime("%E0S", t, tz));
00099   EXPECT_EQ("05.006007008000000", absl::FormatTime("%E15S", t, tz));
00100 
00101   // Times before the Unix epoch.
00102   t = absl::FromUnixMicros(-1);
00103   EXPECT_EQ("1969-12-31 23:59:59.999999",
00104             absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
00105 
00106   // Here is a "%E*S" case we got wrong for a while.  While the first
00107   // instant below is correctly rendered as "...:07.333304", the second
00108   // one used to appear as "...:07.33330499999999999".
00109   t = absl::FromUnixMicros(1395024427333304);
00110   EXPECT_EQ("2014-03-17 02:47:07.333304",
00111             absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
00112   t += absl::Microseconds(1);
00113   EXPECT_EQ("2014-03-17 02:47:07.333305",
00114             absl::FormatTime("%Y-%m-%d %H:%M:%E*S", t, tz));
00115 }
00116 
00117 TEST(FormatTime, RFC1123FormatPadsYear) {  // locale specific
00118   absl::TimeZone tz = absl::UTCTimeZone();
00119 
00120   // A year of 77 should be padded to 0077.
00121   absl::Time t = absl::FromCivil(absl::CivilSecond(77, 6, 28, 9, 8, 7), tz);
00122   EXPECT_EQ("Mon, 28 Jun 0077 09:08:07 +0000",
00123             absl::FormatTime(absl::RFC1123_full, t, tz));
00124   EXPECT_EQ("28 Jun 0077 09:08:07 +0000",
00125             absl::FormatTime(absl::RFC1123_no_wday, t, tz));
00126 }
00127 
00128 TEST(FormatTime, InfiniteTime) {
00129   absl::TimeZone tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
00130 
00131   // The format and timezone are ignored.
00132   EXPECT_EQ("infinite-future",
00133             absl::FormatTime("%H:%M blah", absl::InfiniteFuture(), tz));
00134   EXPECT_EQ("infinite-past",
00135             absl::FormatTime("%H:%M blah", absl::InfinitePast(), tz));
00136 }
00137 
00138 //
00139 // Testing ParseTime()
00140 //
00141 
00142 TEST(ParseTime, Basics) {
00143   absl::Time t = absl::FromTimeT(1234567890);
00144   std::string err;
00145 
00146   // Simple edge cases.
00147   EXPECT_TRUE(absl::ParseTime("", "", &t, &err)) << err;
00148   EXPECT_EQ(absl::UnixEpoch(), t);  // everything defaulted
00149   EXPECT_TRUE(absl::ParseTime(" ", " ", &t, &err)) << err;
00150   EXPECT_TRUE(absl::ParseTime("  ", "  ", &t, &err)) << err;
00151   EXPECT_TRUE(absl::ParseTime("x", "x", &t, &err)) << err;
00152   EXPECT_TRUE(absl::ParseTime("xxx", "xxx", &t, &err)) << err;
00153 
00154   EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
00155                               "2013-06-28 19:08:09 -0800", &t, &err))
00156       << err;
00157   const auto ci = absl::FixedTimeZone(-8 * 60 * 60).At(t);
00158   EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
00159   EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
00160 }
00161 
00162 TEST(ParseTime, NullErrorString) {
00163   absl::Time t;
00164   EXPECT_FALSE(absl::ParseTime("%Q", "invalid format", &t, nullptr));
00165   EXPECT_FALSE(absl::ParseTime("%H", "12 trailing data", &t, nullptr));
00166   EXPECT_FALSE(
00167       absl::ParseTime("%H out of range", "42 out of range", &t, nullptr));
00168 }
00169 
00170 TEST(ParseTime, WithTimeZone) {
00171   const absl::TimeZone tz =
00172       absl::time_internal::LoadTimeZone("America/Los_Angeles");
00173   absl::Time t;
00174   std::string e;
00175 
00176   // We can parse a std::string without a UTC offset if we supply a timezone.
00177   EXPECT_TRUE(
00178       absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
00179       << e;
00180   auto ci = tz.At(t);
00181   EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
00182   EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
00183 
00184   // But the timezone is ignored when a UTC offset is present.
00185   EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
00186                               "2013-06-28 19:08:09 +0800", tz, &t, &e))
00187       << e;
00188   ci = absl::FixedTimeZone(8 * 60 * 60).At(t);
00189   EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
00190   EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
00191 }
00192 
00193 TEST(ParseTime, ErrorCases) {
00194   absl::Time t = absl::FromTimeT(0);
00195   std::string err;
00196 
00197   EXPECT_FALSE(absl::ParseTime("%S", "123", &t, &err)) << err;
00198   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
00199 
00200   // Can't parse an illegal format specifier.
00201   err.clear();
00202   EXPECT_FALSE(absl::ParseTime("%Q", "x", &t, &err)) << err;
00203   // Exact contents of "err" are platform-dependent because of
00204   // differences in the strptime implementation between OSX and Linux.
00205   EXPECT_FALSE(err.empty());
00206 
00207   // Fails because of trailing, unparsed data "blah".
00208   EXPECT_FALSE(absl::ParseTime("%m-%d", "2-3 blah", &t, &err)) << err;
00209   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
00210 
00211   // Feb 31 requires normalization.
00212   EXPECT_FALSE(absl::ParseTime("%m-%d", "2-31", &t, &err)) << err;
00213   EXPECT_THAT(err, HasSubstr("Out-of-range"));
00214 
00215   // Check that we cannot have spaces in UTC offsets.
00216   EXPECT_TRUE(absl::ParseTime("%z", "-0203", &t, &err)) << err;
00217   EXPECT_FALSE(absl::ParseTime("%z", "- 2 3", &t, &err)) << err;
00218   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00219   EXPECT_TRUE(absl::ParseTime("%Ez", "-02:03", &t, &err)) << err;
00220   EXPECT_FALSE(absl::ParseTime("%Ez", "- 2: 3", &t, &err)) << err;
00221   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00222 
00223   // Check that we reject other malformed UTC offsets.
00224   EXPECT_FALSE(absl::ParseTime("%Ez", "+-08:00", &t, &err)) << err;
00225   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00226   EXPECT_FALSE(absl::ParseTime("%Ez", "-+08:00", &t, &err)) << err;
00227   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00228 
00229   // Check that we do not accept "-0" in fields that allow zero.
00230   EXPECT_FALSE(absl::ParseTime("%Y", "-0", &t, &err)) << err;
00231   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00232   EXPECT_FALSE(absl::ParseTime("%E4Y", "-0", &t, &err)) << err;
00233   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00234   EXPECT_FALSE(absl::ParseTime("%H", "-0", &t, &err)) << err;
00235   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00236   EXPECT_FALSE(absl::ParseTime("%M", "-0", &t, &err)) << err;
00237   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00238   EXPECT_FALSE(absl::ParseTime("%S", "-0", &t, &err)) << err;
00239   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00240   EXPECT_FALSE(absl::ParseTime("%z", "+-000", &t, &err)) << err;
00241   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00242   EXPECT_FALSE(absl::ParseTime("%Ez", "+-0:00", &t, &err)) << err;
00243   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00244   EXPECT_FALSE(absl::ParseTime("%z", "-00-0", &t, &err)) << err;
00245   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
00246   EXPECT_FALSE(absl::ParseTime("%Ez", "-00:-0", &t, &err)) << err;
00247   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
00248 }
00249 
00250 TEST(ParseTime, ExtendedSeconds) {
00251   std::string err;
00252   absl::Time t;
00253 
00254   // Here is a "%E*S" case we got wrong for a while.  The fractional
00255   // part of the first instant is less than 2^31 and was correctly
00256   // parsed, while the second (and any subsecond field >=2^31) failed.
00257   t = absl::UnixEpoch();
00258   EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483647", &t, &err)) << err;
00259   EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
00260                 absl::Nanoseconds(1) / 2,
00261             t);
00262   t = absl::UnixEpoch();
00263   EXPECT_TRUE(absl::ParseTime("%E*S", "0.2147483648", &t, &err)) << err;
00264   EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
00265                 absl::Nanoseconds(3) / 4,
00266             t);
00267 
00268   // We should also be able to specify long strings of digits far
00269   // beyond the current resolution and have them convert the same way.
00270   t = absl::UnixEpoch();
00271   EXPECT_TRUE(absl::ParseTime(
00272       "%E*S", "0.214748364801234567890123456789012345678901234567890123456789",
00273       &t, &err))
00274       << err;
00275   EXPECT_EQ(absl::UnixEpoch() + absl::Nanoseconds(214748364) +
00276                 absl::Nanoseconds(3) / 4,
00277             t);
00278 }
00279 
00280 TEST(ParseTime, ExtendedOffsetErrors) {
00281   std::string err;
00282   absl::Time t;
00283 
00284   // %z against +-HHMM.
00285   EXPECT_FALSE(absl::ParseTime("%z", "-123", &t, &err)) << err;
00286   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
00287 
00288   // %z against +-HH.
00289   EXPECT_FALSE(absl::ParseTime("%z", "-1", &t, &err)) << err;
00290   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00291 
00292   // %Ez against +-HH:MM.
00293   EXPECT_FALSE(absl::ParseTime("%Ez", "-12:3", &t, &err)) << err;
00294   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
00295 
00296   // %Ez against +-HHMM.
00297   EXPECT_FALSE(absl::ParseTime("%Ez", "-123", &t, &err)) << err;
00298   EXPECT_THAT(err, HasSubstr("Illegal trailing data"));
00299 
00300   // %Ez against +-HH.
00301   EXPECT_FALSE(absl::ParseTime("%Ez", "-1", &t, &err)) << err;
00302   EXPECT_THAT(err, HasSubstr("Failed to parse"));
00303 }
00304 
00305 TEST(ParseTime, InfiniteTime) {
00306   absl::Time t;
00307   std::string err;
00308   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future", &t, &err));
00309   EXPECT_EQ(absl::InfiniteFuture(), t);
00310 
00311   // Surrounding whitespace.
00312   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-future", &t, &err));
00313   EXPECT_EQ(absl::InfiniteFuture(), t);
00314   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-future  ", &t, &err));
00315   EXPECT_EQ(absl::InfiniteFuture(), t);
00316   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-future  ", &t, &err));
00317   EXPECT_EQ(absl::InfiniteFuture(), t);
00318 
00319   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past", &t, &err));
00320   EXPECT_EQ(absl::InfinitePast(), t);
00321 
00322   // Surrounding whitespace.
00323   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-past", &t, &err));
00324   EXPECT_EQ(absl::InfinitePast(), t);
00325   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "infinite-past  ", &t, &err));
00326   EXPECT_EQ(absl::InfinitePast(), t);
00327   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-past  ", &t, &err));
00328   EXPECT_EQ(absl::InfinitePast(), t);
00329 
00330   // "infinite-future" as literal std::string
00331   absl::TimeZone tz = absl::UTCTimeZone();
00332   EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
00333                               &t, &err));
00334   EXPECT_NE(absl::InfiniteFuture(), t);
00335   EXPECT_EQ(3, tz.At(t).cs.hour());
00336   EXPECT_EQ(4, tz.At(t).cs.minute());
00337 
00338   // "infinite-past" as literal std::string
00339   EXPECT_TRUE(
00340       absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
00341   EXPECT_NE(absl::InfinitePast(), t);
00342   EXPECT_EQ(3, tz.At(t).cs.hour());
00343   EXPECT_EQ(4, tz.At(t).cs.minute());
00344 
00345   // The input doesn't match the format.
00346   EXPECT_FALSE(absl::ParseTime("infinite-future %H:%M", "03:04", &t, &err));
00347   EXPECT_FALSE(absl::ParseTime("infinite-past %H:%M", "03:04", &t, &err));
00348 }
00349 
00350 TEST(ParseTime, FailsOnUnrepresentableTime) {
00351   const absl::TimeZone utc = absl::UTCTimeZone();
00352   absl::Time t;
00353   EXPECT_FALSE(
00354       absl::ParseTime("%Y-%m-%d", "-292277022657-01-27", utc, &t, nullptr));
00355   EXPECT_TRUE(
00356       absl::ParseTime("%Y-%m-%d", "-292277022657-01-28", utc, &t, nullptr));
00357   EXPECT_TRUE(
00358       absl::ParseTime("%Y-%m-%d", "292277026596-12-04", utc, &t, nullptr));
00359   EXPECT_FALSE(
00360       absl::ParseTime("%Y-%m-%d", "292277026596-12-05", utc, &t, nullptr));
00361 }
00362 
00363 //
00364 // Roundtrip test for FormatTime()/ParseTime().
00365 //
00366 
00367 TEST(FormatParse, RoundTrip) {
00368   const absl::TimeZone lax =
00369       absl::time_internal::LoadTimeZone("America/Los_Angeles");
00370   const absl::Time in =
00371       absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax);
00372   const absl::Duration subseconds = absl::Nanoseconds(654321);
00373   std::string err;
00374 
00375   // RFC3339, which renders subseconds.
00376   {
00377     absl::Time out;
00378     const std::string s =
00379         absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);
00380     EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
00381         << s << ": " << err;
00382     EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez
00383   }
00384 
00385   // RFC1123, which only does whole seconds.
00386   {
00387     absl::Time out;
00388     const std::string s = absl::FormatTime(absl::RFC1123_full, in, lax);
00389     EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err))
00390         << s << ": " << err;
00391     EXPECT_EQ(in, out);  // RFC1123_full includes %z
00392   }
00393 
00394   // `absl::FormatTime()` falls back to strftime() for "%c", which appears to
00395   // work. On Windows, `absl::ParseTime()` falls back to std::get_time() which
00396   // appears to fail on "%c" (or at least on the "%c" text produced by
00397   // `strftime()`). This makes it fail the round-trip test.
00398   //
00399   // Under the emscripten compiler `absl::ParseTime() falls back to
00400   // `strptime()`, but that ends up using a different definition for "%c"
00401   // compared to `strftime()`, also causing the round-trip test to fail
00402   // (see https://github.com/kripken/emscripten/pull/7491).
00403 #if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
00404   // Even though we don't know what %c will produce, it should roundtrip,
00405   // but only in the 0-offset timezone.
00406   {
00407     absl::Time out;
00408     const std::string s = absl::FormatTime("%c", in, absl::UTCTimeZone());
00409     EXPECT_TRUE(absl::ParseTime("%c", s, &out, &err)) << s << ": " << err;
00410     EXPECT_EQ(in, out);
00411   }
00412 #endif  // !_MSC_VER && !__EMSCRIPTEN__
00413 }
00414 
00415 TEST(FormatParse, RoundTripDistantFuture) {
00416   const absl::TimeZone tz = absl::UTCTimeZone();
00417   const absl::Time in =
00418       absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());
00419   std::string err;
00420 
00421   absl::Time out;
00422   const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
00423   EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
00424       << s << ": " << err;
00425   EXPECT_EQ(in, out);
00426 }
00427 
00428 TEST(FormatParse, RoundTripDistantPast) {
00429   const absl::TimeZone tz = absl::UTCTimeZone();
00430   const absl::Time in =
00431       absl::FromUnixSeconds(std::numeric_limits<int64_t>::min());
00432   std::string err;
00433 
00434   absl::Time out;
00435   const std::string s = absl::FormatTime(absl::RFC3339_full, in, tz);
00436   EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
00437       << s << ": " << err;
00438   EXPECT_EQ(in, out);
00439 }
00440 
00441 }  // namespace


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14