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 struct tm local_time = {};
79 char time_buf[64] = {};
80 #if defined(OS_WIN)
81 localtime_s(&local_time, ¤t_time);
82 asctime_s(time_buf, arraysize(time_buf), &local_time);
83 #elif defined(OS_POSIX) || defined(OS_FUCHSIA)
84 localtime_r(¤t_time, &local_time);
85 asctime_r(&local_time, time_buf);
86 #endif
87
88 PRTime current_time64 = static_cast<PRTime>(current_time) * PR_USEC_PER_SEC;
89
90 PRTime parsed_time = 0;
91 PRStatus result = PR_ParseTimeString(time_buf, PR_FALSE, &parsed_time);
92 EXPECT_EQ(PR_SUCCESS, result);
93 EXPECT_EQ(current_time64, parsed_time);
94 }
95
TEST_F(PRTimeTest,ParseTimeTest2)96 TEST_F(PRTimeTest, ParseTimeTest2) {
97 PRTime parsed_time = 0;
98 PRStatus result = PR_ParseTimeString("Mon, 15 Oct 2007 19:45:00 GMT",
99 PR_FALSE, &parsed_time);
100 EXPECT_EQ(PR_SUCCESS, result);
101 EXPECT_EQ(comparison_time_pdt, parsed_time);
102 }
103
TEST_F(PRTimeTest,ParseTimeTest3)104 TEST_F(PRTimeTest, ParseTimeTest3) {
105 PRTime parsed_time = 0;
106 PRStatus result = PR_ParseTimeString("15 Oct 07 12:45:00", PR_FALSE,
107 &parsed_time);
108 EXPECT_EQ(PR_SUCCESS, result);
109 EXPECT_EQ(comparison_time_local_, parsed_time);
110 }
111
TEST_F(PRTimeTest,ParseTimeTest4)112 TEST_F(PRTimeTest, ParseTimeTest4) {
113 PRTime parsed_time = 0;
114 PRStatus result = PR_ParseTimeString("15 Oct 07 19:45 GMT", PR_FALSE,
115 &parsed_time);
116 EXPECT_EQ(PR_SUCCESS, result);
117 EXPECT_EQ(comparison_time_pdt, parsed_time);
118 }
119
TEST_F(PRTimeTest,ParseTimeTest5)120 TEST_F(PRTimeTest, ParseTimeTest5) {
121 PRTime parsed_time = 0;
122 PRStatus result = PR_ParseTimeString("Mon Oct 15 12:45 PDT 2007",
123 PR_FALSE, &parsed_time);
124 EXPECT_EQ(PR_SUCCESS, result);
125 EXPECT_EQ(comparison_time_pdt, parsed_time);
126 }
127
TEST_F(PRTimeTest,ParseTimeTest6)128 TEST_F(PRTimeTest, ParseTimeTest6) {
129 PRTime parsed_time = 0;
130 PRStatus result = PR_ParseTimeString("Monday, Oct 15, 2007 12:45 PM",
131 PR_FALSE, &parsed_time);
132 EXPECT_EQ(PR_SUCCESS, result);
133 EXPECT_EQ(comparison_time_local_, parsed_time);
134 }
135
TEST_F(PRTimeTest,ParseTimeTest7)136 TEST_F(PRTimeTest, ParseTimeTest7) {
137 PRTime parsed_time = 0;
138 PRStatus result = PR_ParseTimeString("10/15/07 12:45:00 PM", PR_FALSE,
139 &parsed_time);
140 EXPECT_EQ(PR_SUCCESS, result);
141 EXPECT_EQ(comparison_time_local_, parsed_time);
142 }
143
TEST_F(PRTimeTest,ParseTimeTest8)144 TEST_F(PRTimeTest, ParseTimeTest8) {
145 PRTime parsed_time = 0;
146 PRStatus result = PR_ParseTimeString("10/15/07 12:45:00. PM", PR_FALSE,
147 &parsed_time);
148 EXPECT_EQ(PR_SUCCESS, result);
149 EXPECT_EQ(comparison_time_local_, parsed_time);
150 }
151
TEST_F(PRTimeTest,ParseTimeTest9)152 TEST_F(PRTimeTest, ParseTimeTest9) {
153 PRTime parsed_time = 0;
154 PRStatus result = PR_ParseTimeString("10/15/07 12:45:00.0 PM", PR_FALSE,
155 &parsed_time);
156 EXPECT_EQ(PR_SUCCESS, result);
157 EXPECT_EQ(comparison_time_local_, parsed_time);
158 }
159
TEST_F(PRTimeTest,ParseTimeTest10)160 TEST_F(PRTimeTest, ParseTimeTest10) {
161 PRTime parsed_time = 0;
162 PRStatus result = PR_ParseTimeString("15-OCT-2007 12:45pm", PR_FALSE,
163 &parsed_time);
164 EXPECT_EQ(PR_SUCCESS, result);
165 EXPECT_EQ(comparison_time_local_, parsed_time);
166 }
167
TEST_F(PRTimeTest,ParseTimeTest11)168 TEST_F(PRTimeTest, ParseTimeTest11) {
169 PRTime parsed_time = 0;
170 PRStatus result = PR_ParseTimeString("16 Oct 2007 4:45-JST (Tuesday)",
171 PR_FALSE, &parsed_time);
172 EXPECT_EQ(PR_SUCCESS, result);
173 EXPECT_EQ(comparison_time_pdt, parsed_time);
174 }
175
176 // hh:mm timezone offset.
TEST_F(PRTimeTest,ParseTimeTest12)177 TEST_F(PRTimeTest, ParseTimeTest12) {
178 PRTime parsed_time = 0;
179 PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381+02:00",
180 PR_FALSE, &parsed_time);
181 EXPECT_EQ(PR_SUCCESS, result);
182 EXPECT_EQ(comparison_time_2, parsed_time);
183 }
184
185 // hhmm timezone offset.
TEST_F(PRTimeTest,ParseTimeTest13)186 TEST_F(PRTimeTest, ParseTimeTest13) {
187 PRTime parsed_time = 0;
188 PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381+0200",
189 PR_FALSE, &parsed_time);
190 EXPECT_EQ(PR_SUCCESS, result);
191 EXPECT_EQ(comparison_time_2, parsed_time);
192 }
193
194 // hh timezone offset.
TEST_F(PRTimeTest,ParseTimeTest14)195 TEST_F(PRTimeTest, ParseTimeTest14) {
196 PRTime parsed_time = 0;
197 PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.4413819+02",
198 PR_FALSE, &parsed_time);
199 EXPECT_EQ(PR_SUCCESS, result);
200 EXPECT_EQ(comparison_time_2, parsed_time);
201 }
202
203 // 5 digits fractional second.
TEST_F(PRTimeTest,ParseTimeTest15)204 TEST_F(PRTimeTest, ParseTimeTest15) {
205 PRTime parsed_time = 0;
206 PRStatus result = PR_ParseTimeString("2013-07-08T09:28:12.44138Z",
207 PR_FALSE, &parsed_time);
208 EXPECT_EQ(PR_SUCCESS, result);
209 EXPECT_EQ(comparison_time_2-1, parsed_time);
210 }
211
212 // Fractional seconds, local timezone.
TEST_F(PRTimeTest,ParseTimeTest16)213 TEST_F(PRTimeTest, ParseTimeTest16) {
214 PRTime parsed_time = 0;
215 PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381",
216 PR_FALSE, &parsed_time);
217 EXPECT_EQ(PR_SUCCESS, result);
218 EXPECT_EQ(comparison_time_local_2_, parsed_time);
219 }
220
221 // "Z" (=GMT) timezone.
TEST_F(PRTimeTest,ParseTimeTest17)222 TEST_F(PRTimeTest, ParseTimeTest17) {
223 PRTime parsed_time = 0;
224 PRStatus result = PR_ParseTimeString("2013-07-08T09:28:12.441381Z",
225 PR_FALSE, &parsed_time);
226 EXPECT_EQ(PR_SUCCESS, result);
227 EXPECT_EQ(comparison_time_2, parsed_time);
228 }
229
230 // "T" delimiter replaced by space.
TEST_F(PRTimeTest,ParseTimeTest18)231 TEST_F(PRTimeTest, ParseTimeTest18) {
232 PRTime parsed_time = 0;
233 PRStatus result = PR_ParseTimeString("2013-07-08 09:28:12.441381Z",
234 PR_FALSE, &parsed_time);
235 EXPECT_EQ(PR_SUCCESS, result);
236 EXPECT_EQ(comparison_time_2, parsed_time);
237 }
238
TEST_F(PRTimeTest,ParseTimeTestInvalid1)239 TEST_F(PRTimeTest, ParseTimeTestInvalid1) {
240 PRTime parsed_time = 0;
241 PRStatus result = PR_ParseTimeString("201-07-08T09:28:12.441381Z",
242 PR_FALSE, &parsed_time);
243 EXPECT_EQ(PR_FAILURE, result);
244 }
245
TEST_F(PRTimeTest,ParseTimeTestInvalid2)246 TEST_F(PRTimeTest, ParseTimeTestInvalid2) {
247 PRTime parsed_time = 0;
248 PRStatus result = PR_ParseTimeString("2013-007-08T09:28:12.441381Z",
249 PR_FALSE, &parsed_time);
250 EXPECT_EQ(PR_FAILURE, result);
251 }
252
TEST_F(PRTimeTest,ParseTimeTestInvalid3)253 TEST_F(PRTimeTest, ParseTimeTestInvalid3) {
254 PRTime parsed_time = 0;
255 PRStatus result = PR_ParseTimeString("2013-07-008T09:28:12.441381Z",
256 PR_FALSE, &parsed_time);
257 EXPECT_EQ(PR_FAILURE, result);
258 }
259
260 // This test should not crash when compiled with Visual C++ 2005 (see
261 // http://crbug.com/4387).
TEST_F(PRTimeTest,ParseTimeTestOutOfRange)262 TEST_F(PRTimeTest, ParseTimeTestOutOfRange) {
263 PRTime parsed_time = 0;
264 // Note the lack of timezone in the time string. The year has to be 3001.
265 // The date has to be after 23:59:59, December 31, 3000, US Pacific Time, so
266 // we use January 2, 3001 to make sure it's after the magic maximum in any
267 // timezone.
268 PRStatus result = PR_ParseTimeString("Sun Jan 2 00:00:00 3001",
269 PR_FALSE, &parsed_time);
270 EXPECT_EQ(PR_SUCCESS, result);
271 }
272
TEST_F(PRTimeTest,ParseTimeTestNotNormalized1)273 TEST_F(PRTimeTest, ParseTimeTestNotNormalized1) {
274 PRTime parsed_time = 0;
275 PRStatus result = PR_ParseTimeString("Mon Oct 15 12:44:60 PDT 2007",
276 PR_FALSE, &parsed_time);
277 EXPECT_EQ(PR_SUCCESS, result);
278 EXPECT_EQ(comparison_time_pdt, parsed_time);
279 }
280
TEST_F(PRTimeTest,ParseTimeTestNotNormalized2)281 TEST_F(PRTimeTest, ParseTimeTestNotNormalized2) {
282 PRTime parsed_time = 0;
283 PRStatus result = PR_ParseTimeString("Sun Oct 14 36:45 PDT 2007",
284 PR_FALSE, &parsed_time);
285 EXPECT_EQ(PR_SUCCESS, result);
286 EXPECT_EQ(comparison_time_pdt, parsed_time);
287 }
288
289 } // namespace
290