From c2b27a00e68a13be75d84fa02c392fe69d9be41b Mon Sep 17 00:00:00 2001 From: deepin-wm Date: Tue, 23 Jun 2026 18:01:38 +0800 Subject: [PATCH] fix: fix serial comparison logic in DConfigCache setValue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Fix incorrect early return when checking value equality without serial comparison 2. Add DConfigInfo::checkSerial to compare both value and serial before returning false 3. Update setValue documentation to accurately describe return behavior 4. Add unit tests covering serial comparison scenarios: - Same value and same serial returns false - Same value but different serial returns true (bug fix) - Different value and same serial returns true - Different value and different serial returns true 5. Add test meta and override data files for serial testing 6. Update copyright year from 2023 to 2026 fix: 修复DConfigCache的setValue中序列号比较逻辑 1. 修正仅检查值相等就提前返回的错误逻辑 2. 增加DConfigInfo::checkSerial同时比较值和序列号 3. 更新setValue文档准确描述返回值行为 4. 添加涵盖序列号比较场景的单元测试: - 相同值和相同序列号返回false - 相同值但不同序列号返回true(bug修复) - 不同值相同序列号返回true - 不同值不同序列号返回true 5. 添加序列号测试所需的元数据和覆盖文件 6. 更新版权年份从2023到2026 Influence: 1. Test DConfig setValue when value is same but serial is updated via override 2. Verify no regression when setting different values with same or different serials 3. Validate cache update behavior matches documented return semantics 4. Ensure override layer serial changes properly trigger value updates Influence: 1. 测试当值相同但通过覆盖文件更新序列号时setValue的行为 2. 验证设置不同值(相同或不同序列号)时无回归 3. 确认缓存更新行为符合文档中的返回语义 4. 确保覆盖层序列号变化能正确触发值更新 --- src/dconfigfile.cpp | 8 +-- tests/data.qrc | 2 + tests/data/dconf-serial-test.meta.json | 14 ++++ tests/data/dconf-serial-test.override.json | 10 +++ tests/ut_dconfigfile.cpp | 83 +++++++++++++++++++++- 5 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 tests/data/dconf-serial-test.meta.json create mode 100644 tests/data/dconf-serial-test.override.json 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> {