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(¤t_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, ¤t_time);
83 asctime_s(time_buf, arraysize(time_buf), &local_time);
84 #elif defined(OS_POSIX)
85 localtime_r(¤t_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