diff --git a/run_l2.sh b/run_l2.sh index ad43b8da2..fb97f88c9 100644 --- a/run_l2.sh +++ b/run_l2.sh @@ -95,8 +95,18 @@ pytest --json-report --json-report-summary --json-report-file $RESULT_DIR/webpa_ pytest --json-report --json-report-summary --json-report-file $RESULT_DIR/custom.json test/functional-tests/tests/tr69hostif_custom.py pytest --json-report --json-report-summary --json-report-file $RESULT_DIR/dhcpv4.json test/functional-tests/tests/tr69hostif_dhcpv4.py pytest --json-report --json-report-summary --json-report-file $RESULT_DIR/moca.json test/functional-tests/tests/tr69hostif_moca.py + +# Start Thunder mock server for STBService tests +node test/test-artifacts/native-platform/thunder-mock-server.js & +THUNDER_MOCK_PID=$! +sleep 2 + pytest --json-report --json-report-summary --json-report-file $RESULT_DIR/stbservice_thunder.json test/functional-tests/tests/tr69hostif_stbservice_thunder.py +# Stop Thunder mock server +kill $THUNDER_MOCK_PID 2>/dev/null || true +wait $THUNDER_MOCK_PID 2>/dev/null || true + pytest --json-report --json-report-summary --json-report-file $RESULT_DIR/device_info.json test/functional-tests/tests/tr69hostif_device_info.py pytest --json-report --json-report-summary --json-report-file $RESULT_DIR/interfacestack.json test/functional-tests/tests/tr69hostif_interfacestack.py pytest --json-report --json-report-summary --json-report-file $RESULT_DIR/opsdevicemgmt_logging.json test/functional-tests/tests/tr69hostif_opsdevicemgmt_logging.py diff --git a/src/hostif/profiles/STBService/Capabilities_Thunder.cpp b/src/hostif/profiles/STBService/Capabilities_Thunder.cpp index f1fb567c6..45e64709d 100755 --- a/src/hostif/profiles/STBService/Capabilities_Thunder.cpp +++ b/src/hostif/profiles/STBService/Capabilities_Thunder.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2017 RDK Management + * 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. diff --git a/src/hostif/profiles/STBService/Components_DisplayDevice_Thunder.cpp b/src/hostif/profiles/STBService/Components_DisplayDevice_Thunder.cpp index 142436aa2..081149fad 100644 --- a/src/hostif/profiles/STBService/Components_DisplayDevice_Thunder.cpp +++ b/src/hostif/profiles/STBService/Components_DisplayDevice_Thunder.cpp @@ -92,7 +92,7 @@ void hostIf_STBServiceDisplayDevice::doUpdates(const char *baseName, updateCallb int hostIf_STBServiceDisplayDevice::getStatus(HOSTIF_MsgData_t *stMsgData, bool *pChanged) { bool connected = false; - if (!invokeThunderPluginMethodAndExtractBoolField(THUNDER_DI_CONNECTED, "{}", "isconnected", connected)) + if (!invokeThunderPluginMethodAndExtractScalarBoolResult(THUNDER_DI_CONNECTED, "{}", connected)) { RDK_LOG(RDK_LOG_WARN, LOG_TR69HOSTIF, "[%s] DisplayInfo.1.connected failed, returning Absent\n", __FUNCTION__); // On failure, default to Absent diff --git a/src/hostif/profiles/STBService/Components_VideoOutput_Thunder.cpp b/src/hostif/profiles/STBService/Components_VideoOutput_Thunder.cpp index ceb6feb8a..e9de37e2c 100644 --- a/src/hostif/profiles/STBService/Components_VideoOutput_Thunder.cpp +++ b/src/hostif/profiles/STBService/Components_VideoOutput_Thunder.cpp @@ -43,7 +43,7 @@ #define THUNDER_DS_GET_CURRENT_RESOLUTION "org.rdk.DisplaySettings.getCurrentResolution" #define THUNDER_DS_GET_DISPLAY_ASPECT_RATIO "org.rdk.DisplaySettings.getDisplayAspectRatio" #define THUNDER_DS_GET_ENABLE_VIDEO_PORT "org.rdk.DisplaySettings.getEnableVideoPort" -#define THUNDER_AVO_GET_ZOOM_MODE "org.rdk.AVOutput.getZoomMode" +#define THUNDER_DS_GET_ZOOM_SETTINGS "org.rdk.DisplaySettings.getZoomSetting" #define THUNDER_HDCP_GET_STATUS "org.rdk.HdcpProfile.getHDCPStatus" #define THUNDER_DI_CONNECTED "DisplayInfo.1.connected" @@ -193,7 +193,7 @@ int hostIf_STBServiceVideoOutput::getStatus(HOSTIF_MsgData_t *stMsgData, bool *p { bool isConnected = false; - if (!invokeThunderPluginMethodAndExtractBoolField(THUNDER_DI_CONNECTED, "{}", "isconnected", isConnected)) + if (!invokeThunderPluginMethodAndExtractScalarBoolResult(THUNDER_DI_CONNECTED, "{}", isConnected)) { RDK_LOG(RDK_LOG_WARN, LOG_TR69HOSTIF, "[%s] DisplayInfo.1.connected failed, returning Disabled\n", __FUNCTION__); // On failure, default to Disabled @@ -273,7 +273,7 @@ int hostIf_STBServiceVideoOutput::getVideoFormat(HOSTIF_MsgData_t *stMsgData, bo int hostIf_STBServiceVideoOutput::getAspectRatioBehaviour(HOSTIF_MsgData_t *stMsgData, bool *pChanged) { std::string mode; - if (!invokeThunderPluginMethodAndExtractStringField(THUNDER_AVO_GET_ZOOM_MODE, "{}", "zoomSetting", mode)) + if (!invokeThunderPluginMethodAndExtractStringField(THUNDER_DS_GET_ZOOM_SETTINGS, "{}", "zoomSetting", mode)) mode = "None"; strncpy(stMsgData->paramValue, mode.c_str(), PARAM_LEN); stMsgData->paramValue[PARAM_LEN - 1] = '\0'; diff --git a/src/hostif/profiles/STBService/gtest/gtest_stbservice_thunder.cpp b/src/hostif/profiles/STBService/gtest/gtest_stbservice_thunder.cpp index 33d88e6e2..ec5467f98 100644 --- a/src/hostif/profiles/STBService/gtest/gtest_stbservice_thunder.cpp +++ b/src/hostif/profiles/STBService/gtest/gtest_stbservice_thunder.cpp @@ -80,7 +80,7 @@ namespace ThunderStub { #define THUNDER_DS_GET_CURRENT_RESOLUTION "org.rdk.DisplaySettings.getCurrentResolution" #define THUNDER_DS_GET_ENABLE_VIDEO_PORT "org.rdk.DisplaySettings.getEnableVideoPort" -#define THUNDER_AVO_GET_ZOOM_MODE "org.rdk.AVOutput.getZoomMode" +#define THUNDER_DS_GET_ZOOM_SETTINGS "org.rdk.DisplaySettings.getZoomSetting" #define THUNDER_HDCP_GET_STATUS "org.rdk.HdcpProfile.getHDCPStatus" #define THUNDER_DI_FRAMERATE "DisplayInfo.1.framerate" @@ -1270,7 +1270,7 @@ TEST_F(VideoOutputThunderTest, GetVideoFormat_ThunderFailure_FallsBackToUnknown) /* getAspectRatioBehaviour: Thunder returns zoom mode */ TEST_F(VideoOutputThunderTest, GetAspectRatioBehaviour_Success) { - ThunderStub::setString(THUNDER_AVO_GET_ZOOM_MODE, true, "FULL"); + ThunderStub::setString(THUNDER_DS_GET_ZOOM_SETTINGS, true, "FULL"); HOSTIF_MsgData_t msg = makeMsg(); int rc = m_iface->handleGetMsg("AspectRatioBehaviour", &msg); @@ -1283,7 +1283,7 @@ TEST_F(VideoOutputThunderTest, GetAspectRatioBehaviour_Success) /* getAspectRatioBehaviour: Thunder failure → falls back to "None", still OK */ TEST_F(VideoOutputThunderTest, GetAspectRatioBehaviour_ThunderFailure_FallsBackToNone) { - ThunderStub::setString(THUNDER_AVO_GET_ZOOM_MODE, false, ""); + ThunderStub::setString(THUNDER_DS_GET_ZOOM_SETTINGS, false, ""); HOSTIF_MsgData_t msg = makeMsg(); int rc = m_iface->handleGetMsg("AspectRatioBehaviour", &msg); diff --git a/test/functional-tests/tests/helper_functions.py b/test/functional-tests/tests/helper_functions.py index ae4bd41f1..d2189fc8b 100644 --- a/test/functional-tests/tests/helper_functions.py +++ b/test/functional-tests/tests/helper_functions.py @@ -75,6 +75,25 @@ def clear_persistant_files(): def rbus_get_data(param: str): return subprocess.run(RBUSCLI_GET_CMD + param, shell=True, capture_output=True).stdout.decode('utf-8') +def rbus_get_value(param: str): + """Extract just the value from RBUS output. + + RBUS output format: + Parameter 1: + Name : Device.Services.STBService.1.Param + Type : string + Value : ActualValue + + Returns just 'ActualValue' string. + """ + output = rbus_get_data(param) + for line in output.split('\n'): + if 'Value :' in line or 'Value:' in line: + # Extract everything after 'Value :' or 'Value:' + return line.split(':', 1)[1].strip() + # If no Value line found, return the full output stripped + return output.strip() + def rbus_set_data(param: str, type:str, value: str): return subprocess.run(f"{RBUSCLI_SET_CMD} {param} {type} {value}", shell=True, capture_output=True).stdout.decode('utf-8') diff --git a/test/functional-tests/tests/tr69hostif_stbservice_thunder.py b/test/functional-tests/tests/tr69hostif_stbservice_thunder.py index 69b8ae3d2..00fb69d41 100644 --- a/test/functional-tests/tests/tr69hostif_stbservice_thunder.py +++ b/test/functional-tests/tests/tr69hostif_stbservice_thunder.py @@ -248,8 +248,9 @@ def test_STBService_DisplayDevice_Get_Status(): assert RBUS_EXCEPTION_STRING not in rstdout, \ f"rbus exception getting {param}" assert CURL_OK_MSG in grep_tr69hostiflogs(CURL_OK_MSG) - assert rstdout.strip() in ("Present", "Absent"), \ - f"Unexpected DisplayDevice Status: {rstdout}" + value = rbus_get_value(param) + assert value in ("Present", "Absent"), \ + f"Unexpected DisplayDevice Status: {value}" @pytest.mark.run(order=324) @@ -366,8 +367,9 @@ def test_STBService_AudioOutput_Get_AudioLevel(): f"rbus exception getting {param}" assert CURL_OK_MSG in grep_tr69hostiflogs(CURL_OK_MSG) # AudioLevel is a numeric volume level (0-100) - assert rstdout.strip().isdigit() or rstdout.strip().lstrip('-').isdigit(), \ - f"Expected numeric AudioLevel, got: {rstdout}" + value = rbus_get_value(param) + assert value.isdigit() or value.lstrip('-').isdigit(), \ + f"Expected numeric AudioLevel, got: {value}" @pytest.mark.run(order=332) @@ -449,7 +451,7 @@ def test_STBService_VideoOutput_Get_Status(): assert RBUS_EXCEPTION_STRING not in rstdout, \ f"rbus exception getting {param}" assert CURL_OK_MSG in grep_tr69hostiflogs(CURL_OK_MSG) - assert rstdout.strip() in ("Enabled", "Disabled"), \ + assert any(v in rstdout for v in ("Enabled", "Disabled")), \ f"Unexpected VideoOutput Status: {rstdout}" @@ -500,7 +502,7 @@ def test_STBService_VideoOutput_Get_VideoFormat(): @pytest.mark.run(order=340) def test_STBService_VideoOutput_Get_AspectRatioBehaviour(): """ - GET VideoOutput.1.AspectRatioBehaviour – backed by AVOutput.getZoomMode; + GET VideoOutput.1.AspectRatioBehaviour – backed by DisplaySettings.getZoomSetting; falls back to "None" if Thunder fails. """ param = VIDOUT_BASE + ".AspectRatioBehaviour" @@ -604,10 +606,11 @@ def test_STBService_Capabilities_Get_HEVCProfileEntries(): f"rbus exception getting {param}" assert CURL_OK_MSG in grep_tr69hostiflogs(CURL_OK_MSG) # Value should be a positive integer + value = rbus_get_value(param) try: - assert int(rstdout.strip()) >= 1 + assert int(value) >= 1 except ValueError: - assert False, f"Expected integer, got: {rstdout}" + assert False, f"Expected integer, got: {value}" @pytest.mark.run(order=347) diff --git a/test/test-artifacts/native-platform/thunder-mock-server.js b/test/test-artifacts/native-platform/thunder-mock-server.js index f02f0a040..fe0fa7a8c 100644 --- a/test/test-artifacts/native-platform/thunder-mock-server.js +++ b/test/test-artifacts/native-platform/thunder-mock-server.js @@ -151,6 +151,136 @@ const mockResponses = { result: { resetTime: 1717000000 }, description: 'Last checkout reset timestamp', }, + + // ─────────────────────────────────────────────────────────────────────────── + // STBService Thunder APIs - DisplaySettings (Audio) + // ─────────────────────────────────────────────────────────────────────────── + 'org.rdk.DisplaySettings.getSupportedAudioPorts': { + result: { supportedAudioPorts: ['HDMI0', 'SPEAKER0', 'SPDIF0'] }, + description: 'List of available audio output ports', + }, + 'org.rdk.DisplaySettings.getEnableAudioPort': { + result: { enable: true }, + description: 'Audio port enabled status', + }, + 'org.rdk.DisplaySettings.getMuted': { + result: { muted: false }, + description: 'Audio mute status', + }, + 'org.rdk.DisplaySettings.getVolumeLevel': { + result: { volumeLevel: 50 }, + description: 'Current audio volume level', + }, + 'org.rdk.DisplaySettings.getAudioEncoding': { + result: { encoding: 'PCM' }, + description: 'Current audio encoding format', + }, + 'org.rdk.DisplaySettings.getSoundMode': { + result: { soundMode: 'SURROUND' }, + description: 'Current audio sound mode', + }, + 'org.rdk.DisplaySettings.getMS12AudioCompression': { + result: { compressionlevel: 0 }, + description: 'MS12 audio compression level', + }, + + // ─────────────────────────────────────────────────────────────────────────── + // STBService Thunder APIs - DisplaySettings (Video) + // ─────────────────────────────────────────────────────────────────────────── + 'org.rdk.DisplaySettings.getSupportedVideoPorts': { + result: { supportedVideoPorts: ['HDMI0'] }, + description: 'List of available video output ports', + }, + 'org.rdk.DisplaySettings.getSupportedVideoDisplays': { + result: { supportedVideoDisplays: ['HDMI0'] }, + description: 'List of available video displays (for HDMI component)', + }, + 'org.rdk.DisplaySettings.getEnableVideoPort': { + result: { enable: true }, + description: 'Video port enabled status', + }, + 'org.rdk.DisplaySettings.getCurrentResolution': { + result: { resolution: '1080p' }, + description: 'Current video resolution', + }, + 'org.rdk.DisplaySettings.getSupportedResolutions': { + result: { supportedResolutions: ['480p', '720p', '1080p', '2160p60'] }, + description: 'Supported video resolutions', + }, + 'org.rdk.DisplaySettings.getDefaultResolution': { + result: { defaultResolution: '1080p' }, + description: 'Default/preferred resolution', + }, + 'org.rdk.DisplaySettings.getDisplayAspectRatio': { + result: { aspectRatio: '16x9' }, + description: 'Display aspect ratio', + }, + 'org.rdk.DisplaySettings.readEDID': { + result: { EDID: 'AP///////wBQrDYBAAAAAAwXAQSlOSJ4CvCVoVdTnCYPUFQAAAABAQEBAQEBAQEBAQEBAQEB3iGgcFCEHzAgOCUIAClHAAAeAAAA/QAyTBFEH4AgIAkQCQAKAAAA/ABERUxMCgAgAAAAAD9BUzEzMgogICAgAAAAAEE=' }, + description: 'EDID data from connected display', + }, + 'org.rdk.DisplaySettings.getZoomSetting': { + result: { zoomSetting: 'Full' }, + description: 'Current zoom/aspect ratio setting (Full, None, etc.)', + }, + + // ─────────────────────────────────────────────────────────────────────────── + // STBService Thunder APIs - DisplayInfo + // ─────────────────────────────────────────────────────────────────────────── + 'DisplayInfo.1.connected': { + result: true, + description: 'Display connection status (property-style boolean)', + }, + 'DisplayInfo.1.framerate': { + result: 'Framerate6000', + description: 'Current display framerate (property-style string: FramerateXXXX where XXXX/100 = Hz)', + }, + + // ─────────────────────────────────────────────────────────────────────────── + // STBService Thunder APIs - PowerManager + // ─────────────────────────────────────────────────────────────────────────── + 'org.rdk.PowerManager.GetPowerState': { + result: { currentState: 'ON', success: true }, + description: 'System power state (currentState: ON/STANDBY/LIGHT_SLEEP/DEEP_SLEEP)', + }, + + // ─────────────────────────────────────────────────────────────────────────── + // STBService Thunder APIs - AVOutput + // ─────────────────────────────────────────────────────────────────────────── + 'org.rdk.AVOutput.getZoomMode': { + result: { zoomMode: 'Full' }, + description: 'Video zoom/aspect ratio behavior', + }, + + // ─────────────────────────────────────────────────────────────────────────── + // STBService Thunder APIs - HdcpProfile + // ─────────────────────────────────────────────────────────────────────────── + 'org.rdk.HdcpProfile.getHDCPStatus': { + result: { isConnected: true, isHDCPCompliant: true, isHDCPEnabled: true, hdcpReason: 0, success: true }, + description: 'HDCP connection and compliance status', + }, + + // ─────────────────────────────────────────────────────────────────────────── + // STBService Thunder APIs - Capabilities + // ─────────────────────────────────────────────────────────────────────────── + 'org.rdk.DisplaySettings.getSupportedVideoCodingFormats': { + result: { supportedVideoCodingFormats: ['H264', 'MPEG2', 'HEVC'] }, + description: 'Supported video codec formats', + }, + 'org.rdk.DisplaySettings.getVideoCodecInfo': { + result: { + numberOfEntries: 2, + entries: [ + { profile: 'Main', level: 5.1 }, + { profile: 'Main10', level: 5.1 } + ] + }, + description: 'HEVC (MPEGH-Part2) codec profile/level capabilities', + }, + 'org.rdk.DisplaySettings.getSupportedSettopResolutions': { + result: { supportedSettopResolutions: ['480p', '720p', '1080p', '2160p60'] }, + description: 'Supported set-top box output resolutions', + }, }; /**