Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b4c5291
feature/RDKEMW-9479
hgfell683 Oct 27, 2025
c2b4057
feature/RDKEMW-9479
hgfell683 Oct 27, 2025
970dd77
feature/RDKEMW-9479
hgfell683 Oct 27, 2025
37f7d3d
feature/RDKEMW-9479
hgfell683 Oct 27, 2025
228cdd8
feature/RDKEMW-9479
hgfell683 Oct 27, 2025
36fe33e
feature/RDKEMW-9479
hgfell683 Oct 27, 2025
36441b6
feature/RDKEMW-9479
hgfell683 Oct 27, 2025
a185648
feature/RDKEMW-9479
hgfell683 Oct 27, 2025
638681e
feature/RDKEMW-9479
hgfell683 Oct 28, 2025
235968e
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
6f9f4fe
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
a9b0b14
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
b2b5109
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
9fef330
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
0286df1
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
3252792
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
b68d7dc
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
a0af12c
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
df6022e
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
44f4458
feature/RDKEMW-9479
hgfell683 Oct 30, 2025
fad7142
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
509e209
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
a83a70f
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
efe0347
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
e8298ab
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
4935930
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
f33073f
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
1e1b8eb
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
d2bf770
feature/RDKEMW-9479
hgfell683 Oct 31, 2025
d04feb9
feature/RDKEMW-9479
hgfell683 Nov 4, 2025
43e1b7a
feature/RDKEMW-9479
hgfell683 Nov 5, 2025
e4525c2
feature/RDKEMW-9479
hgfell683 Nov 5, 2025
77c4a57
feature/RDKEMW-9479
hgfell683 Nov 6, 2025
fb792bf
feature/RDKEMW-9479
hgfell683 Nov 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
271 changes: 271 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
# WPEFramework Plugin L2 Integration Tes - Use EXPECT_CALL for mocks with ::testing::_ for arguments unless a specific value is required for the test logic.
- Use only error codes defined in the implementation (e.g., Core::ERROR_NONE, Core::ERROR_GENERAL, Core::ERROR_INVALID_PARAMETER). Do not invent error codes.
- Ensure mock objects are properly initialized and cleaned up in the test fixture setup and teardown.
- Use EXPECT_TRUE, EXPECT_FALSE, and EXPECT_EQ to check returned, updated, or tested event values using the test fixture's initialization, notification flags, handlers, and helper methods.
- Test both successful integration scenarios and failure/error conditions in multi-plugin environments- Use real Thunder framework RPC stack for communication testing - Every test must verify end-to-end integration behavior, state changes across plugins, and event propagationing Guide

### L2 Testing Objectives

For specified APIs, ensure the generated L2 tests meet the following criteria:
- **Integration Testing**: Test complete plugin lifecycle and inter-component communication in realistic environments
- **Cross-Plugin Communication**: Validate interactions between multiple plugins and services
- **Asynchronous Event Testing**: Test notification systems, event propagation, and timing between plugins
- **Real System Integration**: Use actual plugin instances and system APIs rather than mocks

## Testing
When generating L2 tests, please follow the below step-by-step approach:

1. **Checking for Adequate Context and Information**
- Ensure that the test fixture, interface API header file, plugin implementation files, and related plugin dependencies are attached by the user for your reference.
- Verify understanding of cross-plugin communication patterns and dependencies.

2. **Understanding the Plugin Integration**
- For each API/method, step through the complete integration flow:
- Map all plugin dependencies and inter-plugin communication paths
- Identify Thunder framework integration points (JSON-RPC and COM-RPC)
- Document asynchronous event flows and notification systems
- Note real system resources, IARM bus communications, and hardware interactions
- Before creating the tests, fully understand the complete plugin lifecycle and cross-plugin event propagation.

3. **Test Coverage**
- For every cross-plugin interaction and integration scenario specified by the user, generate comprehensive test cases
- Test both JSON-RPC and COM-RPC communication protocols to ensure identical behavior
- Include full plugin activation, configuration, and cleanup testing
- Test asynchronous event handling with proper timing and condition variable usage
- Validate real system integration points and hardware abstraction layer interactions
- Do not summarize, skip, or instruct the user to extrapolate patterns. Every specified integration scenario must be tested explicitly.

4. **Test Design**
- Test complete plugin integration rather than isolated functionality
- Use actual plugin instances instead of mocks for realistic testing
- Implement asynchronous event testing with WaitForRequestStatus and condition variables
- Test cross-plugin communication scenarios (e.g., UserPreferences ↔ UserSettings, SystemMode ↔ DisplaySettings)
- Use GTest syntax for test structure
- Write all tests as modifications to the existing test fixture file
- Use EXPECT_CALL for mocks with ::testing::_ for arguments unless a specific value is required for the test logic.
- Use only error codes defined in the implementation (e.g., Core::ERROR_NONE, Core::ERROR_GENERAL, Core::ERROR_INVALID_PARAMETER). Do not invent error codes.
- Ensure tests activate multiple services when testing plugin interactions
- Use actual IARM bus communication and device settings APIs where applicable
- Use EXPECT_TRUE, EXPECT_FALSE, and EXPECT_EQ to check returned, updated, or tested event values using the test fixture’s initialization, notification flags, handlers, and helper methods.

5. **Format**
- Output only code, as if modifying the existing test fixture file
- Do not include explanations, summaries, or instructions
- Do not include comments like "repeat for other integrations" or "similarly for X"
- Do not include any code that is not a test for a specific integration scenario

## Testing Example
Here are examples from the PowerManager L2 integration tests showing proper L2 test structure:

**L2 Test Class Structure with Notification Handling:**
```cpp
class PowerManager_L2Test : public L2TestMocks {
public:
PowerManager_L2Test();
virtual ~PowerManager_L2Test() override;

void OnPowerModeChanged(const PowerState currentState, const PowerState newState);
void OnPowerModePreChange(const PowerState currentState, const PowerState newState, const int trxnId, const int stateChangeAfter);
void OnThermalModeChanged(const ThermalTemperature currentThermalLevel, const ThermalTemperature newThermalLevel, const float currentTemperature);

uint32_t WaitForRequestStatus(uint32_t timeout_ms, PowerManagerL2test_async_events_t expected_status);

Core::Sink<PwrMgr_Notification> mNotification;

private:
std::mutex m_mutex;
std::condition_variable m_condition_variable;
uint32_t m_event_signalled;
};
```

**Notification Interface Implementation:**
```cpp
class PwrMgr_Notification : public Exchange::IPowerManager::IRebootNotification,
public Exchange::IPowerManager::IModeChangedNotification,
public Exchange::IPowerManager::IThermalModeChangedNotification {
BEGIN_INTERFACE_MAP(PwrMgr_Notification)
INTERFACE_ENTRY(Exchange::IPowerManager::IRebootNotification)
INTERFACE_ENTRY(Exchange::IPowerManager::IModeChangedNotification)
INTERFACE_ENTRY(Exchange::IPowerManager::IThermalModeChangedNotification)
END_INTERFACE_MAP

public:
void OnPowerModeChanged(const PowerState currentState, const PowerState newState) override {
std::unique_lock<std::mutex> lock(m_mutex);
m_event_signalled |= POWERMANAGERL2TEST_SYSTEMSTATE_CHANGED;
m_condition_variable.notify_one();
}

uint32_t WaitForRequestStatus(uint32_t timeout_ms, PowerManagerL2test_async_events_t expected_status) {
std::unique_lock<std::mutex> lock(m_mutex);
auto now = std::chrono::system_clock::now();
std::chrono::milliseconds timeout(timeout_ms);

while (!(expected_status & m_event_signalled)) {
if (m_condition_variable.wait_until(lock, now + timeout) == std::cv_status::timeout) {
return POWERMANAGERL2TEST_STATE_INVALID;
}
}

uint32_t signalled = m_event_signalled;
m_event_signalled = POWERMANAGERL2TEST_STATE_INVALID;
return signalled;
}
};
```

**Constructor with Plugin Activation and Mock Setup:**
```cpp
PowerManager_L2Test::PowerManager_L2Test() : L2TestMocks() {
m_event_signalled = POWERMANAGERL2TEST_STATE_INVALID;

EXPECT_CALL(POWERMANAGER_MOCK, PLAT_DS_INIT())
.WillOnce(::testing::Return(DEEPSLEEPMGR_SUCCESS));

EXPECT_CALL(POWERMANAGER_MOCK, PLAT_INIT())
.WillRepeatedly(::testing::Return(PWRMGR_SUCCESS));

EXPECT_CALL(*p_mfrMock, mfrSetTempThresholds(::testing::_, ::testing::_))
.WillOnce(::testing::Invoke([](int high, int critical) {
EXPECT_EQ(high, 100);
EXPECT_EQ(critical, 110);
return mfrERR_NONE;
}));

// Activate the actual plugin service
uint32_t status = ActivateService("org.rdk.PowerManager");
EXPECT_EQ(Core::ERROR_NONE, status);
}
```

**Destructor with Plugin Cleanup:**
```cpp
PowerManager_L2Test::~PowerManager_L2Test() {
EXPECT_CALL(POWERMANAGER_MOCK, PLAT_TERM())
.WillOnce(::testing::Return(PWRMGR_SUCCESS));

EXPECT_CALL(POWERMANAGER_MOCK, PLAT_DS_TERM())
.WillOnce(::testing::Return(DEEPSLEEPMGR_SUCCESS));

uint32_t status = DeactivateService("org.rdk.PowerManager");
EXPECT_EQ(Core::ERROR_NONE, status);
}
```

**COM-RPC Integration Test with Real Plugin Communication:**
```cpp
TEST_F(PowerManager_L2Test, PowerManagerComRpc) {
Core::ProxyType<RPC::InvokeServerType<1, 0, 4>> mEngine_PowerManager;
Core::ProxyType<RPC::CommunicatorClient> mClient_PowerManager;
PluginHost::IShell *mController_PowerManager;

mEngine_PowerManager = Core::ProxyType<RPC::InvokeServerType<1, 0, 4>>::Create();
mClient_PowerManager = Core::ProxyType<RPC::CommunicatorClient>::Create(
Core::NodeId("/tmp/communicator"),
Core::ProxyType<Core::IIPCServer>(mEngine_PowerManager));

mEngine_PowerManager->Announcements(mClient_PowerManager->Announcement());

if (mClient_PowerManager.IsValid()) {
mController_PowerManager = mClient_PowerManager->Open<PluginHost::IShell>("org.rdk.PowerManager");

if (mController_PowerManager) {
Exchange::IPowerManager* PowerManagerPlugin = mController_PowerManager->QueryInterface<Exchange::IPowerManager>();

if (PowerManagerPlugin) {
PowerManagerPlugin->Register(&mNotification);

Test_PowerStateChange(PowerManagerPlugin);
Test_TemperatureThresholds(PowerManagerPlugin);
Test_WakeupSrcConfig(PowerManagerPlugin);
Test_NetworkStandbyMode(PowerManagerPlugin);

PowerManagerPlugin->Unregister(&mNotification);
PowerManagerPlugin->Release();
}
mController_PowerManager->Release();
}
mClient_PowerManager.Release();
}
}
```

**Asynchronous Event Testing with State Verification:**
```cpp
void PowerManager_L2Test::Test_PowerStateChange(Exchange::IPowerManager* PowerManagerPlugin) {
uint32_t status = Core::ERROR_GENERAL;
uint32_t signalled = POWERMANAGERL2TEST_STATE_INVALID;

PowerState currentState = PowerState::POWER_STATE_STANDBY;
const string standbyReason = "";
int keyCode = KED_FP_POWER;

// Set power state and wait for notification
status = PowerManagerPlugin->SetPowerState(keyCode, currentState, standbyReason);
EXPECT_EQ(status, Core::ERROR_NONE);

// Wait for asynchronous event notification
signalled = mNotification.WaitForRequestStatus(JSON_TIMEOUT, POWERMANAGERL2TEST_SYSTEMSTATE_CHANGED);
EXPECT_TRUE(signalled & POWERMANAGERL2TEST_SYSTEMSTATE_CHANGED);

// Verify state change through plugin interface
PowerState currentState1 = PowerState::POWER_STATE_UNKNOWN;
PowerState prevState1 = PowerState::POWER_STATE_UNKNOWN;

status = PowerManagerPlugin->GetPowerState(currentState1, prevState1);
EXPECT_EQ(currentState1, currentState);
EXPECT_EQ(status, Core::ERROR_NONE);
}
```

**JSON-RPC Integration Test:**
```cpp
TEST_F(PowerManager_L2Test, JsonRpcWakeupSourceChange) {
uint32_t status = Core::ERROR_GENERAL;
JsonObject params;
JsonObject result;
JsonArray configs;

JsonObject source;
source["wakeupSource"] = "WIFI";
source["enabled"] = true;
configs.Add(source);

params["wakeupSources"] = configs;

EXPECT_CALL(POWERMANAGER_MOCK, PLAT_API_SetWakeupSrc(::testing::_, ::testing::_))
.WillOnce(::testing::Invoke([](PWRMGR_WakeupSrcType_t wakeupSrc, bool enabled) {
EXPECT_EQ(wakeupSrc, PWRMGR_WAKEUPSRC_WIFI);
EXPECT_EQ(enabled, true);
return PWRMGR_SUCCESS;
}));

status = InvokeServiceMethod("org.rdk.PowerManager.1.", "setWakeupSourceConfig", params, result);
EXPECT_EQ(status, Core::ERROR_NONE);
}
```

**Cross-Plugin Integration Test with Multiple Services:**
```cpp
void PowerManager_L2Test::Test_NetworkStandbyMode(Exchange::IPowerManager* PowerManagerPlugin) {
uint32_t status = Core::ERROR_GENERAL;
uint32_t signalled = POWERMANAGERL2TEST_STATE_INVALID;
bool standbyMode = true;

// Test setting network standby mode
status = PowerManagerPlugin->SetNetworkStandbyMode(standbyMode);
EXPECT_EQ(status, Core::ERROR_NONE);

// Wait for notification event
signalled = mNotification.WaitForRequestStatus(JSON_TIMEOUT, POWERMANAGERL2TEST_NETWORK_STANDBYMODECHANGED);
EXPECT_TRUE(signalled & POWERMANAGERL2TEST_NETWORK_STANDBYMODECHANGED);

// Verify state persistence
bool standbyMode1;
status = PowerManagerPlugin->GetNetworkStandbyMode(standbyMode1);
EXPECT_EQ(standbyMode, standbyMode1);
EXPECT_EQ(status, Core::ERROR_NONE);
}
```

95 changes: 91 additions & 4 deletions .github/workflows/L2-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,19 @@ jobs:
path: entservices-peripherals
ref: develop

- name: Checkout entservices-deviceanddisplay
uses: actions/checkout@v3
with:
repository: rdkcentral/entservices-deviceanddisplay
path: entservices-deviceanddisplay
ref: develop

- name: Checkout entservices-testframework
uses: actions/checkout@v3
with:
repository: rdkcentral/entservices-testframework
path: entservices-testframework
ref: develop
ref: feature/RDKEMW-9479
token: ${{ secrets.RDKCM_RDKE }}

- name: Checkout googletest
Expand Down Expand Up @@ -309,7 +316,86 @@ jobs:
cmake --build build/mocks -j8
&&
cmake --install build/mocks

- name: Build entservices-deviceanddisplay
run: >
cmake
-S "$GITHUB_WORKSPACE/entservices-deviceanddisplay"
-B build/entservices-deviceanddisplay
-DCMAKE_TOOLCHAIN_FILE="${{ env.TOOLCHAIN_FILE }}"
-DCMAKE_INSTALL_PREFIX="$GITHUB_WORKSPACE/install/usr"
-DCMAKE_MODULE_PATH="$GITHUB_WORKSPACE/install/tools/cmake"
-DHIDE_NON_EXTERNAL_SYMBOLS=OFF
-DCMAKE_CXX_FLAGS="
-DEXCEPTIONS_ENABLE=ON
-fprofile-arcs
-ftest-coverage
-DUSE_THUNDER_R4=ON
-DTHUNDER_VERSION=4
-DTHUNDER_VERSION_MAJOR=4
-DTHUNDER_VERSION_MINOR=4
-DDEVICE_TYPE=AVOutputTV
-DPLUGIN_PERSISTENTSTORE_PATH="/tmp/secure/persistent/rdkservicestore"
-DPLUGIN_PERSISTENTSTORE_LEGACYPATH="/tmp/persistent/rdkservicestore"
-I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers
-I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/ds
-I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/iarmbus
-I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/rdk/iarmmgrs-hal
-I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices
-I $GITHUB_WORKSPACE/entservices-testframework/Tests/headers/systemservices/proc
-I $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks
-I $GITHUB_WORKSPACE/install/usr/include
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/devicesettings.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Iarm.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Rfc.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/RBus.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Udev.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/Wraps.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/maintenanceMGR.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/pkg.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/secure_wrappermock.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/wpa_ctrl_mock.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/readprocMockInterface.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/btmgr.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tr181api.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvSettings.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvError.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvSettingsExtODM.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvSettingsODM.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/tvTypes.h
-include $GITHUB_WORKSPACE/entservices-testframework/Tests/mocks/essos-resmgr.h
-Wall -Wno-unused-result -Wno-deprecated-declarations -Wno-error=format=
-Wl,-wrap,system -Wl,-wrap,popen -Wl,-wrap,syslog -Wl,-wrap,v_secure_system -Wl,-wrap,v_secure_popen -Wl,-wrap,v_secure_pclose -Wl,-wrap,unlink
-DUSE_IARMBUS
-DENABLE_ERM
-DRDK_LOG_MILESTONE
-DRDK_SERVICE_L2_TEST
-DDISABLE_SECURITY_TOKEN
-DHAS_API_POWERSTATE
-DENABLE_THERMAL_PROTECTION"
-DPLUGIN_PERSISTENTSTORE_PATH="/tmp/secure/persistent/rdkservicestore"
-DPLUGIN_PERSISTENTSTORE_LEGACYPATH="/tmp/persistent/rdkservicestore"
-DCOMCAST_CONFIG=OFF
-DCMAKE_DISABLE_FIND_PACKAGE_DS=ON
-DCMAKE_DISABLE_FIND_PACKAGE_IARMBus=ON
-DCMAKE_DISABLE_FIND_PACKAGE_Udev=ON
-DCMAKE_DISABLE_FIND_PACKAGE_RFC=ON
-DCMAKE_DISABLE_FIND_PACKAGE_RBus=ON
-DPLUGIN_SYSTEMSERVICES=OFF
-DPLUGIN_POWERMANAGER=ON
-DPLUGIN_DISPLAYSETTINGS=OFF
-DPLUGIN_USERPREFERENCES=OFF
-DPLUGIN_DEVICEDIAGNOSTICS=OFF
-DPLUGIN_WAREHOUSE=OFF
-DUSE_THUNDER_R4=ON
-DPLUGIN_L2Tests=ON
-DRDK_SERVICE_L2_TEST=ON
-DDS_FOUND=ON
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
&&
cmake --build build/entservices-deviceanddisplay -j8
&&
cmake --install build/entservices-deviceanddisplay

- name: Build entservices-peripherals
run: >
cmake
Expand Down Expand Up @@ -376,7 +462,7 @@ jobs:
-DDS_FOUND=ON
-DHAS_FRONT_PANEL=ON
-DPLUGIN_LEDCONTROL=ON
-DPLUGIN_FRONTPANEL=OFF
-DPLUGIN_FRONTPANEL=ON
-DPLUGIN_MOTION_DETECTION=ON
-DRDK_SERVICE_L2_TEST=ON
-DPLUGIN_L2Tests=ON
Expand Down Expand Up @@ -454,7 +540,8 @@ jobs:
-DDS_FOUND=ON
-DHAS_FRONT_PANEL=ON
-DPLUGIN_LEDCONTROL=ON
-DPLUGIN_FRONTPANEL=OFF
-DPLUGIN_FRONTPANEL=ON
-DPLUGIN_POWERMANAGER=ON
-DPLUGIN_MOTION_DETECTION=ON
-DRDK_SERVICE_L2_TEST=ON
-DPLUGIN_L2Tests=ON
Expand Down
Loading
Loading