1 // Copyright (c) 2012 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 <stdint.h>
6 #include <time.h>
7 
8 #include "base/compiler_specific.h"
9 #include "base/macros.h"
10 #include "base/third_party/nspr/prtime.h"
11 #include "base/time/time.h"
12 #include "build/build_config.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 using base::Time;
16 
17 namespace {
18 
19 // time_t representation of 15th Oct 2007 12:45:00 PDT
20 PRTime comparison_time_pdt = 1192477500 * Time::kMicrosecondsPerSecond;
21 
22 // Time with positive tz offset and fractional seconds:
23 // 2013-07-08T11:28:12.441381+02:00
24 PRTime comparison_time_2 = INT64_C(1373275692441381);   // represented as GMT
25 
26 // Specialized test fixture allowing time strings without timezones to be
27 // tested by comparing them to a known time in the local zone.
28 class PRTimeTest : public testing::Test {
29  protected:
SetUp()30   void SetUp() override {
31     // Use mktime to get a time_t, and turn it into a PRTime by converting
32     // seconds to microseconds.  Use 15th Oct 2007 12:45:00 local.  This
33     // must be a time guaranteed to be outside of a DST fallback hour in
34     // any timezone.
35     struct tm local_comparison_tm = {
36       0,            // second
37       45,           // minute
38       12,           // hour
39       15,           // day of month
40       10 - 1,       // month
41       2007 - 1900,  // year
42       0,            // day of week (ignored, output only)
43       0,            // day of year (ignored, output only)
44       -1            // DST in effect, -1 tells mktime to figure it out
45     };
46     comparison_time_local_ =
47         mktime(&local_comparison_tm) * Time::kMicrosecondsPerSecond;
48     ASSERT_GT(comparison_time_local_, 0);
49 
50     const int microseconds = 441381;
51     struct tm local_comparison_tm_2 = {
52       12,           // second
53       28,           // minute
54       11,           // hour
55       8,            // day of month
56       7 - 1,        // month
57       2013 - 1900,  // year
58       0,            // day of week (ignored, output only)
59       0,            // day of year (ignored, output only)
60       -1            // DST in effect, -1 tells mktime to figure it out
61     };
62     comparison_time_local_2_ =
63         mktime(&local_comparison_tm_2) * Time::kMicrosecondsPerSecond;
64     ASSERT_GT(comparison_time_local_2_, 0);
65     comparison_time_local_2_ += microseconds;
66   }
67 
68   PRTime comparison_time_local_;
69   PRTime comparison_time_local_2_;
70 };
71 
72 // Tests the PR_ParseTimeString nspr helper function for
73 // a variety of time strings.
TEST_F(PRTimeTest,ParseTimeTest1)74 TEST_F(PRTimeTest, ParseTimeTest1) {
75   time_t current_time = 0;
76   time(&current_time);
77 
78   const int BUFFER_SIZE = 64;
79   struct tm local_time = {0};
80   char time_buf[BUFFER_SIZE] = {0};
81 #if defined(OS_WIN)
82   localtime_s(&local_time, &current_time);
83   asctime_s(time_buf, arraysize(time_buf), &local_time);
84 #elif defined(OS_POSIX)
85   localtime_r(&current_time, &local_time);
86   asctime_r(&local_time, time_buf);
87 #endif
88 
89   PRTime current_time64 = static_cast<PRTime>(current_time) * PR_USEC_PER_SEC;
90 
91   PRTime parsed_time = 0;
92   PRStatus result = PR_ParseTimeString(time_buf, PR_FALSE, &parsed_time);
93   EXPECT_EQ(PR_SUCCESS, result);
94   EXPECT_EQ(current_time64, parsed_time);
95 }
96 
TEST_F(PRTimeTest,ParseTimeTest2)97 TEST_F(PRTimeTest, ParseTimeTest2) {
98   PRTime parsed_time = 0;
99   PRStatus result = PR_ParseTimeString("Mon, 15 Oct 2007 19:45:00 GMT",
100                                        PR_FALSE, &parsed_time);
101   EXPECT_EQ(PR_SUCCESS, result);
102   EXPECT_EQ(comparison_time_pdt, parsed_time);
103 }
104 
TEST_F(PRTimeTest,ParseTimeTest3)105 TEST_F(PRTimeTest, ParseTimeTest3) {
106   PRTime parsed_time = 0;
107   PRStatus result = PR_ParseTimeString("15 Oct 07 12:45:00", PR_FALSE,
108                                        &parsed_time);
109   EXPECT_EQ(PR_SUCCESS, result);
110   EXPECT_EQ(comparison_time_local_, parsed_time);
111 }
112 
TEST_F(PRTimeTest,ParseTimeTest4)113 TEST_F(PRTimeTest, ParseTimeTest4) {
114   PRTime parsed_time = 0;
115   PRStatus result = PR_ParseTimeString("15 Oct 07 19:45 GMT", PR_FALSE,
116                                        &parsed_time);
117   EXPECT_EQ(PR_SUCCESS, result);
118   EXPECT_EQ(comparison_time_pdt, parsed_time);
119 }
120 
TEST_F(PRTimeTest,ParseTimeTest5)121 TEST_F(PRTimeTest, ParseTimeTest5) {
122   PRTime parsed_time = 0;
123   PRStatus result = PR_ParseTimeString("Mon Oct 15 12:45 PDT 2007",
124                                        PR_FALSE, &parsed_time);
125   EXPECT_EQ(PR_SUCCESS, result);
126   EXPECT_EQ(comparison_time_pdt, parsed_time);
127 }
128 
TEST_F(PRTimeTest,ParseTimeTest6)129 TEST_F(PRTimeTest, ParseTimeTest6) {
130   PRTime parsed_time = 0;
131   PRStatus result = PR_ParseTimeString("Monday, Oct 15, 2007 12:45 PM",
132                                        PR_FALSE, &parsed_time);
133   EXPECT_EQ(PR_SUCCESS, result);
134   EXPECT_EQ(comparison_time_local_, parsed_time);
135 }
136 
TEST_F(PRTimeTest,ParseTimeTest7)137 TEST_F(PRTimeTest, ParseTimeTest7) {
138   PRTime parsed_time = 0;
139   PRStatus result = PR_ParseTimeString("10/15/07 12:45:00 PM", PR_FALSE,
140                                        &parsed_time);
141   EXPECT_EQ(PR_SUCCESS, result);
142   EXPECT_EQ(comparison_time_local_, parsed_time);
143 }
144 
TEST_F(PRTimeTest,ParseTimeTest8)145 TEST_F(PRTimeTest, ParseTimeTest8) {
146   PRTime parsed_time = 0;
147   PRStatus result = PR_ParseTimeString("10/15/07 12:45:00. PM", PR_FALSE,
148                                        &parsed_time);
149   EXPECT_EQ(PR_SUCCESS, result);
150   EXPECT_EQ(comparison_time_local_, parsed_time);
151 }
152 
TEST_F(PRTimeTest,ParseTimeTest9)153 TEST_F(PRTimeTest, ParseTimeTest9) {
154   PRTime parsed_time = 0;
155   PRStatus result = PR_ParseTimeString("10/15/07 12:45:00.0 PM", PR_FALSE,
156                                        &parsed_time);
157   EXPECT_EQ(PR_SUCCESS, result);
158   EXPECT_EQ(comparison_time_local_, parsed_time);
159 }
160 
TEST_F(PRTimeTest,ParseTimeTest10)161 TEST_F(PRTimeTest, ParseTimeTest10) {
162   PRTime parsed_time = 0;
163   PRStatus result = PR_ParseTimeString("15-OCT-2007 12:45pm", PR_FALSE,
164                                        &parsed_time);
165   EXPECT_EQ(PR_SUCCESS, result);
166   EXPECT_EQ(comparison_time_local_, parsed_time);
167 }
168 
TEST_F(PRTimeTest,ParseTimeTest11)169 TEST_F(PRTimeTest, ParseTimeTest11) {
170   PRTime parsed_time = 0;
171   PRStatus result = PR_ParseTimeString("16 Oct 2007 4:45-JST (Tuesday)",
172                                        PR_FALSE, &parsed_time);
173   EXPECT_EQ(PR_SUCCESS, result);
174   EXPECT_EQ(comparison_time_pdt, parsed_time);
175 }
176 
177 // hh:mm timezone offset.
TEST_F(PRTimeTest,ParseTimeTest12)178 TEST_F(PRTimeTest, ParseTimeTest12) {
179   PRTime parsed_time = 0;
180   PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381+02:00",
181                                        PR_FALSE, &parsed_time);
182   EXPECT_EQ(PR_SUCCESS, result);
183   EXPECT_EQ(comparison_time_2, parsed_time);
184 }
185 
186 // hhmm timezone offset.
TEST_F(PRTimeTest,ParseTimeTest13)187 TEST_F(PRTimeTest, ParseTimeTest13) {
188   PRTime parsed_time = 0;
189   PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381+0200",
190                                        PR_FALSE, &parsed_time);
191   EXPECT_EQ(PR_SUCCESS, result);
192   EXPECT_EQ(comparison_time_2, parsed_time);
193 }
194 
195 // hh timezone offset.
TEST_F(PRTimeTest,ParseTimeTest14)196 TEST_F(PRTimeTest, ParseTimeTest14) {
197   PRTime parsed_time = 0;
198   PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.4413819+02",
199                                        PR_FALSE, &parsed_time);
200   EXPECT_EQ(PR_SUCCESS, result);
201   EXPECT_EQ(comparison_time_2, parsed_time);
202 }
203 
204 // 5 digits fractional second.
TEST_F(PRTimeTest,ParseTimeTest15)205 TEST_F(PRTimeTest, ParseTimeTest15) {
206   PRTime parsed_time = 0;
207   PRStatus result = PR_ParseTimeString("2013-07-08T09:28:12.44138Z",
208                                        PR_FALSE, &parsed_time);
209   EXPECT_EQ(PR_SUCCESS, result);
210   EXPECT_EQ(comparison_time_2-1, parsed_time);
211 }
212 
213 // Fractional seconds, local timezone.
TEST_F(PRTimeTest,ParseTimeTest16)214 TEST_F(PRTimeTest, ParseTimeTest16) {
215   PRTime parsed_time = 0;
216   PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381",
217                                        PR_FALSE, &parsed_time);
218   EXPECT_EQ(PR_SUCCESS, result);
219   EXPECT_EQ(comparison_time_local_2_, parsed_time);
220 }
221 
222 // "Z" (=GMT) timezone.
TEST_F(PRTimeTest,ParseTimeTest17)223 TEST_F(PRTimeTest, ParseTimeTest17) {
224   PRTime parsed_time = 0;
225   PRStatus result = PR_ParseTimeString("2013-07-08T09:28:12.441381Z",
226                                        PR_FALSE, &parsed_time);
227   EXPECT_EQ(PR_SUCCESS, result);
228   EXPECT_EQ(comparison_time_2, parsed_time);
229 }
230 
231 // "T" delimiter replaced by space.
TEST_F(PRTimeTest,ParseTimeTest18)232 TEST_F(PRTimeTest, ParseTimeTest18) {
233   PRTime parsed_time = 0;
234   PRStatus result = PR_ParseTimeString("2013-07-08 09:28:12.441381Z",
235                                        PR_FALSE, &parsed_time);
236   EXPECT_EQ(PR_SUCCESS, result);
237   EXPECT_EQ(comparison_time_2, parsed_time);
238 }
239 
TEST_F(PRTimeTest,ParseTimeTestInvalid1)240 TEST_F(PRTimeTest, ParseTimeTestInvalid1) {
241   PRTime parsed_time = 0;
242   PRStatus result = PR_ParseTimeString("201-07-08T09:28:12.441381Z",
243                                        PR_FALSE, &parsed_time);
244   EXPECT_EQ(PR_FAILURE, result);
245 }
246 
TEST_F(PRTimeTest,ParseTimeTestInvalid2)247 TEST_F(PRTimeTest, ParseTimeTestInvalid2) {
248   PRTime parsed_time = 0;
249   PRStatus result = PR_ParseTimeString("2013-007-08T09:28:12.441381Z",
250                                        PR_FALSE, &parsed_time);
251   EXPECT_EQ(PR_FAILURE, result);
252 }
253 
TEST_F(PRTimeTest,ParseTimeTestInvalid3)254 TEST_F(PRTimeTest, ParseTimeTestInvalid3) {
255   PRTime parsed_time = 0;
256   PRStatus result = PR_ParseTimeString("2013-07-008T09:28:12.441381Z",
257                                        PR_FALSE, &parsed_time);
258   EXPECT_EQ(PR_FAILURE, result);
259 }
260 
261 // This test should not crash when compiled with Visual C++ 2005 (see
262 // http://crbug.com/4387).
TEST_F(PRTimeTest,ParseTimeTestOutOfRange)263 TEST_F(PRTimeTest, ParseTimeTestOutOfRange) {
264   PRTime parsed_time = 0;
265   // Note the lack of timezone in the time string.  The year has to be 3001.
266   // The date has to be after 23:59:59, December 31, 3000, US Pacific Time, so
267   // we use January 2, 3001 to make sure it's after the magic maximum in any
268   // timezone.
269   PRStatus result = PR_ParseTimeString("Sun Jan  2 00:00:00 3001",
270                                        PR_FALSE, &parsed_time);
271   EXPECT_EQ(PR_SUCCESS, result);
272 }
273 
TEST_F(PRTimeTest,ParseTimeTestNotNormalized1)274 TEST_F(PRTimeTest, ParseTimeTestNotNormalized1) {
275   PRTime parsed_time = 0;
276   PRStatus result = PR_ParseTimeString("Mon Oct 15 12:44:60 PDT 2007",
277                                        PR_FALSE, &parsed_time);
278   EXPECT_EQ(PR_SUCCESS, result);
279   EXPECT_EQ(comparison_time_pdt, parsed_time);
280 }
281 
TEST_F(PRTimeTest,ParseTimeTestNotNormalized2)282 TEST_F(PRTimeTest, ParseTimeTestNotNormalized2) {
283   PRTime parsed_time = 0;
284   PRStatus result = PR_ParseTimeString("Sun Oct 14 36:45 PDT 2007",
285                                        PR_FALSE, &parsed_time);
286   EXPECT_EQ(PR_SUCCESS, result);
287   EXPECT_EQ(comparison_time_pdt, parsed_time);
288 }
289 
290 }  // namespace
291