1 #include "common/utils.hpp"
2 #include "libpldmresponder/base.hpp"
3 
4 #include <libpldm/base.h>
5 #include <string.h>
6 
7 #include <sdeventplus/event.hpp>
8 
9 #include <array>
10 
11 #include <gtest/gtest.h>
12 
13 using namespace pldm::responder;
14 
15 class TestBaseCommands : public testing::Test
16 {
17   protected:
18     TestBaseCommands() :
19         requester(pldm::utils::DBusHandler::getBus(), "/abc/def"),
20         event(sdeventplus::Event::get_default())
21     {}
22 
23     uint8_t mctpEid = 0;
24     Requester requester;
25     sdeventplus::Event event;
26 };
27 
28 TEST_F(TestBaseCommands, testPLDMTypesGoodRequest)
29 {
30     std::array<uint8_t, sizeof(pldm_msg_hdr)> requestPayload{};
31     auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
32     // payload length will be 0 in this case
33     size_t requestPayloadLength = 0;
34     base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
35     auto response = handler.getPLDMTypes(request, requestPayloadLength);
36     // Need to support OEM type.
37     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
38     uint8_t* payload_ptr = responsePtr->payload;
39     ASSERT_EQ(payload_ptr[0], 0);
40     ASSERT_EQ(payload_ptr[1], 29); // 0b11101 see DSP0240 table11
41     ASSERT_EQ(payload_ptr[2], 0);
42 }
43 
44 TEST_F(TestBaseCommands, testGetPLDMCommandsGoodRequest)
45 {
46     // Need to support OEM type commands.
47     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES>
48         requestPayload{};
49     auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
50     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
51     base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
52     auto response = handler.getPLDMCommands(request, requestPayloadLength);
53     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
54     uint8_t* payload_ptr = responsePtr->payload;
55     ASSERT_EQ(payload_ptr[0], 0);
56     ASSERT_EQ(payload_ptr[1], 60); // 60 = 0b111100
57     ASSERT_EQ(payload_ptr[2], 0);
58 }
59 
60 TEST_F(TestBaseCommands, testGetPLDMCommandsBadRequest)
61 {
62     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_COMMANDS_REQ_BYTES>
63         requestPayload{};
64     auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
65 
66     request->payload[0] = 0xFF;
67     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
68     base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
69     auto response = handler.getPLDMCommands(request, requestPayloadLength);
70     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
71     uint8_t* payload_ptr = responsePtr->payload;
72     ASSERT_EQ(payload_ptr[0], PLDM_ERROR_INVALID_PLDM_TYPE);
73 }
74 
75 TEST_F(TestBaseCommands, testGetPLDMVersionGoodRequest)
76 {
77     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES>
78         requestPayload{};
79     auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
80     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
81 
82     uint8_t pldmType = PLDM_BASE;
83     uint32_t transferHandle = 0x0;
84     uint8_t flag = PLDM_GET_FIRSTPART;
85     uint8_t retFlag = PLDM_START_AND_END;
86     ver32_t version = {0x00, 0xF0, 0xF0, 0xF1};
87 
88     auto rc =
89         encode_get_version_req(0, transferHandle, flag, pldmType, request);
90 
91     ASSERT_EQ(0, rc);
92 
93     base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
94     auto response = handler.getPLDMVersion(request, requestPayloadLength);
95     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
96 
97     ASSERT_EQ(responsePtr->payload[0], 0);
98     ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]),
99                         &transferHandle, sizeof(transferHandle)));
100     ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]) +
101                             sizeof(transferHandle),
102                         &retFlag, sizeof(flag)));
103     ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]) +
104                             sizeof(transferHandle) + sizeof(flag),
105                         &version, sizeof(version)));
106 }
107 
108 TEST_F(TestBaseCommands, testGetPLDMVersionBadRequest)
109 {
110     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_REQ_BYTES>
111         requestPayload{};
112     auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
113     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
114 
115     uint8_t pldmType = 7;
116     uint32_t transferHandle = 0x0;
117     uint8_t flag = PLDM_GET_FIRSTPART;
118 
119     auto rc =
120         encode_get_version_req(0, transferHandle, flag, pldmType, request);
121 
122     ASSERT_EQ(0, rc);
123 
124     base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
125     auto response = handler.getPLDMVersion(request, requestPayloadLength - 1);
126     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
127 
128     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH);
129 
130     request = reinterpret_cast<pldm_msg*>(requestPayload.data());
131     requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
132 
133     rc = encode_get_version_req(0, transferHandle, flag, pldmType, request);
134 
135     ASSERT_EQ(0, rc);
136 
137     response = handler.getPLDMVersion(request, requestPayloadLength);
138     responsePtr = reinterpret_cast<pldm_msg*>(response.data());
139 
140     ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_PLDM_TYPE);
141 }
142 
143 TEST_F(TestBaseCommands, testGetTIDGoodRequest)
144 {
145     std::array<uint8_t, sizeof(pldm_msg_hdr)> requestPayload{};
146     auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
147     size_t requestPayloadLength = 0;
148 
149     base::Handler handler(mctpEid, requester, event, nullptr, nullptr);
150     auto response = handler.getTID(request, requestPayloadLength);
151 
152     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
153     uint8_t* payload = responsePtr->payload;
154 
155     ASSERT_EQ(payload[0], 0);
156     ASSERT_EQ(payload[1], 1);
157 }
158