Skip to content

Commit 224d821

Browse files
DELIA-67484: RDKE/V User Settings Update Presentation language in Failure (rdkcentral#6228)
* DELIA-67484: RDKE/V User Settings Update Presentation language in Failure Reason for change: RDKE/V User Settings Update Presentation language in Failure Test Procedure: NA Risks: NO Priority: P1 * commenting L1 * commenting in one more place * build error * build error * changelog.md file changes * success trigger --------- Co-authored-by: Anand Kandasamy <[email protected]>
1 parent 9ceaf86 commit 224d821

File tree

12 files changed

+739
-35
lines changed

12 files changed

+739
-35
lines changed

.github/workflows/L1-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ jobs:
275275
-DPLUGIN_SCREENCAPTURE=ON
276276
-DPLUGIN_USBACCESS=ON
277277
-DPLUGIN_LOGGINGPREFERENCES=ON
278-
-DPLUGIN_USERPREFERENCES=ON
278+
-DPLUGIN_USERPREFERENCES=OFF
279279
-DPLUGIN_MESSENGER=ON
280280
-DPLUGIN_DEVICEINFO=ON
281281
-DPLUGIN_SYSTEMSERVICES=ON

.github/workflows/L2-tests-R4-4-1.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ jobs:
274274
-DPLUGIN_USBACCESS=ON
275275
-DPLUGIN_USERSETTINGS=ON
276276
-DPLUGIN_PERSISTENTSTORE=ON
277+
-DPLUGIN_USERPREFERENCES=ON
277278
-DUSE_THUNDER_R4=ON
278279
-DPLUGIN_L2Tests=ON
279280
-DRDK_SERVICE_L2_TEST=ON
@@ -314,6 +315,7 @@ jobs:
314315
/opt/tmtryoptout
315316
/opt/fwdnldstatus.txt
316317
/opt/dcm.properties
318+
/opt/user_preferences.conf
317319
/etc/device.properties
318320
/etc/dcm.properties
319321
/etc/authService.conf

Tests/L1Tests/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ include_directories(../../LocationSync
7272
../../UsbAccess
7373
../../Timer
7474
../../LoggingPreferences
75-
../../UserPreferences
75+
#../../UserPreferences
7676
../../Messenger
7777
../../DeviceInfo
7878
../../helpers
@@ -115,7 +115,7 @@ link_directories(../../LocationSync
115115
../../Timer
116116
../../LoggingPreferences
117117
../../SystemServices
118-
../../UserPreferences
118+
#../../UserPreferences
119119
../../Messenger
120120
../../DeviceInfo
121121
../../HdmiInput
@@ -156,7 +156,7 @@ target_link_libraries(${PROJECT_NAME}
156156
${NAMESPACE}Timer
157157
${NAMESPACE}LoggingPreferences
158158
${NAMESPACE}SystemServices
159-
${NAMESPACE}UserPreferences
159+
# ${NAMESPACE}UserPreferences
160160
${NAMESPACE}Messenger
161161
${NAMESPACE}DeviceInfo
162162
${NAMESPACE}HdmiInput

Tests/L1Tests/tests/test_UserPreferences.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* limitations under the License.
1818
**/
1919

20+
#if 0
21+
2022
#include "gtest/gtest.h"
2123

2224
#include "UserPreferences.h"
@@ -87,3 +89,5 @@ TEST_F(UserPreferencesTest, setUILanguage)
8789

8890
file.Destroy();
8991
}
92+
93+
#endif

Tests/L2Tests/L2TestsPlugin/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ if(PLUGIN_USERSETTINGS)
4747
set(SRC_FILES ${SRC_FILES} tests/UserSettings_L2Test.cpp)
4848
endif()
4949

50+
if(PLUGIN_USERPREFERENCES)
51+
set(SRC_FILES ${SRC_FILES} tests/UserPreferences_L2Test.cpp)
52+
endif()
53+
5054
if(PLUGIN_SYSTEMMODE)
5155
set(SRC_FILES ${SRC_FILES} tests/SystemMode_L2Test.cpp)
5256
endif()
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
#include <gtest/gtest.h>
2+
#include <gmock/gmock.h>
3+
#include "L2Tests.h"
4+
#include "L2TestsMock.h"
5+
#include <mutex>
6+
#include <condition_variable>
7+
#include <fstream>
8+
#include <interfaces/IUserSettings.h>
9+
10+
#define JSON_TIMEOUT (1000)
11+
#define USERSETTING_CALLSIGN _T("org.rdk.UserSettings")
12+
#define USERSETTINGL2TEST_CALLSIGN _T("L2tests.1")
13+
14+
#define USERPREFERENCE_CALLSIGN _T("org.rdk.UserPreferences")
15+
#define USERSETTINGL2TEST_CALLSIGN _T("L2tests.1")
16+
17+
#define TEST_LOG(x, ...) fprintf(stderr, "\033[1;32m[%s:%d](%s)<PID:%d><TID:%d>" x "\n\033[0m", __FILE__, __LINE__, __FUNCTION__, getpid(), gettid(), ##__VA_ARGS__); fflush(stderr);
18+
19+
20+
using ::testing::NiceMock;
21+
using namespace WPEFramework;
22+
using testing::StrictMock;
23+
24+
typedef enum : uint32_t {
25+
UserSettings_onAudioDescriptionChanged = 0x00000001,
26+
UserSettings_onPreferredAudioLanguagesChanged = 0x00000002,
27+
UserSettings_onPresentationLanguageChanged = 0x00000003,
28+
UserSettings_onCaptionsChanged = 0x00000004,
29+
UserSettings_onPreferredCaptionsLanguagesChanged = 0x00000005,
30+
UserSettings_onPreferredClosedCaptionServiceChanged = 0x00000006,
31+
UserSettings_onPrivacyModeChanged = 0x00000007,
32+
UserSettings_onPinControlChanged = 0x00000008,
33+
UserSettings_onViewingRestrictionsChanged = 0x00000009,
34+
UserSettings_onViewingRestrictionsWindowChanged = 0x0000000a,
35+
UserSettings_onLiveWatershedChanged = 0x0000000b,
36+
UserSettings_onPlaybackWatershedChanged = 0x0000000c,
37+
UserSettings_onBlockNotRatedContentChanged = 0x0000000d,
38+
UserSettings_onPinOnPurchaseChanged = 0x0000000e,
39+
UserSettings_StateInvalid = 0x00000000
40+
}UserSettingsL2test_async_events_t;
41+
42+
class AsyncHandlerMock
43+
{
44+
public:
45+
AsyncHandlerMock()
46+
{
47+
}
48+
MOCK_METHOD(void, onAudioDescriptionChanged, (const bool enabled));
49+
MOCK_METHOD(void, onPreferredAudioLanguagesChanged, (const string preferredLanguages));
50+
MOCK_METHOD(void, onPresentationLanguageChanged, (const string presentationLanguage));
51+
MOCK_METHOD(void, onCaptionsChanged, (const bool enabled));
52+
MOCK_METHOD(void, onPreferredCaptionsLanguagesChanged, (const string preferredLanguages));
53+
MOCK_METHOD(void, onPreferredClosedCaptionServiceChanged, (const string service));
54+
MOCK_METHOD(void, onPrivacyModeChanged, (const string privacyMode));
55+
MOCK_METHOD(void, onPinControlChanged, (const bool pinControl));
56+
MOCK_METHOD(void, onViewingRestrictionsChanged, (const string viewingRestrictions));
57+
MOCK_METHOD(void, onViewingRestrictionsWindowChanged, (const string viewingRestrictionsWindow));
58+
MOCK_METHOD(void, onLiveWatershedChanged, (const bool liveWatershed));
59+
MOCK_METHOD(void, onPlaybackWatershedChanged, (const bool playbackWatershed));
60+
MOCK_METHOD(void, onBlockNotRatedContentChanged, (const bool blockNotRatedContent));
61+
MOCK_METHOD(void, onPinOnPurchaseChanged, (const bool pinOnPurchase));
62+
63+
};
64+
65+
class UserpreferencesTest : public L2TestMocks {
66+
protected:
67+
virtual ~UserpreferencesTest() override;
68+
69+
public:
70+
UserpreferencesTest();
71+
72+
// Mock methods for UserPreferences plugin
73+
void onPresentationLanguageChanged(const string presentationLanguage);
74+
uint32_t WaitForRequestStatus(uint32_t timeout_ms, UserSettingsL2test_async_events_t expected_status);
75+
76+
private:
77+
/** @brief Mutex */
78+
std::mutex m_mutex;
79+
80+
/** @brief Condition variable */
81+
std::condition_variable m_condition_variable;
82+
83+
/** @brief Event signalled flag */
84+
uint32_t m_event_signalled;
85+
};
86+
87+
UserpreferencesTest::UserpreferencesTest() : L2TestMocks() {
88+
uint32_t status = Core::ERROR_GENERAL;
89+
m_event_signalled = UserSettings_StateInvalid;
90+
91+
// Activate the UserPreferences plugin in the constructor
92+
status = ActivateService("org.rdk.PersistentStore");
93+
EXPECT_EQ(Core::ERROR_NONE, status);
94+
95+
status = ActivateService("org.rdk.UserSettings");
96+
TEST_LOG("activated user settings");
97+
EXPECT_EQ(Core::ERROR_NONE, status);
98+
99+
status = ActivateService("org.rdk.UserPreferences");
100+
TEST_LOG("activated");
101+
EXPECT_EQ(Core::ERROR_NONE, status);
102+
103+
}
104+
105+
UserpreferencesTest::~UserpreferencesTest() {
106+
uint32_t status = Core::ERROR_GENERAL;
107+
m_event_signalled = UserSettings_StateInvalid;
108+
109+
// Deactivate the UserPreferences plugin in the destructor
110+
status = DeactivateService("org.rdk.UserPreferences");
111+
EXPECT_EQ(Core::ERROR_NONE, status);
112+
113+
status = DeactivateService("org.rdk.UserSettings");
114+
TEST_LOG("deactivated user settings");
115+
116+
status = DeactivateService("org.rdk.PersistentStore");
117+
EXPECT_EQ(Core::ERROR_NONE, status);
118+
119+
sleep(5);
120+
int file_status = remove("/tmp/secure/persistent/rdkservicestore");
121+
// Check if the file has been successfully removed
122+
if (file_status != 0)
123+
{
124+
TEST_LOG("Error deleting file[/tmp/secure/persistent/rdkservicestore]");
125+
}
126+
else
127+
{
128+
TEST_LOG("File[/tmp/secure/persistent/rdkservicestore] successfully deleted");
129+
}
130+
}
131+
132+
void UserpreferencesTest::onPresentationLanguageChanged(const string presentationLanguage) {
133+
TEST_LOG("onPresentationLanguageChanged event triggered ***\n");
134+
std::unique_lock<std::mutex> lock(m_mutex);
135+
136+
TEST_LOG("onPresentationLanguageChanged received: %s\n", presentationLanguage.c_str());
137+
138+
m_event_signalled |= UserSettings_onPresentationLanguageChanged;
139+
m_condition_variable.notify_one();
140+
}
141+
142+
uint32_t UserpreferencesTest::WaitForRequestStatus(uint32_t timeout_ms, UserSettingsL2test_async_events_t expected_status) {
143+
std::unique_lock<std::mutex> lock(m_mutex);
144+
auto now = std::chrono::system_clock::now();
145+
std::chrono::milliseconds timeout(timeout_ms);
146+
uint32_t signalled = UserSettings_StateInvalid;
147+
148+
while (!(expected_status & m_event_signalled)) {
149+
if (m_condition_variable.wait_until(lock, now + timeout) == std::cv_status::timeout) {
150+
TEST_LOG("Timeout waiting for request status event");
151+
break;
152+
}
153+
}
154+
155+
signalled = m_event_signalled;
156+
return signalled;
157+
}
158+
159+
MATCHER_P(MatchRequestStatusString, data, "") {
160+
std::string expected = data;
161+
std::string actual = arg;
162+
TEST_LOG("Expected = %s, Actual = %s", expected.c_str(), actual.c_str());
163+
EXPECT_STREQ(expected.c_str(), actual.c_str());
164+
return expected == actual;
165+
}
166+
167+
TEST_F(UserpreferencesTest, UserPreferencesGetSetLanguage) {
168+
JSONRPC::LinkType<Core::JSON::IElement> jsonrpc(USERPREFERENCE_CALLSIGN, USERSETTINGL2TEST_CALLSIGN);
169+
JSONRPC::LinkType<Core::JSON::IElement> usersettings_jsonrpc(USERSETTING_CALLSIGN, USERSETTINGL2TEST_CALLSIGN);
170+
StrictMock<AsyncHandlerMock> async_handler;
171+
uint32_t status = Core::ERROR_GENERAL;
172+
JsonObject params, result;
173+
Core::JSON::String result_string;
174+
string initialLanguage = "en-US";
175+
string expectedUILanguage = "US_en";
176+
string newUILanguage = "CA_en";
177+
string expectedNewPresentationLanguage = "en-CA";
178+
uint32_t signalled = UserSettings_StateInvalid;
179+
180+
status = usersettings_jsonrpc.Subscribe<JsonObject>(JSON_TIMEOUT,
181+
_T("onPresentationLanguageChanged"),
182+
[&async_handler](const JsonObject& parameters) {
183+
string presentationLanguage = parameters["presentationLanguage"].String();
184+
async_handler.onPresentationLanguageChanged(presentationLanguage);
185+
});
186+
187+
EXPECT_EQ(Core::ERROR_NONE, status);
188+
189+
EXPECT_CALL(async_handler, onPresentationLanguageChanged(MatchRequestStatusString(initialLanguage)))
190+
.WillOnce(Invoke(this, &UserpreferencesTest::onPresentationLanguageChanged));
191+
192+
params["presentationLanguage"] = initialLanguage;
193+
status = InvokeServiceMethod("org.rdk.UserSettings", "setPresentationLanguage", params, result);
194+
EXPECT_EQ(Core::ERROR_NONE, status);
195+
196+
signalled = WaitForRequestStatus(JSON_TIMEOUT, UserSettings_onPresentationLanguageChanged);
197+
EXPECT_TRUE(signalled & UserSettings_onPresentationLanguageChanged);
198+
199+
JsonObject getParams;
200+
status = InvokeServiceMethod("org.rdk.UserPreferences", "getUILanguage", getParams, result);
201+
EXPECT_EQ(Core::ERROR_NONE, status);
202+
EXPECT_TRUE(result["success"].Boolean());
203+
EXPECT_STREQ(expectedUILanguage.c_str(), result["ui_language"].Value().c_str());
204+
205+
EXPECT_CALL(async_handler, onPresentationLanguageChanged(MatchRequestStatusString(expectedNewPresentationLanguage)))
206+
.WillOnce(Invoke(this, &UserpreferencesTest::onPresentationLanguageChanged));
207+
208+
JsonObject setUIParams;
209+
setUIParams["ui_language"] = newUILanguage;
210+
status = InvokeServiceMethod("org.rdk.UserPreferences", "setUILanguage", setUIParams, result);
211+
EXPECT_EQ(Core::ERROR_NONE, status);
212+
EXPECT_TRUE(result["success"].Boolean());
213+
214+
signalled = WaitForRequestStatus(JSON_TIMEOUT, UserSettings_onPresentationLanguageChanged);
215+
EXPECT_TRUE(signalled & UserSettings_onPresentationLanguageChanged);
216+
217+
JsonObject getPresParams;
218+
status = InvokeServiceMethod("org.rdk.UserSettings", "getPresentationLanguage", result_string);
219+
EXPECT_EQ(Core::ERROR_NONE, status);
220+
EXPECT_EQ(expectedNewPresentationLanguage.c_str(), result_string.Value());
221+
222+
status = InvokeServiceMethod("org.rdk.UserPreferences", "getUILanguage", getParams, result);
223+
EXPECT_EQ(Core::ERROR_NONE, status);
224+
EXPECT_TRUE(result["success"].Boolean());
225+
EXPECT_STREQ(newUILanguage.c_str(), result["ui_language"].Value().c_str());
226+
227+
// Step 7: Unsubscribe
228+
usersettings_jsonrpc.Unsubscribe(JSON_TIMEOUT, _T("onPresentationLanguageChanged"));
229+
}
230+
231+

UserPreferences/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ All notable changes to this RDK Service will be documented in this file.
1616

1717
* For more details, refer to [versioning](https://github.com/rdkcentral/rdkservices#versioning) section under Main README.
1818

19+
## [1.0.3] - 2025-05-13
20+
### Changed
21+
- Calling UserSettings from within UserPreferences Get/Set functions
22+
1923
## [1.0.2] - 2024-05-25
2024
### Added
2125
- Make plugin autostart configurable from recipe

UserPreferences/CMakeLists.txt

100644100755
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ set_target_properties(${MODULE_NAME} PROPERTIES
3636
CXX_STANDARD 11
3737
CXX_STANDARD_REQUIRED YES)
3838

39+
if (RDK_SERVICE_L2_TEST)
40+
find_library(TESTMOCKLIB_LIBRARIES NAMES TestMocklib)
41+
if (TESTMOCKLIB_LIBRARIES)
42+
message ("linking mock libraries ${TESTMOCKLIB_LIBRARIES} library")
43+
target_link_libraries(${MODULE_NAME} PRIVATE ${TESTMOCKLIB_LIBRARIES})
44+
else (TESTMOCKLIB_LIBRARIES)
45+
message ("Require ${TESTMOCKLIB_LIBRARIES} library")
46+
endif (TESTMOCKLIB_LIBRARIES)
47+
endif (RDK_SERVICES_L2_TEST)
48+
3949
target_include_directories(${MODULE_NAME}
4050
PRIVATE
4151
../helpers

0 commit comments

Comments
 (0)