1 #include "event_log.hpp"
2 
3 #include <nlohmann/json.hpp>
4 
5 #include <cerrno>
6 #include <cstddef>
7 #include <ctime>
8 #include <string>
9 #include <string_view>
10 #include <vector>
11 
12 #include <gmock/gmock.h>
13 #include <gtest/gtest.h>
14 
15 namespace redfish::event_log
16 {
17 namespace
18 {
19 
TEST(RedfishEventLog,GetUniqueEntryIDSuccess)20 TEST(RedfishEventLog, GetUniqueEntryIDSuccess)
21 {
22     bool success = false;
23     std::string entryID;
24     std::string example = "2000-01-02T03:04:05";
25     success = getUniqueEntryID(example, entryID);
26 
27     ASSERT_EQ(success, true);
28 
29     // assert the prefix since the specific number can depend on timezone
30     ASSERT_TRUE(entryID.starts_with("946"));
31 }
32 
TEST(RedfishEventLog,GetUniqueEntryIDUnique)33 TEST(RedfishEventLog, GetUniqueEntryIDUnique)
34 {
35     bool success = false;
36     std::string entryID1;
37     std::string entryID2;
38     std::string example = "2000-08-02T03:04:05";
39 
40     success = getUniqueEntryID(example, entryID1);
41     ASSERT_EQ(success, true);
42     success = getUniqueEntryID(example, entryID2);
43     ASSERT_EQ(success, true);
44 
45     // when calling a second time with the same argument
46     // there should be an underscore
47     ASSERT_TRUE(entryID2.contains("_"));
48 
49     // only one '_' allowed
50     ASSERT_THAT(entryID2, testing::MatchesRegex("^[0-9]+_[0-9]+$"));
51 }
52 
TEST(RedfishEventLog,GetUniqueEntryIDIndex)53 TEST(RedfishEventLog, GetUniqueEntryIDIndex)
54 {
55     std::string entryID1;
56     std::string entryID2;
57     std::string entryID3;
58     std::string example = "2000-08-02T03:04:05";
59 
60     getUniqueEntryID(example, entryID1);
61     getUniqueEntryID(example, entryID2);
62     getUniqueEntryID(example, entryID3);
63 
64     const size_t index = entryID2.find('_');
65 
66     ASSERT_NE(index, std::string::npos);
67 
68     const long n1 = std::stol(entryID2.substr(index + 1));
69 
70     // unique index for repeated timestamp is >= 0
71     ASSERT_GE(n1, 0);
72 
73     const long n2 = std::stol(entryID3.substr(entryID3.find('_') + 1));
74 
75     // unique index is monotonic increasing
76     ASSERT_TRUE(n2 > n1);
77 }
78 
TEST(RedfishEventLog,GetEventLogParamsSuccess)79 TEST(RedfishEventLog, GetEventLogParamsSuccess)
80 {
81     int status = 0;
82     std::string logEntry = "32938 3,hello";
83 
84     std::string timestamp;
85     std::string messageID;
86     std::vector<std::string> messageArgs;
87 
88     status = getEventLogParams(logEntry, timestamp, messageID, messageArgs);
89 
90     ASSERT_EQ(status, 0);
91 
92     ASSERT_EQ(timestamp, "32938");
93     ASSERT_EQ(messageID, "3");
94     ASSERT_EQ(messageArgs.size(), 1);
95     ASSERT_EQ(messageArgs[0], "hello");
96 }
97 
TEST(RedfishEventLog,GetEventLogParamsFailNoTimestamp)98 TEST(RedfishEventLog, GetEventLogParamsFailNoTimestamp)
99 {
100     int status = 0;
101     std::string logEntry = "3,hello";
102 
103     std::string timestamp;
104     std::string messageID;
105     std::vector<std::string> messageArgs;
106 
107     status = getEventLogParams(logEntry, timestamp, messageID, messageArgs);
108 
109     ASSERT_EQ(status, -EINVAL);
110 }
111 
TEST(RedfishEventLog,GetEventLogParamsFailNoComma)112 TEST(RedfishEventLog, GetEventLogParamsFailNoComma)
113 {
114     int status = 0;
115     std::string logEntry = "malformed";
116 
117     std::string timestamp;
118     std::string messageID;
119     std::vector<std::string> messageArgs;
120 
121     status = getEventLogParams(logEntry, timestamp, messageID, messageArgs);
122 
123     ASSERT_EQ(status, -EINVAL);
124 }
125 
TEST(RedfishEventLog,FormatEventLogEntrySuccess)126 TEST(RedfishEventLog, FormatEventLogEntrySuccess)
127 {
128     int status = 0;
129     std::string logEntryID = "23849423_3";
130     std::string messageID = "OpenBMC.0.1.PowerSupplyFanFailed";
131     std::vector<std::string_view> messageArgs = {"PSU 1", "FAN 2"};
132     std::string timestamp = "my-timestamp";
133     std::string customText = "customText";
134 
135     nlohmann::json::object_t logEntryJson;
136     status = formatEventLogEntry(logEntryID, messageID, messageArgs, timestamp,
137                                  customText, logEntryJson);
138 
139     ASSERT_EQ(status, 0);
140 
141     ASSERT_TRUE(logEntryJson.contains("EventId"));
142     ASSERT_EQ(logEntryJson["EventId"], "23849423_3");
143 
144     ASSERT_TRUE(logEntryJson.contains("Message"));
145     ASSERT_EQ(logEntryJson["Message"], "Power supply PSU 1 fan FAN 2 failed.");
146 
147     ASSERT_TRUE(logEntryJson.contains("MessageId"));
148     ASSERT_EQ(logEntryJson["MessageId"], "OpenBMC.0.1.PowerSupplyFanFailed");
149 
150     ASSERT_TRUE(logEntryJson.contains("MessageArgs"));
151     ASSERT_EQ(logEntryJson["MessageArgs"].size(), 2);
152     ASSERT_EQ(logEntryJson["MessageArgs"][0], "PSU 1");
153     ASSERT_EQ(logEntryJson["MessageArgs"][1], "FAN 2");
154 
155     ASSERT_TRUE(logEntryJson.contains("EventTimestamp"));
156 
157     // May need to fix this, it should not pass like this.
158     ASSERT_EQ(logEntryJson["EventTimestamp"], "my-timestamp");
159 
160     ASSERT_TRUE(logEntryJson.contains("Context"));
161     ASSERT_EQ(logEntryJson["Context"], "customText");
162 }
163 
TEST(RedfishEventLog,FormatEventLogEntryFail)164 TEST(RedfishEventLog, FormatEventLogEntryFail)
165 {
166     int status = 0;
167     std::string logEntryID = "malformed";
168     std::string messageID;
169     std::vector<std::string_view> messageArgs;
170     std::string timestamp;
171     std::string customText;
172 
173     nlohmann::json::object_t logEntryJson;
174     status = formatEventLogEntry(logEntryID, messageID, messageArgs, timestamp,
175                                  customText, logEntryJson);
176 
177     ASSERT_EQ(status, -1);
178 }
179 
180 } // namespace
181 } // namespace redfish::event_log
182