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