1// Copyright 2010 Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9//   notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright
11//   notice, this list of conditions and the following disclaimer in the
12//   documentation and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors
14//   may be used to endorse or promote products derived from this software
15//   without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "utils/datetime.hpp"
30
31extern "C" {
32#include <time.h>
33#include <unistd.h>
34}
35
36#include <sstream>
37
38#include <atf-c++.hpp>
39
40namespace datetime = utils::datetime;
41
42
43ATF_TEST_CASE_WITHOUT_HEAD(delta__defaults);
44ATF_TEST_CASE_BODY(delta__defaults)
45{
46    const datetime::delta delta;
47    ATF_REQUIRE_EQ(0, delta.seconds);
48    ATF_REQUIRE_EQ(0, delta.useconds);
49}
50
51
52ATF_TEST_CASE_WITHOUT_HEAD(delta__overrides);
53ATF_TEST_CASE_BODY(delta__overrides)
54{
55    const datetime::delta delta(1, 2);
56    ATF_REQUIRE_EQ(1, delta.seconds);
57    ATF_REQUIRE_EQ(2, delta.useconds);
58}
59
60
61ATF_TEST_CASE_WITHOUT_HEAD(delta__from_microseconds);
62ATF_TEST_CASE_BODY(delta__from_microseconds)
63{
64    {
65        const datetime::delta delta = datetime::delta::from_microseconds(0);
66        ATF_REQUIRE_EQ(0, delta.seconds);
67        ATF_REQUIRE_EQ(0, delta.useconds);
68    }
69    {
70        const datetime::delta delta = datetime::delta::from_microseconds(
71            999999);
72        ATF_REQUIRE_EQ(0, delta.seconds);
73        ATF_REQUIRE_EQ(999999, delta.useconds);
74    }
75    {
76        const datetime::delta delta = datetime::delta::from_microseconds(
77            1000000);
78        ATF_REQUIRE_EQ(1, delta.seconds);
79        ATF_REQUIRE_EQ(0, delta.useconds);
80    }
81    {
82        const datetime::delta delta = datetime::delta::from_microseconds(
83            10576293);
84        ATF_REQUIRE_EQ(10, delta.seconds);
85        ATF_REQUIRE_EQ(576293, delta.useconds);
86    }
87    {
88        const datetime::delta delta = datetime::delta::from_microseconds(
89            123456789123456);
90        ATF_REQUIRE_EQ(123456789, delta.seconds);
91        ATF_REQUIRE_EQ(123456, delta.useconds);
92    }
93}
94
95
96ATF_TEST_CASE_WITHOUT_HEAD(delta__to_microseconds);
97ATF_TEST_CASE_BODY(delta__to_microseconds)
98{
99    ATF_REQUIRE_EQ(0, datetime::delta(0, 0).to_microseconds());
100    ATF_REQUIRE_EQ(999999, datetime::delta(0, 999999).to_microseconds());
101    ATF_REQUIRE_EQ(1000000, datetime::delta(1, 0).to_microseconds());
102    ATF_REQUIRE_EQ(10576293, datetime::delta(10, 576293).to_microseconds());
103    ATF_REQUIRE_EQ(11576293, datetime::delta(10, 1576293).to_microseconds());
104}
105
106
107ATF_TEST_CASE_WITHOUT_HEAD(delta__equals);
108ATF_TEST_CASE_BODY(delta__equals)
109{
110    ATF_REQUIRE(datetime::delta() == datetime::delta());
111    ATF_REQUIRE(datetime::delta() == datetime::delta(0, 0));
112    ATF_REQUIRE(datetime::delta(1, 2) == datetime::delta(1, 2));
113
114    ATF_REQUIRE(!(datetime::delta() == datetime::delta(0, 1)));
115    ATF_REQUIRE(!(datetime::delta() == datetime::delta(1, 0)));
116    ATF_REQUIRE(!(datetime::delta(1, 2) == datetime::delta(2, 1)));
117}
118
119
120ATF_TEST_CASE_WITHOUT_HEAD(delta__differs);
121ATF_TEST_CASE_BODY(delta__differs)
122{
123    ATF_REQUIRE(!(datetime::delta() != datetime::delta()));
124    ATF_REQUIRE(!(datetime::delta() != datetime::delta(0, 0)));
125    ATF_REQUIRE(!(datetime::delta(1, 2) != datetime::delta(1, 2)));
126
127    ATF_REQUIRE(datetime::delta() != datetime::delta(0, 1));
128    ATF_REQUIRE(datetime::delta() != datetime::delta(1, 0));
129    ATF_REQUIRE(datetime::delta(1, 2) != datetime::delta(2, 1));
130}
131
132
133ATF_TEST_CASE_WITHOUT_HEAD(delta__addition);
134ATF_TEST_CASE_BODY(delta__addition)
135{
136    using datetime::delta;
137
138    ATF_REQUIRE(delta() == delta() + delta());
139    ATF_REQUIRE(delta(0, 10) == delta() + delta(0, 10));
140    ATF_REQUIRE(delta(10, 0) == delta(10, 0) + delta());
141
142    ATF_REQUIRE(delta(1, 234567) == delta(0, 1234567) + delta());
143    ATF_REQUIRE(delta(12, 34) == delta(10, 20) + delta(2, 14));
144}
145
146
147ATF_TEST_CASE_WITHOUT_HEAD(delta__addition_and_set);
148ATF_TEST_CASE_BODY(delta__addition_and_set)
149{
150    using datetime::delta;
151
152    {
153        delta d;
154        d += delta(3, 5);
155        ATF_REQUIRE(delta(3, 5) == d);
156    }
157    {
158        delta d(1, 2);
159        d += delta(3, 5);
160        ATF_REQUIRE(delta(4, 7) == d);
161    }
162    {
163        delta d(1, 2);
164        ATF_REQUIRE(delta(4, 7) == (d += delta(3, 5)));
165    }
166}
167
168
169ATF_TEST_CASE_WITHOUT_HEAD(delta__output);
170ATF_TEST_CASE_BODY(delta__output)
171{
172    {
173        std::ostringstream str;
174        str << datetime::delta(15, 8791);
175        ATF_REQUIRE_EQ("15008791us", str.str());
176    }
177    {
178        std::ostringstream str;
179        str << datetime::delta(12345678, 0);
180        ATF_REQUIRE_EQ("12345678000000us", str.str());
181    }
182}
183
184
185ATF_TEST_CASE_WITHOUT_HEAD(timestamp__copy);
186ATF_TEST_CASE_BODY(timestamp__copy)
187{
188    const datetime::timestamp ts1 = datetime::timestamp::from_values(
189        2011, 2, 16, 19, 15, 30, 0);
190    {
191        const datetime::timestamp ts2 = ts1;
192        const datetime::timestamp ts3 = datetime::timestamp::from_values(
193            2012, 2, 16, 19, 15, 30, 0);
194        ATF_REQUIRE_EQ("2011", ts1.strftime("%Y"));
195        ATF_REQUIRE_EQ("2011", ts2.strftime("%Y"));
196        ATF_REQUIRE_EQ("2012", ts3.strftime("%Y"));
197    }
198    ATF_REQUIRE_EQ("2011", ts1.strftime("%Y"));
199}
200
201
202ATF_TEST_CASE_WITHOUT_HEAD(timestamp__from_microseconds);
203ATF_TEST_CASE_BODY(timestamp__from_microseconds)
204{
205    const datetime::timestamp ts = datetime::timestamp::from_microseconds(
206        1328829351987654LL);
207    ATF_REQUIRE_EQ("2012-02-09 23:15:51", ts.strftime("%Y-%m-%d %H:%M:%S"));
208    ATF_REQUIRE_EQ(1328829351987654LL, ts.to_microseconds());
209    ATF_REQUIRE_EQ(1328829351, ts.to_seconds());
210}
211
212
213ATF_TEST_CASE_WITHOUT_HEAD(timestamp__now__mock);
214ATF_TEST_CASE_BODY(timestamp__now__mock)
215{
216    datetime::set_mock_now(2011, 2, 21, 18, 5, 10, 0);
217    ATF_REQUIRE_EQ("2011-02-21 18:05:10",
218                   datetime::timestamp::now().strftime("%Y-%m-%d %H:%M:%S"));
219
220    datetime::set_mock_now(2012, 3, 22, 19, 6, 11, 54321);
221    ATF_REQUIRE_EQ("2012-03-22 19:06:11",
222                   datetime::timestamp::now().strftime("%Y-%m-%d %H:%M:%S"));
223    ATF_REQUIRE_EQ("2012-03-22 19:06:11",
224                   datetime::timestamp::now().strftime("%Y-%m-%d %H:%M:%S"));
225}
226
227
228ATF_TEST_CASE_WITHOUT_HEAD(timestamp__now__real);
229ATF_TEST_CASE_BODY(timestamp__now__real)
230{
231    // This test is might fail if we happen to run at the crossing of one
232    // day to the other and the two measures we pick of the current time
233    // differ.  This is so unlikely that I haven't bothered to do this in any
234    // other way.
235
236    const time_t just_before = ::time(NULL);
237    const datetime::timestamp now = datetime::timestamp::now();
238
239    ::tm data;
240    char buf[1024];
241    ATF_REQUIRE(::gmtime_r(&just_before, &data) != 0);
242    ATF_REQUIRE(::strftime(buf, sizeof(buf), "%Y-%m-%d", &data) != 0);
243    ATF_REQUIRE_EQ(buf, now.strftime("%Y-%m-%d"));
244
245    ATF_REQUIRE(now.strftime("%Z") == "GMT" || now.strftime("%Z") == "UTC");
246}
247
248
249ATF_TEST_CASE_WITHOUT_HEAD(timestamp__now__granularity);
250ATF_TEST_CASE_BODY(timestamp__now__granularity)
251{
252    const datetime::timestamp first = datetime::timestamp::now();
253    ::usleep(1);
254    const datetime::timestamp second = datetime::timestamp::now();
255    ATF_REQUIRE(first.to_microseconds() != second.to_microseconds());
256}
257
258
259ATF_TEST_CASE_WITHOUT_HEAD(timestamp__strftime);
260ATF_TEST_CASE_BODY(timestamp__strftime)
261{
262    const datetime::timestamp ts1 = datetime::timestamp::from_values(
263        2010, 12, 10, 8, 45, 50, 0);
264    ATF_REQUIRE_EQ("2010-12-10", ts1.strftime("%Y-%m-%d"));
265    ATF_REQUIRE_EQ("08:45:50", ts1.strftime("%H:%M:%S"));
266
267    const datetime::timestamp ts2 = datetime::timestamp::from_values(
268        2011, 2, 16, 19, 15, 30, 0);
269    ATF_REQUIRE_EQ("2011-02-16T19:15:30", ts2.strftime("%Y-%m-%dT%H:%M:%S"));
270}
271
272
273ATF_TEST_CASE_WITHOUT_HEAD(timestamp__to_microseconds);
274ATF_TEST_CASE_BODY(timestamp__to_microseconds)
275{
276    const datetime::timestamp ts1 = datetime::timestamp::from_values(
277        2010, 12, 10, 8, 45, 50, 123456);
278    ATF_REQUIRE_EQ(1291970750123456LL, ts1.to_microseconds());
279}
280
281
282ATF_TEST_CASE_WITHOUT_HEAD(timestamp__to_seconds);
283ATF_TEST_CASE_BODY(timestamp__to_seconds)
284{
285    const datetime::timestamp ts1 = datetime::timestamp::from_values(
286        2010, 12, 10, 8, 45, 50, 123456);
287    ATF_REQUIRE_EQ(1291970750, ts1.to_seconds());
288}
289
290
291ATF_TEST_CASE_WITHOUT_HEAD(timestamp__leap_second);
292ATF_TEST_CASE_BODY(timestamp__leap_second)
293{
294    // This is actually a test for from_values(), which is the function that
295    // includes assertions to validate the input parameters.
296    const datetime::timestamp ts1 = datetime::timestamp::from_values(
297        2012, 6, 30, 23, 59, 60, 543);
298    ATF_REQUIRE_EQ(1341100800, ts1.to_seconds());
299}
300
301
302ATF_TEST_CASE_WITHOUT_HEAD(timestamp__equals);
303ATF_TEST_CASE_BODY(timestamp__equals)
304{
305    ATF_REQUIRE(datetime::timestamp::from_microseconds(1291970750123456LL) ==
306                datetime::timestamp::from_microseconds(1291970750123456LL));
307}
308
309
310ATF_TEST_CASE_WITHOUT_HEAD(timestamp__differs);
311ATF_TEST_CASE_BODY(timestamp__differs)
312{
313    ATF_REQUIRE(datetime::timestamp::from_microseconds(1291970750123456LL) !=
314                datetime::timestamp::from_microseconds(1291970750123455LL));
315}
316
317
318ATF_TEST_CASE_WITHOUT_HEAD(timestamp__subtraction);
319ATF_TEST_CASE_BODY(timestamp__subtraction)
320{
321    const datetime::timestamp ts1 = datetime::timestamp::from_microseconds(
322        1291970750123456LL);
323    const datetime::timestamp ts2 = datetime::timestamp::from_microseconds(
324        1291970750123468LL);
325    const datetime::timestamp ts3 = datetime::timestamp::from_microseconds(
326        1291970850123456LL);
327
328    ATF_REQUIRE(datetime::delta(0, 0) == ts1 - ts1);
329    ATF_REQUIRE(datetime::delta(0, 12) == ts2 - ts1);
330    ATF_REQUIRE(datetime::delta(100, 0) == ts3 - ts1);
331    ATF_REQUIRE(datetime::delta(99, 999988) == ts3 - ts2);
332}
333
334
335ATF_TEST_CASE_WITHOUT_HEAD(timestamp__output);
336ATF_TEST_CASE_BODY(timestamp__output)
337{
338    {
339        std::ostringstream str;
340        str << datetime::timestamp::from_microseconds(1291970750123456LL);
341        ATF_REQUIRE_EQ("1291970750123456us", str.str());
342    }
343    {
344        std::ostringstream str;
345        str << datetime::timestamp::from_microseconds(1028309798759812LL);
346        ATF_REQUIRE_EQ("1028309798759812us", str.str());
347    }
348}
349
350
351ATF_INIT_TEST_CASES(tcs)
352{
353    ATF_ADD_TEST_CASE(tcs, delta__defaults);
354    ATF_ADD_TEST_CASE(tcs, delta__overrides);
355    ATF_ADD_TEST_CASE(tcs, delta__from_microseconds);
356    ATF_ADD_TEST_CASE(tcs, delta__to_microseconds);
357    ATF_ADD_TEST_CASE(tcs, delta__equals);
358    ATF_ADD_TEST_CASE(tcs, delta__differs);
359    ATF_ADD_TEST_CASE(tcs, delta__addition);
360    ATF_ADD_TEST_CASE(tcs, delta__addition_and_set);
361    ATF_ADD_TEST_CASE(tcs, delta__output);
362
363    ATF_ADD_TEST_CASE(tcs, timestamp__copy);
364    ATF_ADD_TEST_CASE(tcs, timestamp__from_microseconds);
365    ATF_ADD_TEST_CASE(tcs, timestamp__now__mock);
366    ATF_ADD_TEST_CASE(tcs, timestamp__now__real);
367    ATF_ADD_TEST_CASE(tcs, timestamp__now__granularity);
368    ATF_ADD_TEST_CASE(tcs, timestamp__strftime);
369    ATF_ADD_TEST_CASE(tcs, timestamp__to_microseconds);
370    ATF_ADD_TEST_CASE(tcs, timestamp__to_seconds);
371    ATF_ADD_TEST_CASE(tcs, timestamp__leap_second);
372    ATF_ADD_TEST_CASE(tcs, timestamp__equals);
373    ATF_ADD_TEST_CASE(tcs, timestamp__differs);
374    ATF_ADD_TEST_CASE(tcs, timestamp__subtraction);
375    ATF_ADD_TEST_CASE(tcs, timestamp__output);
376}
377