diff --git a/src/dconfigfile.cpp b/src/dconfigfile.cpp
index bac32b24..d40a7e18 100644
--- a/src/dconfigfile.cpp
+++ b/src/dconfigfile.cpp
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd.
+// SPDX-FileCopyrightText: 2021 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
@@ -985,7 +985,7 @@ DConfigMetaImpl::~DConfigMetaImpl()
\a value Configuration name
\a uid User Id at setup time
\a callerAppid Application id at setup time
- @return A value of true indicates that the new value has been reset, and false indicates that it has not been set
+ @return true if the cache was updated (value or serial changed), false if no update was needed
*/
/*!
@@ -1124,7 +1124,7 @@ class Q_DECL_HIDDEN DConfigCacheImpl : public DConfigCache {
}
bool setValue(const QString &key, const QVariant &value, const int serial, const uint uid, const QString &appid) override
{
- if (values.value(key) == value) {
+ if (values.value(key) == value && DConfigInfo::checkSerial(values.serial(key), serial)) {
return false;
}
values.setValue(key, value);
@@ -1487,7 +1487,7 @@ QVariant DConfigFile::cacheValue(DConfigCache *userCache, const QString &key) co
\a value The value to set
\a userCache Specific user cache at setup time
\a appid Application id at setup time
- @return A value of true indicates that the new value has been reset, and false indicates that it has not been set
+ @return true if the cache was updated (value or serial changed), false if no update was needed
*/
bool DConfigFile::setValue(const QString &key, const QVariant &value, const QString &callerAppid, DConfigCache *userCache)
{
diff --git a/tests/data.qrc b/tests/data.qrc
index 8f2b8eb5..0b63e4c7 100644
--- a/tests/data.qrc
+++ b/tests/data.qrc
@@ -11,6 +11,8 @@
data/LGPLv3.txt
data/example-license.json
data/dconf-example.override.noexistitem.json
+ data/dconf-serial-test.meta.json
+ data/dconf-serial-test.override.json
data/dconfig2cpp/basic-types.meta.json
data/dconfig2cpp/numeric-types.meta.json
data/dconfig2cpp/complex-types.meta.json
diff --git a/tests/data/dconf-serial-test.meta.json b/tests/data/dconf-serial-test.meta.json
new file mode 100644
index 00000000..2a2473e3
--- /dev/null
+++ b/tests/data/dconf-serial-test.meta.json
@@ -0,0 +1,14 @@
+{
+ "magic": "dsg.config.meta",
+ "version": "1.0",
+ "contents": {
+ "testKey": {
+ "value": "initial",
+ "serial": 0,
+ "flags": [],
+ "name": "test key for serial comparison",
+ "permissions": "readwrite",
+ "visibility": "private"
+ }
+ }
+}
diff --git a/tests/data/dconf-serial-test.override.json b/tests/data/dconf-serial-test.override.json
new file mode 100644
index 00000000..2c73113b
--- /dev/null
+++ b/tests/data/dconf-serial-test.override.json
@@ -0,0 +1,10 @@
+{
+ "magic": "dsg.config.override",
+ "version": "1.0",
+ "contents": {
+ "testKey": {
+ "value": "initial",
+ "serial": 1
+ }
+ }
+}
diff --git a/tests/ut_dconfigfile.cpp b/tests/ut_dconfigfile.cpp
index 45c007d8..8938709b 100644
--- a/tests/ut_dconfigfile.cpp
+++ b/tests/ut_dconfigfile.cpp
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2021 - 2023 UnionTech Software Technology Co., Ltd.
+// SPDX-FileCopyrightText: 2021 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
@@ -506,6 +506,87 @@ TEST_F(ut_DConfigFile, userPublic) {
}
}
+TEST_F(ut_DConfigFile, setValueWithSerialComparison) {
+ // 测试 DConfigCacheImpl::setValue 中的 serial 比较逻辑
+ // 当值相同但 serial 不同时,应该返回 true(更新缓存)
+
+ FileCopyGuard guard(":/data/dconf-serial-test.meta.json", QString("%1/%2.json").arg(metaPath, FILE_NAME));
+
+ // 场景1: 值和 serial 都相同 → 返回 false
+ {
+ DConfigFile config(APP_ID, FILE_NAME);
+ ASSERT_TRUE(config.load(LocalPrefix));
+ QScopedPointer userCache(config.createUserCache(uid));
+ ASSERT_TRUE(userCache->load(LocalPrefix));
+
+ // 首次设置值,serial=0 从 meta 传入
+ ASSERT_TRUE(config.setValue("testKey", "test_value", "test", userCache.get()));
+
+ // 再次设置相同的值,serial 相同 → 返回 false
+ ASSERT_FALSE(config.setValue("testKey", "test_value", "test", userCache.get()));
+ }
+
+ // 场景2: 值相同,serial 不同 → 返回 true(新修复的场景)
+ {
+ DConfigFile config(APP_ID, FILE_NAME);
+ ASSERT_TRUE(config.load(LocalPrefix));
+ QScopedPointer userCache(config.createUserCache(uid));
+ ASSERT_TRUE(userCache->load(LocalPrefix));
+
+ // 设置值,缓存中 serial=0
+ ASSERT_TRUE(config.setValue("testKey", "test_value", "test", userCache.get()));
+
+ // 使用 override 文件将 serial 升级到 1
+ FileCopyGuard guard2(":/data/dconf-serial-test.override.json", QString("%1/%2.json").arg(overridePath, FILE_NAME));
+
+ // 重新加载配置,此时 meta serial=1
+ DConfigFile config2(APP_ID, FILE_NAME);
+ ASSERT_TRUE(config2.load(LocalPrefix));
+ QScopedPointer userCache2(config2.createUserCache(uid));
+ ASSERT_TRUE(userCache2->load(LocalPrefix));
+
+ // 设置相同的值,但 meta serial=1, cache serial=0 → 应该返回 true
+ ASSERT_TRUE(config2.setValue("testKey", "test_value", "test", userCache2.get()));
+ }
+
+ // 场景3: 值不同,serial 相同 → 返回 true
+ {
+ DConfigFile config(APP_ID, FILE_NAME);
+ ASSERT_TRUE(config.load(LocalPrefix));
+ QScopedPointer userCache(config.createUserCache(uid));
+ ASSERT_TRUE(userCache->load(LocalPrefix));
+
+ // 设置初始值
+ ASSERT_TRUE(config.setValue("testKey", "value1", "test", userCache.get()));
+
+ // 设置不同的值,serial 相同 → 返回 true
+ ASSERT_TRUE(config.setValue("testKey", "value2", "test", userCache.get()));
+ }
+
+ // 场景4: 值不同,serial 不同 → 返回 true
+ {
+ DConfigFile config(APP_ID, FILE_NAME);
+ ASSERT_TRUE(config.load(LocalPrefix));
+ QScopedPointer userCache(config.createUserCache(uid));
+ ASSERT_TRUE(userCache->load(LocalPrefix));
+
+ // 设置初始值
+ ASSERT_TRUE(config.setValue("testKey", "value1", "test", userCache.get()));
+
+ // 使用 override 文件将 serial 升级到 1
+ FileCopyGuard guard2(":/data/dconf-serial-test.override.json", QString("%1/%2.json").arg(overridePath, FILE_NAME));
+
+ // 重新加载配置
+ DConfigFile config2(APP_ID, FILE_NAME);
+ ASSERT_TRUE(config2.load(LocalPrefix));
+ QScopedPointer userCache2(config2.createUserCache(uid));
+ ASSERT_TRUE(userCache2->load(LocalPrefix));
+
+ // 设置不同的值,serial 也不同 → 返回 true
+ ASSERT_TRUE(config2.setValue("testKey", "value3", "test", userCache2.get()));
+ }
+}
+
class ut_DConfigFileCheckName : public ut_DConfigFile, public ::testing::WithParamInterface>
{