1 // Copyright (C) 2010-2015 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <string>
10 
11 #include <time.h>
12 
13 #include <util/time_utilities.h>
14 
15 #include <gtest/gtest.h>
16 
17 using namespace std;
18 using namespace isc::util;
19 
20 // See time_utilities.cc
21 namespace isc {
22 namespace util {
23 namespace detail {
24 extern int64_t (*gettimeFunction)();
25 }
26 }
27 }
28 
29 namespace {
30 
31 class DNSSECTimeTest : public ::testing::Test {
32 protected:
~DNSSECTimeTest()33     ~DNSSECTimeTest() {
34         detail::gettimeFunction = NULL;
35     }
36 };
37 
TEST_F(DNSSECTimeTest,fromText)38 TEST_F(DNSSECTimeTest, fromText) {
39     // In most cases (in practice) the 32-bit and 64-bit versions should
40     // behave identically, so we'll mainly test the 32-bit version, which
41     // will be more commonly used in actual code (because many of the wire
42     // format time field are 32-bit).  The subtle cases where these two
43     // return different values will be tested at the end of this test case.
44 
45     // These are bogus and should be rejected
46     EXPECT_THROW(timeFromText32("2011 101120000"), InvalidTime);
47     EXPECT_THROW(timeFromText32("201101011200-0"), InvalidTime);
48 
49     // Short length (or "decimal integer" version of representation;
50     // it's valid per RFC4034, but is not supported in this implementation)
51     EXPECT_THROW(timeFromText32("20100223"), InvalidTime);
52 
53     // Leap year checks
54     EXPECT_THROW(timeFromText32("20110229120000"), InvalidTime);
55     EXPECT_THROW(timeFromText32("21000229120000"), InvalidTime);
56     EXPECT_NO_THROW(timeFromText32("20000229120000"));
57     EXPECT_NO_THROW(timeFromText32("20120229120000"));
58 
59     // unusual case: this implementation allows SS=60 for "leap seconds"
60     EXPECT_NO_THROW(timeFromText32("20110101120060"));
61 
62     // Out of range parameters
63     EXPECT_THROW(timeFromText32("19100223214617"), InvalidTime); // YY<1970
64     EXPECT_THROW(timeFromText32("20110001120000"), InvalidTime); // MM=00
65     EXPECT_THROW(timeFromText32("20111301120000"), InvalidTime); // MM=13
66     EXPECT_THROW(timeFromText32("20110100120000"), InvalidTime); // DD=00
67     EXPECT_THROW(timeFromText32("20110132120000"), InvalidTime); // DD=32
68     EXPECT_THROW(timeFromText32("20110431120000"), InvalidTime); // 'Apr31'
69     EXPECT_THROW(timeFromText32("20110101250000"), InvalidTime); // HH=25
70     EXPECT_THROW(timeFromText32("20110101126000"), InvalidTime); // mm=60
71     EXPECT_THROW(timeFromText32("20110101120061"), InvalidTime); // SS=61
72 
73     // Feb 7, 06:28:15 UTC 2106 is the possible maximum time that can be
74     // represented as an unsigned 32bit integer without overflow.
75     EXPECT_EQ(4294967295LU, timeFromText32("21060207062815"));
76 
77     // After that, timeFromText32() should start returning the second count
78     // modulo 2^32.
79     EXPECT_EQ(0, timeFromText32("21060207062816"));
80     EXPECT_EQ(10, timeFromText32("21060207062826"));
81 
82     // On the other hand, the 64-bit version should return monotonically
83     // increasing counters.
84     EXPECT_EQ(4294967296LL, timeFromText64("21060207062816"));
85     EXPECT_EQ(4294967306LL, timeFromText64("21060207062826"));
86 }
87 
88 // This helper templated function tells timeToText32 a faked current time.
89 // The template parameter is that faked time in the form of int64_t seconds
90 // since epoch.
91 template <int64_t NOW>
92 int64_t
testGetTime()93 testGetTime() {
94     return (NOW);
95 }
96 
97 // Seconds since epoch for the year 10K eve.  Commonly used in some tests
98 // below.
99 const uint64_t YEAR10K_EVE = 253402300799LL;
100 
TEST_F(DNSSECTimeTest,toText)101 TEST_F(DNSSECTimeTest, toText) {
102     // Check a basic case with the default (normal) gettimeFunction
103     // based on the "real current time".
104     // Note: this will fail after year 2078, but at that point we won't use
105     // this program anyway:-)
106     EXPECT_EQ("20100311233000", timeToText32(1268350200));
107 
108     // Set the current time to: Feb 18 09:04:14 UTC 2012 (an arbitrary choice
109     // in the range of the first half of uint32 since epoch).
110     detail::gettimeFunction = testGetTime<1329555854LL>;
111 
112     // Test the "year 2038" problem.
113     // Check the result of toText() for "INT_MIN" in int32_t.  It's in the
114     // 68-year range from the faked current time, so the result should be
115     // in year 2038, instead of 1901.
116     EXPECT_EQ("20380119031408", timeToText64(0x80000000L));
117     EXPECT_EQ("20380119031408", timeToText32(0x80000000L));
118 
119     // A controversial case: what should we do with "-1"?  It's out of range
120     // in future, but according to RFC time before epoch doesn't seem to be
121     // considered "in-range" either.  Our toText() implementation handles
122     // this range as a special case and always treats them as future time
123     // until year 2038.  This won't be a real issue in practice, though,
124     // since such too large values won't be used in actual deployment by then.
125     EXPECT_EQ("21060207062815", timeToText32(0xffffffffL));
126 
127     // After the singular point of year 2038, the first half of uint32 can
128     // point to a future time.
129     // Set the current time to: Apr 1 00:00:00 UTC 2038:
130     detail::gettimeFunction = testGetTime<2153692800LL>;
131     // then time "10" is Feb 7 06:28:26 UTC 2106
132     EXPECT_EQ("21060207062826", timeToText32(10));
133     // in 64-bit, it's 2^32 + 10
134     EXPECT_EQ("21060207062826", timeToText64(0x10000000aLL));
135 
136     // After year 2106, the upper half of uint32 can point to past time
137     // (as it should).
138     detail::gettimeFunction = testGetTime<0x10000000aLL>;
139     EXPECT_EQ("21060207062815", timeToText32(0xffffffffL));
140 
141     // Try very large time value.  Actually it's the possible farthest time
142     // that can be represented in the form of YYYYMMDDHHmmSS.
143     EXPECT_EQ("99991231235959", timeToText64(YEAR10K_EVE));
144     detail::gettimeFunction = testGetTime<YEAR10K_EVE - 10>;
145     EXPECT_EQ("99991231235959", timeToText32(4294197631LU));
146 }
147 
TEST_F(DNSSECTimeTest,overflow)148 TEST_F(DNSSECTimeTest, overflow) {
149     // Jan 1, Year 10,000.
150     EXPECT_THROW(timeToText64(253402300800LL), InvalidTime);
151     detail::gettimeFunction = testGetTime<YEAR10K_EVE - 10>;
152     EXPECT_THROW(timeToText32(4294197632LU), InvalidTime);
153 }
154 
155 }
156