diff --git a/cov_build.sh b/cov_build.sh index fa0c1c31..79c93013 100644 --- a/cov_build.sh +++ b/cov_build.sh @@ -43,7 +43,7 @@ fi if [ ! -d tr69hostif ]; then git clone https://github.com/rdkcentral/tr69hostif.git fi -git clone https://github.com/rdkcentral/dcm-agent.git -b feature/logupload_copilot_lib +git clone https://github.com/rdkcentral/dcm-agent.git -b develop cd dcm-agent sh cov_build.sh diff --git a/run_l2.sh b/run_l2.sh index 430c47c2..9a0a0d15 100644 --- a/run_l2.sh +++ b/run_l2.sh @@ -30,6 +30,8 @@ mkdir -p "$LIB_DIR" mkdir -p /media/apps/RDK-RRD-Test/etc/rrd touch /media/apps/RDK-RRD-Test/etc/rrd/remote_debugger.json +echo "AA:BB:CC:DD:EE:FF" >> /tmp/.estb_mac + apt-get remove systemd apt-get update && apt-get install -y tcpdump diff --git a/src/rrd_archive.c b/src/rrd_archive.c index 665855ae..9cf31103 100644 --- a/src/rrd_archive.c +++ b/src/rrd_archive.c @@ -384,7 +384,7 @@ int rrd_archive_generate_filename(const char *mac, const char *issue_type, const RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "[%s] Filename truncated\n", __FUNCTION__); return -1; } - RDK_LOG(RDK_LOG_DEBUG, LOG_REMDEBUG, "[%s] Generated filename: %s\n", __FUNCTION__, filename); + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "[%s] Generated filename: %s\n", __FUNCTION__, filename); return 0; } diff --git a/src/uploadRRDLogs.c b/src/uploadRRDLogs.c index a55ef149..14e364ab 100644 --- a/src/uploadRRDLogs.c +++ b/src/uploadRRDLogs.c @@ -1,12 +1,21 @@ /* - * uploadRRDLogs.c - Skeleton for C migration of uploadRRDLogs.sh + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: * - * This file is auto-generated following HLD and implementation instructions. + * Copyright 2018 RDK Management * - * Modules: Main Orchestration, Config Manager, System Info, Log Processing, Archive, Upload, Logging - * See: .github/docs/uploadRRDLogs_HLD.md - */ - + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ #include #include @@ -27,13 +36,13 @@ int rrd_upload_orchestrate(const char *upload_dir, const char *issue_type) { - RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Entry\n", __FUNCTION__); - // Validate input parameters if (!upload_dir || !issue_type) { RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "%s: Invalid parameters\n", __FUNCTION__); return 1; } + + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Executing binary to upload Debug info of ISSUETYPE=%s\n", __FUNCTION__, issue_type); // 2. Initialize logging subsystem // Logging is initialized by RDK_LOGGER macros; no explicit init needed @@ -61,6 +70,7 @@ int rrd_upload_orchestrate(const char *upload_dir, const char *issue_type) RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: MAC: %s, Timestamp: %s\n", __FUNCTION__, mac_addr, timestamp); // 5. Validate and prepare log directory + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Checking %s size and contents\n", __FUNCTION__, upload_dir); if (rrd_logproc_validate_source(upload_dir) != 0) { RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "%s: Invalid or empty upload directory: %s\n", __FUNCTION__, upload_dir); return 6; @@ -81,7 +91,7 @@ int rrd_upload_orchestrate(const char *upload_dir, const char *issue_type) // 6.5. Handle LOGUPLOAD_ENABLE special case (matching shell script lines 128-131) if (strcmp(issue_type_sanitized, "LOGUPLOAD_ENABLE") == 0) { - RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Handling LOGUPLOAD_ENABLE - checking for live logs\n", __FUNCTION__); + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Check and upload live device logs for the issuetype\n", __FUNCTION__); if (rrd_logproc_handle_live_logs(upload_dir) != 0) { RDK_LOG(RDK_LOG_WARN, LOG_REMDEBUG, "%s: Failed to handle live logs for LOGUPLOAD_ENABLE\n", __FUNCTION__); } @@ -97,15 +107,18 @@ int rrd_upload_orchestrate(const char *upload_dir, const char *issue_type) // 8. Create archive in /tmp/rrd/ directory (matching shell script line 127) const char *rrd_log_dir = "/tmp/rrd/"; + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Creating %s tarfile from Debug Commands output\n", __FUNCTION__, archive_filename); if (rrd_archive_create(upload_dir, rrd_log_dir, archive_filename) != 0) { RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "%s: Failed to create archive %s\n", __FUNCTION__, archive_filename); return 10; } - RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Archive created: %s\n", __FUNCTION__, archive_filename); // 9. Upload archive from /tmp/rrd/ directory + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Invoking uploadSTBLogs binary to upload %s file\n", __FUNCTION__, archive_filename); + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: uploadSTBLogs parameters - server: %s, protocol: %s, http_link: %s, file: %s\n", + __FUNCTION__, config.log_server, config.upload_protocol, config.http_upload_link, archive_filename); if (rrd_upload_execute(config.log_server, config.upload_protocol, config.http_upload_link, rrd_log_dir, archive_filename, upload_dir) != 0) { - RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "%s: Failed to upload archive\n", __FUNCTION__); + RDK_LOG(RDK_LOG_ERROR, LOG_REMDEBUG, "%s: RRD %s Debug Information Report upload Failed!!!\n", __FUNCTION__, issue_type_sanitized); // Cleanup on failure (matching shell script lines 139-140) char archive_fullpath[512]; snprintf(archive_fullpath, sizeof(archive_fullpath), "%s%s", rrd_log_dir, archive_filename); @@ -113,14 +126,14 @@ int rrd_upload_orchestrate(const char *upload_dir, const char *issue_type) rrd_upload_cleanup_source_dir(upload_dir); return 11; } - RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Archive uploaded successfully\n", __FUNCTION__); + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: RRD %s Debug Information Report upload Success\n", __FUNCTION__, issue_type_sanitized); // 10. Cleanup archive and source directory (matching shell script line 143) + RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Removing uploaded report %s\n", __FUNCTION__, archive_filename); char archive_fullpath[512]; snprintf(archive_fullpath, sizeof(archive_fullpath), "%s%s", rrd_log_dir, archive_filename); rrd_archive_cleanup(archive_fullpath); rrd_upload_cleanup_source_dir(upload_dir); - RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Cleanup complete\n", __FUNCTION__); RDK_LOG(RDK_LOG_INFO, LOG_REMDEBUG, "%s: Exit\n", __FUNCTION__); return 0; diff --git a/test/functional-tests/features/rrd_c_api_upload.feature b/test/functional-tests/features/rrd_c_api_upload.feature index e43419ea..0ed42fbb 100644 --- a/test/functional-tests/features/rrd_c_api_upload.feature +++ b/test/functional-tests/features/rrd_c_api_upload.feature @@ -23,6 +23,19 @@ Feature: Remote Debugger C API Upload Orchestration And test log files are created in the upload directory When I call rrd_upload_orchestrate with valid upload directory and issue type Then the C API should return success code 0 + And logs should contain "Executing binary to upload Debug info of ISSUETYPE" + And logs should contain "Logging ready" + And logs should contain "Configuration loaded" + And logs should contain "MAC:" for MAC address + And logs should contain "Timestamp:" for timestamp generation + And logs should contain "size and contents" for directory size check + And logs should contain "Log directory validated and prepared" + And logs should contain "Issue type sanitized" + And logs should contain "Archive filename:" with the generated filename + And logs should contain "Creating" for tarfile creation + And logs should contain "tarfile from Debug Commands output" + And logs should contain "Invoking uploadSTBLogs binary to upload" + And logs should contain "uploadSTBLogs parameters - server:" And the archive should be created with correct naming format And the archive should contain all log files from the directory And the upload should be triggered successfully @@ -107,17 +120,19 @@ Feature: Remote Debugger C API Upload Orchestration Given the remote debugger is configured And successful upload has completed When I call rrd_upload_orchestrate with valid parameters - Then the archive file should be cleaned up + Then logs should contain "Debug Information Report upload Success" + And logs should contain "Removing uploaded report" + And logs should contain "Exit" for orchestration exit + And the archive file should be cleaned up And temporary files should be removed - And logs should show "Cleanup complete" Scenario: Test rrd_upload_orchestrate cleanup after upload failure Given the remote debugger is configured And upload will fail When I call rrd_upload_orchestrate with valid parameters - Then the archive file should still be cleaned up + Then logs should contain "Debug Information Report upload Failed" + And the archive file should still be cleaned up And error code 11 should be returned - And logs should show upload failure Scenario: Test uploadDebugoutput wrapper function Given the remote debugger is running @@ -145,16 +160,49 @@ Feature: Remote Debugger C API Upload Orchestration And logs should be prepared for upload And archive should include live log data - Scenario: Verify rrd_upload_orchestrate logging throughout execution - Given the remote debugger is configured with debug logging - When I call rrd_upload_orchestrate with valid parameters - Then entry and exit logs should be present - And each step should log progress - And configuration values should be logged - And system info should be logged - And archive creation should be logged - And upload status should be logged - And cleanup should be logged + Scenario: Test remote debugger end-to-end with RFC trigger + Given the remote debugger process is running + And the issue type RFC is reset to empty string + When I set RFC parameter "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType" to test issue string + Then logs should contain "Received event for RRD_SET_ISSUE_EVENT" + And logs should contain "SUCCESS: Message sending Done" + And logs should contain "SUCCESS: Message Reception Done" + And logs should contain "MSG=" followed by the issue string + And logs should contain "Start Reading JSON File... /etc/rrd/remote_debugger.json" + And logs should contain "Json File parse Success... /etc/rrd/remote_debugger.json" + And logs should contain "Issue Data Node:" with node and subnode information + And logs should contain "Creating Directory" + And logs should contain "Found valid Commands" + And logs should contain "Adding Details of Debug commands to Output File" + And logs should contain "Starting remote_debugger_" service success message + And logs should contain "journalctl remote_debugger_" service success message + And logs should contain "Sleeping with timeout" + And logs should contain "Stopping remote_debugger_" service message + And logs should contain "Starting Upload Debug output via API" + And the output directory should contain generated files + + Scenario: Test upload report validation with success path + Given the remote debugger has completed upload orchestration + When upload completes successfully + Then logs should contain "Debug Information Report upload Success" + And logs should contain "Removing uploaded report" + And logs should contain "Exit" for orchestration completion + And logs should contain "Logging ready" from orchestration initialization + And logs should contain "Configuration loaded" from orchestration setup + + Scenario: Test upload report validation with failure path + Given the remote debugger has completed upload orchestration + When upload fails + Then logs should contain "Debug Information Report upload Failed" + And logs should contain "Logging ready" from orchestration initialization + And logs should contain "Configuration loaded" from orchestration setup + And cleanup should still occur + + Scenario: Test upload report with legacy log compatibility + Given the remote debugger is using legacy logging + When upload completes + Then logs should contain either "RRD Upload Script Execution Success" or "RRD Upload Script Execution Failure" + And upload orchestration logs should confirm execution Scenario: Test rrd_upload_orchestrate error propagation Given the remote debugger is configured diff --git a/test/functional-tests/tests/test_rrd_c_api_upload.py b/test/functional-tests/tests/test_rrd_c_api_upload.py index 77ef07c2..dc7f895d 100644 --- a/test/functional-tests/tests/test_rrd_c_api_upload.py +++ b/test/functional-tests/tests/test_rrd_c_api_upload.py @@ -17,602 +17,197 @@ # limitations under the License. ########################################################################## -import os -import subprocess -import tarfile -import gzip -import re -import time from helper_functions import * -# Test Constants -TEST_UPLOAD_DIR = "/tmp/rrd_test_upload" -TEST_ISSUE_TYPE = "test_issue" -RRD_LOG_FILE = "/opt/logs/remote-debugger.log" -RRD_BINARY = "/usr/local/bin/remotedebugger" - -class TestCAPIHelper: - """Helper class for C API testing""" - - @staticmethod - def create_test_directory(path): - """Create test directory structure""" - os.makedirs(path, exist_ok=True) - return os.path.exists(path) - - @staticmethod - def create_test_files(directory, file_count=5): - """Create test log files in directory""" - created_files = [] - for i in range(file_count): - filepath = os.path.join(directory, f"test_log_{i}.txt") - with open(filepath, 'w') as f: - f.write(f"Test log content {i}\n" * 10) - created_files.append(filepath) - return created_files - - @staticmethod - def cleanup_test_directory(path): - """Remove test directory and contents""" - if os.path.exists(path): - subprocess.run(['rm', '-rf', path], check=False) - - @staticmethod - def get_archive_filename_pattern(mac, issue_type): - """Generate expected archive filename pattern""" - # Format: MAC_ISSUETYPE_TIMESTAMP.tar.gz - return f"{mac}_{issue_type}_*.tar.gz" - - @staticmethod - def validate_archive_format(archive_path): - """Validate that archive is valid tar.gz""" - try: - with gzip.open(archive_path, 'rb') as gz: - with tarfile.open(fileobj=gz, mode='r:') as tar: - return tar is not None - except Exception as e: - print(f"Archive validation failed: {e}") - return False - - @staticmethod - def get_archive_contents(archive_path): - """Get list of files in archive""" - try: - with gzip.open(archive_path, 'rb') as gz: - with tarfile.open(fileobj=gz, mode='r:') as tar: - return tar.getnames() - except Exception as e: - print(f"Failed to read archive: {e}") - return [] - - @staticmethod - def check_log_contains(pattern, log_file=RRD_LOG_FILE): - """Check if log file contains pattern""" - try: - with open(log_file, 'r') as f: - content = f.read() - return pattern in content - except FileNotFoundError: - return False - - @staticmethod - def get_mac_address(): - """Get system MAC address""" - result = subprocess.run(['sh', '-c', 'getMacAddressOnly'], - capture_output=True, text=True) - if result.returncode == 0: - return result.stdout.strip() - return None - - @staticmethod - def create_upload_lock(): - """Create upload lock file for testing""" - lock_file = "/tmp/.log-upload.lock" - with open(lock_file, 'w') as f: - f.write(str(os.getpid())) - return lock_file - - @staticmethod - def remove_upload_lock(): - """Remove upload lock file""" - lock_file = "/tmp/.log-upload.lock" - if os.path.exists(lock_file): - os.remove(lock_file) +def test_check_remote_debugger_config_file(): + config_file_path = JSON_FILE + assert check_file_exists(config_file_path), f"Configuration file '{config_file_path}' does not exist." +def test_check_rrd_directory_exists(): + dir_path = OUTPUT_DIR + assert check_directory_exists(dir_path), f"Directory '{dir_path}' does not exist." -# Test Functions - -def test_rrd_upload_orchestrate_valid_parameters(): - """Test rrd_upload_orchestrate with valid parameters""" - helper = TestCAPIHelper() - - # Setup - helper.cleanup_test_directory(TEST_UPLOAD_DIR) - assert helper.create_test_directory(TEST_UPLOAD_DIR) - created_files = helper.create_test_files(TEST_UPLOAD_DIR) - assert len(created_files) == 5 - - # Clear previous logs - remove_logfile() - remove_upload_lock() - - # Trigger via RRD daemon (which calls uploadDebugoutput -> rrd_upload_orchestrate) - kill_rrd() - time.sleep(2) - - # Start remotedebugger - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger event to invoke C API - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', TEST_ISSUE_TYPE - ] - result = subprocess.run(command, capture_output=True, text=True) +def reset_issuetype_rfc(): + command = 'rbuscli set Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType string ""' + result = subprocess.run(command, shell=True, capture_output=True, text=True) assert result.returncode == 0 - - time.sleep(20) # Wait for processing - - # Verify logs - assert helper.check_log_contains("Entry") - assert helper.check_log_contains("Configuration loaded") - assert helper.check_log_contains("MAC address obtained") - assert helper.check_log_contains("Timestamp generated") - assert helper.check_log_contains("Archive created") - assert helper.check_log_contains("rrd_upload_orchestrate: Exit") - - # Cleanup - helper.cleanup_test_directory(TEST_UPLOAD_DIR) - kill_rrd() - -def test_rrd_upload_orchestrate_null_parameters(): - """Test rrd_upload_orchestrate with NULL parameters""" - helper = TestCAPIHelper() - - # This test would require a test harness that directly calls the C API - # For now, we verify that the daemon doesn't crash with invalid params - - # The uploadDebugoutput function checks for NULL before calling orchestrate - # So we verify the error handling logs - - remove_logfile() +def test_check_and_start_remotedebugger(): kill_rrd() - time.sleep(2) - - # Normal startup - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # The daemon should handle edge cases gracefully - pid = run_shell_command("pidof remotedebugger") - assert pid != "", "remotedebugger should still be running" - - kill_rrd() - - -def test_rrd_upload_orchestrate_empty_directory(): - """Test rrd_upload_orchestrate with empty directory""" - helper = TestCAPIHelper() - - # Setup empty directory - helper.cleanup_test_directory(TEST_UPLOAD_DIR) - helper.create_test_directory(TEST_UPLOAD_DIR) - remove_logfile() - kill_rrd() - time.sleep(2) - - # Start remotedebugger - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" + print("Starting remotedebugger process") + command_to_start = "nohup /usr/local/bin/remotedebugger > /dev/null 2>&1 &" run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger with empty directory (would fail at validation) - # The actual upload directory used by RRD is controlled by JSON config - # This test validates that empty directory detection works - - # Create a scenario where the output directory is empty - # In practice, RRD won't create archive if no commands produced output - - # Cleanup - helper.cleanup_test_directory(TEST_UPLOAD_DIR) - kill_rrd() - + command_to_get_pid = "pidof remotedebugger" + pid = run_shell_command(command_to_get_pid) + assert pid != "", "remotedebugger process did not start" -def test_rrd_config_loading(): - """Test configuration loading in rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - # Ensure config files exist - assert os.path.exists('/etc/include.properties'), "include.properties should exist" - - remove_logfile() - kill_rrd() - time.sleep(2) - - # Start with config - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger upload to test config loading +def test_remote_debugger_trigger_event(): + reset_issuetype_rfc() + sleep(10) command = [ 'rbuscli', 'set', 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'config_test' - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(15) - - # Verify configuration was loaded - assert helper.check_log_contains("Loading configuration") - assert helper.check_log_contains("Configuration loaded") - - # Check that config sources were tried - log_patterns = [ - "Parsing /etc/include.properties", - "Configuration loaded - LOG_SERVER:", - "UPLOAD_PROTOCOL:", - "HTTP_UPLOAD_LINK:" + 'string', ISSUE_STRING ] - - for pattern in log_patterns: - assert helper.check_log_contains(pattern), f"Missing log pattern: {pattern}" - - kill_rrd() + result = subprocess.run(command, capture_output=True, text=True) + assert result.returncode == 0, f"Command failed with error: {result.stderr}" + sleep(15) -def test_mac_address_retrieval(): - """Test MAC address retrieval in rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - # Get system MAC for comparison - mac = helper.get_mac_address() - assert mac is not None, "System should have a MAC address" - - remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger upload - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'mac_test' - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(15) - - # Verify MAC was retrieved - assert helper.check_log_contains("MAC address obtained") - assert helper.check_log_contains(f"MAC: {mac}"), f"MAC {mac} should be in logs" - - kill_rrd() - + QUERY_MSG = "Received event for RRD_SET_ISSUE_EVENT" + assert QUERY_MSG in grep_rrdlogs(QUERY_MSG) -def test_timestamp_generation(): - """Test timestamp generation in rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger upload - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'timestamp_test' - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(15) - - # Verify timestamp was generated - assert helper.check_log_contains("Timestamp generated") - - # Check timestamp format in logs (YYYY-MM-DD-HH-MM-SS[AM|PM]) - timestamp_pattern = r'\d{4}-\d{2}-\d{2}-\d{2}-\d{2}-\d{2}[AP]M' - - with open(RRD_LOG_FILE, 'r') as f: - content = f.read() - assert re.search(timestamp_pattern, content), "Timestamp format should match expected pattern" - - kill_rrd() + MSG_SEND = "SUCCESS: Message sending Done" + sleep(2) + assert MSG_SEND in grep_rrdlogs(MSG_SEND) + MSG_RECEIVE = "SUCCESS: Message Reception Done" + sleep(2) + assert MSG_RECEIVE in grep_rrdlogs(MSG_RECEIVE) -def test_issue_type_sanitization(): - """Test issue type sanitization in rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger with issue type containing dots and hyphens - test_issue = "test.issue-type.example" - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', test_issue - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(15) - - # Verify sanitization (dots become underscores, uppercase) - # normalizeIssueName converts dots to underscores - # rrd_logproc_convert_issue_type converts to uppercase and sanitizes - expected_normalized = "TEST_ISSUE_TYPE_EXAMPLE" - - assert helper.check_log_contains("Issue type sanitized") - assert helper.check_log_contains(expected_normalized) or helper.check_log_contains("test_issue_type_example") - - kill_rrd() + ISSUE_MSG = f'MSG={ISSUE_STRING}' + assert ISSUE_MSG in grep_rrdlogs(ISSUE_MSG) + print("Sent and received messages are found and match in the logfile") + READ_JSON = "Start Reading JSON File... /etc/rrd/remote_debugger.json" + assert READ_JSON in grep_rrdlogs(READ_JSON) -def test_archive_creation(): - """Test archive creation in rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - # Create test files - helper.cleanup_test_directory(TEST_UPLOAD_DIR) - helper.create_test_directory(TEST_UPLOAD_DIR) - helper.create_test_files(TEST_UPLOAD_DIR) - - remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger upload - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'archive_test' - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(15) - - # Verify archive creation logs - assert helper.check_log_contains("Creating archive") - assert helper.check_log_contains("Archive created") - assert helper.check_log_contains(".tar.gz") - - # Note: Archive is typically created in /tmp/rrd/ and then cleaned up - # So we verify logs rather than checking for file existence - - helper.cleanup_test_directory(TEST_UPLOAD_DIR) - kill_rrd() + PARSE_JSON = "Json File parse Success... /etc/rrd/remote_debugger.json" + assert PARSE_JSON in grep_rrdlogs(PARSE_JSON) + if '.' in ISSUE_STRING: + ISSUE_NODE, ISSUE_SUBNODE = ISSUE_STRING.split('.') + else: + node = ISSUE_STRING + subnode = None -def test_upload_execution(): - """Test upload execution in rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger upload - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'upload_test' - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(20) - - # Verify upload was attempted - assert helper.check_log_contains("Starting upload") - - # Check for either success or failure (depending on server availability) - upload_attempted = ( - helper.check_log_contains("Upload completed successfully") or - helper.check_log_contains("Log upload failed") - ) - assert upload_attempted, "Upload should have been attempted" - - kill_rrd() + ISSUE_FOUND = f"Issue Data Node: {ISSUE_NODE} and Sub-Node: {ISSUE_SUBNODE} found in Static JSON File /etc/rrd/remote_debugger.json" + DIR_CREATION = "Creating Directory" + assert DIR_CREATION in grep_rrdlogs(DIR_CREATION) -def test_cleanup_after_upload(): - """Test cleanup in rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger upload - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'cleanup_test' - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(20) - - # Verify cleanup logs - assert helper.check_log_contains("Cleanup complete") - - kill_rrd() + SANITY_CHECK = "Found valid Commands" + assert SANITY_CHECK in grep_rrdlogs(SANITY_CHECK) + DEBUG_FILE = "Adding Details of Debug commands to Output File" + assert DEBUG_FILE in grep_rrdlogs(DEBUG_FILE) -def test_upload_debug_output_wrapper(): - """Test uploadDebugoutput wrapper function""" - helper = TestCAPIHelper() - - remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger with issue containing dots (tests normalization) - test_issue = "wrapper.test.issue" - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', test_issue - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(15) - - # Verify wrapper was called - assert helper.check_log_contains("Starting Upload Debug output via API") - - # Verify outcome logging - outcome_logged = ( - helper.check_log_contains("Upload orchestration completed successfully") or - helper.check_log_contains("Upload orchestration failed") + SERVICE_START = f"Starting remote_debugger_{ISSUE_STRING} service success" + assert SERVICE_START in grep_rrdlogs(SERVICE_START) + + JOURNAL_START = f"journalctl remote_debugger_{ISSUE_STRING} service success" + assert JOURNAL_START in grep_rrdlogs(JOURNAL_START) + + SLEEP_TIME = "Sleeping with timeout" + assert SLEEP_TIME in grep_rrdlogs(SLEEP_TIME) + sleep(20) + + SERVICE_STOP = f"Stopping remote_debugger_{ISSUE_STRING} service" + assert SERVICE_STOP in grep_rrdlogs(SERVICE_STOP) + + result = check_output_dir() + print(result) + + UPLOAD_LOGS = "Starting Upload Debug output via API" + assert UPLOAD_LOGS in grep_rrdlogs(UPLOAD_LOGS) + + # Verify rrd_upload_orchestrate() function logs + print("Validating rrd_upload_orchestrate logs...") + + # Check orchestration entry + ORCHESTRATE_ENTRY = "Executing binary to upload Debug info of ISSUETYPE" + assert ORCHESTRATE_ENTRY in grep_rrdlogs(ORCHESTRATE_ENTRY), "Missing orchestration entry log" + + # Check logging subsystem initialization + LOGGING_READY = "Logging ready" + assert LOGGING_READY in grep_rrdlogs(LOGGING_READY), "Missing logging ready log" + + # Check configuration loading + CONFIG_LOADED = "Configuration loaded" + assert CONFIG_LOADED in grep_rrdlogs(CONFIG_LOADED), "Missing configuration loaded log" + + # Check MAC and timestamp + MAC_TIMESTAMP = "MAC:" + assert MAC_TIMESTAMP in grep_rrdlogs(MAC_TIMESTAMP), "Missing MAC address log" + + TIMESTAMP_LOG = "Timestamp:" + assert TIMESTAMP_LOG in grep_rrdlogs(TIMESTAMP_LOG), "Missing timestamp log" + + # Check directory validation + CHECKING_SIZE = "size and contents" + assert CHECKING_SIZE in grep_rrdlogs(CHECKING_SIZE), "Missing directory size check log" + + LOG_DIR_VALIDATED = "Log directory validated and prepared" + assert LOG_DIR_VALIDATED in grep_rrdlogs(LOG_DIR_VALIDATED), "Missing log directory validation log" + + # Check issue type sanitization + ISSUE_SANITIZED = "Issue type sanitized" + assert ISSUE_SANITIZED in grep_rrdlogs(ISSUE_SANITIZED), "Missing issue type sanitized log" + + # Check archive filename generation + ARCHIVE_FILENAME = "Archive filename:" + assert ARCHIVE_FILENAME in grep_rrdlogs(ARCHIVE_FILENAME), "Missing archive filename log" + + # Check archive creation + CREATING_TARFILE = "Creating" + TARFILE_TEXT = "tarfile from Debug Commands output" + assert CREATING_TARFILE in grep_rrdlogs(CREATING_TARFILE), "Missing tarfile creation log" + assert TARFILE_TEXT in grep_rrdlogs(TARFILE_TEXT), "Missing tarfile output log" + + # Check upload invocation + INVOKING_UPLOAD = "Invoking uploadSTBLogs binary to upload" + assert INVOKING_UPLOAD in grep_rrdlogs(INVOKING_UPLOAD), "Missing upload invocation log" + + UPLOAD_PARAMS = "uploadSTBLogs parameters - server:" + assert UPLOAD_PARAMS in grep_rrdlogs(UPLOAD_PARAMS), "Missing upload parameters log" + + print("All rrd_upload_orchestrate logs validated successfully") + +def test_remotedebugger_upload_report(): + print("Validating upload report logs...") + + # Check for upload result logs from rrd_upload_orchestrate + UPLOAD_SUCCESS = "Debug Information Report upload Success" + UPLOAD_FAILURE = "Debug Information Report upload Failed" + + if UPLOAD_SUCCESS in grep_rrdlogs(UPLOAD_SUCCESS): + print("Upload successful - validating success path logs") + + # On success, check for cleanup logs + REMOVING_REPORT = "Removing uploaded report" + assert REMOVING_REPORT in grep_rrdlogs(REMOVING_REPORT), "Missing report removal log" + + # Check for orchestration exit + ORCHESTRATE_EXIT = "Exit" + assert ORCHESTRATE_EXIT in grep_rrdlogs(ORCHESTRATE_EXIT), "Missing orchestration exit log" + + elif UPLOAD_FAILURE in grep_rrdlogs(UPLOAD_FAILURE): + print("Upload failed - validating failure path logs") + # On failure, cleanup still happens but with different flow + + else: + # Check legacy log messages for backward compatibility + LEGACY_SUCCESS = "RRD Upload Script Execution Success" + LEGACY_FAILURE = "RRD Upload Script Execution Failure" + + if LEGACY_SUCCESS in grep_rrdlogs(LEGACY_SUCCESS): + print("Legacy upload success log found") + elif LEGACY_FAILURE in grep_rrdlogs(LEGACY_FAILURE): + print("Legacy upload failure log found") + else: + print("Warning: No upload status logs found") + + # Verify that the upload orchestration completed + ORCHESTRATE_LOGS_PRESENT = ( + "Logging ready" in grep_rrdlogs("Logging ready") and + "Configuration loaded" in grep_rrdlogs("Configuration loaded") ) - assert outcome_logged, "Wrapper should log outcome" - - kill_rrd() - - -def test_concurrent_upload_lock(): - """Test upload lock handling""" - helper = TestCAPIHelper() - - # Create a lock file - helper.remove_upload_lock() - lock_file = helper.create_upload_lock() - - remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger upload while lock exists - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'lock_test' - ] - subprocess.run(command, capture_output=True, text=True) - - time.sleep(5) - - # Remove lock to allow completion - helper.remove_upload_lock() - - time.sleep(15) - - # Note: Lock handling is done in rrd_upload_execute - # Verify that it doesn't crash with lock present - pid = run_shell_command("pidof remotedebugger") - assert pid != "", "remotedebugger should handle lock gracefully" - - kill_rrd() - - -def test_comprehensive_logging(): - """Test comprehensive logging throughout rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - remove_logfile() - kill_rrd() - time.sleep(2) + assert ORCHESTRATE_LOGS_PRESENT, "Upload orchestration did not execute properly" - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger upload - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'logging_test' - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(20) - - # Verify comprehensive logging at each step - expected_logs = [ - "rrd_upload_orchestrate: Entry", - "Logging ready", - "Loading configuration", - "Configuration loaded", - "MAC address obtained", - "Timestamp generated", - "Log directory validated and prepared", - "Issue type sanitized", - "Archive filename:", - "Archive created", - "Cleanup complete", - "rrd_upload_orchestrate: Exit" - ] - - for log_pattern in expected_logs: - assert helper.check_log_contains(log_pattern), f"Missing expected log: {log_pattern}" - - kill_rrd() - - -def test_error_code_propagation(): - """Test error code propagation in rrd_upload_orchestrate""" - helper = TestCAPIHelper() - - # This test verifies that errors are logged with appropriate codes - # Actual return codes are checked by the wrapper function + print("Upload report validation completed") + # Cleanup remove_logfile() - kill_rrd() - time.sleep(2) - - command_to_start = f"nohup {RRD_BINARY} > /dev/null 2>&1 &" - run_shell_silent(command_to_start) - time.sleep(5) - - # Trigger normal upload - command = [ - 'rbuscli', 'set', - 'Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType', - 'string', 'error_test' - ] - subprocess.run(command, capture_output=True, text=True) - time.sleep(15) - - # Verify that errors would be logged if they occurred - # In normal operation, we should see success path - - # Check that the function completes one way or another - assert ( - helper.check_log_contains("rrd_upload_orchestrate: Exit") or - helper.check_log_contains("Upload orchestration failed") - ) - + remove_outdir_contents(OUTPUT_DIR) kill_rrd() diff --git a/test/functional-tests/tests/test_rrd_debug_report_upload.py b/test/functional-tests/tests/test_rrd_debug_report_upload.py index dc515c3c..f6d798c3 100644 --- a/test/functional-tests/tests/test_rrd_debug_report_upload.py +++ b/test/functional-tests/tests/test_rrd_debug_report_upload.py @@ -34,7 +34,7 @@ def reset_issuetype_rfc(): def get_rrd_tarfile(): logfile = '/opt/logs/remotedebugger.log.0' - command = f"grep -oP '\\S+\\.tgz' {logfile}" + command = f"grep 'Generated filename:' {logfile} | grep -oP '\\S+\\.tgz'" result = subprocess.run(command, shell=True, capture_output=True, text=True) if result.returncode == 0: return result.stdout.strip()