Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion source/test/t2parser/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ bin_PROGRAMS = t2parser_gtest.bin

t2parser_gtest_bin_CPPFLAGS = -I$(PKG_CONFIG_SYSROOT_DIR)$(includedir)/gtest -I$(PKG_CONFIG_SYSROOT_DIR)$(includedir)/glib-2.0 -I$(PKG_CONFIG_SYSROOT_DIR)/usr/local/lib -I${top_srcdir}/source/include -I${top_srcdir}/source/xconf-client -I${top_srcdir}/source/dcautil -I${top_srcdir}/source/t2parser -I${top_srcdir}/source/bulkdata -I${top_srcdir}/source/utils -I${top_srcdir}/source/ccspinterface -I${top_srcdir}/source -I${top_srcdir}/include -I${top_srcdir}/source/reportgen -I$(PKG_CONFIG_SYSROOT_DIR)/usr/lib -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/cjson -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/gmock -I$(PKG_CONFIG_SYSROOT_DIR)/usr/src/googletest/googlemock/include -I$(PKG_CONFIG_SYSROOT_DIR)/usr/lib/glib-2.0/include -I$(PKG_CONFIG_SYSROOT_DIR)/usr/include/glib-2.0 -I${RDK_PROJECT_ROOT_PATH}/$(GLIB_CFLAGS) -I${PKG_CONFIG_SYSROOT_DIR}$(includedir)/glib-2.0 -I${PKG_CONFIG_SYSROOT_DIR}$(libdir)/glib-2.0/include

t2parser_gtest_bin_SOURCES = gtest_main.cpp t2parserMock.cpp ../mocks/rdklogMock.cpp ../mocks/rbusMock.cpp t2parserTest.cpp ../../utils/vector.c ../../utils/t2common.c ../../utils/t2log_wrapper.c ../../t2parser/t2parserxconf.c ../../t2parser/t2parser.c ../../dcautil/legacyutils.c ../../utils/t2collection.c
t2parser_gtest_bin_SOURCES = gtest_main.cpp t2parserMock.cpp ../mocks/rdklogMock.cpp ../mocks/rbusMock.cpp t2parserTest.cpp t2parserxconfTest.cpp ../../utils/vector.c ../../utils/t2common.c ../../utils/t2log_wrapper.c ../../t2parser/t2parserxconf.c ../../t2parser/t2parser.c ../../dcautil/legacyutils.c ../../utils/t2collection.c

t2parser_gtest_bin_LDFLAGS = -lgtest -lgcov -L/src/googletest/googlemock/lib -L/usr/src/googletest/googlemock/lib/.libs -lgmock -lcjson -lcurl -lmsgpackc -L/usr/include/glib-2.0 -lglib-2.0

264 changes: 260 additions & 4 deletions source/test/t2parser/t2parserTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ sigset_t blocking_signal;
#include "test/mocks/rdklogMock.h"
#include "test/mocks/rbusMock.h"

extern "C" {
// tell C++ about the C function defined in t2parser.c
T2ERROR verifyTriggerCondition(cJSON *jprofileTriggerCondition);
T2ERROR addTriggerCondition(Profile *profile, cJSON *jprofileTriggerCondition);
T2ERROR encodingSet(Profile* profile, cJSON *jprofileEncodingType, cJSON *jprofileJSONReportFormat, cJSON *jprofileJSONReportTimestamp);
T2ERROR protocolSet (Profile *profile, cJSON *jprofileProtocol, cJSON *jprofileHTTPURL, cJSON *jprofileHTTPRequestURIParameter, int ThisprofileHTTPRequestURIParameter_count, cJSON *jprofileRBUSMethodName, cJSON *jprofileRBUSMethodParamArr, int rbusMethodParamArrCount);
}
T2parserMock *m_t2parserMock = NULL;
rdklogMock *m_rdklogMock = NULL;
rbusMock *g_rbusMock = NULL;
Expand All @@ -72,7 +79,7 @@ TEST(PROCESSXCONFCONFIGURATION, TEST_NULL_INVALID)
ProfileXConf *profile = 0;
fstream new_file;
char* data = NULL;
new_file.open("xconfInputfile.txt", ios::in);
new_file.open("source/test/t2parser/xconfInputfile.txt", ios::in);

if (new_file.is_open()) {
string sa;
Expand Down Expand Up @@ -136,7 +143,7 @@ TEST(PROCESSCONFIGURATION_CJSON, TEST_NULL_INVALID_PARAM)
fstream new_file;
string sa;
int len = 0;
new_file.open("rpInputfile.txt", ios::in);
new_file.open("source/test/t2parser/rpInputfile.txt", ios::in);
char* data = NULL;
if (new_file.is_open()) {
getline(new_file, sa);
Expand All @@ -154,7 +161,6 @@ TEST(PROCESSCONFIGURATION_CJSON, TEST_NULL_INVALID_PARAM)
//Protocol NULL
EXPECT_EQ(T2ERROR_FAILURE, processConfiguration(&data, "RDKB_Profile2", "hash2", &profile));
delete[] data;

getline(new_file, sa);
len = sa.length();
data = new char[len + 1];
Expand Down Expand Up @@ -336,7 +342,6 @@ TEST(PROCESSCONFIGURATION_CJSON, TEST_NULL_INVALID_PARAM)
strcpy(data, sa.c_str());
EXPECT_EQ(T2ERROR_SUCCESS, processConfiguration(&data, "RDKB_Profile25", "hash25", &profile));
delete[] data;

}
new_file.close();
}
Expand Down Expand Up @@ -780,4 +785,255 @@ TEST(PROCESSCONFIGURATION_MSGPACK, WORKING_CASE)
}


/* Helper to create a TriggerCondition JSON object */
static cJSON* create_tc_obj(const char* type, const char* op, const char* ref, int threshold, int report)
{
cJSON* obj = cJSON_CreateObject();
if (type) cJSON_AddStringToObject(obj, "type", type);
if (op) cJSON_AddStringToObject(obj, "operator", op);
if (ref) cJSON_AddStringToObject(obj, "reference", ref);
if (threshold >= 0) cJSON_AddNumberToObject(obj, "threshold", threshold);
if (report >= 0) cJSON_AddBoolToObject(obj, "report", report);
return obj;
}

/* verifyTriggerCondition failure: missing type */
TEST(T2ParserVerifyTC, MissingTypeShouldFail)
{
cJSON* arr = cJSON_CreateArray();
cJSON* tc = cJSON_CreateObject();
// intentionally no "type"
cJSON_AddStringToObject(tc, "operator", "any");
cJSON_AddStringToObject(tc, "reference", "Device.Param");
cJSON_AddItemToArray(arr, tc);

EXPECT_EQ(T2ERROR_FAILURE, verifyTriggerCondition(arr));
cJSON_Delete(arr);
}
/* verifyTriggerCondition failure: wrong type string */
TEST(T2ParserVerifyTC, WrongTypeShouldFail)
{
cJSON* arr = cJSON_CreateArray();
cJSON* tc = create_tc_obj("notDataModel", "any", "Device.Param", -1, -1);
cJSON_AddItemToArray(arr, tc);
EXPECT_EQ(T2ERROR_FAILURE, verifyTriggerCondition(arr));
cJSON_Delete(arr);
}

/* verifyTriggerCondition failure: missing operator */
TEST(T2ParserVerifyTC, MissingOperatorShouldFail)
{
cJSON* arr = cJSON_CreateArray();
cJSON* tc = create_tc_obj("dataModel", NULL, "Device.Param", -1, -1);
cJSON_AddItemToArray(arr, tc);
EXPECT_EQ(T2ERROR_FAILURE, verifyTriggerCondition(arr));
cJSON_Delete(arr);
}

/* verifyTriggerCondition failure: invalid operator */
TEST(T2ParserVerifyTC, InvalidOperatorShouldFail)
{
cJSON* arr = cJSON_CreateArray();
cJSON* tc = create_tc_obj("dataModel", "badop", "Device.Param", -1, -1);
cJSON_AddItemToArray(arr, tc);
EXPECT_EQ(T2ERROR_FAILURE, verifyTriggerCondition(arr));
cJSON_Delete(arr);
}

/* verifyTriggerCondition failure: missing threshold for lt operator */
TEST(T2ParserVerifyTC, ThresholdMissingForLtShouldFail)
{
cJSON* arr = cJSON_CreateArray();
cJSON* tc = create_tc_obj("dataModel", "lt", "Device.Param", -1, -1); // no threshold
cJSON_AddItemToArray(arr, tc);
EXPECT_EQ(T2ERROR_FAILURE, verifyTriggerCondition(arr));
cJSON_Delete(arr);
}

/* verifyTriggerCondition failure: missing reference */
TEST(T2ParserVerifyTC, MissingReferenceShouldFail)
{
cJSON* arr = cJSON_CreateArray();
cJSON* tc = cJSON_CreateObject();
cJSON_AddStringToObject(tc, "type", "dataModel");
cJSON_AddStringToObject(tc, "operator", "any");
// no reference
cJSON_AddItemToArray(arr, tc);
EXPECT_EQ(T2ERROR_FAILURE, verifyTriggerCondition(arr));
cJSON_Delete(arr);
}

/* verifyTriggerCondition failure: empty reference */
TEST(T2ParserVerifyTC, EmptyReferenceShouldFail)
{
cJSON* arr = cJSON_CreateArray();
cJSON* tc = create_tc_obj("dataModel", "any", "", -1, -1);
cJSON_AddItemToArray(arr, tc);
EXPECT_EQ(T2ERROR_FAILURE, verifyTriggerCondition(arr));
cJSON_Delete(arr);
}

/* verifyTriggerCondition success: valid tc */
TEST(T2ParserVerifyTC, ValidShouldSucceed)
{
cJSON* arr = cJSON_CreateArray();
cJSON* tc = create_tc_obj("dataModel", "any", "Device.Param", -1, -1);
cJSON_AddItemToArray(arr, tc);
EXPECT_EQ(T2ERROR_SUCCESS, verifyTriggerCondition(arr));
cJSON_Delete(arr);
}
/* addTriggerCondition should accept a valid TC array and return success */
TEST(T2ParserAddTC, AddTriggerConditionSuccess)
{
Profile p;
memset(&p, 0, sizeof(p));
// Initialize the vector pointer (function will Vector_Create)
p.triggerConditionList = NULL;

cJSON* arr = cJSON_CreateArray();
cJSON* tc = create_tc_obj("dataModel", "eq", "Device.Param", 5, 1);
cJSON_AddItemToArray(arr, tc);

EXPECT_EQ(T2ERROR_SUCCESS, addTriggerCondition(&p, arr));
// function should have created the triggerConditionList (non-NULL)
EXPECT_NE((void*)NULL, (void*)p.triggerConditionList);

// clean up: free internal structures created by addTriggerCondition
// We don't have a public destructor here; best-effort free for the test's allocations:
// iterate vector if available (Vector API may provide size/get functions in the project),
// but to stay robust, simply free profile memory fields that addTriggerCondition could set.
// For safety, reset pointer to avoid double-free during test teardown.
// (The CI process reclaims process memory after tests.)
cJSON_Delete(arr);
}
/* encodingSet should set jsonEncoding fields based on JSON nodes */
TEST(T2ParserEncodingSet, JSONEncodingMapping)
{
Profile p;
memset(&p, 0, sizeof(p));
p.jsonEncoding = (JSONEncoding*)malloc(sizeof(JSONEncoding));
memset(p.jsonEncoding, 0, sizeof(JSONEncoding));

cJSON* jEncodingType = cJSON_CreateString("JSON");
cJSON* jJSONReportFormat = cJSON_CreateString("ObjectHierarchy");
cJSON* jJSONReportTimestamp = cJSON_CreateString("Unix-Epoch");

EXPECT_EQ(T2ERROR_SUCCESS, encodingSet(&p, jEncodingType, jJSONReportFormat, jJSONReportTimestamp));
EXPECT_EQ(JSONRF_OBJHIERARCHY, p.jsonEncoding->reportFormat);
EXPECT_EQ(TIMESTAMP_UNIXEPOCH, p.jsonEncoding->tsFormat);

if (p.jsonEncoding)
{
free(p.jsonEncoding);
p.jsonEncoding = NULL;
}

if (p.name)
{
free(p.name);
p.name = NULL;
}

cJSON_Delete(jEncodingType);
cJSON_Delete(jJSONReportFormat);
cJSON_Delete(jJSONReportTimestamp);
}
/* protocolSet tests: HTTP branch */
TEST(T2ParserProtocolSet, HTTPBranchSetsURLAndParams)
{
Profile p;
memset(&p, 0, sizeof(p));
p.t2HTTPDest = (T2HTTP*)malloc(sizeof(T2HTTP));
memset(p.t2HTTPDest, 0, sizeof(T2HTTP));
p.name = strdup("TestProfile");

cJSON* jProtocol = cJSON_CreateString("HTTP");
// create HTTP nested object
cJSON* jHTTP = cJSON_CreateObject();
cJSON_AddStringToObject(jHTTP, "URL", "http://upload.test");
cJSON_AddStringToObject(jHTTP, "Compression", "None");
cJSON_AddStringToObject(jHTTP, "Method", "POST");

// RequestURIParameter array with one valid entry
cJSON* arr = cJSON_CreateArray();
cJSON* entry = cJSON_CreateObject();
cJSON_AddStringToObject(entry, "Reference", "someRef");
cJSON_AddStringToObject(entry, "Name", "someName");
cJSON_AddItemToArray(arr, entry);
cJSON_AddItemToObject(jHTTP, "RequestURIParameter", arr);

// Call protocolSet (note: jprofileHTTPRequestURIParameter_count must be set properly by caller)
EXPECT_EQ(T2ERROR_SUCCESS, protocolSet(&p, jProtocol, cJSON_GetObjectItem(jHTTP, "URL"), cJSON_GetObjectItem(jHTTP, "RequestURIParameter"), 1, NULL, NULL, 0));

EXPECT_STREQ("http://upload.test", p.t2HTTPDest->URL);
// Cleanup to avoid memory leaks
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment has extra indentation (8 spaces instead of 4). It should align with the surrounding code block indentation.

Suggested change
// Cleanup to avoid memory leaks
// Cleanup to avoid memory leaks

Copilot uses AI. Check for mistakes.
if (p.t2HTTPDest)
{
if (p.t2HTTPDest->URL)
{
free(p.t2HTTPDest->URL);
p.t2HTTPDest->URL = NULL;
}
// If protocolSet allocated other heap members inside T2HTTP, free them here as needed.

free(p.t2HTTPDest);
p.t2HTTPDest = NULL;
}

if (p.name)
{
free(p.name);
p.name = NULL;
}

cJSON_Delete(jProtocol);
cJSON_Delete(jHTTP);
}

/* protocolSet tests: RBUS_METHOD branch */
TEST(T2ParserProtocolSet, RBUSMethodBranchSetsMethodAndParams)
{
Profile p;
memset(&p, 0, sizeof(p));
p.t2RBUSDest = (T2RBUS*)malloc(sizeof(T2RBUS));
memset(p.t2RBUSDest, 0, sizeof(T2RBUS));
p.name = strdup("RbusProfile");

cJSON* jProtocol = cJSON_CreateString("RBUS_METHOD");
cJSON* jRBUS = cJSON_CreateObject();
cJSON_AddStringToObject(jRBUS, "Method", "TestMethod");

cJSON* params = cJSON_CreateArray();
cJSON* param = cJSON_CreateObject();
cJSON_AddStringToObject(param, "name", "param1");
cJSON_AddStringToObject(param, "value", "val1");
cJSON_AddItemToArray(params, param);
cJSON_AddItemToObject(jRBUS, "Parameters", params);

// protocolSet expects jprofileRBUSMethodName and jprofileRBUSMethodParamArr separately; pass appropriate items
EXPECT_EQ(T2ERROR_SUCCESS, protocolSet(&p, jProtocol, NULL, NULL, 0, cJSON_GetObjectItem(jRBUS, "Method"), cJSON_GetObjectItem(jRBUS, "Parameters"), 1));

EXPECT_STREQ("TestMethod", p.t2RBUSDest->rbusMethodName);
// Cleanup to avoid memory leaks
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment has extra indentation (8 spaces instead of 4). It should align with the surrounding code block indentation.

Suggested change
// Cleanup to avoid memory leaks
// Cleanup to avoid memory leaks

Copilot uses AI. Check for mistakes.
if (p.t2RBUSDest)
{
// free any strings allocated by protocolSet if present
if (p.t2RBUSDest->rbusMethodName)
{
free(p.t2RBUSDest->rbusMethodName);
p.t2RBUSDest->rbusMethodName = NULL;
}
// If protocolSet allocated other heap members inside T2RBUS, free them here as needed.
free(p.t2RBUSDest);
p.t2RBUSDest = NULL;
}

if (p.name)
{
free(p.name);
p.name = NULL;
}

cJSON_Delete(jProtocol);
cJSON_Delete(jRBUS);
}
Loading