1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <time.h> 6 7 #include "base/third_party/nspr/prtime.h" 8 #include "base/time.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 using base::Time; 12 13 namespace { 14 15 // time_t representation of 15th Oct 2007 12:45:00 PDT 16 PRTime comparison_time_pdt = 1192477500 * Time::kMicrosecondsPerSecond; 17 18 // Specialized test fixture allowing time strings without timezones to be 19 // tested by comparing them to a known time in the local zone. 20 class PRTimeTest : public testing::Test { 21 protected: 22 virtual void SetUp() { 23 // Use mktime to get a time_t, and turn it into a PRTime by converting 24 // seconds to microseconds. Use 15th Oct 2007 12:45:00 local. This 25 // must be a time guaranteed to be outside of a DST fallback hour in 26 // any timezone. 27 struct tm local_comparison_tm = { 28 0, // second 29 45, // minute 30 12, // hour 31 15, // day of month 32 10 - 1, // month 33 2007 - 1900, // year 34 0, // day of week (ignored, output only) 35 0, // day of year (ignored, output only) 36 -1 // DST in effect, -1 tells mktime to figure it out 37 }; 38 comparison_time_local_ = mktime(&local_comparison_tm) * 39 Time::kMicrosecondsPerSecond; 40 ASSERT_GT(comparison_time_local_, 0); 41 } 42 43 PRTime comparison_time_local_; 44 }; 45 46 // Tests the PR_ParseTimeString nspr helper function for 47 // a variety of time strings. 48 TEST_F(PRTimeTest, ParseTimeTest1) { 49 time_t current_time = 0; 50 time(¤t_time); 51 52 const int BUFFER_SIZE = 64; 53 struct tm local_time = {0}; 54 char time_buf[BUFFER_SIZE] = {0}; 55 #if defined(OS_WIN) 56 localtime_s(&local_time, ¤t_time); 57 asctime_s(time_buf, arraysize(time_buf), &local_time); 58 #elif defined(OS_POSIX) 59 localtime_r(¤t_time, &local_time); 60 asctime_r(&local_time, time_buf); 61 #endif 62 63 PRTime current_time64 = static_cast<PRTime>(current_time) * PR_USEC_PER_SEC; 64 65 PRTime parsed_time = 0; 66 PRStatus result = PR_ParseTimeString(time_buf, PR_FALSE, &parsed_time); 67 EXPECT_EQ(PR_SUCCESS, result); 68 EXPECT_EQ(current_time64, parsed_time); 69 } 70 71 TEST_F(PRTimeTest, ParseTimeTest2) { 72 PRTime parsed_time = 0; 73 PRStatus result = PR_ParseTimeString("Mon, 15 Oct 2007 19:45:00 GMT", 74 PR_FALSE, &parsed_time); 75 EXPECT_EQ(PR_SUCCESS, result); 76 EXPECT_EQ(parsed_time, comparison_time_pdt); 77 } 78 79 TEST_F(PRTimeTest, ParseTimeTest3) { 80 PRTime parsed_time = 0; 81 PRStatus result = PR_ParseTimeString("15 Oct 07 12:45:00", PR_FALSE, 82 &parsed_time); 83 EXPECT_EQ(PR_SUCCESS, result); 84 EXPECT_EQ(parsed_time, comparison_time_local_); 85 } 86 87 TEST_F(PRTimeTest, ParseTimeTest4) { 88 PRTime parsed_time = 0; 89 PRStatus result = PR_ParseTimeString("15 Oct 07 19:45 GMT", PR_FALSE, 90 &parsed_time); 91 EXPECT_EQ(PR_SUCCESS, result); 92 EXPECT_EQ(parsed_time, comparison_time_pdt); 93 } 94 95 TEST_F(PRTimeTest, ParseTimeTest5) { 96 PRTime parsed_time = 0; 97 PRStatus result = PR_ParseTimeString("Mon Oct 15 12:45 PDT 2007", 98 PR_FALSE, &parsed_time); 99 EXPECT_EQ(PR_SUCCESS, result); 100 EXPECT_EQ(parsed_time, comparison_time_pdt); 101 } 102 103 TEST_F(PRTimeTest, ParseTimeTest6) { 104 PRTime parsed_time = 0; 105 PRStatus result = PR_ParseTimeString("Monday, Oct 15, 2007 12:45 PM", 106 PR_FALSE, &parsed_time); 107 EXPECT_EQ(PR_SUCCESS, result); 108 EXPECT_EQ(parsed_time, comparison_time_local_); 109 } 110 111 TEST_F(PRTimeTest, ParseTimeTest7) { 112 PRTime parsed_time = 0; 113 PRStatus result = PR_ParseTimeString("10/15/07 12:45:00 PM", PR_FALSE, 114 &parsed_time); 115 EXPECT_EQ(PR_SUCCESS, result); 116 EXPECT_EQ(parsed_time, comparison_time_local_); 117 } 118 119 TEST_F(PRTimeTest, ParseTimeTest8) { 120 PRTime parsed_time = 0; 121 PRStatus result = PR_ParseTimeString("15-OCT-2007 12:45pm", PR_FALSE, 122 &parsed_time); 123 EXPECT_EQ(PR_SUCCESS, result); 124 EXPECT_EQ(parsed_time, comparison_time_local_); 125 } 126 127 TEST_F(PRTimeTest, ParseTimeTest9) { 128 PRTime parsed_time = 0; 129 PRStatus result = PR_ParseTimeString("16 Oct 2007 4:45-JST (Tuesday)", 130 PR_FALSE, &parsed_time); 131 EXPECT_EQ(PR_SUCCESS, result); 132 EXPECT_EQ(parsed_time, comparison_time_pdt); 133 } 134 135 // This tests the Time::FromString wrapper over PR_ParseTimeString 136 TEST_F(PRTimeTest, ParseTimeTest10) { 137 Time parsed_time; 138 bool result = Time::FromString(L"15/10/07 12:45", &parsed_time); 139 EXPECT_TRUE(result); 140 141 time_t computed_time = parsed_time.ToTimeT(); 142 time_t time_to_compare = comparison_time_local_ / 143 Time::kMicrosecondsPerSecond; 144 EXPECT_EQ(computed_time, time_to_compare); 145 } 146 147 // This tests the Time::FromString wrapper over PR_ParseTimeString 148 TEST_F(PRTimeTest, ParseTimeTest11) { 149 Time parsed_time; 150 bool result = Time::FromString(L"Mon, 15 Oct 2007 19:45:00 GMT", 151 &parsed_time); 152 EXPECT_TRUE(result); 153 154 time_t computed_time = parsed_time.ToTimeT(); 155 time_t time_to_compare = comparison_time_pdt / Time::kMicrosecondsPerSecond; 156 EXPECT_EQ(computed_time, time_to_compare); 157 } 158 159 // Test some of edge cases around epoch, etc. 160 TEST_F(PRTimeTest, ParseTimeTestEpoch0) { 161 Time parsed_time; 162 163 // time_t == epoch == 0 164 EXPECT_TRUE(Time::FromString(L"Thu Jan 01 01:00:00 +0100 1970", 165 &parsed_time)); 166 EXPECT_EQ(0, parsed_time.ToTimeT()); 167 EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:00:00 GMT 1970", 168 &parsed_time)); 169 EXPECT_EQ(0, parsed_time.ToTimeT()); 170 } 171 172 TEST_F(PRTimeTest, ParseTimeTestEpoch1) { 173 Time parsed_time; 174 175 // time_t == 1 second after epoch == 1 176 EXPECT_TRUE(Time::FromString(L"Thu Jan 01 01:00:01 +0100 1970", 177 &parsed_time)); 178 EXPECT_EQ(1, parsed_time.ToTimeT()); 179 EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:00:01 GMT 1970", 180 &parsed_time)); 181 EXPECT_EQ(1, parsed_time.ToTimeT()); 182 } 183 184 TEST_F(PRTimeTest, ParseTimeTestEpoch2) { 185 Time parsed_time; 186 187 // time_t == 2 seconds after epoch == 2 188 EXPECT_TRUE(Time::FromString(L"Thu Jan 01 01:00:02 +0100 1970", 189 &parsed_time)); 190 EXPECT_EQ(2, parsed_time.ToTimeT()); 191 EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:00:02 GMT 1970", 192 &parsed_time)); 193 EXPECT_EQ(2, parsed_time.ToTimeT()); 194 } 195 196 TEST_F(PRTimeTest, ParseTimeTestEpochNeg1) { 197 Time parsed_time; 198 199 // time_t == 1 second before epoch == -1 200 EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:59:59 +0100 1970", 201 &parsed_time)); 202 EXPECT_EQ(-1, parsed_time.ToTimeT()); 203 EXPECT_TRUE(Time::FromString(L"Wed Dec 31 23:59:59 GMT 1969", 204 &parsed_time)); 205 EXPECT_EQ(-1, parsed_time.ToTimeT()); 206 } 207 208 // If time_t is 32 bits, a date after year 2038 will overflow time_t and 209 // cause timegm() to return -1. The parsed time should not be 1 second 210 // before epoch. 211 TEST_F(PRTimeTest, ParseTimeTestEpochNotNeg1) { 212 Time parsed_time; 213 214 EXPECT_TRUE(Time::FromString(L"Wed Dec 31 23:59:59 GMT 2100", 215 &parsed_time)); 216 EXPECT_NE(-1, parsed_time.ToTimeT()); 217 } 218 219 TEST_F(PRTimeTest, ParseTimeTestEpochNeg2) { 220 Time parsed_time; 221 222 // time_t == 2 seconds before epoch == -2 223 EXPECT_TRUE(Time::FromString(L"Thu Jan 01 00:59:58 +0100 1970", 224 &parsed_time)); 225 EXPECT_EQ(-2, parsed_time.ToTimeT()); 226 EXPECT_TRUE(Time::FromString(L"Wed Dec 31 23:59:58 GMT 1969", 227 &parsed_time)); 228 EXPECT_EQ(-2, parsed_time.ToTimeT()); 229 } 230 231 TEST_F(PRTimeTest, ParseTimeTestEpoch1960) { 232 Time parsed_time; 233 234 // time_t before Epoch, in 1960 235 EXPECT_TRUE(Time::FromString(L"Wed Jun 29 19:40:01 +0100 1960", 236 &parsed_time)); 237 EXPECT_EQ(-299999999, parsed_time.ToTimeT()); 238 EXPECT_TRUE(Time::FromString(L"Wed Jun 29 18:40:01 GMT 1960", 239 &parsed_time)); 240 EXPECT_EQ(-299999999, parsed_time.ToTimeT()); 241 EXPECT_TRUE(Time::FromString(L"Wed Jun 29 17:40:01 GMT 1960", 242 &parsed_time)); 243 EXPECT_EQ(-300003599, parsed_time.ToTimeT()); 244 } 245 246 TEST_F(PRTimeTest, ParseTimeTestEmpty) { 247 Time parsed_time; 248 EXPECT_FALSE(Time::FromString(L"", &parsed_time)); 249 } 250 251 // This test should not crash when compiled with Visual C++ 2005 (see 252 // http://crbug.com/4387). 253 TEST_F(PRTimeTest, ParseTimeTestOutOfRange) { 254 PRTime parsed_time = 0; 255 // Note the lack of timezone in the time string. The year has to be 3001. 256 // The date has to be after 23:59:59, December 31, 3000, US Pacific Time, so 257 // we use January 2, 3001 to make sure it's after the magic maximum in any 258 // timezone. 259 PRStatus result = PR_ParseTimeString("Sun Jan 2 00:00:00 3001", 260 PR_FALSE, &parsed_time); 261 EXPECT_EQ(PR_SUCCESS, result); 262 } 263 264 TEST_F(PRTimeTest, ParseTimeTestNotNormalized1) { 265 PRTime parsed_time = 0; 266 PRStatus result = PR_ParseTimeString("Mon Oct 15 12:44:60 PDT 2007", 267 PR_FALSE, &parsed_time); 268 EXPECT_EQ(PR_SUCCESS, result); 269 EXPECT_EQ(comparison_time_pdt, parsed_time); 270 } 271 272 TEST_F(PRTimeTest, ParseTimeTestNotNormalized2) { 273 PRTime parsed_time = 0; 274 PRStatus result = PR_ParseTimeString("Sun Oct 14 36:45 PDT 2007", 275 PR_FALSE, &parsed_time); 276 EXPECT_EQ(PR_SUCCESS, result); 277 EXPECT_EQ(comparison_time_pdt, parsed_time); 278 } 279 280 } // namespace 281