Skip to content

RDKB-65730: Integrate Dynamic Table Support - MsgPack support and L2 tests - #404

Open
yogeswaransky wants to merge 5 commits into
developfrom
topic/RDKB-65730
Open

RDKB-65730: Integrate Dynamic Table Support - MsgPack support and L2 tests#404
yogeswaransky wants to merge 5 commits into
developfrom
topic/RDKB-65730

Conversation

@yogeswaransky

Copy link
Copy Markdown
Contributor

No description provided.

…tests

Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
@yogeswaransky
yogeswaransky requested a review from a team as a code owner July 31, 2026 06:56
Copilot AI review requested due to automatic review settings July 31, 2026 06:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the Telemetry 2.0 profile parser to support dynamic table (“dataModelTable”) configuration in the MsgPack profile flow, aligning MsgPack behavior more closely with the existing JSON dynamic-table parsing path.

Changes:

  • Added MsgPack dynamic-table parser helper (parseDataModelTableParamsMsgpack) under ENABLE_DYNAMIC_TABLE_SUPPORT.
  • Implemented MsgPack handling for type == "dataModelTable" in addParameterMsgpack_marker_config, including optional index expansion and dynamic-table structure parsing.
  • Introduced a msgpack_add_param label to allow the no-index dynamic-table case to fall through into the existing parameter-add path.
Suppressed comments (1)

source/t2parser/t2parser.c:2351

  • referenceStr ownership differs between root vs nested calls (root stores it in currentTable->reference). On these failure paths it is currently freed only when parentTable == NULL, which can leave currentTable->reference dangling (and later double-freed in freeDataModelTable) and also leaks referenceStr for nested calls. Free referenceStr only for nested calls on error paths.
    if (buildFullPath(currentPath, parentPath, referenceStr) != 0)
    {
        T2Error("Failed to build current path\n");
        if (!parentTable) free(referenceStr);
        return T2ERROR_FAILURE;

Comment on lines +2339 to +2343
{
currentTable = parentTable;
free(referenceStr);
referenceStr = msgpack_strdup(mpReference);
}
Comment on lines +2669 to +2676
char basePath[256] = "";
char *baseRefStr = msgpack_strdup(mpBaseRef);
if (baseRefStr)
{
strncpy(basePath, baseRefStr, sizeof(basePath) - 1);
basePath[sizeof(basePath) - 1] = '\0';
free(baseRefStr);
}
Comment on lines +2780 to +2782
free(paramtype);
paramtype = strdup("dataModel");
// Parse sub-parameters for dynamic table structure (no-index case)
…tests

Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Copilot AI review requested due to automatic review settings July 31, 2026 08:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

source/t2parser/t2parser.c:2764

  • Same as above: snprintf truncation/failure when building basePathWithIndex is logged but addParameter() is still called with a potentially truncated path. Skip the entry if snprintf fails/truncates.
                            int written = snprintf(basePathWithIndex, sizeof(basePathWithIndex), "%s%d.", basePath, val);
                            if (written < 0 || (size_t)written >= sizeof(basePathWithIndex))
                            {
                                T2Error("%s: snprintf truncated or failed while building path: '%s'\n", __FUNCTION__, basePathWithIndex);
                            }

source/t2parser/t2parser.c:2737

  • When building basePathWithIndex, snprintf truncation/failure is logged but execution still calls addParameter() with a potentially truncated path. That can add incorrect parameter names into the profile. Treat truncation as an error and skip the index entry.

This issue also appears on line 2760 of the same file.

                                int written = snprintf(basePathWithIndex, sizeof(basePathWithIndex), "%s%d.", basePath, k);
                                if (written < 0 || (size_t)written >= sizeof(basePathWithIndex))
                                {
                                    T2Error("%s: snprintf truncated or failed while building path: '%s'\n", __FUNCTION__, basePathWithIndex);
                                }

source/t2parser/t2parser.c:2678

  • This PR adds a new MsgPack-specific dataModelTable parsing flow, but there don’t appear to be any unit tests covering MsgPack profiles with dataModelTable (existing dynamic table tests are JSON-based). Please add/extend gtest coverage to include (at minimum) dataModelTable with and without index in MsgPack, plus a nested table case, to prevent regressions in addParameterMsgpack_marker_config()/parseDataModelTableParamsMsgpack().
            T2Debug("Processing dataModelTable in MsgPack profile\n");
            msgpack_object *mpBaseRef = msgpack_get_map_value(Parameter_array_map, "reference");
            if (mpBaseRef)
            {
                char basePath[256] = "";

Comment on lines +2346 to +2366
char currentPath[MAX_PATH_LENGTH];
if (buildFullPath(currentPath, parentPath, referenceStr) != 0)
{
T2Error("Failed to build current path\n");
if (!parentTable)
{
free(referenceStr);
}
return T2ERROR_FAILURE;
}

char pathWithWildcard[MAX_PATH_LENGTH];
if ((size_t)snprintf(pathWithWildcard, sizeof(pathWithWildcard), "%s*.", currentPath) >= sizeof(pathWithWildcard))
{
T2Error("Path with wildcard exceeded buffer size\n");
if (!parentTable)
{
free(referenceStr);
}
return T2ERROR_FAILURE;
}
…tests

Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Copilot AI review requested due to automatic review settings August 3, 2026 15:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

source/t2parser/t2parser.c:2351

  • On buildFullPath / wildcard-path failures, the code frees referenceStr when parsing the root table. But for the root table currentTable->reference points to referenceStr, so freeing it leaves a dangling pointer in profile->dataModelTableList and can crash later (e.g., report generation / cleanup). Clean up the table entry from the vector on failure instead of freeing the owned string.
    if (buildFullPath(currentPath, parentPath, referenceStr) != 0)
    {
        T2Error("Failed to build current path\n");
        if (!parentTable)
        {

test/run_l2.sh:58

  • mock_table_provider is started in the background but cleanup is only a best-effort kill at the end of the test block. If the script exits early (e.g., gcc/pytest failure, SIGINT), the provider can be left running and interfere with subsequent test runs. Add a trap-based cleanup and fail fast if compilation/startup fails.
# Compile mock table provider for dataModelTable L2 tests
gcc -o test/functional-tests/tests/mock_table_provider test/functional-tests/tests/mock_table_provider.c \
    -I/usr/local/include -I/usr/local/include/rbus \
    -L/usr/local/lib -lrbus -lrbuscore -lrtMessage -lmsgpackc

# Start mock table provider in background (provides Device.X_T2TEST_Table.AccessPoint.{1,2,3}.*)
test/functional-tests/tests/mock_table_provider &
MOCK_TABLE_PROVIDER_PID=$!
sleep 2

final_result=0
# removing --exitfirst flag as it is causing the test to exit after first failure
pytest -v --json-report --json-report-summary --json-report-file $RESULT_DIR/runs_as_daemon.json test/functional-tests/tests/test_runs_as_daemon.py || final_result=1
pytest -v --json-report --json-report-summary --json-report-file $RESULT_DIR/bootup_sequence.json test/functional-tests/tests/test_bootup_sequence.py || final_result=1
pytest -v --json-report --json-report-summary --json-report-file $RESULT_DIR/xconf_communications.json test/functional-tests/tests/test_xconf_communications.py || final_result=1
pytest -v --json-report --json-report-summary --json-report-file $RESULT_DIR/msg_packet.json test/functional-tests/tests/test_multiprofile_msgpacket.py || final_result=1
pytest -v --json-report --json-report-summary --json-report-file $RESULT_DIR/datamodeltable.json test/functional-tests/tests/test_datamodeltable.py || final_result=1

# Stop mock table provider
kill $MOCK_TABLE_PROVIDER_PID 2>/dev/null

source/t2parser/t2parser.c:2408

  • param->reference is used unconditionally in buildFullPath(...), but msgpack_strdup can fail and return NULL (OOM). That would turn into a NULL dereference in buildFullPath (which logs an error but still dereferences reference to compute length/indexing in some code paths). Add a NULL check and free param early.
            param->reference = msgpack_strdup(mpParamRef);
            char fullPath[MAX_PATH_LENGTH];
            if (buildFullPath(fullPath, pathWithWildcard, param->reference) != 0)

Comment thread test/functional-tests/tests/mock_table_provider.c
…tests

Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Copilot AI review requested due to automatic review settings August 3, 2026 15:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

Suppressed comments (6)

test/functional-tests/tests/mock_table_provider.c:112

  • In the wildcard query path, current is set to next after rbusProperty_Release(next), so the next loop iteration appends to a released property (use-after-free / corrupted property chain). Avoid using next after releasing it; typically the appended property should remain owned by the list until the RBUS framework releases the head property.
                rbusProperty_t next;
                rbusProperty_Init(&next, paramNames[i], val);
                rbusProperty_Append(current, next);
                rbusProperty_Release(next);
                current = next;

source/t2parser/t2parser.c:2343

  • referenceStr is reallocated for nested tables without a NULL-check, and the error path frees referenceStr when !parentTable even though ownership was already transferred to currentTable->reference. This can lead to NULL dereference in buildFullPath and a dangling currentTable->reference (double-free later).
        currentTable = parentTable;
        free(referenceStr);
        referenceStr = msgpack_strdup(mpReference);
    }

source/t2parser/t2parser.c:2360

  • On the wildcard-path snprintf failure, the error path frees referenceStr when !parentTable, but in the root-table case referenceStr is stored in currentTable->reference. Freeing it here leaves a dangling pointer in the table list and can cause a double-free during freeDataModelTable.
    if ((size_t)snprintf(pathWithWildcard, sizeof(pathWithWildcard), "%s*.", currentPath) >= sizeof(pathWithWildcard))
    {
        T2Error("Path with wildcard exceeded buffer size\n");

test/run_l2.sh:47

  • The mock table provider is started in the background without any guarantee it will be stopped if the script exits early (e.g., gcc failure, interrupted CI job). Also, the gcc invocation isn’t checked, so the script may continue with a missing/old binary. Add an explicit build check and an EXIT trap that always terminates the background provider.
# Compile mock table provider for dataModelTable L2 tests
gcc -o test/functional-tests/tests/mock_table_provider test/functional-tests/tests/mock_table_provider.c \
    -I/usr/local/include -I/usr/local/include/rbus \
    -L/usr/local/lib -lrbus -lrbuscore -lrtMessage -lmsgpackc

test/run_l2.sh:58

  • After introducing cleanup_mock_table_provider, use it here instead of a raw kill so the process is waited on and the logic stays in one place (and matches the EXIT trap).
# Stop mock table provider
kill $MOCK_TABLE_PROVIDER_PID 2>/dev/null

source/t2parser/t2parser.c:2675

  • MsgPack dataModelTable parsing is now implemented, but there are no unit tests covering this MsgPack-only path (existing dynamic table tests exercise the JSON flow). Add gtests under source/test/t2parser/ that build a MsgPack profile containing dataModelTable (wildcard, explicit index, and nested) and assert profile->dataModelTableList and paramList contents.
        else if(0 == msgpack_strcmp(Parameter_type_str, "dataModelTable"))
        {
#ifdef ENABLE_DYNAMIC_TABLE_SUPPORT
            T2Debug("Processing dataModelTable in MsgPack profile\n");
            msgpack_object *mpBaseRef = msgpack_get_map_value(Parameter_array_map, "reference");

…tests

Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Copilot AI review requested due to automatic review settings August 3, 2026 16:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Suppressed comments (8)

test/functional-tests/tests/mock_table_provider.c:112

  • next is appended to the RBUS property list and then immediately released, but current is set to next afterwards. This breaks the property chain and can become a use-after-free when RBUS later traverses the list (the main codebase releases only the head property after iteration; see source/ccspinterface/rbusInterface.c:391-394).
                rbusProperty_t next;
                rbusProperty_Init(&next, paramNames[i], val);
                rbusProperty_Append(current, next);
                rbusProperty_Release(next);
                current = next;

source/t2parser/t2parser.c:2351

  • On the buildFullPath error path, referenceStr is freed when parentTable is NULL, but in that case the pointer is owned by currentTable->reference (stored earlier). This can leave currentTable->reference dangling inside profile->dataModelTableList and cause a later free/crash.
    if (buildFullPath(currentPath, parentPath, referenceStr) != 0)
    {
        T2Error("Failed to build current path\n");
        if (!parentTable)
        {

source/t2parser/t2parser.c:2362

  • On the wildcard snprintf overflow path, referenceStr is freed only when parentTable is NULL. For nested table parsing (parentTable != NULL), referenceStr is newly allocated and will leak on this error path; for root parsing, freeing it can again leave currentTable->reference dangling.
    if ((size_t)snprintf(pathWithWildcard, sizeof(pathWithWildcard), "%s*.", currentPath) >= sizeof(pathWithWildcard))
    {
        T2Error("Path with wildcard exceeded buffer size\n");
        if (!parentTable)
        {

test/functional-tests/tests/test_datamodeltable.py:38

  • subprocess and dt are imported but never used, which adds noise and can mask real unused-import issues.
import subprocess
from time import sleep
from datetime import datetime as dt
import pytest

test/run_l2.sh:58

  • The mock table provider is started in the background but only killed at the end without a trap or wait. If this script exits early (pytest error, SIGINT/TERM, etc.), the provider can keep running and interfere with later runs; kill without wait can also leave a zombie process. Also, the mock provider compile step is not checked for failure, so tests can run against a missing binary.
# Start mock table provider in background (provides Device.X_T2TEST_Table.AccessPoint.{1,2,3}.*)
test/functional-tests/tests/mock_table_provider &
MOCK_TABLE_PROVIDER_PID=$!
sleep 2

build_inside_container.sh:34

  • This script now always enables dynamic table support, which makes the feature effectively non-optional for the container build and prevents running CI scenarios against a feature-disabled build (the L2 workflow uses this script). Consider gating this behind an environment variable so the default build remains representative.
./configure --prefix=${INSTALL_DIR} --enable-rdkcertselector=yes --enable-dynamic-table-support=yes && make && make install

test/functional-tests/tests/test_datamodeltable.py:26

  • The scenario list claims the tests validate report JSON structure / row contents, but the assertions currently only check logs and that the process didn’t crash. Updating the scenario descriptions will avoid misleading future maintainers.

This issue also appears on line 35 of the same file.

1. Push a profile with dataModelTable (explicit index) -> verify report JSON structure
2. Push a profile with dataModelTable (wildcard) -> verify all rows appear in report
3. Push a profile with dataModelTable while a reporting cycle is active -> verify no crash

source/t2parser/t2parser.c:2681

  • MsgPack dataModelTable support is newly added here, but there don’t appear to be any unit tests exercising the MsgPack profile parsing path (existing parser tests cover JSON/dynamic-table parsing only). Adding a focused unit test would help prevent regressions in the MsgPack flow.
            T2Debug("Processing dataModelTable in MsgPack profile\n");
            msgpack_object *mpBaseRef = msgpack_get_map_value(Parameter_array_map, "reference");
            if (mpBaseRef)
            {
                char basePath[256] = "";
                char *baseRefStr = msgpack_strdup(mpBaseRef);
                if (baseRefStr)
                {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants