xref: /openbmc/dbus-sensors/src/nvidia-gpu/tests/NvidiaGpuSensorTest.cpp (revision 560e6af7b1f74e9c020a0f82817f9d926e0c4f72)
1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION &
3  * AFFILIATES. All rights reserved.
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "NvidiaGpuMctpVdm.hpp"
8 #include "OcpMctpVdm.hpp"
9 
10 #include <endian.h>
11 
12 #include <array>
13 #include <cerrno>
14 #include <cstdint>
15 #include <cstring>
16 #include <vector>
17 
18 #include <gtest/gtest.h>
19 
20 namespace ocp_mctp_tests
21 {
22 
23 class OcpMctpVdmTests : public ::testing::Test
24 {
25   protected:
SetUp()26     void SetUp() override
27     {
28         // Initialize common test data here
29     }
30 };
31 
32 // Tests for OcpMctpVdm::packHeader function
TEST_F(OcpMctpVdmTests,PackHeaderRequestSuccess)33 TEST_F(OcpMctpVdmTests, PackHeaderRequestSuccess)
34 {
35     const uint16_t pciVendorId = 0x1234;
36     ocp::accelerator_management::BindingPciVidInfo hdr{};
37     ocp::accelerator_management::BindingPciVid msg{};
38 
39     hdr.ocp_accelerator_management_msg_type =
40         static_cast<uint8_t>(ocp::accelerator_management::MessageType::REQUEST);
41     hdr.instance_id = 5;
42     hdr.msg_type = 0x7E;
43 
44     int result = ocp::accelerator_management::packHeader(pciVendorId, hdr, msg);
45 
46     EXPECT_EQ(result, 0);
47     EXPECT_EQ(msg.pci_vendor_id, htobe16(pciVendorId));
48     EXPECT_EQ(msg.instance_id & ocp::accelerator_management::instanceIdBitMask,
49               5);
50     EXPECT_NE(msg.instance_id & ocp::accelerator_management::requestBitMask, 0);
51     EXPECT_EQ(msg.ocp_version & 0x0F, ocp::accelerator_management::ocpVersion);
52     EXPECT_EQ((msg.ocp_version & 0xF0) >>
53                   ocp::accelerator_management::ocpTypeBitOffset,
54               ocp::accelerator_management::ocpType);
55     EXPECT_EQ(msg.ocp_accelerator_management_msg_type, 0x7E);
56 }
57 
TEST_F(OcpMctpVdmTests,PackHeaderResponseSuccess)58 TEST_F(OcpMctpVdmTests, PackHeaderResponseSuccess)
59 {
60     const uint16_t pciVendorId = 0x1234;
61     ocp::accelerator_management::BindingPciVidInfo hdr{};
62     ocp::accelerator_management::BindingPciVid msg{};
63 
64     hdr.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
65         ocp::accelerator_management::MessageType::RESPONSE);
66     hdr.instance_id = 10;
67     hdr.msg_type = 0x7E;
68 
69     int result = ocp::accelerator_management::packHeader(pciVendorId, hdr, msg);
70 
71     EXPECT_EQ(result, 0);
72     EXPECT_EQ(msg.pci_vendor_id, htobe16(pciVendorId));
73     EXPECT_EQ(msg.instance_id & ocp::accelerator_management::instanceIdBitMask,
74               10);
75     EXPECT_EQ(msg.instance_id & ocp::accelerator_management::requestBitMask, 0);
76     EXPECT_EQ(msg.ocp_version & 0x0F, ocp::accelerator_management::ocpVersion);
77     EXPECT_EQ((msg.ocp_version & 0xF0) >>
78                   ocp::accelerator_management::ocpTypeBitOffset,
79               ocp::accelerator_management::ocpType);
80     EXPECT_EQ(msg.ocp_accelerator_management_msg_type, 0x7E);
81 }
82 
TEST_F(OcpMctpVdmTests,PackHeaderInvalidMessageType)83 TEST_F(OcpMctpVdmTests, PackHeaderInvalidMessageType)
84 {
85     const uint16_t pciVendorId = 0x1234;
86     ocp::accelerator_management::BindingPciVidInfo hdr{};
87     ocp::accelerator_management::BindingPciVid msg{};
88 
89     hdr.ocp_accelerator_management_msg_type = 3; // Invalid message type
90     hdr.instance_id = 5;
91     hdr.msg_type = 0x7E;
92 
93     int result = ocp::accelerator_management::packHeader(pciVendorId, hdr, msg);
94 
95     EXPECT_EQ(result, EINVAL);
96 }
97 
TEST_F(OcpMctpVdmTests,PackHeaderInvalidInstanceId)98 TEST_F(OcpMctpVdmTests, PackHeaderInvalidInstanceId)
99 {
100     const uint16_t pciVendorId = 0x1234;
101     ocp::accelerator_management::BindingPciVidInfo hdr{};
102     ocp::accelerator_management::BindingPciVid msg{};
103 
104     hdr.ocp_accelerator_management_msg_type =
105         static_cast<uint8_t>(ocp::accelerator_management::MessageType::REQUEST);
106     hdr.instance_id = 32; // Out of range (0-31 valid)
107     hdr.msg_type = 0x7E;
108 
109     int result = ocp::accelerator_management::packHeader(pciVendorId, hdr, msg);
110 
111     EXPECT_EQ(result, EINVAL);
112 }
113 
114 // Tests for OcpMctpVdm::decodeReasonCodeAndCC function
TEST_F(OcpMctpVdmTests,DecodeReasonCodeAndCCSuccessCase)115 TEST_F(OcpMctpVdmTests, DecodeReasonCodeAndCCSuccessCase)
116 {
117     ocp::accelerator_management::CommonNonSuccessResponse response{};
118     response.command = 0x42;
119     response.completion_code = static_cast<uint8_t>(
120         ocp::accelerator_management::CompletionCode::SUCCESS);
121     response.reason_code = htole16(0x1234);
122 
123     ocp::accelerator_management::CompletionCode cc{};
124     uint16_t reasonCode{};
125 
126     std::array<uint8_t, sizeof(response)> buf{};
127     std::memcpy(buf.data(), &response, sizeof(response));
128 
129     int result =
130         ocp::accelerator_management::decodeReasonCodeAndCC(buf, cc, reasonCode);
131 
132     EXPECT_EQ(result, 0);
133     EXPECT_EQ(cc, ocp::accelerator_management::CompletionCode::SUCCESS);
134     EXPECT_EQ(reasonCode, 0); // Should be 0 for SUCCESS
135 }
136 
TEST_F(OcpMctpVdmTests,DecodeReasonCodeAndCCErrorCase)137 TEST_F(OcpMctpVdmTests, DecodeReasonCodeAndCCErrorCase)
138 {
139     ocp::accelerator_management::CommonNonSuccessResponse response{};
140     response.command = 0x42;
141     response.completion_code = static_cast<uint8_t>(
142         ocp::accelerator_management::CompletionCode::ERROR);
143     response.reason_code = htole16(0x5678);
144 
145     ocp::accelerator_management::CompletionCode cc{};
146     uint16_t reasonCode{};
147 
148     std::array<uint8_t, sizeof(response)> buf{};
149     std::memcpy(buf.data(), &response, sizeof(response));
150 
151     int result =
152         ocp::accelerator_management::decodeReasonCodeAndCC(buf, cc, reasonCode);
153 
154     EXPECT_EQ(result, 0);
155     EXPECT_EQ(cc, ocp::accelerator_management::CompletionCode::ERROR);
156     EXPECT_EQ(reasonCode, 0x5678);
157 }
158 
159 } // namespace ocp_mctp_tests
160 
161 namespace gpu_mctp_tests
162 {
163 
164 class GpuMctpVdmTests : public ::testing::Test
165 {
166   protected:
SetUp()167     void SetUp() override
168     {
169         // Initialize common test data here
170     }
171 };
172 
173 // Tests for GpuMctpVdm::packHeader function
TEST_F(GpuMctpVdmTests,PackHeaderSuccess)174 TEST_F(GpuMctpVdmTests, PackHeaderSuccess)
175 {
176     ocp::accelerator_management::BindingPciVidInfo hdr{};
177     ocp::accelerator_management::BindingPciVid msg{};
178 
179     hdr.ocp_accelerator_management_msg_type =
180         static_cast<uint8_t>(ocp::accelerator_management::MessageType::REQUEST);
181     hdr.instance_id = 5;
182     hdr.msg_type = 0x7E;
183 
184     int result = gpu::packHeader(hdr, msg);
185 
186     EXPECT_EQ(result, 0);
187     EXPECT_EQ(msg.pci_vendor_id, htobe16(gpu::nvidiaPciVendorId));
188     EXPECT_EQ(msg.instance_id & ocp::accelerator_management::instanceIdBitMask,
189               5);
190     EXPECT_NE(msg.instance_id & ocp::accelerator_management::requestBitMask, 0);
191     EXPECT_EQ(msg.ocp_version & 0x0F, ocp::accelerator_management::ocpVersion);
192     EXPECT_EQ((msg.ocp_version & 0xF0) >>
193                   ocp::accelerator_management::ocpTypeBitOffset,
194               ocp::accelerator_management::ocpType);
195     EXPECT_EQ(msg.ocp_accelerator_management_msg_type, 0x7E);
196 }
197 
198 // Tests for GpuMctpVdm::encodeQueryDeviceIdentificationRequest function
TEST_F(GpuMctpVdmTests,EncodeQueryDeviceIdentificationRequestSuccess)199 TEST_F(GpuMctpVdmTests, EncodeQueryDeviceIdentificationRequestSuccess)
200 {
201     const uint8_t instanceId = 3;
202     std::vector<uint8_t> buf(256);
203 
204     int result = gpu::encodeQueryDeviceIdentificationRequest(instanceId, buf);
205 
206     EXPECT_EQ(result, 0);
207 
208     gpu::QueryDeviceIdentificationRequest request{};
209     std::memcpy(&request, buf.data(), sizeof(request));
210 
211     EXPECT_EQ(request.hdr.msgHdr.hdr.pci_vendor_id,
212               htobe16(gpu::nvidiaPciVendorId));
213     EXPECT_EQ(request.hdr.msgHdr.hdr.instance_id &
214                   ocp::accelerator_management::instanceIdBitMask,
215               instanceId & ocp::accelerator_management::instanceIdBitMask);
216     EXPECT_NE(request.hdr.msgHdr.hdr.instance_id &
217                   ocp::accelerator_management::requestBitMask,
218               0);
219 
220     EXPECT_EQ(request.hdr.command,
221               static_cast<uint8_t>(gpu::DeviceCapabilityDiscoveryCommands::
222                                        QUERY_DEVICE_IDENTIFICATION));
223     EXPECT_EQ(request.hdr.data_size, 0);
224 }
225 
226 // Tests for GpuMctpVdm::decodeQueryDeviceIdentificationResponse function
TEST_F(GpuMctpVdmTests,DecodeQueryDeviceIdentificationResponseSuccess)227 TEST_F(GpuMctpVdmTests, DecodeQueryDeviceIdentificationResponseSuccess)
228 {
229     // Create a mock successful response
230     std::vector<uint8_t> buf(sizeof(gpu::QueryDeviceIdentificationResponse));
231 
232     gpu::QueryDeviceIdentificationResponse response{};
233     ocp::accelerator_management::BindingPciVidInfo headerInfo{};
234     headerInfo.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
235         ocp::accelerator_management::MessageType::RESPONSE);
236     headerInfo.instance_id = 3;
237     headerInfo.msg_type =
238         static_cast<uint8_t>(gpu::MessageType::DEVICE_CAPABILITY_DISCOVERY);
239 
240     gpu::packHeader(headerInfo, response.hdr.msgHdr.hdr);
241 
242     // Populate response data
243     response.hdr.command = static_cast<uint8_t>(
244         gpu::DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION);
245     response.hdr.completion_code = static_cast<uint8_t>(
246         ocp::accelerator_management::CompletionCode::SUCCESS);
247     response.hdr.reserved = 0;
248     response.hdr.data_size =
249         htole16(2); // Size of device_identification + instance_id
250     response.device_identification =
251         static_cast<uint8_t>(gpu::DeviceIdentification::DEVICE_GPU);
252     response.instance_id = 7;
253 
254     std::memcpy(buf.data(), &response, sizeof(response));
255 
256     // Test decoding
257     ocp::accelerator_management::CompletionCode cc{};
258     uint16_t reasonCode{};
259     uint8_t deviceIdentification{};
260     uint8_t deviceInstance{};
261 
262     int result = gpu::decodeQueryDeviceIdentificationResponse(
263         buf, cc, reasonCode, deviceIdentification, deviceInstance);
264 
265     EXPECT_EQ(result, 0);
266     EXPECT_EQ(cc, ocp::accelerator_management::CompletionCode::SUCCESS);
267     EXPECT_EQ(reasonCode, 0);
268     EXPECT_EQ(deviceIdentification,
269               static_cast<uint8_t>(gpu::DeviceIdentification::DEVICE_GPU));
270     EXPECT_EQ(deviceInstance, 7);
271 }
272 
TEST_F(GpuMctpVdmTests,DecodeQueryDeviceIdentificationResponseError)273 TEST_F(GpuMctpVdmTests, DecodeQueryDeviceIdentificationResponseError)
274 {
275     // Create a mock successful response
276     std::vector<uint8_t> buf(
277         sizeof(ocp::accelerator_management::CommonNonSuccessResponse));
278 
279     ocp::accelerator_management::CommonNonSuccessResponse response{};
280     ocp::accelerator_management::BindingPciVidInfo headerInfo{};
281     headerInfo.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
282         ocp::accelerator_management::MessageType::RESPONSE);
283     headerInfo.instance_id = 3;
284     headerInfo.msg_type =
285         static_cast<uint8_t>(gpu::MessageType::DEVICE_CAPABILITY_DISCOVERY);
286 
287     gpu::packHeader(headerInfo, response.msgHdr.hdr);
288 
289     // Populate response data
290     response.command = static_cast<uint8_t>(
291         gpu::DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION);
292     response.command = static_cast<uint8_t>(
293         gpu::DeviceCapabilityDiscoveryCommands::QUERY_DEVICE_IDENTIFICATION);
294     response.completion_code = static_cast<uint8_t>(
295         ocp::accelerator_management::CompletionCode::ERROR);
296     response.reason_code = htole16(0x1234);
297 
298     std::memcpy(buf.data(), &response, sizeof(response));
299 
300     // Test decoding
301     ocp::accelerator_management::CompletionCode cc{};
302     uint16_t reasonCode{};
303     uint8_t deviceIdentification{};
304     uint8_t deviceInstance{};
305 
306     int result = gpu::decodeQueryDeviceIdentificationResponse(
307         buf, cc, reasonCode, deviceIdentification, deviceInstance);
308 
309     EXPECT_EQ(result, 0);
310     EXPECT_EQ(cc, ocp::accelerator_management::CompletionCode::ERROR);
311     EXPECT_EQ(reasonCode, 0x1234);
312 }
313 
TEST_F(GpuMctpVdmTests,DecodeQueryDeviceIdentificationResponseInvalidSize)314 TEST_F(GpuMctpVdmTests, DecodeQueryDeviceIdentificationResponseInvalidSize)
315 {
316     // Create a too-small buffer
317     std::vector<uint8_t> buf(
318         sizeof(ocp::accelerator_management::Message) + 2); // Too small
319 
320     // Populate Message header only
321     ocp::accelerator_management::Message msg{};
322     ocp::accelerator_management::BindingPciVidInfo headerInfo{};
323     headerInfo.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
324         ocp::accelerator_management::MessageType::RESPONSE);
325     headerInfo.instance_id = 3;
326     headerInfo.msg_type =
327         static_cast<uint8_t>(gpu::MessageType::DEVICE_CAPABILITY_DISCOVERY);
328 
329     gpu::packHeader(headerInfo, msg.hdr);
330     std::memcpy(buf.data(), &msg, sizeof(msg));
331 
332     // Test decoding with insufficient data
333     ocp::accelerator_management::CompletionCode cc{};
334     uint16_t reasonCode{};
335     uint8_t deviceIdentification{};
336     uint8_t deviceInstance{};
337 
338     int result = gpu::decodeQueryDeviceIdentificationResponse(
339         buf, cc, reasonCode, deviceIdentification, deviceInstance);
340 
341     EXPECT_EQ(result, EINVAL); // Should indicate error for invalid size
342 }
343 
344 // Tests for GpuMctpVdm::encodeGetTemperatureReadingRequest function
TEST_F(GpuMctpVdmTests,EncodeGetTemperatureReadingRequestSuccess)345 TEST_F(GpuMctpVdmTests, EncodeGetTemperatureReadingRequestSuccess)
346 {
347     const uint8_t instanceId = 4;
348     const uint8_t sensorId = 0;
349     std::vector<uint8_t> buf(256);
350 
351     int result =
352         gpu::encodeGetTemperatureReadingRequest(instanceId, sensorId, buf);
353 
354     EXPECT_EQ(result, 0);
355 
356     gpu::GetTemperatureReadingRequest request{};
357     std::memcpy(&request, buf.data(), sizeof(request));
358 
359     EXPECT_EQ(request.hdr.msgHdr.hdr.pci_vendor_id,
360               htobe16(gpu::nvidiaPciVendorId));
361     EXPECT_EQ(request.hdr.msgHdr.hdr.instance_id &
362                   ocp::accelerator_management::instanceIdBitMask,
363               instanceId & ocp::accelerator_management::instanceIdBitMask);
364     EXPECT_NE(request.hdr.msgHdr.hdr.instance_id &
365                   ocp::accelerator_management::requestBitMask,
366               0);
367     EXPECT_EQ(request.hdr.msgHdr.hdr.ocp_accelerator_management_msg_type,
368               static_cast<uint8_t>(gpu::MessageType::PLATFORM_ENVIRONMENTAL));
369 
370     // Verify request data
371     EXPECT_EQ(request.hdr.command,
372               static_cast<uint8_t>(
373                   gpu::PlatformEnvironmentalCommands::GET_TEMPERATURE_READING));
374     EXPECT_EQ(request.hdr.data_size, sizeof(sensorId));
375     EXPECT_EQ(request.sensor_id, sensorId);
376 }
377 
378 // Tests for GpuMctpVdm::decodeGetTemperatureReadingResponse function
TEST_F(GpuMctpVdmTests,DecodeGetTemperatureReadingResponseSuccess)379 TEST_F(GpuMctpVdmTests, DecodeGetTemperatureReadingResponseSuccess)
380 {
381     // Create a mock successful response
382     std::vector<uint8_t> buf(sizeof(gpu::GetTemperatureReadingResponse));
383 
384     gpu::GetTemperatureReadingResponse response{};
385     ocp::accelerator_management::BindingPciVidInfo headerInfo{};
386     headerInfo.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
387         ocp::accelerator_management::MessageType::RESPONSE);
388     headerInfo.instance_id = 4;
389     headerInfo.msg_type =
390         static_cast<uint8_t>(gpu::MessageType::PLATFORM_ENVIRONMENTAL);
391 
392     gpu::packHeader(headerInfo, response.hdr.msgHdr.hdr);
393 
394     // Populate response data
395     response.hdr.command = static_cast<uint8_t>(
396         gpu::PlatformEnvironmentalCommands::GET_TEMPERATURE_READING);
397     response.hdr.completion_code = static_cast<uint8_t>(
398         ocp::accelerator_management::CompletionCode::SUCCESS);
399     response.hdr.reserved = 0;
400     response.hdr.data_size = htole16(sizeof(int32_t));
401 
402     // Set a temperature value of 75.5°C (75.5 * 256 = 19328)
403     response.reading = htole32(19328);
404 
405     std::memcpy(buf.data(), &response, sizeof(response));
406 
407     // Test decoding
408     ocp::accelerator_management::CompletionCode cc{};
409     uint16_t reasonCode{};
410     double temperatureReading{};
411 
412     int result = gpu::decodeGetTemperatureReadingResponse(
413         buf, cc, reasonCode, temperatureReading);
414 
415     EXPECT_EQ(result, 0);
416     EXPECT_EQ(cc, ocp::accelerator_management::CompletionCode::SUCCESS);
417     EXPECT_EQ(reasonCode, 0);
418     EXPECT_NEAR(temperatureReading, 75.5, 0.01);
419 }
420 
TEST_F(GpuMctpVdmTests,DecodeGetTemperatureReadingResponseError)421 TEST_F(GpuMctpVdmTests, DecodeGetTemperatureReadingResponseError)
422 {
423     std::vector<uint8_t> buf(
424         sizeof(ocp::accelerator_management::CommonNonSuccessResponse));
425 
426     // Populate error response data
427     ocp::accelerator_management::CommonNonSuccessResponse errorResponse{};
428     ocp::accelerator_management::BindingPciVidInfo headerInfo{};
429     headerInfo.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
430         ocp::accelerator_management::MessageType::RESPONSE);
431     headerInfo.instance_id = 3;
432     headerInfo.msg_type =
433         static_cast<uint8_t>(gpu::MessageType::DEVICE_CAPABILITY_DISCOVERY);
434 
435     gpu::packHeader(headerInfo, errorResponse.msgHdr.hdr);
436 
437     errorResponse.command = static_cast<uint8_t>(
438         gpu::PlatformEnvironmentalCommands::GET_TEMPERATURE_READING);
439     errorResponse.completion_code = static_cast<uint8_t>(
440         ocp::accelerator_management::CompletionCode::ERR_NOT_READY);
441     errorResponse.reason_code = htole16(0x4321);
442 
443     std::memcpy(buf.data(), &errorResponse, sizeof(errorResponse));
444 
445     // Test decoding
446     ocp::accelerator_management::CompletionCode cc{};
447     uint16_t reasonCode{};
448     double temperatureReading{};
449 
450     int result = gpu::decodeGetTemperatureReadingResponse(
451         buf, cc, reasonCode, temperatureReading);
452 
453     EXPECT_EQ(result, 0);
454     EXPECT_EQ(cc, ocp::accelerator_management::CompletionCode::ERR_NOT_READY);
455     EXPECT_EQ(reasonCode, 0x4321);
456 }
457 
TEST_F(GpuMctpVdmTests,DecodeGetTemperatureReadingResponseInvalidSize)458 TEST_F(GpuMctpVdmTests, DecodeGetTemperatureReadingResponseInvalidSize)
459 {
460     // Create a mock response with invalid data_size
461     std::vector<uint8_t> buf(sizeof(gpu::GetTemperatureReadingResponse));
462 
463     gpu::GetTemperatureReadingResponse response{};
464     ocp::accelerator_management::BindingPciVidInfo headerInfo{};
465     headerInfo.ocp_accelerator_management_msg_type = static_cast<uint8_t>(
466         ocp::accelerator_management::MessageType::RESPONSE);
467     headerInfo.instance_id = 4;
468     headerInfo.msg_type =
469         static_cast<uint8_t>(gpu::MessageType::PLATFORM_ENVIRONMENTAL);
470 
471     gpu::packHeader(headerInfo, response.hdr.msgHdr.hdr);
472 
473     response.hdr.command = static_cast<uint8_t>(
474         gpu::PlatformEnvironmentalCommands::GET_TEMPERATURE_READING);
475     response.hdr.completion_code = static_cast<uint8_t>(
476         ocp::accelerator_management::CompletionCode::SUCCESS);
477     response.hdr.reserved = 0;
478     response.hdr.data_size = htole16(1); // Invalid - should be sizeof(int32_t)
479     response.reading = htole32(19328);
480 
481     std::memcpy(buf.data(), &response, sizeof(response));
482 
483     // Test decoding
484     ocp::accelerator_management::CompletionCode cc{};
485     uint16_t reasonCode{};
486     double temperatureReading{};
487 
488     int result = gpu::decodeGetTemperatureReadingResponse(
489         buf, cc, reasonCode, temperatureReading);
490 
491     EXPECT_EQ(result, EINVAL); // Should indicate error for invalid data size
492 }
493 
494 } // namespace gpu_mctp_tests
495 
main(int argc,char ** argv)496 int main(int argc, char** argv)
497 {
498     ::testing::InitGoogleTest(&argc, argv);
499     return RUN_ALL_TESTS();
500 }
501