RDK-60476: Update L1 and L2 testcases for fork elimination#260
RDK-60476: Update L1 and L2 testcases for fork elimination#260yogeswaransky wants to merge 41 commits intodevelopfrom
Conversation
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Pull request overview
Updates unit tests to align with the new “fork elimination” HTTP implementation (connection-pool + libcurl), replacing older pipe/fork/read-based expectations and expanding the test mocks to interpose additional libcurl calls.
Changes:
- Enable previously disabled xconf-client and protocol HTTP tests and update them to use curl/pool expectations instead of
fork()/pipe(). - Extend
FileioMockinterposition to covercurl_easy_getinfo()andcurl_easy_setopt(). - Add helper logic intended to avoid deadlocks when GTest/logging writes to
FILE*while file I/O is mocked.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
source/test/xconf-client/xconfclientTest.cpp |
Enables/updates doHttpGet tests to mock curl/pool behavior; adds a helper macro intended to prevent GTest logging deadlocks. |
source/test/protocol/ProtocolTest.cpp |
Updates protocol HTTP tests to mock curl/pool behavior; adds default curl behaviors in fixture setup and a helper macro/comment. |
source/test/mocks/FileioMock.h |
Adds/adjusts mock method signatures for curl interposition (curl_easy_setopt). |
source/test/mocks/FileioMock.cpp |
Adds interposed curl_easy_getinfo() and a new interposed curl_easy_setopt() implementation for tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 12 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 8 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (4)
test/functional-tests/tests/helper_functions.py:60
- The certificate discovery logic runs at import time and prints to stdout, which adds side effects/noise to every test that imports helper_functions. Consider moving certificate detection into a function (lazy initialization) and using the test logger instead of print, so importing utilities doesn’t change runtime behavior/output.
# Certificate configuration for mTLS
# Check for combined PEM files (cert+key in one file) first, then separate files
CERT_COMBINED_PATHS = [
'/opt/certs/client.pem',
'/etc/pki/Test-RDK-root/Test-RDK-client-ICA/certs/rdkclient.pem',
]
CERT_SEPARATE_PATHS = [
('/opt/certs/client.pem', '/opt/certs/client.key'),
('/etc/pki/Test-RDK-root/Test-RDK-client-ICA/certs/rdkclient.pem', '/etc/pki/Test-RDK-root/Test-RDK-client-ICA/private/rdkclient.key'),
]
# Find the first valid certificate
CERT_PATH = None
# Try combined PEM files first (cert+key in single file)
for cert_file in CERT_COMBINED_PATHS:
if os.path.exists(cert_file):
CERT_PATH = cert_file
print(f"Using combined client certificate+key: {cert_file}")
break
# If no combined file found, try separate cert and key files
if CERT_PATH is None:
for cert_file, key_file in CERT_SEPARATE_PATHS:
if os.path.exists(cert_file) and os.path.exists(key_file):
CERT_PATH = (cert_file, key_file)
print(f"Using client certificate: {cert_file} with key: {key_file}")
break
if CERT_PATH is None:
print("WARNING: No valid client certificate found!")
source/protocol/http/multicurlinterface.c:66
- DEFAULT_POOL_SIZE was reduced from 2 to 1, which removes parallelism for HTTP requests by default and can increase latency when multiple threads contend for the pool. If this is only meant for low-end devices, consider keeping the previous default and relying on T2_CONNECTION_POOL_SIZE (or a device-type-based default) instead of globally lowering the default.
#define DEFAULT_POOL_SIZE 1
test/run_l2.sh:41
- Two L2 test invocations are now commented out, which reduces coverage and can hide regressions. If these tests are intentionally disabled for fork elimination, please switch to an explicit mechanism (e.g., conditional execution with an env flag + a clear message, or pytest markers) so CI output makes it obvious what was skipped and why.
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/runs_as_daemon.json test/functional-tests/tests/test_runs_as_daemon.py || final_result=1
test/functional-tests/tests/test_multiprofile_msgpacket.py:79
- A large block of tests is being disabled by wrapping it in a module-level triple-quoted string. This silently removes coverage and is easy to miss during maintenance; prefer marking individual tests with pytest skip/xfail (with a reason) or deleting the dead tests if they’re no longer valid.
'''
#negative case without hashvalue, without version field & without Protocol field
@pytest.mark.run(order=2)
def test_without_hashvalue():
clear_T2logs()
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (14)
source/protocol/http/Makefile.am:27
- Added -lrdkconfig to LDFLAGS when LIBRDKCERTSEL is enabled. Similar to the issue in xconf-client/Makefile.am, this creates a dependency on librdkconfig even when using RdkCertSelector. The code guards rdkconfig.h includes with
#ifndef LIBRDKCERTSEL_BUILDin curlinterface.c and multicurlinterface.c, suggesting rdkconfig should only be linked when LIBRDKCERTSEL is NOT enabled.
libhttp_la_LDFLAGS += -lRdkCertSelector -lrdkconfig
source/test/xconf-client/xconfclientTest.cpp:421
- Comment says "default 2" but DEFAULT_POOL_SIZE was changed to 1 in line 66 of multicurlinterface.c. Update this comment to reflect the correct default pool size of 1.
// The pool will call curl_easy_init() based on pool size (default 2)
source/test/protocol/ProtocolTest.cpp:372
- Unused variable 'cm' is declared but never used in this test. This appears to be leftover from the fork-based implementation that was removed. Consider removing this unused variable declaration.
char *cm = (char*)0xFFFFFFFF;
source/protocol/http/multicurlinterface.c:779
- The removed line clearing CURLOPT_HTTPGET is important when reusing pooled handles. When switching from GET to POST, if CURLOPT_HTTPGET was previously set to 1L (line 497 in http_pool_get), it needs to be explicitly cleared. While CURLOPT_POST sets the request method, not clearing CURLOPT_HTTPGET could lead to ambiguous state. Consider adding back CURLOPT_HTTPGET reset to 0L before setting up POST.
// Clear any GET-specific settings from previous use
source/xconf-client/Makefile.am:27
- Added -lrdkconfig to LDFLAGS when LIBRDKCERTSEL is enabled. This creates a dependency on librdkconfig even when using RdkCertSelector. Review whether rdkconfig is actually needed when LIBRDKCERTSEL_BUILD is defined, as the code has
#ifndef LIBRDKCERTSEL_BUILDguards around rdkconfig.h includes in xconfclient.c and t2MtlsUtils.c. This suggests rdkconfig should only be linked when LIBRDKCERTSEL is NOT enabled, which contradicts this change.
libxconfclient_la_LDFLAGS += -lRdkCertSelector -lrdkconfig
source/xconf-client/xconfclient.c:287
- Added null/empty check before strdup(zone). This is a good defensive programming practice that prevents potential issues when zone is NULL or empty. However, there's a subtle issue: the warning message at line 286 says "zone is NULL or empty, skipping", but zoneValue is already set to NULL at line 285. The real issue is that the code continues the while loop even after this condition, potentially reading more data. Consider whether the loop should break when zone is NULL/empty, or if this is intentional to skip empty lines.
if (zone != NULL && strlen(zone) > 0)
{
zoneValue = strdup(zone);
}
else
{
zoneValue = NULL;
T2Warning("Warning: zone is NULL or empty, skipping\n");
}
source/test/xconf-client/xconfclientTest.cpp:627
- Test expects doHttpGet to return T2ERROR_SUCCESS but doesn't free the allocated data. When doHttpGet succeeds with a 200 response, it allocates memory for the data parameter. The test should free this memory to prevent memory leaks in test runs. Add
if (data) free(data);after the assertion.
EXPECT_EQ(T2ERROR_SUCCESS, doHttpGet("https://test.com", &data));
test/functional-tests/tests/helper_functions.py:114
- The CERT_PATH variable can be either a string (combined PEM file) or a tuple (separate cert and key files). While the requests library supports both formats, the code should handle the case where CERT_PATH is None (when no certificate is found). Currently, passing cert=None to requests.get is valid but may cause unexpected behavior. Consider adding a check before the requests call to handle missing certificates more explicitly, or ensure that tests skip mTLS validation when CERT_PATH is None.
if(requests.get(ADMIN_SUPPORT_SET, verify=CA_BUNDLE, cert=CERT_PATH, params={ADMIN_CACHE_ARG: str(save).lower()})):
source/test/xconf-client/xconfclientTest.cpp:674
- Test expects doHttpGet to return T2ERROR_SUCCESS but doesn't free the allocated data. When doHttpGet succeeds with a 200 response, it allocates memory for the data parameter. The test should free this memory to prevent memory leaks in test runs. Add
if (data) free(data);after the assertion.
EXPECT_EQ(doHttpGet("https://test.com", &data), T2ERROR_SUCCESS);
source/test/protocol/ProtocolTest.cpp:274
- Test expects sendReportOverHTTP to return T2ERROR_SUCCESS but the test doesn't verify that the report was actually sent. Unlike the old fork-based tests, the new pooled implementation needs to mock the actual HTTP write callback to simulate data transmission. Consider enhancing this test to verify the write callback is invoked with the correct payload.
EXPECT_EQ(T2ERROR_SUCCESS, sendReportOverHTTP(httpURL, payload));
source/test/protocol/ProtocolTest.cpp:333
- Unused variable 'cm' is declared but never used in this test. This appears to be leftover from the fork-based implementation that was removed. Consider removing this unused variable declaration.
char *cm = (char*)0xFFFFFFFF;
source/protocol/http/multicurlinterface.c:66
- Changed DEFAULT_POOL_SIZE from 2 to 1. This reduces the default connection pool size, which may impact performance for concurrent HTTP requests. While this may be appropriate for low-end devices, consider documenting the rationale for this change. The environment variable T2_CONNECTION_POOL_SIZE allows runtime configuration, but the default affects systems where it's not set. Verify that single-connection pooling doesn't create bottlenecks in production scenarios with concurrent telemetry uploads.
#define DEFAULT_POOL_SIZE 1
source/test/xconf-client/xconfclientTest.cpp:478
- Test expects doHttpGet to return T2ERROR_SUCCESS but doesn't free the allocated data. When doHttpGet succeeds with a 200 response, it allocates memory for the data parameter (see multicurlinterface.c lines 677-682). The test should free this memory to prevent memory leaks in test runs. Add
if (data) free(data);after the assertion.
EXPECT_EQ(T2ERROR_SUCCESS, doHttpGet("https://test.com", &data));
source/test/xconf-client/xconfclientTest.cpp:721
- Test expects doHttpGet to return T2ERROR_SUCCESS but doesn't free the allocated data. When doHttpGet succeeds with a 200 response, it allocates memory for the data parameter. The test should free this memory to prevent memory leaks in test runs. Add
if (data) free(data);after the assertion.
EXPECT_EQ(doHttpGet("https://test.com", &data), T2ERROR_SUCCESS);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
RDK-60805: Adding L1 unit test cases for reportprofiles (#265)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (3)
source/test/mocks/FileioMock.cpp:503
- This wrapper returns
CURLE_FAILED_INITwheneverg_fileIOMockis null, instead of falling back to the realcurl_easy_setopt(similar to how other wrappers fall back viadlsym). This can cause unrelated tests or code paths to fail if they invokecurl_easy_setoptbefore the mock is installed. Prefer callingcurl_easy_setopt_funcwheng_fileIOMock == nullptr.
extern "C" CURLcode curl_easy_setopt(CURL* handle, CURLoption option, ...) {
if (g_fileIOMock != nullptr) {
va_list args;
va_start(args, option);
void* param = va_arg(args, void*);
va_end(args);
return g_fileIOMock->curl_easy_setopt(handle, option, param);
}
return CURLE_FAILED_INIT;
}
test/functional-tests/tests/helper_functions.py:120
verify=CA_BUNDLEhard-codes/etc/ssl/certs/ca-certificates.crtwithout checking it exists. In minimal containers/distros this file may be missing or in a different location, causingrequests.get(...)to raise and fail tests. Consider checkingos.path.exists(CA_BUNDLE)and falling back toverify=True(requests default) or toverify=Falsein the test environment, and/or make the CA bundle path configurable via env var.
# CA certificate for server verification
CA_BUNDLE = '/etc/ssl/certs/ca-certificates.crt' # System CA bundle
def run_telemetry():
return subprocess.run("/usr/local/bin/telemetry2_0", shell=True)
def run_shell_silent(command):
subprocess.run(command, shell=True, capture_output=False, text=False)
return
def run_shell_command(command):
result = subprocess.run(command, shell=True, capture_output=True, text=True)
return result.stdout.strip()
def kill_telemetry(signal: int=9):
print(f"Recived Signal to kill telemetry2_0 {signal} with pid {get_pid('telemetry2_0')}")
resp = subprocess.run(f"kill -{signal} {get_pid('telemetry2_0')}", shell=True, capture_output=True)
print(resp.stdout.decode('utf-8'))
print(resp.stderr.decode('utf-8'))
return ""
"""
def sigterm_telemetry(pid:str):
resp = subprocess.run(f"echo 'this is a test'; kill -15 `pidof telemetry2_0`; echo $?; echo !!", shell=True, capture_output=True)
print(resp.stdout.decode('utf-8'))
print(resp.stderr.decode('utf-8'))
print(get_pid("telemetry2_0"))
cmd=["kill","-15",str(pid)]
print(f"Running command: {' '.join(cmd)}")
result = subprocess.run(cmd, capture_output=True, text=True)
print("Output:", result.stdout)
print("Error:", result.stderr)
"""
def sigterm_telemetry(pid):
try:
# Print the command being executed
print(f"Sending SIGTERM to process {pid}")
# Send the SIGTERM signal to the process
os.kill(int(pid), signal.SIGTERM)
print(f"Process {pid} has been terminated.")
except ProcessLookupError:
print(f"No process with PID {pid} found.")
except PermissionError:
print(f"Permission denied to kill process {pid}.")
except Exception as e:
print(f"An error occurred: {e}")
def adminSupport_cache(save: bool = True):
if(requests.get(ADMIN_SUPPORT_SET, verify=CA_BUNDLE, cert=CERT_PATH, params={ADMIN_CACHE_ARG: str(save).lower()})):
return True
return False
def adminSupport_requestData():
return_data = requests.get(ADMIN_SUPPORT_GET, verify=CA_BUNDLE, cert=CERT_PATH, params={ADMIN_RQUEST_DATA: "true"})
try:
test/run_l2.sh:41
$RESULT_DIRis expanded unquoted in the--json-report-filearguments. Quoting it avoids failures if the path ever contains spaces or glob characters (and is consistent with howmkdir -pis called above).
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
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (12)
source/protocol/http/multicurlinterface.c:115
- The log message incorrectly states "Curl connection pool size set from environment" even though it's printed regardless of whether the value came from the environment or the default. This should only be logged when env_size is actually set. Consider moving this log inside the if condition or changing the message to indicate whether it's from the environment or the default.
T2Info("Curl connection pool size set from environment: %d\n", configured_size);
source/protocol/http/multicurlinterface.c:472
- This comment is misleading. The function still clears CURLOPT_POSTFIELDS, CURLOPT_POSTFIELDSIZE, and CURLOPT_HTTPHEADER even though the comment only mentions that CURLOPT_CUSTOMREQUEST was removed. The comment should be updated to accurately describe which POST-specific options are being cleared. Note that line 469 that clears CURLOPT_CUSTOMREQUEST was removed but the comment wasn't updated accordingly.
// Clear any POST-specific settings so that the handle can be used for GET operations
// curl_easy_perform ends up in crash when POST specific options are not cleared
CURL_SETOPT_CHECK(easy, CURLOPT_POSTFIELDS, NULL);
CURL_SETOPT_CHECK(easy, CURLOPT_POSTFIELDSIZE, 0L);
CURL_SETOPT_CHECK(easy, CURLOPT_HTTPHEADER, NULL);
source/xconf-client/xconfclient.c:547
- Logging level changed from T2Info to T2Debug. This reduces log verbosity for successful HTTP GET operations. While this may be intentional for reducing log noise, consider whether successful HTTP GET operations should still be logged at INFO level for operational visibility. Debug-level logging may make troubleshooting more difficult in production environments.
T2Debug("HTTP GET request completed successfully\n");
source/test/xconf-client/xconfclientTest.cpp:651
- The lambda function for getParameterValue mock returns void (empty return statement at line 650), but the function is expected to return T2ERROR. This will cause a compilation error or undefined behavior. The return statement should be 'return T2ERROR_SUCCESS;' to match the function signature and the pattern used in other similar mocks in this file.
EXPECT_CALL(*m_xconfclientMock, getParameterValue(_,_))
.Times(1)
.WillOnce([](const char* paramName, char** paramValue) {
if (strcmp(paramName, "Device.X_RDK_WanManager.CurrentActiveInterface") == 0)
*paramValue = strdup("erouter0");
else
*paramValue = strdup("unknown");
return ;
});
source/test/xconf-client/xconfclientTest.cpp:698
- The lambda function for getParameterValue mock returns void (empty return statement at line 697), but the function is expected to return T2ERROR. This will cause a compilation error or undefined behavior. The return statement should be 'return T2ERROR_SUCCESS;' to match the function signature and the pattern used in other similar mocks in this file.
EXPECT_CALL(*m_xconfclientMock, getParameterValue(_,_))
.Times(1)
.WillOnce([](const char* paramName, char** paramValue) {
if (strcmp(paramName, "Device.X_RDK_WanManager.CurrentActiveInterface") == 0)
*paramValue = strdup("erouter0");
else
*paramValue = strdup("unknown");
return ;
});
source/test/xconf-client/xconfclientTest.cpp:68
- The comment describes preventing a deadlock caused by mocked fwrite calls when GTest logs output. However, this macro only mocks fwrite and not fputs which is also mentioned in the comment. If fputs can also cause deadlock issues, it should be included in the macro. Otherwise, the comment should be updated to only mention fwrite.
// Helper macro to prevent deadlock from mocked fwrite and fputs calls in the protocol code when GTest tries to log output, which can cause a deadlock if the logging functions are mocked without allowing real calls to them.
#define PREVENT_GTEST_LOGGING_DEADLOCK() \
EXPECT_CALL(*g_fileIOMock, fwrite(::testing::_, ::testing::_, ::testing::_, ::testing::_)) \
.Times(::testing::AnyNumber()) \
.WillRepeatedly(::testing::Invoke( \
[](const void* ptr, size_t size, size_t nitems, FILE* stream) { \
return ::fwrite(ptr, size, nitems, stream); \
}))
source/xconf-client/Makefile.am:27
- Adding -lrdkconfig to the linker flags when LIBRDKCERTSEL is enabled. However, based on the conditional compilation guards in the code (#ifndef LIBRDKCERTSEL_BUILD wrapping #ifdef LIBRDKCONFIG_BUILD), rdkconfig should NOT be used when LIBRDKCERTSEL_BUILD is defined. This creates a potential inconsistency - the library will be linked but the code won't use it when LIBRDKCERTSEL is enabled. Consider whether -lrdkconfig should be added unconditionally or under a separate IS_LIBRDKCONFIG_ENABLED condition rather than within the IS_LIBRDKCERTSEL_ENABLED block.
libxconfclient_la_LDFLAGS += -lRdkCertSelector -lrdkconfig
test/functional-tests/tests/helper_functions.py:60
- The certificate path discovery logic attempts to find valid certificates by checking multiple standard locations. However, if CERT_PATH remains None (no valid certificates found), subsequent requests.get() calls will still use cert=CERT_PATH which passes None, effectively disabling client certificates. While a warning is printed, consider whether the tests should fail explicitly if no certificates are found, or if this is intentional to allow running tests without mTLS in some environments.
if CERT_PATH is None:
print("WARNING: No valid client certificate found!")
build_inside_container.sh:34
- Adding -DENABLE_MTLS to CFLAGS and --enable-rdkcertselector=yes to configure. This enables mTLS support in the build. Ensure that the test environment (docker containers) has the necessary certificates and configuration to support mTLS testing, as indicated by the ENABLE_MTLS=true environment variable being passed to the docker containers in the L2-tests.yml workflow.
export CFLAGS=" ${DEBUG_CFLAGS} -I${INSTALL_DIR}/include/rtmessage -I${INSTALL_DIR}/include/msgpack -I${INSTALL_DIR}/include/rbus -I${INSTALL_DIR}/include -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/local/include -DFEATURE_SUPPORT_WEBCONFIG -DRDK_LOGGER -DPERSIST_LOG_MON_REF -DDCMAGENT -DENABLE_MTLS"
export LDFLAGS="-L/usr/lib/x86_64-linux-gnu -lglib-2.0"
./configure --prefix=${INSTALL_DIR} --enable-rdkcertselector=yes && make && make install
source/test/protocol/ProtocolTest.cpp:363
- The test expects T2ERROR_FAILURE but doesn't set up the necessary mocks to simulate the failure condition. The test only mocks isMtlsEnabled() to return true and access() to return 0, but doesn't mock curl_easy_perform or curl_easy_getinfo_mock, which are likely needed for the actual HTTP operation. Without these mocks, the test may not behave as intended. Consider adding the missing mock expectations or documenting why this specific failure case is being tested.
TEST_F(protocolTestFixture, SENDREPORTOVERHTTP3)
{
char* httpURL = "https://mockxconf:50051/dataLakeMock";
char* payload = strdup("This is a payload string");
char *cm = (char*)0xFFFFFFFF;
EXPECT_CALL(*g_fileIOMock, curl_easy_init())
.Times(::testing::AnyNumber())
.WillRepeatedly(::testing::Invoke([]() {
// Return unique fake handles for each call
static int handle_counter = 1;
return (CURL*)(uintptr_t)(0x1000 + handle_counter++);
}));
#if defined(ENABLE_RDKB_SUPPORT) && !defined(RDKB_EXTENDER)
#if defined(WAN_FAILOVER_SUPPORTED) || defined(FEATURE_RDKB_CONFIGURABLE_WAN_INTERFACE)
EXPECT_CALL(*m_xconfclientMock, getParameterValue(_,_))
.Times(1)
.WillOnce(Return(T2ERROR_SUCCESS));
#endif
#endif
EXPECT_CALL(*m_xconfclientMock, isMtlsEnabled())
.Times(1)
.WillOnce(Return(true));
EXPECT_CALL(*g_systemMock, access(_,_))
.Times(1)
.WillOnce(Return(0));
#ifdef LIBRDKCONFIG_BUILD
EXPECT_CALL(*g_rdkconfigMock, rdkconfig_get(_,_,_))
.Times(1)
.WillOnce(Return(RDKCONFIG_OK));
#endif
EXPECT_EQ(T2ERROR_FAILURE, sendReportOverHTTP(httpURL, payload));
free(payload);
}
source/protocol/http/multicurlinterface.c:66
- The DEFAULT_POOL_SIZE is reduced from 2 to 1. While this is a valid optimization for low-end devices, consider verifying that this change doesn't negatively impact performance in scenarios with concurrent HTTP requests. The pool size can still be configured via the T2_CONNECTION_POOL_SIZE environment variable for devices that need higher concurrency.
#define DEFAULT_POOL_SIZE 1
source/protocol/http/Makefile.am:27
- Adding -lrdkconfig to the linker flags when LIBRDKCERTSEL is enabled. However, based on the conditional compilation guards in the code (#ifndef LIBRDKCERTSEL_BUILD wrapping #ifdef LIBRDKCONFIG_BUILD), rdkconfig should NOT be used when LIBRDKCERTSEL_BUILD is defined. This creates a potential inconsistency - the library will be linked but the code won't use it when LIBRDKCERTSEL is enabled. Consider whether -lrdkconfig should be added unconditionally or under a separate IS_LIBRDKCONFIG_ENABLED condition rather than within the IS_LIBRDKCERTSEL_ENABLED block.
libhttp_la_LDFLAGS += -lRdkCertSelector -lrdkconfig
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (5)
source/protocol/http/multicurlinterface.c:781
- The removal of
CURL_SETOPT_CHECK(easy, CURLOPT_HTTPGET, 0L);from the POST request cleanup could cause issues. When a curl handle is reused from the pool after performing a GET request, CURLOPT_HTTPGET may still be set to 1L (from line 497). Setting CURLOPT_POST to 1L doesn't necessarily disable the GET flag. According to libcurl documentation, you should explicitly disable HTTPGET before doing a POST to avoid undefined behavior. Consider restoring this line or verifying that CURLOPT_POST automatically clears CURLOPT_HTTPGET.
// Clear any GET-specific settings from previous use
CURL_SETOPT_CHECK(easy, CURLOPT_WRITEFUNCTION, NULL);
CURL_SETOPT_CHECK(easy, CURLOPT_WRITEDATA, NULL);
source/protocol/http/multicurlinterface.c:66
- The DEFAULT_POOL_SIZE was changed from 2 to 1. This is a significant change that may impact performance. With a pool size of 1, concurrent HTTP requests will have to wait for the single handle to become available, potentially creating a bottleneck. Consider documenting why this change was made, especially since the comment on line 106 mentions "configure the connection pool size based on the device type" and there's an environment variable T2_CONNECTION_POOL_SIZE to override this. If this is intentional for low-end devices, it should be clearly documented.
#define DEFAULT_POOL_SIZE 1
source/protocol/http/multicurlinterface.c:469
- The comment states "curl_easy_perform ends up in crash when POST specific options are not cleared", but this is actually clearing POST options before a GET request, not after. The comment should say "Clear any POST-specific settings from previous use to prevent crashes" to be more accurate.
// curl_easy_perform ends up in crash when POST specific options are not cleared
source/protocol/http/multicurlinterface.c:107
- The comment on line 106 has a typo: "to have the size" should be part of a grammatically complete sentence. Consider rewording to: "Check environment variable T2_CONNECTION_POOL_SIZE to configure the connection pool size based on the device type".
// Check environment variable T2_CONNECTION_POOL_SIZE to have the size
// of the connection pool based on the device type
source/protocol/http/multicurlinterface.c:726
- The spelling of "certicates" is incorrect. It should be "certificates" for consistency with standard spelling.
// In case of CertSelector, CertSelector will take care of freeing the certicates
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
…etry into topic/RDK-60476
Signed-off-by: Yogeswaran K <yogeswaransky@gmail.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (3)
test/functional-tests/tests/report_profiles.py:1240
- This URL change updates the
Split66profile endpoint, but related functional tests still assert the olddataLookeMockURL (e.g.,test_temp_profile.pyandtest_multiprofile_msgpacket.pygrep for it). Either keep the profile URL consistent with those expectations or update the assertions/test data so they match the new endpoint.
"HTTP": {
"URL": "https://mockxconf:50051/dataLakeMockXconf/",
"Compression": "None",
"Method": "POST",
"RequestURIParameter": [
test/run_l2.sh:44
- Unquoted shell variables can break if paths ever contain spaces or glob characters. Quote
$RESULT_DIR(and$final_resultin the test) consistently in the pytest invocations and the[ ... ]comparison to avoid word-splitting issues.
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
if [ $final_result -ne 0 ]; then
echo "Some tests failed. Please check the JSON reports in $RESULT_DIR for details."
source/test/xconf-client/xconfclientTest.cpp:422
- The comment here says the pool default size is 2, but this PR changes
DEFAULT_POOL_SIZEto 1 inmulticurlinterface.c. Please update the comment to reflect the current default (or avoid hard-coding the number in the comment).
// Set up curl_easy_init to return valid handles for pool initialization
// The pool will call curl_easy_init() based on pool size (default 2)
EXPECT_CALL(*g_fileIOMock, curl_easy_init())
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
shibu-kv
left a comment
There was a problem hiding this comment.
Please revisit . There are high chances of race conditions and deadlocks.
| active_requests--; | ||
| // Wake both waiting acquire threads AND cleanup function | ||
| // in case they are waiting for handles to be released | ||
| pthread_cond_broadcast(&pool_cond); |
There was a problem hiding this comment.
This change suggests that there are multiple parallel threads waiting on something. We should try to avoid this if possible as this creates a lot of context switching.
|
|
||
| // Wait for for active_requests to drop to 0, which indicates all threads have completed | ||
| // their curl_easy_perform calls and released their handles back to the pool. | ||
| while (active_requests > 0) |
There was a problem hiding this comment.
High risks of dead locks. Is the active_requests are not decremented in the shutdown sequence, then this part gets hung forever. If this path is chosen further, there should be some bound checks. Value of active_requests should never exceed the poolsize. So some sort of boundry checks should be added. Fact that this implementation limits the pool size to 1, there seems to be something that is not quite right with the mutex locking some critical path.
| static http_pool_entry_t *pool_entries = NULL; // Dynamic array of pool entries | ||
| static struct curl_slist *post_headers = NULL; // Shared POST headers | ||
| static int pool_size = 0; // Number of pool entries | ||
| static int active_requests = 0; // Number of curl handles in use |
There was a problem hiding this comment.
Use unsigned int or even unsigned short int.
No description provided.