1 #include "utils/time_utils.hpp"
2
3 #include <chrono>
4 #include <cstdint>
5 #include <ctime>
6 #include <limits>
7 #include <optional>
8
9 #include <gtest/gtest.h>
10
11 namespace redfish::time_utils
12 {
13 namespace
14 {
15
TEST(FromDurationTest,PositiveTests)16 TEST(FromDurationTest, PositiveTests)
17 {
18 EXPECT_EQ(fromDurationString("PT12S"), std::chrono::milliseconds(12000));
19 EXPECT_EQ(fromDurationString("PT0.204S"), std::chrono::milliseconds(204));
20 EXPECT_EQ(fromDurationString("PT0.2S"), std::chrono::milliseconds(200));
21 EXPECT_EQ(fromDurationString("PT50M"), std::chrono::milliseconds(3000000));
22 EXPECT_EQ(fromDurationString("PT23H"), std::chrono::milliseconds(82800000));
23 EXPECT_EQ(fromDurationString("P51D"),
24 std::chrono::milliseconds(4406400000));
25 EXPECT_EQ(fromDurationString("PT2H40M10.1S"),
26 std::chrono::milliseconds(9610100));
27 EXPECT_EQ(fromDurationString("P20DT2H40M10.1S"),
28 std::chrono::milliseconds(1737610100));
29 EXPECT_EQ(fromDurationString(""), std::chrono::milliseconds(0));
30 }
31
TEST(FromDurationTest,NegativeTests)32 TEST(FromDurationTest, NegativeTests)
33 {
34 EXPECT_EQ(fromDurationString("PTS"), std::nullopt);
35 EXPECT_EQ(fromDurationString("P1T"), std::nullopt);
36 EXPECT_EQ(fromDurationString("PT100M1000S100"), std::nullopt);
37 EXPECT_EQ(fromDurationString("PDTHMS"), std::nullopt);
38 EXPECT_EQ(fromDurationString("P9999999999999999999999999DT"), std::nullopt);
39 EXPECT_EQ(fromDurationString("PD222T222H222M222.222S"), std::nullopt);
40 EXPECT_EQ(fromDurationString("PT99999H9999999999999999999999M99999999999S"),
41 std::nullopt);
42 EXPECT_EQ(fromDurationString("PT-9H"), std::nullopt);
43 }
TEST(ToDurationTest,PositiveTests)44 TEST(ToDurationTest, PositiveTests)
45 {
46 EXPECT_EQ(toDurationString(std::chrono::milliseconds(12000)), "PT12.000S");
47 EXPECT_EQ(toDurationString(std::chrono::milliseconds(204)), "PT0.204S");
48 EXPECT_EQ(toDurationString(std::chrono::milliseconds(200)), "PT0.200S");
49 EXPECT_EQ(toDurationString(std::chrono::milliseconds(3000000)), "PT50M");
50 EXPECT_EQ(toDurationString(std::chrono::milliseconds(82800000)), "PT23H");
51 EXPECT_EQ(toDurationString(std::chrono::milliseconds(4406400000)), "P51DT");
52 EXPECT_EQ(toDurationString(std::chrono::milliseconds(9610100)),
53 "PT2H40M10.100S");
54 EXPECT_EQ(toDurationString(std::chrono::milliseconds(1737610100)),
55 "P20DT2H40M10.100S");
56 }
57
TEST(ToDurationTest,NegativeTests)58 TEST(ToDurationTest, NegativeTests)
59 {
60 EXPECT_EQ(toDurationString(std::chrono::milliseconds(-250)), "");
61 }
62
TEST(ToDurationStringFromUintTest,PositiveTests)63 TEST(ToDurationStringFromUintTest, PositiveTests)
64 {
65 uint64_t maxAcceptedTimeMs =
66 static_cast<uint64_t>(std::chrono::milliseconds::max().count());
67
68 EXPECT_NE(toDurationStringFromUint(maxAcceptedTimeMs), std::nullopt);
69 EXPECT_EQ(toDurationStringFromUint(0), "PT");
70 EXPECT_EQ(toDurationStringFromUint(250), "PT0.250S");
71 EXPECT_EQ(toDurationStringFromUint(5000), "PT5.000S");
72 }
73
TEST(ToDurationStringFromUintTest,NegativeTests)74 TEST(ToDurationStringFromUintTest, NegativeTests)
75 {
76 uint64_t minNotAcceptedTimeMs =
77 static_cast<uint64_t>(std::chrono::milliseconds::max().count()) + 1;
78
79 EXPECT_EQ(toDurationStringFromUint(minNotAcceptedTimeMs), std::nullopt);
80 EXPECT_EQ(toDurationStringFromUint(static_cast<uint64_t>(-1)),
81 std::nullopt);
82 }
83
TEST(GetDateTimeStdtime,ConversionTests)84 TEST(GetDateTimeStdtime, ConversionTests)
85 {
86 // some time before the epoch
87 EXPECT_EQ(getDateTimeStdtime(std::time_t{-1234567}),
88 "1970-01-01T00:00:00+00:00");
89
90 // epoch
91 EXPECT_EQ(getDateTimeStdtime(std::time_t{0}), "1970-01-01T00:00:00+00:00");
92
93 // Limits
94 EXPECT_EQ(getDateTimeStdtime(std::numeric_limits<std::time_t>::max()),
95 "9999-12-31T23:59:59+00:00");
96 EXPECT_EQ(getDateTimeStdtime(std::numeric_limits<std::time_t>::min()),
97 "1970-01-01T00:00:00+00:00");
98 }
99
TEST(GetDateTimeUint,ConversionTests)100 TEST(GetDateTimeUint, ConversionTests)
101 {
102 EXPECT_EQ(getDateTimeUint(uint64_t{1638312095}),
103 "2021-11-30T22:41:35+00:00");
104 // some time in the future, beyond 2038
105 EXPECT_EQ(getDateTimeUint(uint64_t{41638312095}),
106 "3289-06-18T21:48:15+00:00");
107 // the maximum time we support
108 EXPECT_EQ(getDateTimeUint(uint64_t{253402300799}),
109 "9999-12-31T23:59:59+00:00");
110
111 // returns the maximum Redfish date
112 EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::max()),
113 "9999-12-31T23:59:59+00:00");
114
115 EXPECT_EQ(getDateTimeUint(std::numeric_limits<uint64_t>::min()),
116 "1970-01-01T00:00:00+00:00");
117 }
118
TEST(GetDateTimeUintMs,ConverstionTests)119 TEST(GetDateTimeUintMs, ConverstionTests)
120 {
121 EXPECT_EQ(getDateTimeUintMs(uint64_t{1638312095123}),
122 "2021-11-30T22:41:35.123+00:00");
123 // returns the maximum Redfish date
124 EXPECT_EQ(getDateTimeUintMs(std::numeric_limits<uint64_t>::max()),
125 "9999-12-31T23:59:59.999+00:00");
126 EXPECT_EQ(getDateTimeUintMs(std::numeric_limits<uint64_t>::min()),
127 "1970-01-01T00:00:00.000+00:00");
128 }
129
TEST(Utility,GetDateTimeUintUs)130 TEST(Utility, GetDateTimeUintUs)
131 {
132 EXPECT_EQ(getDateTimeUintUs(uint64_t{1638312095123456}),
133 "2021-11-30T22:41:35.123456+00:00");
134 // returns the maximum Redfish date
135 EXPECT_EQ(getDateTimeUintUs(std::numeric_limits<uint64_t>::max()),
136 "9999-12-31T23:59:59.999999+00:00");
137 EXPECT_EQ(getDateTimeUintUs(std::numeric_limits<uint64_t>::min()),
138 "1970-01-01T00:00:00.000000+00:00");
139 }
140
TEST(Utility,DateStringToEpoch)141 TEST(Utility, DateStringToEpoch)
142 {
143 EXPECT_EQ(dateStringToEpoch("2021-11-30T22:41:35.123456+00:00"),
144 usSinceEpoch{1638312095123456});
145 // no timezone
146 EXPECT_EQ(dateStringToEpoch("2021-11-30T22:41:35.123456"),
147 usSinceEpoch{1638312095123456});
148 // Milliseconds precision
149 EXPECT_EQ(dateStringToEpoch("2021-11-30T22:41:35.123"),
150 usSinceEpoch{1638312095123000});
151 // Seconds precision
152 EXPECT_EQ(dateStringToEpoch("2021-11-30T22:41:35"),
153 usSinceEpoch{1638312095000000});
154
155 // Non zero timezone
156 EXPECT_EQ(dateStringToEpoch("2021-11-30T22:41:35.123456+04:00"),
157 usSinceEpoch{1638297695123456});
158
159 // Epoch
160 EXPECT_EQ(dateStringToEpoch("1970-01-01T00:00:00.000000+00:00"),
161 usSinceEpoch{0});
162
163 // Max time
164 EXPECT_EQ(dateStringToEpoch("9999-12-31T23:59:59.999999+00:00"),
165 usSinceEpoch{253402300799999999});
166
167 // Underflow
168 EXPECT_EQ(dateStringToEpoch("1969-12-30T23:59:59.999999+00:00"),
169 std::nullopt);
170 }
171
TEST(Utility,DateStringToEpochWithInvalidDateTimeFormats)172 TEST(Utility, DateStringToEpochWithInvalidDateTimeFormats)
173 {
174 // invalid month (13)
175 EXPECT_EQ(dateStringToEpoch("2024-13-01T12:00:00Z"), std::nullopt);
176
177 // invalid character for month
178 EXPECT_EQ(dateStringToEpoch("2024-X-01T12:00:00Z"), std::nullopt);
179
180 // invalid day (32)
181 EXPECT_EQ(dateStringToEpoch("2024-07-32T12:00:00Z"), std::nullopt);
182
183 // invalid character for day
184 EXPECT_EQ(dateStringToEpoch("2024-07-XT12:00:00Z"), std::nullopt);
185
186 // invalid hour (25)
187 EXPECT_EQ(dateStringToEpoch("2024-07-01T25:00:00Z"), std::nullopt);
188
189 // invalid character for hour
190 EXPECT_EQ(dateStringToEpoch("2024-07-01TX:00:00Z"), std::nullopt);
191
192 // invalid minute (60)
193 EXPECT_EQ(dateStringToEpoch("2024-07-01T12:60:00Z"), std::nullopt);
194
195 // invalid character for minute
196 EXPECT_EQ(dateStringToEpoch("2024-13-01T12:X:00Z"), std::nullopt);
197
198 // invalid second (60)
199 EXPECT_EQ(dateStringToEpoch("2024-07-01T12:00:XZ"), std::nullopt);
200
201 // invalid character for second
202 EXPECT_EQ(dateStringToEpoch("2024-13-01T12:00:00Z"), std::nullopt);
203
204 // invalid timezone
205 EXPECT_EQ(dateStringToEpoch("2024-07-01T12:00:00X"), std::nullopt);
206 }
207
208 } // namespace
209 } // namespace redfish::time_utils
210