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