From cfb51dba51ea5f5732d6625239b0b5c5a11e6e81 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 07:00:38 +0000 Subject: [PATCH 1/2] Initial plan From 0b6140e6cb062d3d1515c266305ce294d6082ef7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Mar 2026 07:17:08 +0000 Subject: [PATCH 2/2] Add/update unit tests for isSecureDbgSrvUnlocked() gating logic - Remove broken isDebugServicesEnabled() Times(1) from VBN (non-PROD) tests (non-PROD builds now bypass this call since they are always unlocked) - Add getDeviceTypeRFC and getDevicePropertyData(LABSIGNED_ENABLED) mock expectations to PROD+debug-enabled tests (required for ePROD unlock) - Add getDeviceTypeRFC and getDevicePropertyData(LABSIGNED_ENABLED) mock expectations to PROD+debug-disabled tests (both are called for all ePROD builds before the dbgServices check) - Add 3 new tests covering new gating combinations: - TestName_GetServURL_Locked_Prod_WrongDeviceType (deviceType=prod, locked) - TestName_GetServURL_Locked_Prod_LabsignedNotEnabled (labsigned=false, locked) - TestName_GetServURL_Locked_Prod_LabsignedReadFail (read fails, locked) - Add size > 0 guards in Invoke lambdas to prevent size_t underflow" Co-authored-by: KTirumalaSrihari <102281309+KTirumalaSrihari@users.noreply.github.com> --- unittest/deviceutils/device_api_gtest.cpp | 203 +++++++++++++++++++++- 1 file changed, 199 insertions(+), 4 deletions(-) diff --git a/unittest/deviceutils/device_api_gtest.cpp b/unittest/deviceutils/device_api_gtest.cpp index f7918bbd..7af5313d 100644 --- a/unittest/deviceutils/device_api_gtest.cpp +++ b/unittest/deviceutils/device_api_gtest.cpp @@ -509,7 +509,7 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessStatered_DebugServices_E //EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)).Times(1).WillOnce(Return(1)); ret = system("echo \"BUILD_TYPE=vbn\" > /tmp/device_gtest.prop"); //EXPECT_CALL(*g_DeviceUtilsMock, filePresentCheck(_)).Times(1).WillOnce(Return(1)); - EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(true)); + // Non-PROD builds are always unlocked; isDebugServicesEnabled() is not called for VBN ret = system("echo \"https://www.statered.com\" > /tmp/stateredrecovry.conf"); ret = GetServURL(output, sizeof(output)); EXPECT_EQ(strncmp(output,servUrl,strlen(servUrl)),0); @@ -528,7 +528,7 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessStatered_DebugServices_D //EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)).Times(1).WillOnce(Return(1)); ret = system("echo \"BUILD_TYPE=vbn\" > /tmp/device_gtest.prop"); //EXPECT_CALL(*g_DeviceUtilsMock, filePresentCheck(_)).Times(1).WillOnce(Return(1)); - EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(false)); + // Non-PROD builds are always unlocked; isDebugServicesEnabled() is not called for VBN ret = system("echo \"https://www.statered.com\" > /tmp/stateredrecovry.conf"); ret = GetServURL(output, sizeof(output)); EXPECT_EQ(strncmp(output,servUrl,strlen(servUrl)),0); @@ -548,6 +548,24 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessStatered_Prod_DebugServi ret = system("echo \"BUILD_TYPE=PROD\" > /tmp/device_gtest.prop"); //EXPECT_CALL(*g_DeviceUtilsMock, filePresentCheck(_)).Times(1).WillOnce(Return(1)); EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(true)); + // For ePROD unlock: getDeviceTypeRFC must return "test" and LABSIGNED_ENABLED must be "true" + EXPECT_CALL(*g_DeviceUtilsMock, getDeviceTypeRFC(_, _)) + .Times(1) + .WillOnce(Invoke([](char* deviceType, size_t size) { + if (size > 0) { + strncpy(deviceType, "test", size - 1); + deviceType[size - 1] = '\0'; + } + })); + EXPECT_CALL(*g_DeviceUtilsMock, getDevicePropertyData(StrEq("LABSIGNED_ENABLED"), _, _)) + .Times(1) + .WillOnce(Invoke([](const char*, char* data, int size) -> int { + if (size > 0) { + strncpy(data, "true", size - 1); + data[size - 1] = '\0'; + } + return 0; // UTILS_SUCCESS + })); ret = system("echo \"https://www.statered.com\" > /tmp/stateredrecovry.conf"); ret = GetServURL(output, sizeof(output)); EXPECT_EQ(strncmp(output,servUrl,strlen(servUrl)),0); @@ -567,6 +585,24 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessStatered_Prod_DebugServi ret = system("echo \"BUILD_TYPE=PROD\" > /tmp/device_gtest.prop"); //EXPECT_CALL(*g_DeviceUtilsMock, filePresentCheck(_)).Times(1).WillOnce(Return(1)); EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(false)); + // getDeviceTypeRFC and LABSIGNED_ENABLED are still called for ePROD even when dbgServices=false + EXPECT_CALL(*g_DeviceUtilsMock, getDeviceTypeRFC(_, _)) + .Times(1) + .WillOnce(Invoke([](char* deviceType, size_t size) { + if (size > 0) { + strncpy(deviceType, "test", size - 1); + deviceType[size - 1] = '\0'; + } + })); + EXPECT_CALL(*g_DeviceUtilsMock, getDevicePropertyData(StrEq("LABSIGNED_ENABLED"), _, _)) + .Times(1) + .WillOnce(Invoke([](const char*, char* data, int size) -> int { + if (size > 0) { + strncpy(data, "true", size - 1); + data[size - 1] = '\0'; + } + return 0; // UTILS_SUCCESS - but dbgServices=false prevents unlock + })); ret = system("echo \"https://www.statered.com\" > /tmp/stateredrecovry.conf"); ret = system("echo \"https://www.autotool.com\" > /tmp/swupdate.conf"); EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)) @@ -594,7 +630,7 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessSwupdate_DebugServices_E EXPECT_CALL(*g_DeviceUtilsMock, filePresentCheck(_)).Times(1).WillOnce(Return(0)); //EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)).Times(1).WillOnce(Return(1)); ret = system("echo \"BUILD_TYPE=vbn\" > /tmp/device_gtest.prop"); - EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(true)); + // Non-PROD builds are always unlocked; isDebugServicesEnabled() is not called for VBN ret = system("echo \"https://www.rdkautotool.com\" > /tmp/swupdate.conf"); ret=GetServURL(output , sizeof(output)); EXPECT_EQ(strncmp(output , servUrl , strlen(servUrl)),0); @@ -614,7 +650,7 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessSwupdate_DebugServices_D EXPECT_CALL(*g_DeviceUtilsMock, filePresentCheck(_)).Times(1).WillOnce(Return(0)); //EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)).Times(1).WillOnce(Return(1)); ret = system("echo \"BUILD_TYPE=vbn\" > /tmp/device_gtest.prop"); - EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(false)); + // Non-PROD builds are always unlocked; isDebugServicesEnabled() is not called for VBN ret = system("echo \"https://www.rdkautotool.com\" > /tmp/swupdate.conf"); ret=GetServURL(output , sizeof(output)); EXPECT_EQ(strncmp(output , servUrl , strlen(servUrl)),0); @@ -634,6 +670,24 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessSwupdate_Prod_DebugServi EXPECT_CALL(*g_DeviceUtilsMock, filePresentCheck(_)).Times(1).WillOnce(Return(0)); ret = system("echo \"BUILD_TYPE=PROD\" > /tmp/device_gtest.prop"); EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(true)); + // For ePROD unlock: getDeviceTypeRFC must return "test" and LABSIGNED_ENABLED must be "true" + EXPECT_CALL(*g_DeviceUtilsMock, getDeviceTypeRFC(_, _)) + .Times(1) + .WillOnce(Invoke([](char* deviceType, size_t size) { + if (size > 0) { + strncpy(deviceType, "test", size - 1); + deviceType[size - 1] = '\0'; + } + })); + EXPECT_CALL(*g_DeviceUtilsMock, getDevicePropertyData(StrEq("LABSIGNED_ENABLED"), _, _)) + .Times(1) + .WillOnce(Invoke([](const char*, char* data, int size) -> int { + if (size > 0) { + strncpy(data, "true", size - 1); + data[size - 1] = '\0'; + } + return 0; // UTILS_SUCCESS + })); ret = system("echo \"https://www.rdkautotool.com\" > /tmp/swupdate.conf"); ret=GetServURL(output , sizeof(output)); EXPECT_EQ(strncmp(output , servUrl , strlen(servUrl)),0); @@ -652,6 +706,24 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessSwupdate_Prod_DebugServi EXPECT_CALL(*g_DeviceUtilsMock, isInStateRed()).Times(1).WillOnce(Return(false)); ret = system("echo \"BUILD_TYPE=PROD\" > /tmp/device_gtest.prop"); EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(false)); + // getDeviceTypeRFC and LABSIGNED_ENABLED are still called for ePROD even when dbgServices=false + EXPECT_CALL(*g_DeviceUtilsMock, getDeviceTypeRFC(_, _)) + .Times(1) + .WillOnce(Invoke([](char* deviceType, size_t size) { + if (size > 0) { + strncpy(deviceType, "test", size - 1); + deviceType[size - 1] = '\0'; + } + })); + EXPECT_CALL(*g_DeviceUtilsMock, getDevicePropertyData(StrEq("LABSIGNED_ENABLED"), _, _)) + .Times(1) + .WillOnce(Invoke([](const char*, char* data, int size) -> int { + if (size > 0) { + strncpy(data, "true", size - 1); + data[size - 1] = '\0'; + } + return 0; // UTILS_SUCCESS - but dbgServices=false prevents unlock + })); ret = system("echo \"https://www.rdkautotool.com\" > /tmp/swupdate.conf"); EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)) .Times(1) @@ -670,6 +742,129 @@ TEST_F(DeviceApiTestFixture, TestName_GetServURL_SuccessSwupdate_Prod_DebugServi printf("Server URL = %s\n", output); } +// Tests for new isSecureDbgSrvUnlocked() logic: PROD + wrong device type stays locked +TEST_F(DeviceApiTestFixture, TestName_GetServURL_Locked_Prod_WrongDeviceType) +{ + char output[64]; + int ret; + char servUrl[]="https://www.tr181Rfc.com"; + EXPECT_CALL(*g_DeviceUtilsMock, isInStateRed()).Times(1).WillOnce(Return(true)); + ret = system("echo \"BUILD_TYPE=PROD\" > /tmp/device_gtest.prop"); + EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(true)); + // deviceType is "prod" (not "test"), so ePROD remains locked even with labsigned=true + EXPECT_CALL(*g_DeviceUtilsMock, getDeviceTypeRFC(_, _)) + .Times(1) + .WillOnce(Invoke([](char* deviceType, size_t size) { + if (size > 0) { + strncpy(deviceType, "prod", size - 1); + deviceType[size - 1] = '\0'; + } + })); + EXPECT_CALL(*g_DeviceUtilsMock, getDevicePropertyData(StrEq("LABSIGNED_ENABLED"), _, _)) + .Times(1) + .WillOnce(Invoke([](const char*, char* data, int size) -> int { + if (size > 0) { + strncpy(data, "true", size - 1); + data[size - 1] = '\0'; + } + return 0; // UTILS_SUCCESS + })); + ret = system("echo \"https://www.statered.com\" > /tmp/stateredrecovry.conf"); + EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)) + .Times(1) + .WillOnce(Invoke([&servUrl](char* type, const char* key, char *out_value, size_t datasize) { + strncpy(out_value, servUrl, datasize - 1); + out_value[datasize - 1] = '\0'; + return strlen(out_value); + })); + ret = GetServURL(output, sizeof(output)); + // Should NOT use state-red override (locked); falls through to RFC URL + EXPECT_EQ(strncmp(output, servUrl, strlen(servUrl)), 0); + ret = system("rm -f /tmp/stateredrecovry.conf"); + ret = system("rm -f /tmp/device_gtest.prop"); + printf("Server URL = %s\n", output); +} + +// Tests for new isSecureDbgSrvUnlocked() logic: PROD + LABSIGNED_ENABLED=false stays locked +TEST_F(DeviceApiTestFixture, TestName_GetServURL_Locked_Prod_LabsignedNotEnabled) +{ + char output[64]; + int ret; + char servUrl[]="https://www.tr181Rfc.com"; + EXPECT_CALL(*g_DeviceUtilsMock, isInStateRed()).Times(1).WillOnce(Return(true)); + ret = system("echo \"BUILD_TYPE=PROD\" > /tmp/device_gtest.prop"); + EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(true)); + // deviceType is "test" but LABSIGNED_ENABLED is "false", so ePROD remains locked + EXPECT_CALL(*g_DeviceUtilsMock, getDeviceTypeRFC(_, _)) + .Times(1) + .WillOnce(Invoke([](char* deviceType, size_t size) { + if (size > 0) { + strncpy(deviceType, "test", size - 1); + deviceType[size - 1] = '\0'; + } + })); + EXPECT_CALL(*g_DeviceUtilsMock, getDevicePropertyData(StrEq("LABSIGNED_ENABLED"), _, _)) + .Times(1) + .WillOnce(Invoke([](const char*, char* data, int size) -> int { + if (size > 0) { + strncpy(data, "false", size - 1); + data[size - 1] = '\0'; + } + return 0; // UTILS_SUCCESS + })); + ret = system("echo \"https://www.statered.com\" > /tmp/stateredrecovry.conf"); + EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)) + .Times(1) + .WillOnce(Invoke([&servUrl](char* type, const char* key, char *out_value, size_t datasize) { + strncpy(out_value, servUrl, datasize - 1); + out_value[datasize - 1] = '\0'; + return strlen(out_value); + })); + ret = GetServURL(output, sizeof(output)); + // Should NOT use state-red override (locked); falls through to RFC URL + EXPECT_EQ(strncmp(output, servUrl, strlen(servUrl)), 0); + ret = system("rm -f /tmp/stateredrecovry.conf"); + ret = system("rm -f /tmp/device_gtest.prop"); + printf("Server URL = %s\n", output); +} + +// Tests for new isSecureDbgSrvUnlocked() logic: PROD + LABSIGNED_ENABLED read failure stays locked +TEST_F(DeviceApiTestFixture, TestName_GetServURL_Locked_Prod_LabsignedReadFail) +{ + char output[64]; + int ret; + char servUrl[]="https://www.tr181Rfc.com"; + EXPECT_CALL(*g_DeviceUtilsMock, isInStateRed()).Times(1).WillOnce(Return(true)); + ret = system("echo \"BUILD_TYPE=PROD\" > /tmp/device_gtest.prop"); + EXPECT_CALL(*g_DeviceUtilsMock, isDebugServicesEnabled()).Times(1).WillOnce(Return(true)); + EXPECT_CALL(*g_DeviceUtilsMock, getDeviceTypeRFC(_, _)) + .Times(1) + .WillOnce(Invoke([](char* deviceType, size_t size) { + if (size > 0) { + strncpy(deviceType, "test", size - 1); + deviceType[size - 1] = '\0'; + } + })); + // getDevicePropertyData fails (returns non-UTILS_SUCCESS), so ePROD remains locked + EXPECT_CALL(*g_DeviceUtilsMock, getDevicePropertyData(StrEq("LABSIGNED_ENABLED"), _, _)) + .Times(1) + .WillOnce(Return(-1)); // failure + ret = system("echo \"https://www.statered.com\" > /tmp/stateredrecovry.conf"); + EXPECT_CALL(*g_DeviceUtilsMock, read_RFCProperty(_, _, _, _)) + .Times(1) + .WillOnce(Invoke([&servUrl](char* type, const char* key, char *out_value, size_t datasize) { + strncpy(out_value, servUrl, datasize - 1); + out_value[datasize - 1] = '\0'; + return strlen(out_value); + })); + ret = GetServURL(output, sizeof(output)); + // Should NOT use state-red override (locked); falls through to RFC URL + EXPECT_EQ(strncmp(output, servUrl, strlen(servUrl)), 0); + ret = system("rm -f /tmp/stateredrecovry.conf"); + ret = system("rm -f /tmp/device_gtest.prop"); + printf("Server URL = %s\n", output); +} + /* COMMENTED OUT: GetBuildType is now in common_utilities TEST_F(DeviceApiTestFixture, TestName_GetBuildType_Success) {