From 2e07fbf0a67902c44fe7b1696d08bba60198b120 Mon Sep 17 00:00:00 2001 From: Hanasi Date: Wed, 20 May 2026 10:35:10 -0400 Subject: [PATCH] L2 Document update --- .github/skills/bdd-feature-generator/SKILL.md | 892 ++++++++++++++++++ test/functional-tests/L2_Test_Coverage.md | 399 ++++++++ 2 files changed, 1291 insertions(+) create mode 100644 .github/skills/bdd-feature-generator/SKILL.md create mode 100644 test/functional-tests/L2_Test_Coverage.md diff --git a/.github/skills/bdd-feature-generator/SKILL.md b/.github/skills/bdd-feature-generator/SKILL.md new file mode 100644 index 000000000..053053eca --- /dev/null +++ b/.github/skills/bdd-feature-generator/SKILL.md @@ -0,0 +1,892 @@ +--- +name: bdd-feature-generator +description: Generate BDD (Behavior Driven Development) feature files from remote debugger source code analysis. Use for creating Gherkin-format documentation of RBUS event handling, static/dynamic profile processing, command execution, harmful command detection, log archive and upload, deep sleep handling, and uploadRRDLogs C API orchestration. Produces gap analysis between feature files and L2 test implementations. +--- + +# BDD Feature Generator for Remote Debugger + +## Purpose + +Automatically generate BDD feature files in Gherkin format by analyzing the remote debugger source code. This skill creates comprehensive behavioral documentation that can serve as: +- **Functional documentation** of daemon lifecycle, event handling, and profile processing +- **Test specifications** for L2 functional tests (`test/functional-tests/`) +- **Requirements traceability** linking source modules to observable behavior +- **Gap analysis baseline** for comparing L2 tests vs implemented behavior + +## Usage + +Invoke this skill when: +- Documenting existing remote debugger behaviors in BDD format +- Creating test specifications for new features (e.g., new profile types, upload mechanisms) +- Generating feature files for untested code paths (e.g., WebCfg events, deep sleep edge cases) +- Performing gap analysis between L2 tests and source implementation +- Onboarding new team members with behavioral documentation of the daemon + +## Project Context + +The remote debugger (`remotedebugger`) is an RDK component that enables remote collection, packaging, and upload of device diagnostic logs. It: +- Listens for **RBUS/TR-181 events** (IssueType triggers) to initiate debug data collection +- Processes **static profiles** (built-in JSON config at `/etc/rrd/remote_debugger.json`) and **dynamic profiles** (downloaded packages at `/media/apps/RDK-RRD-/etc/rrd/remote_debugger.json`) +- Executes diagnostic **commands** from profiles, with **sanity checks** against harmful commands +- Archives collected outputs as `.tgz` and **uploads** them to a remote server via `uploadRRDLogs.sh` or the **C API** (`rrd_upload_orchestrate`) +- Supports **append mode** combining commands from both static and dynamic profiles +- Handles **deep sleep** events for deferred processing +- Supports **category-only** issue types (all sub-nodes under a category) +- Enforces **single-instance** execution and **RFC enable/disable** control +- Runs as a **systemd service** with a main thread and a dedicated event-processing thread + +## Prerequisites + +Before running this skill: + +1. **Review the build system** — `Makefile.am`, `src/Makefile.am`, and `configure.ac` +2. **Identify compiled modules** — Core sources are always compiled; IARMBUS sources are conditional +3. **Review existing feature files** — Match the format in `test/functional-tests/features/` +4. **Understand test interfaces** — L2 tests use `rbuscli` (RBUS event trigger), log scraping (`/opt/logs/remotedebugger.log.0`), and file system checks (`/tmp/rrd/`) + +## Process + +### Step 1: Analyze Build Configuration + +The remote debugger build is Autotools-based. Identify compiled components from the Makefile chain: + +```bash +# Top-level: identifies src/ as the main SUBDIR +cat Makefile.am | grep "SUBDIRS" +# → SUBDIRS = src + +# Source level: identifies the remotedebugger binary and its sources +cat src/Makefile.am +# → bin_PROGRAMS = remotedebugger +# → remotedebugger_SOURCES = rrdMain.c rrdEventProcess.c rrdJsonParser.c +# rrdRunCmdThread.c rrdCommandSanity.c rrdDynamic.c rrdExecuteScript.c +# rrdMsgPackDecoder.c rrdInterface.c +# → if IARMBUS_ENABLE: +# remotedebugger_SOURCES += rrdIarmEvents.c uploadRRDLogs.c rrd_config.c +# rrd_sysinfo.c rrd_logproc.c rrd_archive.c rrd_upload.c +``` + +**Always compiled modules:** + +| Source File | Header | Purpose | +|---|---|---| +| `rrdMain.c` | `rrdMain.h` | Daemon entry, event thread, RFC enable check, message queue setup | +| `rrdEventProcess.c` | `rrdEventProcess.h` | IssueType/WebCfg/DeepSleep event dispatch, static/dynamic profile flow | +| `rrdJsonParser.c` | `rrdJsonParser.h` | JSON profile parsing, command/timeout extraction, issue node lookup | +| `rrdRunCmdThread.c` | `rrdRunCmdThread.h` | Command execution, output file management, result caching | +| `rrdCommandSanity.c` | `rrdCommandSanity.h` | Command validation against harmful command blocklist | +| `rrdDynamic.c` | `rrdDynamic.h` | Dynamic profile handling, deep sleep event processing | +| `rrdExecuteScript.c` | `rrdExecuteScript.h` | Upload debug output orchestration | +| `rrdMsgPackDecoder.c` | `rrdMsgPackDecoder.h` | WebConfig parameter decoding (MsgPack format) | +| `rrdInterface.c` | `rrdInterface.h` | RBUS registration, event handler setup, profile data elements | + +**Conditionally compiled modules (IARMBUS_ENABLE):** + +| Source File | Header | Purpose | +|---|---|---| +| `rrdIarmEvents.c` | — | IARM bus event handling (power state, deep sleep) | +| `uploadRRDLogs.c` | — | C implementation of upload orchestration entry point | +| `rrd_config.c` | `rrd_config.h` | Configuration loading (server URLs, paths, protocol, RFC/DCM) | +| `rrd_sysinfo.c` | `rrd_sysinfo.h` | System info (MAC address, timestamp, file/dir checks) | +| `rrd_logproc.c` | `rrd_logproc.h` | Log directory validation, preparation, live log handling | +| `rrd_archive.c` | `rrd_archive.h` | Archive creation (.tgz), filename generation, cleanup, CPU checks | +| `rrd_upload.c` | `rrd_upload.h` | Upload orchestration, lock handling, cleanup | + +**Shared headers (no implementation file):** + +| Header | Purpose | +|---|---| +| `rrdCommon.h` | Common constants, macros, data structures (data_buf, msgRRDHdr, etc.) | +| `rrdRbus.h` | RBUS event subscription, blob versioning | +| `rrd_log.h` | Logging subsystem initialization | + +**Exclude from feature generation:** +- `src/unittest/` — Unit tests (L1) +- `test/` — Test infrastructure +- `scripts/` — Runtime scripts (documented as behavior, not source) +- `docs/` — Existing documentation + +### Step 2: Analyze Source Code Structure + +For each compiled module: + +1. **Read the header file** (`.h`) — Identify public functions, data structures, constants +2. **Read the implementation** (`.c`) — Extract event flows, log messages, error paths +3. **Identify RBUS parameters/events** — Map registered data elements in `rrdInterface.c` +4. **Note conditional compilation** — `#ifdef IARMBUS_SUPPORT` gates upload and IARM modules +5. **Note key log messages** — Tests validate behavior by grepping these from log files +6. **Note file paths** — `/etc/rrd/remote_debugger.json`, `/tmp/rrd/`, `/media/apps/RDK-RRD-*` + +**Key elements to extract for each module:** + +| Element | Where to Find | Example | +|---|---|---| +| RBUS data elements | `rrdInterface.c` registration | `Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType` | +| Event handlers | `rrdInterface.c` set handlers | `RRD_SET_ISSUE_EVENT` | +| Profile JSON paths | `rrdEventProcess.c`, `rrdDynamic.c` | `/etc/rrd/remote_debugger.json`, `/media/apps/RDK-RRD-{Node}/etc/rrd/remote_debugger.json` | +| Log messages | All `.c` files `RDK_LOG_*` calls | `"SUCCESS: Message sending Done"`, `"Json File parse Success..."` | +| Error conditions | `.c` return/log on failure | `"FAILED: Json File parse..."`, `"Harmful Command Found"` | +| File outputs | `rrdRunCmdThread.c` | `/tmp/rrd/{IssueType}/debug_outputs.txt` | +| Archive naming | `rrd_archive.c` | `{MAC}_{ISSUETYPE}_{TIMESTAMP}_RRD_DEBUG_LOGS.tgz` | +| Upload API | `rrd_upload.h` | `rrd_upload_orchestrate(upload_dir, issue_type)` | +| Compile guards | `.c` / `.h` `#ifdef` | `IARMBUS_SUPPORT` | + +### Step 3: Create Feature File Structure + +Feature files are placed in `test/functional-tests/features/`. + +**Naming convention for remote debugger:** + +| Behavior Area | Feature File | Description | +|---|---|---| +| Daemon startup | `rrd_start_subscribe_and_wait.feature` | RBUS subscription, event loop entry | +| RFC enable/disable | `rrd_start_control.feature` | RFC-controlled start/stop | +| Single instance | `rrd_single_instance.feature` | Prevents duplicate daemon instances | +| Static profile processing | `rrd_static_profile_report.feature` | End-to-end static profile flow | +| Static category report | `rrd_static_profile_category_report.feature` | Category-only issue type | +| Static profile with suffix | `test_rrd_static_profile_report_with_suffix.feature` | Suffixed issue type handling | +| Background command | `rrd_background_cmd_static_profile_report.feature` | Background command execution | +| Dynamic profile processing | `rrd_dynamic_profile_report.feature` | Dynamic profile fallback flow | +| Dynamic subcategory | `rrd_dynamic_profile_subcategory_report.feature` | Dynamic profile subcategory | +| Dynamic profile missing | `rrd_dynamic_profile_missing_report.feature` | Missing dynamic profile | +| Append mode | `rrd_append_report.feature` | Static+dynamic profile append | +| Append (static not found) | `rrd_append_dynamic_profile_static_not_found.feature` | Append when static missing | +| Harmful commands | `rrd_harmful_command_static_report.feature` | Sanity check blocks execution | +| Dynamic harmful | `test_rrd_dynamic_profile_harmful_report.feature` | Harmful command in dynamic profile | +| Corrupted profile | `rrd_corrupted_static_profile_report.feature` | Invalid/corrupted JSON handling | +| Static missing command | `rrd_static_profile_missing_command_report.feature` | Missing command in profile | +| Empty issue type | `rrd_empty_issuetype_event.feature` | Empty event value handling | +| Deep sleep | `rrd_deepsleep_static_report.feature` | Deep sleep issue type handling | +| Debug report upload | `rrd_debug_report_upload.feature` | Full upload + download validation | +| C API upload | `rrd_c_api_upload.feature` | `rrd_upload_orchestrate` C API tests | +| Suffix negative case | `test_rrd_static_profile_report_with_suffix_negative_case.feature` | Invalid suffix handling | + +### Step 4: Generate Feature Files + +Use this template for remote debugger feature files: + +```gherkin +########################################################################## +# If not stated otherwise in this file or this component's LICENSE +# file the following copyright and licenses apply: +# +# Copyright [YEAR] RDK Management +# +# 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. +########################################################################## + +# Source: src/{SourceFile}.c + +Feature: Remote Debugger {Behavior Description} + + Scenario: {Prerequisite Check} + Given the configuration file path is set + When I check if the configuration file exists + Then the configuration file should exist + + Scenario: Verify remote debugger process is running + Given the remote debugger process is not running + When I start the remote debugger process + Then the remote debugger process should be running + + Scenario: {Main Behavior Scenario} + Given the remote debugger is running + When I trigger the event "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType" + Then {expected behavior validated via log scraping} +``` + +### Step 5: Map Source Code to Scenarios + +**For each remote debugger behavior, create scenarios covering:** + +1. **Prerequisites** — Config file exists, output directory exists, daemon not already running +2. **Daemon startup** — Process starts, RBUS subscription succeeds, event loop enters wait +3. **Event trigger** — RBUS IssueType set via `rbuscli`, message queue send/receive +4. **Profile parsing** — JSON read, parse success/failure, issue node lookup +5. **Command execution** — Sanity check, command run, output file creation +6. **Service management** — systemd service start/stop, journalctl collection +7. **Upload flow** — Archive creation, upload script invocation, success/failure +8. **Error/edge cases** — Harmful commands, empty events, corrupted profiles, missing profiles + +**Example mapping — RBUS event trigger (rrdInterface.c → rrdEventProcess.c):** + +```c +// Source: src/rrdInterface.c — RBUS set handler for IssueType +// Sends message to event thread via message queue +// Source: src/rrdEventProcess.c — Event thread receives and dispatches +``` + +**Generated scenarios:** + +```gherkin +Scenario: Send WebPA event for IssueType and verify message flow + Given the remote debugger is running + When I trigger the event "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType" + Then the event for RRD_SET_ISSUE_EVENT should be received + And the logs should contain "SUCCESS: Message sending Done" + And the logs should be seen with "SUCCESS: Message Reception Done" +``` + +**Example mapping — Static profile processing (rrdEventProcess.c → rrdJsonParser.c):** + +```gherkin +Scenario: Process static profile for issue type + When the remotedebugger received the message from webPA event + Then remotedebugger should read the Json file + And remotedebugger logs should contain the Json File Parse success + And the issue data node and sub-node should be found in the JSON file + And the directory should be created to store the executed output + And Sanity check to validate the commands should be executed + And Command output should be added to the output file +``` + +**Example mapping — Dynamic profile fallback (rrdDynamic.c):** + +```gherkin +Scenario: Verify the Issuetype in dynamic path + Given the remote debugger issuetype is missing in static profile + When the remotedebugger read the json file form the dynamic path + Then remotedebugger json read and parse should be success + And remotedebugger should read the Issuetype from dynamic profile + And the issue data node and sub-node should be found in the JSON file +``` + +**Example mapping — Harmful command detection (rrdCommandSanity.c):** + +```gherkin +Scenario: Check for harmful commands and abort + Given remote debugger parse the static json profile successfully + When the issue command and the sanity commands are matched + Then the remote debugger should exit the processing of commands + And Abort the command execution and skip report upload +``` + +**Example mapping — Upload orchestration C API (rrd_upload.c):** + +```gherkin +Scenario: Validate rrd_upload_orchestrate C API with valid parameters + Given the remote debugger is configured + 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 "Configuration loaded" + And logs should contain "MAC:" for MAC address + 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 "Invoking uploadSTBLogs binary to upload" +``` + +**Example mapping — Single instance enforcement (rrdMain.c):** + +```gherkin +Scenario: Remote debugger exits if another instance is invoked + Given the RemoteDebugger is not already running + When the RemoteDebugger binary is invoked + Then the RemoteDebugger should be started + And when the RemoteDebugger is attempted to be started again + Then the RemoteDebugger should not start another instance +``` + +### Step 6: Document Issue Type Variations + +For issue types with multiple forms, use individual scenarios: + +```gherkin +Scenario: Static profile with Node.SubNode issue type + Given the remote debugger is running + When I trigger IssueType "Device.Info" + Then the issue data node "Device" and sub-node "Info" should be found in the JSON file + +Scenario: Category-only issue type (all sub-nodes) + Given the remote debugger is running + When I trigger IssueType "Device" + Then all sub-nodes under category "Device" should be processed + +Scenario: Suffixed issue type + Given the remote debugger is running + When I trigger IssueType "Device.Info_ab1bghjh" + Then the base issue "Device.Info" should be matched in the profile + And the archive filename should include the full suffixed issue type +``` + +### Step 7: Create README Index + +Create or update `test/functional-tests/features/README.md`: + +```markdown +# Remote Debugger Feature Documentation + +This folder contains BDD feature files documenting the remote debugger +daemon behavior implemented in `src/`. + +## Feature Files Overview + +| Feature File | Source Components | Description | +|---|---|---| +| `rrd_start_subscribe_and_wait.feature` | `rrdMain.c`, `rrdInterface.c` | RBUS subscription, event loop | +| `rrd_start_control.feature` | `rrdMain.c` | RFC enable/disable control | +| `rrd_single_instance.feature` | `rrdMain.c` | Single instance enforcement | +| `rrd_static_profile_report.feature` | `rrdEventProcess.c`, `rrdJsonParser.c`, `rrdRunCmdThread.c` | Static profile end-to-end | +| `rrd_static_profile_category_report.feature` | `rrdEventProcess.c`, `rrdJsonParser.c` | Category-only issue type | +| `rrd_dynamic_profile_report.feature` | `rrdDynamic.c`, `rrdJsonParser.c` | Dynamic profile fallback | +| `rrd_dynamic_profile_subcategory_report.feature` | `rrdDynamic.c` | Dynamic subcategory | +| `rrd_append_report.feature` | `rrdDynamic.c`, `rrdEventProcess.c` | Append mode (static+dynamic) | +| `rrd_harmful_command_static_report.feature` | `rrdCommandSanity.c` | Harmful command blocking | +| `rrd_corrupted_static_profile_report.feature` | `rrdJsonParser.c` | Corrupted JSON handling | +| `rrd_empty_issuetype_event.feature` | `rrdEventProcess.c` | Empty event value | +| `rrd_deepsleep_static_report.feature` | `rrdDynamic.c`, `rrdIarmEvents.c` | Deep sleep handling | +| `rrd_debug_report_upload.feature` | `rrdExecuteScript.c`, `uploadRRDLogs.sh` | Upload + download validation | +| `rrd_c_api_upload.feature` | `rrd_upload.c`, `rrd_config.c`, `rrd_archive.c` | C API upload orchestration | + +## Source Module Mapping + +Based on `src/Makefile.am` and `configure.ac`: + +### Always Compiled +- `rrdMain.c` — Daemon lifecycle, event thread, RFC enable check +- `rrdEventProcess.c` — IssueType/WebCfg event dispatch +- `rrdJsonParser.c` — JSON profile parsing, command extraction +- `rrdRunCmdThread.c` — Command execution, output management +- `rrdCommandSanity.c` — Harmful command validation +- `rrdDynamic.c` — Dynamic profile handling, deep sleep +- `rrdExecuteScript.c` — Upload debug output orchestration +- `rrdMsgPackDecoder.c` — WebConfig MsgPack decoding +- `rrdInterface.c` — RBUS registration, event handlers + +### Conditionally Compiled (IARMBUS_ENABLE) +- `rrdIarmEvents.c` — IARM bus events (power state) +- `uploadRRDLogs.c` — C upload orchestration entry point +- `rrd_config.c` — Configuration loading (RFC/DCM/fallback) +- `rrd_sysinfo.c` — System info (MAC, timestamp) +- `rrd_logproc.c` — Log directory validation/preparation +- `rrd_archive.c` — Archive creation (.tgz) +- `rrd_upload.c` — Upload orchestration, lock handling + +## RBUS Data Elements + +| Data Element | Type | Handler | +|---|---|---| +| `Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType` | SET event | Triggers debug data collection | +| `Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.WebCfgData` | SET event | WebConfig-based trigger | +| `Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.setProfileData` | SET | Profile data injection | +| `Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.getProfileData` | GET | Profile data retrieval | + +## Test Interface Summary + +| Interface | Tool | Log File | Used For | +|---|---|---|---| +| RBUS event | `rbuscli set` | `/opt/logs/remotedebugger.log.0` | IssueType trigger | +| Log scraping | Python `grep_rrdlogs()` | `/opt/logs/remotedebugger.log.0` | Behavior validation | +| File system | Python `os.path`, `subprocess` | `/tmp/rrd/`, `/etc/rrd/` | Config/output checks | +| Upload | Mock xconf server | — | Archive upload validation | +| Process control | `pidof`, `kill`, `nohup` | — | Daemon start/stop | + +## Generation Date + +Generated: {DATE} +``` + +## Scenario Patterns for Remote Debugger + +### Prerequisite Check Pattern + +```gherkin +Scenario: Check if remote debugger configuration file exists + Given the configuration file path is set + When I check if the configuration file exists + Then the configuration file should exist + +Scenario: Check if /tmp/rrd output directory exists + Given the /tmp/rrd directory path is set + When I check if the /tmp/rrd directory exists + Then the /tmp/rrd directory should exist +``` + +### Daemon Startup Pattern + +```gherkin +Scenario: Verify remote debugger process is running + Given the remote debugger process is not running + When I start the remote debugger process + Then the remote debugger process should be running + +Scenario: Remote debugger should subscribe to events + Given the remote debugger binary is invoked + When the remote debugger is started + Then the remote debugger should subscribe to rbus and wait for the events + And the log file should contain "SUCCESS: RBUS Event Subscribe for RRD done!" + And the log file should contain "Waiting for TR69/RBUS Events..." +``` + +### RFC Enable/Disable Pattern + +```gherkin +Scenario: Remote Debugger Starts when Enabled + Given RFC Value for RDKRemoteDebugger.Enable is enabled + When the remotedebugger is started check the value of the RFC parameter + And the RDKRemoteDebugger Enable value is true + Then the remotedebugger should be started and running as daemon + +Scenario: Remote Debugger Stops when Disabled + Given RFC Value for RDKRemoteDebugger.Enable is disabled + When the remotedebugger is started check the value of the RFC parameter + And the RDKRemoteDebugger Enable value is false + Then the remotedebugger must be stopped and process should not be running +``` + +### RBUS Event Trigger Pattern + +```gherkin +Scenario: Send WebPA event for IssueType + Given the remote debugger is running + When I trigger the event "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType" + Then the event for RRD_SET_ISSUE_EVENT should be received + And the logs should contain "SUCCESS: Message sending Done" + And the logs should be seen with "SUCCESS: Message Reception Done" +``` + +### Static Profile Processing Pattern + +```gherkin +Scenario: Process static profile commands + When the remotedebugger received the message from webPA event + Then remotedebugger should read the Json file + And remotedebugger logs should contain the Json File Parse success + And the issue data node and sub-node should be found in the JSON file + And the directory should be created to store the executed output + And Sanity check to validate the commands should be executed + And Command output should be added to the output file + And the issuetype systemd service should start successfully + And the journalctl service should start successfully + And the process should sleep with timeout + And the issuetype systemd service should stop successfully + And the remotedebugger should call script to upload the debug report +``` + +### Dynamic Profile Fallback Pattern + +```gherkin +Scenario: Verify the Issuetype is not found in static profile + Given the remote debugger received the message from RBUS command + When the remotedebugger static json profile is present + Then remotedebugger should read the Json file + And remotedebugger logs should contain the Json File Parse Success + And remotedebugger should log as the Issue requested is not found in the profile + +Scenario: Verify the Issuetype in dynamic path + Given the remote debugger issuetype is missing in static profile + When the remotedebugger read the json file from the dynamic path + Then remotedebugger json read and parse should be success + And remotedebugger should read the Issuetype from dynamic profile + And the issue data node and sub-node should be found in the JSON file +``` + +### Append Mode Pattern + +```gherkin +Scenario: Verify append of static and dynamic profile commands + Given the remote debugger received the message from RBUS command + When the remotedebugger read the json file from the dynamic path + Then remotedebugger json read and parse should be success in dynamic path + And remotedebugger should read the Json file + And remotedebugger logs should contain the Json File Parse Success + And remotedebugger should log as the Issue requested found in the profile + And Update the command after appending data from both profiles, then execute +``` + +### Harmful Command Detection Pattern + +```gherkin +Scenario: Check for harmful commands and abort + Given remote debugger parse the static json profile successfully + When the issue node and subnode are present in the profile + Then the remote debugger should read the Sanity Check list from profile + And the remotedebugger should perform sanity check on issue commands + Given the remote debugger profile has the harmful commands + When the issue command and the sanity commands are matched + Then the remote debugger should exit the processing of commands + And Abort the command execution and skip report upload +``` + +### Upload Flow Pattern + +```gherkin +Scenario: Upload remote debugger debug report + Given the remote debugger completed the command execution + When remotedebugger calls the uploadRRD.sh script + Then check for the tarfile is created in the output directory + And the file is uploaded to the mockxconf server + And the upload success logs are seen in the logs + +Scenario: Download the file from the mockxconf server + Given the remote debugger report upload success + When curl command is used to download the file + Then the curl command should return success + And the file should be downloaded successfully +``` + +### C API Upload Orchestration Pattern + +```gherkin +Scenario: Validate rrd_upload_orchestrate with valid parameters + Given the remote debugger is configured + 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 "Configuration loaded" + And logs should contain "MAC:" for MAC address + 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 "Invoking uploadSTBLogs binary to upload" + +Scenario: Test rrd_upload_orchestrate with NULL parameters + Given the remote debugger is configured + When I call rrd_upload_orchestrate with NULL upload directory + Then the C API should return error code 1 + And error logs should contain "Invalid parameters" + +Scenario: Test rrd_upload_orchestrate with empty directory + Given the remote debugger is configured + And the upload directory is empty + When I call rrd_upload_orchestrate with the empty directory + Then the C API should return error code 6 + And error logs should contain "Invalid or empty upload directory" +``` + +### Error/Edge Case Pattern + +```gherkin +Scenario: Corrupted JSON profile + When the remotedebugger received the message from webPA event + Then remotedebugger should read the Json file + And remotedebugger logs should contain the Json File Parse Failed + +Scenario: Empty issue type event + Given the remote debugger is running + When I trigger the event with empty IssueType value + Then the remotedebugger receives the message from webPA event + And remotedebugger should log as not processing empty event + +Scenario: Missing issue type in static profile + When the remotedebugger received the message + Then remotedebugger should log as the Issue requested is not found in the profile +``` + +### Single Instance Pattern + +```gherkin +Scenario: Remote debugger exits if another instance is invoked + Given the RemoteDebugger is not already running + When the RemoteDebugger binary is invoked + Then the RemoteDebugger should be started + And when the RemoteDebugger is attempted to be started again + Then the RemoteDebugger should not start another instance +``` + +## Quality Checklist + +Before completing feature generation for remote debugger: + +- [ ] All source modules analyzed (`src/Makefile.am` sources list) +- [ ] Conditional modules noted with build flags (`IARMBUS_ENABLE`) +- [ ] Each RBUS event handler has at least one trigger scenario +- [ ] Static profile happy path has end-to-end scenario (trigger → parse → execute → upload) +- [ ] Dynamic profile fallback flow documented +- [ ] Append mode (static+dynamic) documented +- [ ] Harmful command sanity check scenarios included +- [ ] Corrupted/missing profile error scenarios documented +- [ ] Empty/invalid issue type edge cases documented +- [ ] Deep sleep event handling documented +- [ ] C API upload orchestration scenarios included (valid + error cases) +- [ ] RFC enable/disable control documented +- [ ] Single instance enforcement documented +- [ ] Suffixed issue type handling documented +- [ ] License headers included (Apache 2.0, RDK Management) +- [ ] Source file references included as comments +- [ ] Log message assertions match actual daemon log output +- [ ] Feature-to-test file mapping documented for gap analysis +- [ ] Scenarios are atomic (one behavior per scenario) +- [ ] Given/When/Then/And/Or structure followed consistently + +## Output Structure + +``` +test/functional-tests/ +├── features/ +│ ├── README.md # Index, module mapping, gap summary +│ ├── rrd_start_subscribe_and_wait.feature # RBUS subscription, event loop +│ ├── rrd_start_control.feature # RFC enable/disable +│ ├── rrd_single_instance.feature # Single instance enforcement +│ ├── rrd_static_profile_report.feature # Static profile end-to-end +│ ├── rrd_static_profile_category_report.feature # Category-only issue type +│ ├── test_rrd_static_profile_report_with_suffix.feature # Suffixed issue type +│ ├── test_rrd_static_profile_report_with_suffix_negative_case.feature # Invalid suffix +│ ├── rrd_background_cmd_static_profile_report.feature # Background command execution +│ ├── rrd_dynamic_profile_report.feature # Dynamic profile fallback +│ ├── rrd_dynamic_profile_subcategory_report.feature # Dynamic subcategory +│ ├── rrd_dynamic_profile_missing_report.feature # Missing dynamic profile +│ ├── rrd_append_report.feature # Append mode (static+dynamic) +│ ├── rrd_append_dynamic_profile_static_not_found.feature # Append when static missing +│ ├── rrd_harmful_command_static_report.feature # Harmful command blocking +│ ├── test_rrd_dynamic_profile_harmful_report.feature # Dynamic harmful commands +│ ├── rrd_corrupted_static_profile_report.feature # Invalid/corrupted JSON +│ ├── rrd_static_profile_missing_command_report.feature # Missing command in profile +│ ├── rrd_empty_issuetype_event.feature # Empty event value +│ ├── rrd_deepsleep_static_report.feature # Deep sleep handling +│ ├── rrd_debug_report_upload.feature # Upload + download validation +│ └── rrd_c_api_upload.feature # C API upload orchestration +└── tests/ + ├── helper_functions.py # Log grep, process control, constants + ├── test_rrd_static_profile_report.py # Static profile test + ├── test_rrd_dynamic_profile_report.py # Dynamic profile test + ├── test_rrd_c_api_upload.py # C API upload test + ├── test_rrd_single_instance.py # Single instance test + ├── ... # (see full listing below) + └── uploadSTBLogs.sh # Mock upload script +``` + +## Example: Complete Remote Debugger Feature File + +```gherkin +########################################################################## +# If not stated otherwise in this file or this component's LICENSE +# file the following copyright and licenses apply: +# +# Copyright 2026 RDK Management +# +# 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. +########################################################################## + +# Source: src/rrdEventProcess.c +# Source: src/rrdJsonParser.c +# Source: src/rrdRunCmdThread.c +# Source: src/rrdCommandSanity.c + +Feature: Remote Debugger Static Report + + Scenario: Check if remote debugger configuration file exists + Given the configuration file path is set + When I check if the configuration file exists + Then the configuration file should exist + + Scenario: Check if /tmp/rrd output directory exists + Given the /tmp/rrd directory path is set + When I check if the /tmp/rrd directory exists + Then the /tmp/rrd directory should exist + + Scenario: Verify remote debugger process is running + Given the remote debugger process is not running + When I start the remote debugger process + Then the remote debugger process should be running + + Scenario: Send WebPA event for IssueType and verify end-to-end processing + Given the remote debugger is running + When I trigger the event "Device.DeviceInfo.X_RDKCENTRAL-COM_RFC.Feature.RDKRemoteDebugger.IssueType" + Then the event for RRD_SET_ISSUE_EVENT should be received + And the logs should contain "SUCCESS: Message sending Done" + And the logs should be seen with "SUCCESS: Message Reception Done" + When the remotedebugger received the message from webPA event + Then remotedebugger should read the Json file + And remotedebugger logs should contain the Json File Parse success + And the issue data node and sub-node should be found in the JSON file + And the directory should be created to store the executed output + And Sanity check to validate the commands should be executed + And Command output should be added to the output file + And the issuetype systemd service should start successfully + And the journalctl service should start successfully + And the process should sleep with timeout + And the issuetype systemd service should stop successfully + And the remotedebugger should call script to upload the debug report + + Scenario: Upload remote debugger debug report + When I check the upload status in the logs + Then the upload should be successful if upload is success + Or the upload should fail if upload fails +``` + +## Integration with Gap Analysis + +After generating feature files, use them for gap analysis against the L2 test suite: + +### Step 1: Map Features to Existing Tests + +``` +features/rrd_start_subscribe_and_wait.feature ↔ tests/test_rrd_start_subscribe_and_wait.py +features/rrd_start_control.feature ↔ tests/test_rrd_start_control.py +features/rrd_single_instance.feature ↔ tests/test_rrd_single_instance.py +features/rrd_static_profile_report.feature ↔ tests/test_rrd_static_profile_report.py +features/rrd_static_profile_category_report.feature ↔ tests/test_rrd_static_profile_category_report.py +features/rrd_background_cmd_static_profile_report.feature ↔ tests/test_rrd_background_cmd_static_profile_report.py +features/rrd_dynamic_profile_report.feature ↔ tests/test_rrd_dynamic_profile_report.py +features/rrd_dynamic_profile_subcategory_report.feature ↔ tests/test_rrd_dynamic_subcategory_report.py +features/rrd_dynamic_profile_missing_report.feature ↔ tests/test_rrd_dynamic_profile_missing_report.py +features/rrd_append_report.feature ↔ tests/test_rrd_append_report.py +features/rrd_append_dynamic_profile_static_not_found.feature ↔ tests/test_rrd_append_dynamic_profile_static_notfound.py +features/rrd_harmful_command_static_report.feature ↔ tests/test_rrd_harmful_command_static_report.py +features/test_rrd_dynamic_profile_harmful_report.feature ↔ tests/test_rrd_dynamic_profile_harmful_report.py +features/rrd_corrupted_static_profile_report.feature ↔ tests/test_rrd_corrupted_static_profile_report.py +features/rrd_static_profile_missing_command_report.feature ↔ tests/test_rrd_static_profile_missing_command_report.py +features/rrd_empty_issuetype_event.feature ↔ tests/test_rrd_empty_issuetype_event.py +features/rrd_deepsleep_static_report.feature ↔ tests/test_rrd_deepsleep_static_report.py +features/rrd_debug_report_upload.feature ↔ tests/test_rrd_debug_report_upload.py +features/rrd_c_api_upload.feature ↔ tests/test_rrd_c_api_upload.py +features/test_rrd_static_profile_report_with_suffix.feature ↔ tests/test_rrd_static_profile_report_with_suffix.py +features/test_rrd_static_profile_report_with_suffix_negative_case.feature ↔ tests/test_rrd_static_profile_report_with_suffix_negative_case.py +``` + +### Step 2: Count Coverage + +For each feature file: +1. Count total scenarios (= total testable behaviors) +2. Count scenarios that have a matching `test_*` function in `test/functional-tests/tests/` +3. Calculate coverage = matched / total + +### Step 3: Identify Missing Tests + +Features without test coverage fall into categories: + +| Category | Example | Required Infrastructure | +|---|---|---| +| WebCfg event handling | WebCfgData RBUS event trigger | WebConfig mock, MsgPack payload | +| Profile data SET/GET | setProfileData / getProfileData | `rbuscli` SET/GET validation | +| Upload lock contention | Concurrent upload attempts | Lock file manipulation | +| Deep sleep edge cases | Deep sleep during active collection | IARM event simulation | +| Archive CPU throttle | CPU usage too high during archive | CPU load simulation | +| Configuration fallback | RFC → DCM → dcm.properties chain | Config file manipulation | + +### Step 4: Identify Undocumented Tests + +Tests that exist in `test/functional-tests/tests/` but have no matching scenario in the +`test/functional-tests/features/` files. These should be documented retroactively: + +- `test_rrd_profile_data.py` — Profile data SET/GET (no matching `.feature`) + +### Step 5: Generate Gap Report + +Include a summary table in `test/functional-tests/features/README.md`: + +```markdown +| Behavior Area | Feature Scenarios | L2 Tests | Coverage | Top Gaps | +|---|:---:|:---:|:---:|---| +| Daemon startup/subscribe | 3 | 3 | 100% | — | +| RFC enable/disable | 2 | 2 | 100% | — | +| Single instance | 1 | 1 | 100% | — | +| Static profile report | 5 | 5 | 100% | — | +| Static category report | 5 | 5 | 100% | — | +| Dynamic profile report | 5 | 5 | 100% | — | +| Append mode | 4 | 4 | 100% | — | +| Harmful commands | 4 | 4 | 100% | — | +| Corrupted profile | 4 | 4 | 100% | — | +| Empty issuetype | 2 | 2 | 100% | — | +| Deep sleep | 5 | 5 | 100% | — | +| Debug report upload | 7 | 7 | 100% | — | +| C API upload | 8+ | 8+ | ~100% | Error path coverage | +| WebCfg event | 0 | 0 | 0% | Entire flow | +| Profile data SET/GET | 0 | 1 | partial | No feature file | +| Upload lock contention | 0 | 0 | 0% | Concurrency tests | +``` + +## Current L2 Test Layout + +``` +test/functional-tests/ +├── features/ # BDD feature files (documentation + test specs) +│ ├── rrd_start_subscribe_and_wait.feature # RBUS subscription +│ ├── rrd_start_control.feature # RFC enable/disable +│ ├── rrd_single_instance.feature # Single instance +│ ├── rrd_static_profile_report.feature # Static profile end-to-end +│ ├── rrd_static_profile_category_report.feature +│ ├── test_rrd_static_profile_report_with_suffix.feature +│ ├── test_rrd_static_profile_report_with_suffix_negative_case.feature +│ ├── rrd_background_cmd_static_profile_report.feature +│ ├── rrd_dynamic_profile_report.feature +│ ├── rrd_dynamic_profile_subcategory_report.feature +│ ├── rrd_dynamic_profile_missing_report.feature +│ ├── rrd_append_report.feature +│ ├── rrd_append_dynamic_profile_static_not_found.feature +│ ├── rrd_harmful_command_static_report.feature +│ ├── test_rrd_dynamic_profile_harmful_report.feature +│ ├── rrd_corrupted_static_profile_report.feature +│ ├── rrd_static_profile_missing_command_report.feature +│ ├── rrd_empty_issuetype_event.feature +│ ├── rrd_deepsleep_static_report.feature +│ ├── rrd_debug_report_upload.feature +│ └── rrd_c_api_upload.feature +├── tests/ # Runnable pytest functions +│ ├── helper_functions.py # Log grep, process control, file checks, constants +│ ├── test_rrd_start_subscribe_and_wait.py +│ ├── test_rrd_start_control.py +│ ├── test_rrd_single_instance.py +│ ├── test_rrd_static_profile_report.py +│ ├── test_rrd_static_profile_category_report.py +│ ├── test_rrd_static_profile_report_with_suffix.py +│ ├── test_rrd_static_profile_report_with_suffix_negative_case.py +│ ├── test_rrd_background_cmd_static_profile_report.py +│ ├── test_rrd_dynamic_profile_report.py +│ ├── test_rrd_dynamic_subcategory_report.py +│ ├── test_rrd_dynamic_profile_missing_report.py +│ ├── test_rrd_append_report.py +│ ├── test_rrd_append_dynamic_profile_static_notfound.py +│ ├── test_rrd_harmful_command_static_report.py +│ ├── test_rrd_dynamic_profile_harmful_report.py +│ ├── test_rrd_corrupted_static_profile_report.py +│ ├── test_rrd_static_profile_missing_command_report.py +│ ├── test_rrd_empty_issuetype_event.py +│ ├── test_rrd_deepsleep_static_report.py +│ ├── test_rrd_debug_report_upload.py +│ ├── test_rrd_c_api_upload.py +│ ├── test_rrd_profile_data.py # ⚠ No matching .feature file +│ ├── create_json.sh # JSON profile creation helper +│ ├── deepsleep_main.c # Deep sleep simulation binary +│ ├── power_controller.h # Power controller mock header +│ ├── Makefile # Test build file +│ └── uploadSTBLogs.sh # Mock upload script +``` + +**Test runner:** `pytest`, executed sequentially per test file. +**Interfaces exercised:** `rbuscli` (RBUS event trigger), log scraping (`/opt/logs/remotedebugger.log.0`), file system checks (`/tmp/rrd/`, `/etc/rrd/`), mock xconf server (upload validation). + +## Maintenance + +When remote debugger source code changes: + +1. **New RBUS event/parameter added** — Add scenario to appropriate `.feature` file; update RBUS data elements table in README +2. **New profile processing mode** — Create a new `.feature` file; add to README index +3. **New upload mechanism** — Document the upload flow; add C API test scenarios if applicable +4. **Handler removed** — Remove corresponding scenario; note in gap analysis +5. **Build flag changed** — Update conditional compilation notes in README +6. **L2 test added** — Update gap analysis coverage numbers; create `.feature` file if missing +7. **New log messages added** — Update log assertion strings in relevant feature scenarios +8. **New sanity check rules** — Add harmful command detection scenarios +9. **Version tag** — Include generation date in README + +## Related Skills + +- `technical-documentation-writer` — For detailed architecture and API docs (`docs/`) +- `memory-safety-analyzer` — For safety analysis of C source code +- `thread-safety-analyzer` — For concurrency analysis of event thread and message queue +- `quality-checker` — For running static analysis and build verification +- `triage-logs` — For correlating device logs with remote debugger source code diff --git a/test/functional-tests/L2_Test_Coverage.md b/test/functional-tests/L2_Test_Coverage.md new file mode 100644 index 000000000..fcd872f15 --- /dev/null +++ b/test/functional-tests/L2_Test_Coverage.md @@ -0,0 +1,399 @@ +# Remote Debugger L2 Test Coverage Report + +**Generated:** 2026-05-19 +**Component:** `remotedebugger` (src/) +**Test Suite:** `test/functional-tests/` + +--- + +## Executive Summary + +| Metric | Count | +|---|:---:| +| Feature files | 21 | +| Feature scenarios | 90 | +| Test files (pytest) | 22 | +| Test functions (`test_*`) | 112 | +| Feature→Test mapped pairs | 21 / 21 (+ 1 orphan test) | +| Source modules (always compiled) | 9 | +| Source modules (conditional IARMBUS) | 7 | +| **Overall feature coverage** | **95%** (21/22 test files have matching features) | +| **Source behavior coverage** | **~65%** (happy paths covered; error/edge paths mostly untested) | + +--- + +## 1. Feature File ↔ Test File Mapping + +### Fully Mapped (feature + test exist) + +| # | Feature File | Scenarios | Test File | Test Functions | Status | +|:---:|---|:---:|---|:---:|:---:| +| 1 | `rrd_start_subscribe_and_wait.feature` | 1 | `test_rrd_start_subscribe_and_wait.py` | 4 | PASS | +| 2 | `rrd_start_control.feature` | 2 | `test_rrd_start_control.py` | 1 | PASS | +| 3 | `rrd_single_instance.feature` | 1 | `test_rrd_single_instance.py` | 3 | PASS | +| 4 | `rrd_static_profile_report.feature` | 5 | `test_rrd_static_profile_report.py` | 5 | PASS | +| 5 | `rrd_static_profile_category_report.feature` | 5 | `test_rrd_static_profile_category_report.py` | 5 | PASS | +| 6 | `test_rrd_static_profile_report_with_suffix.feature` | 4 | `test_rrd_static_profile_report_with_suffix.py` | 5 | PASS | +| 7 | `test_rrd_static_profile_report_with_suffix_negative_case.feature` | 4 | `test_rrd_static_profile_report_with_suffix_negative_case.py` | 5 | PASS | +| 8 | `rrd_background_cmd_static_profile_report.feature` | 5 | `test_rrd_background_cmd_static_profile_report.py` | 5 | PASS | +| 9 | `rrd_dynamic_profile_report.feature` | 5 | `test_rrd_dynamic_profile_report.py` | 9 | PASS | +| 10 | `rrd_dynamic_profile_subcategory_report.feature` | 5 | `test_rrd_dynamic_subcategory_report.py` | 7 | PASS | +| 11 | `rrd_dynamic_profile_missing_report.feature` | 4 | `test_rrd_dynamic_profile_missing_report.py` | 7 | PASS | +| 12 | `rrd_append_report.feature` | 4 | `test_rrd_append_report.py` | 7 | PASS | +| 13 | `rrd_append_dynamic_profile_static_not_found.feature` | 4 | `test_rrd_append_dynamic_profile_static_notfound.py` | 7 | PASS | +| 14 | `rrd_harmful_command_static_report.feature` | 5 | `test_rrd_harmful_command_static_report.py` | 5 | PASS | +| 15 | `test_rrd_dynamic_profile_harmful_report.feature` | 5 | `test_rrd_dynamic_profile_harmful_report.py` | 7 | PASS | +| 16 | `rrd_corrupted_static_profile_report.feature` | 4 | `test_rrd_corrupted_static_profile_report.py` | 4 | PASS | +| 17 | `rrd_static_profile_missing_command_report.feature` | 5 | `test_rrd_static_profile_missing_command_report.py` | 5 | PASS | +| 18 | `rrd_empty_issuetype_event.feature` | 2 | `test_rrd_empty_issuetype_event.py` | 2 | PASS | +| 19 | `rrd_deepsleep_static_report.feature` | 2 | `test_rrd_deepsleep_static_report.py` | 5 | PASS | +| 20 | `rrd_debug_report_upload.feature` | 6 | `test_rrd_debug_report_upload.py` | 5 | PASS | +| 21 | `rrd_c_api_upload.feature` | 21 | `test_rrd_c_api_upload.py` | 5 | GAP | +| | **Totals** | **97** | | **112** | | + +> **Note:** Scenario count for `rrd_c_api_upload.feature` (21) far exceeds its test function count (5). See Section 3 for details. + +### Orphan Tests (test exists, no matching feature file) + +| Test File | Test Functions | Description | Gap | +|---|:---:|---|---| +| `test_rrd_profile_data.py` | 3 | RBUS profile data SET/GET via `rbuscli` | **Missing `.feature` file** | + +### Orphan Features (feature exists, no matching test file) + +None — all 21 feature files have corresponding test files. + +--- + +## 2. Per-Behavior Coverage Detail + +### 2.1 Daemon Lifecycle + +| Behavior | Feature | Test | Covered | +|---|---|---|:---:| +| RBUS subscription + event wait | `rrd_start_subscribe_and_wait` | `test_rrd_start_subscribe_and_wait` | YES | +| RFC enable → daemon starts | `rrd_start_control` | `test_rrd_start_control` | YES | +| RFC disable → daemon stops | `rrd_start_control` | `test_rrd_start_control` | YES | +| Single instance enforcement | `rrd_single_instance` | `test_rrd_single_instance` | YES | +| Message queue creation failure | — | — | **NO** | +| Event thread creation failure | — | — | **NO** | +| Signal handling / graceful shutdown | — | — | **NO** | +| Device info file read failure | — | — | **NO** | + +### 2.2 Static Profile Processing + +| Behavior | Feature | Test | Covered | +|---|---|---|:---:| +| Config file exists check | `rrd_static_profile_report` | `test_rrd_static_profile_report` | YES | +| Output directory exists check | `rrd_static_profile_report` | `test_rrd_static_profile_report` | YES | +| IssueType event trigger + message flow | `rrd_static_profile_report` | `test_rrd_static_profile_report` | YES | +| JSON parse success + command execution | `rrd_static_profile_report` | `test_rrd_static_profile_report` | YES | +| Upload report success/failure | `rrd_static_profile_report` | `test_rrd_static_profile_report` | YES | +| Category-only issue type (all sub-nodes) | `rrd_static_profile_category_report` | `test_rrd_static_profile_category_report` | YES | +| Suffixed issue type | `test_rrd_static_profile_report_with_suffix` | `test_rrd_static_profile_report_with_suffix` | YES | +| Overlength suffix (negative) | `test_rrd_static_profile_report_with_suffix_negative_case` | `test_rrd_static_profile_report_with_suffix_negative_case` | YES | +| Background command execution | `rrd_background_cmd_static_profile_report` | `test_rrd_background_cmd_static_profile_report` | YES | +| Missing command in profile | `rrd_static_profile_missing_command_report` | `test_rrd_static_profile_missing_command_report` | YES | +| Corrupted/invalid JSON profile | `rrd_corrupted_static_profile_report` | `test_rrd_corrupted_static_profile_report` | YES | + +### 2.3 Dynamic Profile Processing + +| Behavior | Feature | Test | Covered | +|---|---|---|:---:| +| Dynamic profile fallback (static miss) | `rrd_dynamic_profile_report` | `test_rrd_dynamic_profile_report` | YES | +| Dynamic subcategory | `rrd_dynamic_profile_subcategory_report` | `test_rrd_dynamic_subcategory_report` | YES | +| Dynamic profile missing → RDM trigger | `rrd_dynamic_profile_missing_report` | `test_rrd_dynamic_profile_missing_report` | YES | +| Append mode (static + dynamic) | `rrd_append_report` | `test_rrd_append_report` | YES | +| Append when static not found | `rrd_append_dynamic_profile_static_not_found` | `test_rrd_append_dynamic_profile_static_notfound` | YES | +| RDM download event (cache miss) | — | — | **NO** | +| Dynamic profile JSON parse failure | — | — | **NO** | + +### 2.4 Harmful Command Detection + +| Behavior | Feature | Test | Covered | +|---|---|---|:---:| +| Static profile harmful command abort | `rrd_harmful_command_static_report` | `test_rrd_harmful_command_static_report` | YES | +| Dynamic profile harmful command abort | `test_rrd_dynamic_profile_harmful_report` | `test_rrd_dynamic_profile_harmful_report` | YES | +| Macro replacement edge cases | — | — | **NO** | +| Background command modification | — | — | **PARTIAL** (via background cmd test) | + +### 2.5 Event Handling + +| Behavior | Feature | Test | Covered | +|---|---|---|:---:| +| IssueType RBUS event | Multiple features | Multiple tests | YES | +| Empty IssueType event | `rrd_empty_issuetype_event` | `test_rrd_empty_issuetype_event` | YES | +| Deep sleep event | `rrd_deepsleep_static_report` | `test_rrd_deepsleep_static_report` | YES | +| WebCfg event (MsgPack decode) | — | — | **NO** | +| WebCfg corrupted data | — | — | **NO** | +| Multiple simultaneous IssueType events | — | — | **NO** | +| Invalid deep sleep event type | — | — | **NO** | + +### 2.6 Upload & Archive + +| Behavior | Feature | Test | Covered | +|---|---|---|:---:| +| Upload via shell script | `rrd_debug_report_upload` | `test_rrd_debug_report_upload` | YES | +| Upload + download validation | `rrd_debug_report_upload` | `test_rrd_debug_report_upload` | YES | +| C API `rrd_upload_orchestrate` (happy path) | `rrd_c_api_upload` | `test_rrd_c_api_upload` | YES | +| C API NULL parameters | `rrd_c_api_upload` | — | **GAP** | +| C API empty directory | `rrd_c_api_upload` | — | **GAP** | +| C API non-existent directory | `rrd_c_api_upload` | — | **GAP** | +| C API config loading validation | `rrd_c_api_upload` | — | **GAP** | +| C API MAC retrieval | `rrd_c_api_upload` | — | **GAP** | +| C API timestamp generation | `rrd_c_api_upload` | — | **GAP** | +| C API issue type sanitization | `rrd_c_api_upload` | — | **GAP** | +| C API archive creation | `rrd_c_api_upload` | — | **GAP** | +| C API upload execution | `rrd_c_api_upload` | — | **GAP** | +| C API cleanup after success/failure | `rrd_c_api_upload` | — | **GAP** | +| C API concurrent upload lock | `rrd_c_api_upload` | — | **GAP** | +| C API LOGUPLOAD_ENABLE | `rrd_c_api_upload` | — | **GAP** | +| C API end-to-end with RFC trigger | `rrd_c_api_upload` | — | **GAP** | +| C API error propagation | `rrd_c_api_upload` | — | **GAP** | +| Upload lock file contention | — | — | **NO** | +| Archive CPU throttle logic | — | — | **NO** | + +### 2.7 Profile Data SET/GET (RBUS) + +| Behavior | Feature | Test | Covered | +|---|---|---|:---:| +| `setProfileData` / `getProfileData` | — | `test_rrd_profile_data` | **PARTIAL** (no feature) | +| Profile category load error | — | — | **NO** | +| Profile file write error | — | — | **NO** | + +--- + +## 3. Feature ↔ Test Gap Analysis + +### 3.1 `rrd_c_api_upload.feature` — Major Scenario-to-Test Gap + +The feature file documents **21 scenarios** covering the full `rrd_upload_orchestrate` C API, but the test file `test_rrd_c_api_upload.py` only implements **5 test functions** that cover the basic end-to-end flow (config check, dir check, start, trigger event, upload report). + +**Missing test implementations for feature scenarios:** + +| Feature Scenario | Test Status | +|---|---| +| Validate rrd_upload_orchestrate C API with valid parameters | Covered (within `test_remote_debugger_trigger_event`) | +| Test rrd_upload_orchestrate with NULL upload directory | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate with NULL issue type | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate with empty upload directory | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate with non-existent directory | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate configuration loading | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate MAC address retrieval | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate timestamp generation | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate issue type sanitization | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate archive creation | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate upload execution | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate cleanup after success | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate cleanup after upload failure | **NOT IMPLEMENTED** | +| Test uploadDebugoutput wrapper function | **NOT IMPLEMENTED** | +| Test concurrent upload lock handling | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate with LOGUPLOAD_ENABLE issue type | **NOT IMPLEMENTED** | +| Test remote debugger end-to-end with RFC trigger | Covered | +| Test upload report validation with success path | Covered (within `test_remotedebugger_upload_report`) | +| Test upload report validation with failure path | Covered (within `test_remotedebugger_upload_report`) | +| Test upload report with legacy log compatibility | **NOT IMPLEMENTED** | +| Test rrd_upload_orchestrate error propagation | **NOT IMPLEMENTED** | + +**Gap: 16 of 21 scenarios have no dedicated test implementation.** + +### 3.2 `test_rrd_profile_data.py` — Orphan Test (No Feature File) + +This test file contains 3 test functions exercising `rbuscli set/get` on profile data RBUS elements (`setProfileData` / `getProfileData`). No corresponding `.feature` file exists. + +**Recommendation:** Create `rrd_profile_data.feature` to document this behavior. + +### 3.3 Scenario Count vs Test Count Discrepancy + +Some test files implement more test functions than their feature has scenarios, due to setup/teardown and prerequisite tests being split more granularly: + +| Feature File | Scenarios | Test File | Tests | Delta | +|---|:---:|---|:---:|:---:| +| `rrd_start_subscribe_and_wait` | 1 | `test_rrd_start_subscribe_and_wait` | 4 | +3 | +| `rrd_single_instance` | 1 | `test_rrd_single_instance` | 3 | +2 | +| `rrd_dynamic_profile_report` | 5 | `test_rrd_dynamic_profile_report` | 9 | +4 | +| `rrd_dynamic_profile_missing_report` | 4 | `test_rrd_dynamic_profile_missing_report` | 7 | +3 | +| `rrd_append_report` | 4 | `test_rrd_append_report` | 7 | +3 | +| `rrd_append_dynamic_profile_static_not_found` | 4 | `test_rrd_append_dynamic_profile_static_notfound` | 7 | +3 | +| `rrd_dynamic_profile_harmful_report` | 5 | `test_rrd_dynamic_profile_harmful_report` | 7 | +2 | +| `rrd_deepsleep_static_report` | 2 | `test_rrd_deepsleep_static_report` | 5 | +3 | +| `rrd_c_api_upload` | 21 | `test_rrd_c_api_upload` | 5 | **-16** | + +The **only deficit** is `rrd_c_api_upload` where the feature documents far more scenarios than tests implement. + +--- + +## 4. Source Module Coverage Analysis + +### 4.1 Module-Level Coverage Summary + +| Source Module | Happy Path | Error Paths | L2 Coverage | +|---|:---:|:---:|---| +| `rrdMain.c` | YES | NO | Startup, RFC check, event thread — tested. Msgqueue/thread failures — not tested. | +| `rrdInterface.c` | YES | NO | RBUS registration, event handlers — tested. Registration failures, file I/O errors — not tested. | +| `rrdEventProcess.c` | YES | PARTIAL | Static/dynamic/append/deepsleep — tested. WebCfg event, malloc failures — not tested. | +| `rrdJsonParser.c` | YES | PARTIAL | Valid/corrupted/missing JSON — tested. Dir creation failures, malloc failures — not tested. | +| `rrdRunCmdThread.c` | YES | NO | Command execution, output files — tested. File write errors, systemd-run failures — not tested. | +| `rrdCommandSanity.c` | YES | NO | Harmful command detection — tested. Macro replacement errors — not tested. | +| `rrdDynamic.c` | YES | NO | Dynamic profile, deep sleep — tested. RBUS set failure, invalid event type — not tested. | +| `rrdExecuteScript.c` | YES | NO | Upload orchestration — tested. Script exec failure, API failure — not tested. | +| `rrdMsgPackDecoder.c` | NO | NO | **Entirely untested** — WebCfg MsgPack decode not exercised by any L2 test. | +| `rrd_config.c` | INDIRECT | NO | Indirectly tested via daemon startup. Config parse errors, RFC query failures — not tested. | +| `rrd_sysinfo.c` | INDIRECT | NO | Indirectly tested via upload flow. MAC/timestamp retrieval errors — not tested. | +| `rrd_logproc.c` | INDIRECT | NO | Indirectly tested via upload flow. Log dir validation errors — not tested. | +| `rrd_archive.c` | INDIRECT | NO | Indirectly tested via upload flow. CPU throttle, archive errors — not tested. | +| `rrd_upload.c` | INDIRECT | NO | Indirectly tested via upload flow. Lock errors, cleanup failures — not tested. | +| `rrdIarmEvents.c` | PARTIAL | NO | Deep sleep event — tested. Other IARM events — not tested. | +| `uploadRRDLogs.c` | INDIRECT | NO | Entry point tested via daemon trigger. Direct API error paths — not tested. | + +### 4.2 Completely Untested Source Behaviors + +| Priority | Behavior | Source Module | Required Infrastructure | +|:---:|---|---|---| +| **P1** | WebCfg event (MsgPack decode + dispatch) | `rrdMsgPackDecoder.c`, `rrdEventProcess.c` | WebConfig mock, base64-encoded MsgPack payload | +| **P1** | C API upload error paths (NULL params, empty dir, non-existent dir) | `rrd_upload.c` | Direct C API invocation or test binary | +| **P1** | Profile data SET/GET feature documentation | `rrdInterface.c` | Feature file creation only | +| **P2** | Concurrent upload lock contention | `rrd_upload.c` | Parallel upload trigger + lock file manipulation | +| **P2** | Archive CPU usage throttle | `rrd_archive.c` | CPU load simulation | +| **P2** | Configuration fallback chain (RFC → DCM → dcm.properties) | `rrd_config.c` | Config file manipulation | +| **P2** | RDM download event with cache miss | `rrdInterface.c`, `rrdDynamic.c` | RDM mock, empty cache | +| **P3** | RBUS registration/unregistration failures | `rrdInterface.c` | RBUS mock failure injection | +| **P3** | Message queue creation failure | `rrdMain.c` | System resource exhaustion mock | +| **P3** | Event thread creation failure | `rrdMain.c` | Thread creation failure mock | +| **P3** | Directory creation/chdir failures | `rrdJsonParser.c`, `rrdRunCmdThread.c` | Filesystem permission mock | +| **P3** | systemd-run / journalctl execution failures | `rrdRunCmdThread.c` | Binary removal or mock failure | +| **P3** | Output file write errors | `rrdRunCmdThread.c` | Filesystem full or permission mock | +| **P3** | Dynamic profile JSON parse failure | `rrdDynamic.c` | Corrupted dynamic JSON file | +| **P3** | Invalid deep sleep event type | `rrdDynamic.c` | IARM event simulation with bad type | +| **P3** | Memory allocation failures (all modules) | All `.c` files | malloc failure injection (not practical in L2) | + +--- + +## 5. Gap Summary + +### 5.1 Feature vs Test Gap Table + +| Behavior Area | Feature Scenarios | Test Functions | Coverage | Top Gaps | +|---|:---:|:---:|:---:|---| +| Daemon startup/subscribe | 1 | 4 | 100% | — | +| RFC enable/disable | 2 | 1 | 100% | — | +| Single instance | 1 | 3 | 100% | — | +| Static profile report | 5 | 5 | 100% | — | +| Static category report | 5 | 5 | 100% | — | +| Static suffix report | 4 | 5 | 100% | — | +| Static suffix negative | 4 | 5 | 100% | — | +| Background command | 5 | 5 | 100% | — | +| Dynamic profile report | 5 | 9 | 100% | — | +| Dynamic subcategory | 5 | 7 | 100% | — | +| Dynamic missing | 4 | 7 | 100% | — | +| Append mode | 4 | 7 | 100% | — | +| Append (static not found) | 4 | 7 | 100% | — | +| Harmful static | 5 | 5 | 100% | — | +| Harmful dynamic | 5 | 7 | 100% | — | +| Corrupted profile | 4 | 4 | 100% | — | +| Missing command | 5 | 5 | 100% | — | +| Empty issuetype | 2 | 2 | 100% | — | +| Deep sleep | 2 | 5 | 100% | — | +| Debug report upload | 6 | 5 | 100% | — | +| **C API upload** | **21** | **5** | **~24%** | **16 scenarios not implemented** | +| **Profile data SET/GET** | **0** | **3** | **N/A** | **No feature file** | +| **WebCfg event** | **0** | **0** | **0%** | **Entire flow untested** | +| **Upload lock contention** | **0** | **0** | **0%** | **No test** | +| **Config fallback chain** | **0** | **0** | **0%** | **No test** | + +### 5.2 Action Items (Prioritized) + +| # | Priority | Action | Effort | +|:---:|:---:|---|:---:| +| 1 | P1 | Implement 16 missing `test_rrd_c_api_upload.py` test functions matching feature scenarios | High | +| 2 | P1 | Create `rrd_profile_data.feature` for the existing `test_rrd_profile_data.py` test | Low | +| 3 | P1 | Add WebCfg event L2 test (`test_rrd_webcfg_event.py` + `rrd_webcfg_event.feature`) | High | +| 4 | P2 | Add upload lock contention test | Medium | +| 5 | P2 | Add configuration fallback chain test | Medium | +| 6 | P2 | Add archive CPU throttle test | Medium | +| 7 | P2 | Add dynamic profile JSON parse failure test | Low | +| 8 | P3 | Add RBUS registration failure test | Low | +| 9 | P3 | Add systemd-run / journalctl failure test | Low | +| 10 | P3 | Add output file write error test | Low | + +--- + +## 6. Test Infrastructure Notes + +### Test Interfaces + +| Interface | Tool | Used By | +|---|---|---| +| RBUS event trigger | `rbuscli set` | All event-based tests | +| RBUS profile data | `rbuscli set/get` | `test_rrd_profile_data.py` | +| Log scraping | `grep_rrdlogs()` in `helper_functions.py` | All tests | +| File system checks | `os.path.isfile()`, `os.path.isdir()` | Prerequisite tests | +| Process control | `pidof`, `kill -9`, `nohup` | Setup/teardown | +| Mock upload server | Mock xconf server | `test_rrd_debug_report_upload.py` | +| Mock upload script | `uploadSTBLogs.sh` | Upload tests | + +### Test Execution + +- **Runner:** `pytest`, sequential per file +- **No ordering decorators:** Tests rely on file-level sequential execution order +- **Shared state:** Tests within a file depend on prior test side effects (daemon start → trigger → validate) +- **Cleanup:** Most files kill the daemon and remove logs in setup + +--- + +## 7. Appendix: Complete File Inventory + +### Feature Files (21) + +| # | File | Scenarios | +|:---:|---|:---:| +| 1 | `rrd_start_subscribe_and_wait.feature` | 1 | +| 2 | `rrd_start_control.feature` | 2 | +| 3 | `rrd_single_instance.feature` | 1 | +| 4 | `rrd_static_profile_report.feature` | 5 | +| 5 | `rrd_static_profile_category_report.feature` | 5 | +| 6 | `test_rrd_static_profile_report_with_suffix.feature` | 4 | +| 7 | `test_rrd_static_profile_report_with_suffix_negative_case.feature` | 4 | +| 8 | `rrd_background_cmd_static_profile_report.feature` | 5 | +| 9 | `rrd_dynamic_profile_report.feature` | 5 | +| 10 | `rrd_dynamic_profile_subcategory_report.feature` | 5 | +| 11 | `rrd_dynamic_profile_missing_report.feature` | 4 | +| 12 | `rrd_append_report.feature` | 4 | +| 13 | `rrd_append_dynamic_profile_static_not_found.feature` | 4 | +| 14 | `rrd_harmful_command_static_report.feature` | 5 | +| 15 | `test_rrd_dynamic_profile_harmful_report.feature` | 5 | +| 16 | `rrd_corrupted_static_profile_report.feature` | 4 | +| 17 | `rrd_static_profile_missing_command_report.feature` | 5 | +| 18 | `rrd_empty_issuetype_event.feature` | 2 | +| 19 | `rrd_deepsleep_static_report.feature` | 2 | +| 20 | `rrd_debug_report_upload.feature` | 6 | +| 21 | `rrd_c_api_upload.feature` | 21 | +| | **Total** | **97** | + +### Test Files (22) + +| # | File | Test Functions | +|:---:|---|:---:| +| 1 | `test_rrd_start_subscribe_and_wait.py` | 4 | +| 2 | `test_rrd_start_control.py` | 1 | +| 3 | `test_rrd_single_instance.py` | 3 | +| 4 | `test_rrd_static_profile_report.py` | 5 | +| 5 | `test_rrd_static_profile_category_report.py` | 5 | +| 6 | `test_rrd_static_profile_report_with_suffix.py` | 5 | +| 7 | `test_rrd_static_profile_report_with_suffix_negative_case.py` | 5 | +| 8 | `test_rrd_background_cmd_static_profile_report.py` | 5 | +| 9 | `test_rrd_dynamic_profile_report.py` | 9 | +| 10 | `test_rrd_dynamic_subcategory_report.py` | 7 | +| 11 | `test_rrd_dynamic_profile_missing_report.py` | 7 | +| 12 | `test_rrd_append_report.py` | 7 | +| 13 | `test_rrd_append_dynamic_profile_static_notfound.py` | 7 | +| 14 | `test_rrd_harmful_command_static_report.py` | 5 | +| 15 | `test_rrd_dynamic_profile_harmful_report.py` | 7 | +| 16 | `test_rrd_corrupted_static_profile_report.py` | 4 | +| 17 | `test_rrd_static_profile_missing_command_report.py` | 5 | +| 18 | `test_rrd_empty_issuetype_event.py` | 2 | +| 19 | `test_rrd_deepsleep_static_report.py` | 5 | +| 20 | `test_rrd_debug_report_upload.py` | 5 | +| 21 | `test_rrd_c_api_upload.py` | 5 | +| 22 | `test_rrd_profile_data.py` | 3 | +| | **Total** | **112** |