557 lines
22 KiB
C++
557 lines
22 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#include <utcommon.h>
|
|
|
|
// Module being tested
|
|
#include <k4ainternal/depth_mcu.h>
|
|
#include <../src/depth_mcu/depthcommands.h>
|
|
|
|
// Module being mocked
|
|
#include <k4ainternal/usbcommand.h>
|
|
|
|
using namespace testing;
|
|
|
|
#define USB_INDEX (0)
|
|
#define FAKE_USB ((usbcmd_t)0xface000)
|
|
|
|
// Define a mock class for the public functions usb_cmd
|
|
class MockUsbCmd
|
|
{
|
|
public:
|
|
MOCK_CONST_METHOD4(usb_cmd_create,
|
|
k4a_result_t(usb_command_device_type_t device_type,
|
|
uint32_t device_index,
|
|
const guid_t *container_id,
|
|
usbcmd_t *p_command_handle));
|
|
|
|
MOCK_CONST_METHOD1(usb_cmd_destroy, void(usbcmd_t p_command_handle));
|
|
|
|
MOCK_CONST_METHOD7(usb_cmd_read,
|
|
k4a_result_t(usbcmd_t p_handle,
|
|
uint32_t cmd,
|
|
uint8_t *p_cmd_data, /* changed void* to uint8_t */
|
|
size_t cmd_data_size,
|
|
uint8_t *p_data, /* changed void* to uint8_t */
|
|
size_t data_size,
|
|
size_t *bytes_read));
|
|
|
|
MOCK_CONST_METHOD8(usb_cmd_read_with_status,
|
|
k4a_result_t(usbcmd_t p_handle,
|
|
uint32_t cmd,
|
|
uint8_t *p_cmd_data, /* changed void* to uint8_t */
|
|
size_t cmd_data_size,
|
|
uint8_t *p_data, /* changed void* to uint8_t */
|
|
size_t data_size,
|
|
size_t *bytes_read,
|
|
uint32_t *cmd_status));
|
|
|
|
MOCK_CONST_METHOD6(usb_cmd_write,
|
|
k4a_result_t(usbcmd_t p_handle,
|
|
uint32_t cmd,
|
|
uint8_t *p_cmd_data, /* changed void* to uint8_t */
|
|
size_t cmd_data_size,
|
|
uint8_t *p_data, /* changed void* to uint8_t */
|
|
size_t data_size));
|
|
|
|
MOCK_CONST_METHOD7(usb_cmd_write_with_status,
|
|
k4a_result_t(usbcmd_t p_handle,
|
|
uint32_t cmd,
|
|
uint8_t *p_cmd_data, /* changed void* to uint8_t */
|
|
size_t cmd_data_size,
|
|
uint8_t *p_data, /* changed void* to uint8_t */
|
|
size_t data_size,
|
|
uint32_t *cmd_status));
|
|
|
|
MOCK_CONST_METHOD3(usb_cmd_stream_register_cb,
|
|
k4a_result_t(usbcmd_t p_command_handle, usb_cmd_stream_cb_t *frame_ready_cb, void *context));
|
|
|
|
MOCK_CONST_METHOD2(usb_cmd_stream_start, k4a_result_t(usbcmd_t p_command_handle, size_t payload_size));
|
|
|
|
MOCK_CONST_METHOD1(usb_cmd_stream_stop, k4a_result_t(usbcmd_t p_command_handle));
|
|
};
|
|
|
|
extern "C" {
|
|
|
|
// Use a global singleton for the mock object.
|
|
static MockUsbCmd *g_MockUsbCmd;
|
|
|
|
// Define the symbols needed from the usb_cmd module.
|
|
// Only functions required to link the depth module are needed
|
|
k4a_result_t usb_cmd_create(usb_command_device_type_t device_type,
|
|
uint32_t device_index,
|
|
const guid_t *container_id,
|
|
usbcmd_t *p_command_handle)
|
|
{
|
|
return g_MockUsbCmd->usb_cmd_create(device_type, device_index, container_id, p_command_handle);
|
|
}
|
|
|
|
void usb_cmd_destroy(usbcmd_t p_command_handle)
|
|
{
|
|
g_MockUsbCmd->usb_cmd_destroy(p_command_handle);
|
|
}
|
|
|
|
k4a_result_t usb_cmd_read(usbcmd_t p_handle,
|
|
uint32_t cmd,
|
|
uint8_t *p_cmd_data,
|
|
size_t cmd_data_size,
|
|
uint8_t *p_data,
|
|
size_t data_size,
|
|
size_t *bytes_read)
|
|
{
|
|
// Direct the call to the mock class
|
|
return g_MockUsbCmd->usb_cmd_read(p_handle, cmd, p_cmd_data, cmd_data_size, p_data, data_size, bytes_read);
|
|
}
|
|
|
|
k4a_result_t usb_cmd_read_with_status(usbcmd_t p_handle,
|
|
uint32_t cmd,
|
|
uint8_t *p_cmd_data,
|
|
size_t cmd_data_size,
|
|
uint8_t *p_data,
|
|
size_t data_size,
|
|
size_t *bytes_read,
|
|
uint32_t *cmd_status)
|
|
{
|
|
// Direct the call to the mock class
|
|
return g_MockUsbCmd
|
|
->usb_cmd_read_with_status(p_handle, cmd, p_cmd_data, cmd_data_size, p_data, data_size, bytes_read, cmd_status);
|
|
}
|
|
|
|
k4a_result_t usb_cmd_write(usbcmd_t p_handle,
|
|
uint32_t cmd,
|
|
uint8_t *p_cmd_data,
|
|
size_t cmd_data_size,
|
|
uint8_t *p_data,
|
|
size_t data_size)
|
|
{
|
|
// Direct the call to the mock class
|
|
return g_MockUsbCmd->usb_cmd_write(p_handle, cmd, p_cmd_data, cmd_data_size, p_data, data_size);
|
|
}
|
|
|
|
k4a_result_t usb_cmd_write_with_status(usbcmd_t p_handle,
|
|
uint32_t cmd,
|
|
uint8_t *p_cmd_data,
|
|
size_t cmd_data_size,
|
|
uint8_t *p_data,
|
|
size_t data_size,
|
|
uint32_t *cmd_status)
|
|
{
|
|
// Direct the call to the mock class
|
|
return g_MockUsbCmd
|
|
->usb_cmd_write_with_status(p_handle, cmd, p_cmd_data, cmd_data_size, p_data, data_size, cmd_status);
|
|
}
|
|
|
|
k4a_result_t usb_cmd_stream_register_cb(usbcmd_t p_command_handle, usb_cmd_stream_cb_t *frame_ready_cb, void *context)
|
|
{
|
|
// Direct the call to the mock class
|
|
return g_MockUsbCmd->usb_cmd_stream_register_cb(p_command_handle, frame_ready_cb, context);
|
|
}
|
|
|
|
k4a_result_t usb_cmd_stream_start(usbcmd_t p_command_handle, size_t payload_size)
|
|
{
|
|
return g_MockUsbCmd->usb_cmd_stream_start(p_command_handle, payload_size);
|
|
}
|
|
|
|
k4a_result_t usb_cmd_stream_stop(usbcmd_t p_command_handle)
|
|
{
|
|
return g_MockUsbCmd->usb_cmd_stream_stop(p_command_handle);
|
|
}
|
|
}
|
|
|
|
// Set an expectation on the mock object for a serial number USB request which will succeed
|
|
static void EXPECT_SerialNumberCall(MockUsbCmd &usbcmd, char *mockSerialNumber, size_t mockSerialNumberBytes)
|
|
{
|
|
EXPECT_CALL(usbcmd,
|
|
usb_cmd_read(
|
|
/* usbcmd_t p_handle */ FAKE_USB,
|
|
/* uint32_t cmd */ DEV_CMD_DEPTH_READ_PRODUCT_SN,
|
|
/* uint8_t* p_cmd_data */ IsNull(),
|
|
/* size_t cmd_data_size */ 0,
|
|
/* uint8_t* p_data */ NotNull(),
|
|
/* size_t data_size */ _,
|
|
/* size_t *bytes_read */ NotNull()))
|
|
.WillRepeatedly(Invoke([mockSerialNumber, mockSerialNumberBytes](Unused /* usbcmd_t p_handle */,
|
|
Unused /* uint32_t cmd */,
|
|
Unused /* uint8_t* p_cmd_data */,
|
|
Unused /* uint32_t cmd_data_size */,
|
|
uint8_t *p_data,
|
|
size_t data_size,
|
|
size_t *bytes_read) {
|
|
if (data_size >= mockSerialNumberBytes)
|
|
{
|
|
memcpy(p_data, mockSerialNumber, mockSerialNumberBytes);
|
|
*bytes_read = mockSerialNumberBytes;
|
|
return K4A_RESULT_SUCCEEDED;
|
|
}
|
|
return K4A_RESULT_FAILED;
|
|
}));
|
|
}
|
|
|
|
// Set an expectation on the mock object for a serial number USB request which will fail
|
|
static void EXPECT_SerialNumberCallFail(MockUsbCmd &usbcmd, k4a_result_t failure)
|
|
{
|
|
EXPECT_CALL(usbcmd,
|
|
usb_cmd_read(
|
|
/* usbcmd_t p_handle */ FAKE_USB,
|
|
/* uint32_t cmd */ DEV_CMD_DEPTH_READ_PRODUCT_SN,
|
|
/* void* p_cmd_data */ IsNull(),
|
|
/* size_t cmd_data_size */ 0,
|
|
/* void* p_data */ NotNull(),
|
|
/* size_t data_size */ _,
|
|
/* size_t *bytes_read */ NotNull()))
|
|
.WillRepeatedly(Invoke([failure](Unused /* usbcmd_t p_handle */,
|
|
Unused /* uint32_t cmd */,
|
|
Unused /* void* p_cmd_data */,
|
|
Unused /* size_t cmd_data_size */,
|
|
Unused /* void* p_data */,
|
|
Unused /* size_t data_size */,
|
|
Unused /* size_t *bytes_read */) { return failure; }));
|
|
}
|
|
|
|
static void EXPECT_UsbCmdCreateSuccess(MockUsbCmd &usbcmd)
|
|
{
|
|
EXPECT_CALL(usbcmd,
|
|
usb_cmd_create(
|
|
/* usb_command_device_type_t device_type */ USB_DEVICE_DEPTH_PROCESSOR,
|
|
/* uint32_t device_index */ 0,
|
|
/* const guid_t *container_id */ NULL,
|
|
/* usbcmd_t *p_command_handle */ NotNull()))
|
|
.WillRepeatedly(Invoke([](Unused, // usb_command_device_type_t device_type
|
|
Unused, // uint8_t device_index
|
|
Unused, // const guid_t* container_id
|
|
usbcmd_t *p_command_handle) {
|
|
*p_command_handle = FAKE_USB;
|
|
return K4A_RESULT_SUCCEEDED;
|
|
}));
|
|
}
|
|
|
|
// Validate the contract of errors returned from usb_cmd_create and how
|
|
// depthmcu_create responds to that.
|
|
static void EXPECT_UsbCmdCreateFailure3(MockUsbCmd &usbcmd)
|
|
{
|
|
EXPECT_CALL(usbcmd,
|
|
usb_cmd_create(
|
|
/* usb_command_device_type_t device_type */ USB_DEVICE_DEPTH_PROCESSOR,
|
|
/* uint32_t device_index */ 0,
|
|
/* const guid_t *container_id */ NULL,
|
|
/* usbcmd_t *p_command_handle */ NotNull()))
|
|
.WillOnce(Return(K4A_RESULT_FAILED))
|
|
.WillOnce(Return(K4A_RESULT_FAILED))
|
|
.WillOnce(Return(K4A_RESULT_FAILED));
|
|
}
|
|
|
|
static void EXPECT_UsbCmdDestroyNone(MockUsbCmd &usbcmd)
|
|
{
|
|
EXPECT_CALL(usbcmd,
|
|
usb_cmd_destroy(
|
|
/* usbcmd_t p_command_handle */ NotNull()))
|
|
.Times(0);
|
|
}
|
|
|
|
static void EXPECT_UsbCmdDestroy(MockUsbCmd &usbcmd)
|
|
{
|
|
EXPECT_CALL(usbcmd,
|
|
usb_cmd_destroy(
|
|
/* usbcmd_t p_command_handle */ NotNull()))
|
|
.WillRepeatedly(Return());
|
|
}
|
|
|
|
static void EXPECT_UsbCmdRegisterCallback(MockUsbCmd &usbcmd)
|
|
{
|
|
EXPECT_CALL(usbcmd,
|
|
usb_cmd_stream_register_cb(
|
|
/* usbcmd_t p_command_handle, */ FAKE_USB,
|
|
/* usb_cmd_stream_cb_t* frame_ready_cb */ NotNull(),
|
|
/* void *context*/ _))
|
|
.WillRepeatedly(Return(K4A_RESULT_SUCCEEDED));
|
|
}
|
|
|
|
const guid_t *usb_cmd_get_container_id(usbcmd_t usbcmd_handle)
|
|
{
|
|
(void)usbcmd_handle;
|
|
return NULL;
|
|
}
|
|
|
|
class depthmcu_ut : public ::testing::Test
|
|
{
|
|
protected:
|
|
MockUsbCmd m_MockUsb;
|
|
|
|
void SetUp() override
|
|
{
|
|
g_MockUsbCmd = &m_MockUsb;
|
|
EXPECT_UsbCmdCreateSuccess(m_MockUsb);
|
|
EXPECT_UsbCmdDestroy(m_MockUsb);
|
|
EXPECT_UsbCmdRegisterCallback(m_MockUsb);
|
|
}
|
|
|
|
void TearDown() override
|
|
{
|
|
// Verify all expectations and clear them before the next test
|
|
Mock::VerifyAndClear(&m_MockUsb);
|
|
g_MockUsbCmd = NULL;
|
|
}
|
|
};
|
|
|
|
TEST_F(depthmcu_ut, create)
|
|
{
|
|
// Create the depth instance
|
|
depthmcu_t depthmcu_handle1 = NULL;
|
|
depthmcu_t depthmcu_handle2 = NULL;
|
|
|
|
// no call to usb_cmd_create should be made
|
|
ASSERT_EQ(K4A_RESULT_FAILED, depthmcu_create(USB_INDEX, NULL));
|
|
ASSERT_EQ(K4A_RESULT_FAILED, depthmcu_create(255, &depthmcu_handle1));
|
|
|
|
EXPECT_UsbCmdCreateFailure3(m_MockUsb);
|
|
EXPECT_UsbCmdDestroyNone(m_MockUsb);
|
|
ASSERT_EQ(K4A_RESULT_FAILED, depthmcu_create(USB_INDEX, &depthmcu_handle1));
|
|
ASSERT_EQ(K4A_RESULT_FAILED, depthmcu_create(USB_INDEX, &depthmcu_handle1));
|
|
ASSERT_EQ(K4A_RESULT_FAILED, depthmcu_create(USB_INDEX, &depthmcu_handle1));
|
|
|
|
EXPECT_UsbCmdCreateSuccess(m_MockUsb);
|
|
EXPECT_UsbCmdDestroy(m_MockUsb);
|
|
ASSERT_EQ(K4A_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle1));
|
|
ASSERT_NE(depthmcu_handle1, (depthmcu_t)NULL);
|
|
|
|
// Create a second instance
|
|
ASSERT_EQ(K4A_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle2));
|
|
ASSERT_NE(depthmcu_handle2, (depthmcu_t)NULL);
|
|
|
|
// Verify the instances are unique
|
|
EXPECT_NE(depthmcu_handle1, depthmcu_handle2);
|
|
|
|
// Destroy the depth instances
|
|
depthmcu_destroy(depthmcu_handle1);
|
|
depthmcu_destroy(depthmcu_handle2);
|
|
|
|
// No calls to the usb_cmd layer should have been made. It is assumed that the
|
|
// create call should be fast and not conduct any I/O
|
|
|
|
// By not defining any expectations, we should fail when we leave this test if any have been
|
|
}
|
|
|
|
#define MAX_USER_ALLOCATED_BUFFER 128
|
|
static void TestSerialNumInputConditions(depthmcu_t depthmcu_handle, char *expectedMockSerialNumber)
|
|
{
|
|
char serialno_initvalue[MAX_USER_ALLOCATED_BUFFER] = { 0 };
|
|
char serialno[MAX_USER_ALLOCATED_BUFFER] = { 0 };
|
|
|
|
// Use 0xab as the initial value of the buffer so we can see which bytes get modified
|
|
memset(serialno_initvalue, 0xab, sizeof(serialno_initvalue));
|
|
memcpy(serialno, serialno_initvalue, sizeof(serialno));
|
|
ASSERT_EQ(sizeof(serialno_initvalue), sizeof(serialno));
|
|
|
|
size_t serialnoSize = 0;
|
|
// If the string parameter is null, we expect only serialnoSize to be set
|
|
// Since serialnoSize is too small, we expect K4A_BUFFER_RESULT_TOO_SMALL
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_TOO_SMALL, depthmcu_get_serialnum(depthmcu_handle, NULL, &serialnoSize));
|
|
// serialnoSize should be the size of the serial number, plus the null terminator
|
|
EXPECT_EQ(serialnoSize, strlen(expectedMockSerialNumber) + 1);
|
|
|
|
serialnoSize = 1000;
|
|
// If the string parameter is null, we expect only serialnoSize to be set
|
|
// Since the string parameter is null, we expect K4A_BUFFER_RESULT_TOO_SMALL
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_TOO_SMALL, depthmcu_get_serialnum(depthmcu_handle, NULL, &serialnoSize));
|
|
// serialnoSize should be the size of the serial number, plus the null terminator
|
|
EXPECT_EQ(serialnoSize, strlen(expectedMockSerialNumber) + 1);
|
|
|
|
// Check the case where the input buffer is larger than needed
|
|
|
|
serialnoSize = sizeof(serialno);
|
|
memcpy(serialno, serialno_initvalue, sizeof(serialno));
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_SUCCEEDED, depthmcu_get_serialnum(depthmcu_handle, serialno, &serialnoSize));
|
|
// serialnoSize should be the size of the serial number, plus the null terminator
|
|
EXPECT_EQ(serialnoSize, strlen(expectedMockSerialNumber) + 1);
|
|
|
|
// The string should have been properly set
|
|
EXPECT_STREQ(expectedMockSerialNumber, serialno);
|
|
|
|
// Check the case where the input buffer is exactly the correct size
|
|
|
|
serialnoSize = strlen(expectedMockSerialNumber) + 1;
|
|
memcpy(serialno, serialno_initvalue, sizeof(serialno));
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_SUCCEEDED, depthmcu_get_serialnum(depthmcu_handle, serialno, &serialnoSize));
|
|
// serialnoSize should be the size of the serial number, plus the null terminator
|
|
EXPECT_EQ(serialnoSize, strlen(expectedMockSerialNumber) + 1);
|
|
// The string should have been properly set
|
|
EXPECT_STREQ(expectedMockSerialNumber, serialno);
|
|
|
|
// Check the case where the input buffer is too small
|
|
|
|
serialnoSize = 5;
|
|
ASSERT_LT(serialnoSize, strlen(expectedMockSerialNumber));
|
|
|
|
memcpy(serialno, serialno_initvalue, sizeof(serialno));
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_TOO_SMALL, depthmcu_get_serialnum(depthmcu_handle, serialno, &serialnoSize));
|
|
// serialnoSize should be the size of the serial number, plus the null terminator
|
|
EXPECT_EQ(serialnoSize, strlen(expectedMockSerialNumber) + 1);
|
|
|
|
// Expect the buffer has been initialized to a safe value
|
|
EXPECT_STREQ("", serialno);
|
|
|
|
// Check the case where the input buffer is an empty string
|
|
|
|
serialnoSize = 0;
|
|
ASSERT_LT(serialnoSize, strlen(expectedMockSerialNumber));
|
|
|
|
memcpy(serialno, serialno_initvalue, sizeof(serialno));
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_TOO_SMALL, depthmcu_get_serialnum(depthmcu_handle, serialno, &serialnoSize));
|
|
// serialnoSize should be the size of the serial number, plus the null terminator
|
|
EXPECT_EQ(serialnoSize, strlen(expectedMockSerialNumber) + 1);
|
|
|
|
// Expect the buffer has not been touched
|
|
EXPECT_EQ(0, memcmp(serialno_initvalue, serialno, strlen(expectedMockSerialNumber)));
|
|
}
|
|
|
|
TEST_F(depthmcu_ut, depthmcu_get_serialnum_base)
|
|
{
|
|
EXPECT_UsbCmdCreateSuccess(m_MockUsb);
|
|
EXPECT_UsbCmdDestroy(m_MockUsb);
|
|
|
|
// Create the depth instance
|
|
depthmcu_t depthmcu_handle = NULL;
|
|
ASSERT_EQ(K4A_BUFFER_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle));
|
|
ASSERT_NE(depthmcu_handle, (depthmcu_t)NULL);
|
|
|
|
// serial_number_size is a required parameter
|
|
char serialno[10];
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_FAILED, depthmcu_get_serialnum(depthmcu_handle, NULL, NULL));
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_FAILED, depthmcu_get_serialnum(depthmcu_handle, serialno, NULL));
|
|
|
|
depthmcu_destroy(depthmcu_handle);
|
|
}
|
|
|
|
TEST_F(depthmcu_ut, depthmcu_get_serialnum_null_terminated)
|
|
{
|
|
// Create the depth instance
|
|
depthmcu_t depthmcu_handle = NULL;
|
|
ASSERT_EQ(K4A_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle));
|
|
ASSERT_NE(depthmcu_handle, (depthmcu_t)NULL);
|
|
|
|
char mockSerialNumber[] = "1234567890";
|
|
char expectedSerialNumber[] = "1234567890";
|
|
|
|
// If the implementation caches the result, only a single call may be made. Otherwise it may be called multiple
|
|
// times
|
|
EXPECT_SerialNumberCall(m_MockUsb, mockSerialNumber, sizeof(mockSerialNumber));
|
|
|
|
// Test the various input edge cases
|
|
TestSerialNumInputConditions(depthmcu_handle, expectedSerialNumber);
|
|
|
|
depthmcu_destroy(depthmcu_handle);
|
|
}
|
|
|
|
TEST_F(depthmcu_ut, depthmcu_get_serialnum_not_terminated)
|
|
{
|
|
// Create the depth instance
|
|
depthmcu_t depthmcu_handle = NULL;
|
|
ASSERT_EQ(K4A_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle));
|
|
ASSERT_NE(depthmcu_handle, (depthmcu_t)NULL);
|
|
|
|
// Create a serial number with no NULL termination
|
|
char mockSerialNumber[10];
|
|
memcpy(mockSerialNumber, "1234567890", 10);
|
|
char expectedSerialNumber[] = "1234567890";
|
|
|
|
// If the implementation caches the result, only a single call may be made. Otherwise it may be called multiple
|
|
// times
|
|
EXPECT_SerialNumberCall(m_MockUsb, mockSerialNumber, sizeof(mockSerialNumber));
|
|
|
|
// Test the various input edge cases
|
|
TestSerialNumInputConditions(depthmcu_handle, expectedSerialNumber);
|
|
|
|
depthmcu_destroy(depthmcu_handle);
|
|
}
|
|
|
|
TEST_F(depthmcu_ut, depthmcu_get_serialnum_extra_padding)
|
|
{
|
|
// Create the depth instance
|
|
depthmcu_t depthmcu_handle = NULL;
|
|
ASSERT_EQ(K4A_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle));
|
|
ASSERT_NE(depthmcu_handle, (depthmcu_t)NULL);
|
|
|
|
// Create a serial number with extra characters after the NULL
|
|
char mockSerialNumber[20];
|
|
memcpy(mockSerialNumber, "1234567890\0WXYZ", sizeof("1234567890\0WXYZ"));
|
|
char expectedSerialNumber[] = "1234567890";
|
|
|
|
// If the implementation caches the result, only a single call may be made. Otherwise it may be called multiple
|
|
// times
|
|
EXPECT_SerialNumberCall(m_MockUsb, mockSerialNumber, sizeof(mockSerialNumber));
|
|
|
|
// Test the various input edge cases
|
|
TestSerialNumInputConditions(depthmcu_handle, expectedSerialNumber);
|
|
|
|
depthmcu_destroy(depthmcu_handle);
|
|
}
|
|
|
|
TEST_F(depthmcu_ut, depthmcu_get_serialnum_non_ascii)
|
|
{
|
|
// Create the depth instance
|
|
depthmcu_t depthmcu_handle = NULL;
|
|
ASSERT_EQ(K4A_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle));
|
|
ASSERT_NE(depthmcu_handle, (depthmcu_t)NULL);
|
|
|
|
// Create a serial number with non-ACII characters
|
|
char mockSerialNumber[20];
|
|
memcpy(mockSerialNumber, "12\145\t67890\0WXYZ", sizeof("12\145\t67890\0WXYZ"));
|
|
|
|
// If the implementation caches the result, only a single call may be made. Otherwise it may be called multiple
|
|
// times
|
|
EXPECT_SerialNumberCall(m_MockUsb, mockSerialNumber, sizeof(mockSerialNumber));
|
|
|
|
char serialno[MAX_USER_ALLOCATED_BUFFER];
|
|
size_t serialnoSize = sizeof(serialno);
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_FAILED, depthmcu_get_serialnum(depthmcu_handle, serialno, &serialnoSize));
|
|
|
|
depthmcu_destroy(depthmcu_handle);
|
|
}
|
|
|
|
TEST_F(depthmcu_ut, depthmcu_get_serialnum_devicefailure)
|
|
{
|
|
// Create the depth instance
|
|
depthmcu_t depthmcu_handle = NULL;
|
|
ASSERT_EQ(K4A_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle));
|
|
ASSERT_NE(depthmcu_handle, (depthmcu_t)NULL);
|
|
|
|
// Cause the mock to return a failure
|
|
EXPECT_SerialNumberCallFail(m_MockUsb, K4A_RESULT_FAILED);
|
|
|
|
char serialno[MAX_USER_ALLOCATED_BUFFER];
|
|
size_t serialnoSize = sizeof(serialno);
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_FAILED, depthmcu_get_serialnum(depthmcu_handle, serialno, &serialnoSize));
|
|
|
|
depthmcu_destroy(depthmcu_handle);
|
|
}
|
|
|
|
TEST_F(depthmcu_ut, depthmcu_get_serialnum_extra_long)
|
|
{
|
|
// Create the depth instance
|
|
depthmcu_t depthmcu_handle = NULL;
|
|
ASSERT_EQ(K4A_RESULT_SUCCEEDED, depthmcu_create(USB_INDEX, &depthmcu_handle));
|
|
ASSERT_NE(depthmcu_handle, (depthmcu_t)NULL);
|
|
|
|
// Construct a large null string
|
|
size_t largeSize = 1024 * 1024;
|
|
char *bigbuffer = (char *)malloc(largeSize);
|
|
memset(bigbuffer, 'a', largeSize);
|
|
bigbuffer[largeSize - 1] = '\0';
|
|
|
|
// Cause the mock to return the large buffer
|
|
EXPECT_SerialNumberCall(m_MockUsb, bigbuffer, largeSize);
|
|
|
|
// Hardware returning excessively large buffers is considered an error
|
|
char serialno[MAX_USER_ALLOCATED_BUFFER];
|
|
size_t serialnoSize = sizeof(serialno);
|
|
EXPECT_EQ(K4A_BUFFER_RESULT_FAILED, depthmcu_get_serialnum(depthmcu_handle, serialno, &serialnoSize));
|
|
|
|
free(bigbuffer);
|
|
depthmcu_destroy(depthmcu_handle);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
return k4a_test_common_main(argc, argv);
|
|
}
|