diff --git a/services/distributeddataservice/framework/test/BUILD.gn b/services/distributeddataservice/framework/test/BUILD.gn index 4e1fb58fc8d394bdd63ecb1b2ee82ec7a1f69f5d..89d48976e5165d143f068e8b38a3ef5e9889e7c3 100644 --- a/services/distributeddataservice/framework/test/BUILD.gn +++ b/services/distributeddataservice/framework/test/BUILD.gn @@ -155,6 +155,7 @@ ohos_unittest("StoreTest") { "access_token:libnativetoken", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "googletest:gmock", "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", diff --git a/services/distributeddataservice/service/test/BUILD.gn b/services/distributeddataservice/service/test/BUILD.gn index e7d9784768c74503239b9072a1d9d0d8f023a150..61b104dc78659a41260633c599e74a6b757ccbb6 100644 --- a/services/distributeddataservice/service/test/BUILD.gn +++ b/services/distributeddataservice/service/test/BUILD.gn @@ -24,6 +24,7 @@ config("module_private_config") { "${data_service_path}/adapter/include", "${data_service_path}/app/src", "${data_service_path}/framework/include", + "${data_service_path}/framework/include/cloud", "${data_service_path}/service/bootstrap/include/", "${data_service_path}/service/backup/include/", "${data_service_path}/service/cloud/", @@ -483,6 +484,7 @@ ohos_unittest("RdbResultSetImplTest") { "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "c_utils:utils", + "googletest:gmock_main", "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", @@ -537,6 +539,7 @@ ohos_unittest("RdbServiceTest") { "access_token:libnativetoken", "c_utils:utils", "device_manager:devicemanagersdk", + "googletest:gmock_main", "googletest:gtest_main", "hilog:libhilog", "ipc:ipc_core", diff --git a/services/distributeddataservice/service/test/mock/cloud_db_mock.h b/services/distributeddataservice/service/test/mock/cloud_db_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..d86aad27f92286a0d72f53bb1f96decd9adab359 --- /dev/null +++ b/services/distributeddataservice/service/test/mock/cloud_db_mock.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef OHOS_CLOUD_DB_MOCK_H +#define OHOS_CLOUD_DB_MOCK_H + +#include + +#include "cloud_db.h" + +namespace OHOS::DistributedData { + +class MockCloudDB : public CloudDB { +public: + using Watcher = GeneralWatcher; + using Async = std::function>)>; + using Devices = std::vector; + + MOCK_METHOD(int32_t, Execute, (const std::string &, const std::string &, const VBucket &), (override)); + MOCK_METHOD(int32_t, BatchInsert, (const std::string &, VBuckets &&, VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchUpdate, (const std::string &, VBuckets &&, VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchUpdate, (const std::string &, VBuckets &&, const VBuckets &), (override)); + MOCK_METHOD(int32_t, BatchDelete, (const std::string &, VBuckets &), (override)); + MOCK_METHOD( + (std::pair>), Query, (const std::string &, const VBucket &), (override)); + MOCK_METHOD((std::pair>), Query, (GenQuery &, const VBucket &), (override)); + MOCK_METHOD(int32_t, PreSharing, (const std::string &, VBuckets &), (override)); + MOCK_METHOD(int32_t, Sync, (const Devices &, int32_t, const GenQuery &, Async, int32_t), (override)); + MOCK_METHOD(int32_t, Watch, (int32_t, Watcher &), (override)); + MOCK_METHOD(int32_t, Unwatch, (int32_t, Watcher &), (override)); + MOCK_METHOD(int32_t, Lock, (), (override)); + MOCK_METHOD(int32_t, Heartbeat, (), (override)); + MOCK_METHOD(int32_t, Unlock, (), (override)); + MOCK_METHOD(int64_t, AliveTime, (), (override)); + MOCK_METHOD(int32_t, Close, (), (override)); + MOCK_METHOD((std::pair), GetEmptyCursor, (const std::string &), (override)); + MOCK_METHOD(void, SetPrepareTraceId, (const std::string &), (override)); +}; +} // namespace OHOS::DistributedData +#endif // OHOS_CLOUD_DB_MOCK_H diff --git a/services/distributeddataservice/service/test/mock/cursor_mock.h b/services/distributeddataservice/service/test/mock/cursor_mock.h index c63bdacc07e7f0ecb790e23e8a881339105c97d3..57be55a6fbef71f9e58a4a8be84bffedff7ea4e5 100644 --- a/services/distributeddataservice/service/test/mock/cursor_mock.h +++ b/services/distributeddataservice/service/test/mock/cursor_mock.h @@ -14,6 +14,8 @@ */ #ifndef OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H #define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H +#include + #include #include #include @@ -45,6 +47,22 @@ private: std::shared_ptr resultSet_; int32_t index_ = 0; }; + +class MockCursor : public DistributedData::Cursor { + MOCK_METHOD(int32_t, GetColumnNames, (std::vector &names), (const, override)); + MOCK_METHOD(int32_t, GetColumnName, (int32_t col, std::string &name), (const, override)); + MOCK_METHOD(int32_t, GetColumnType, (int32_t col), (const, override)); + MOCK_METHOD(int32_t, GetCount, (), (const, override)); + MOCK_METHOD(int32_t, MoveToFirst, (), (override)); + MOCK_METHOD(int32_t, MoveToNext, (), (override)); + MOCK_METHOD(int32_t, MoveToPrev, (), (override)); + MOCK_METHOD(int32_t, GetEntry, (VBucket &entry), (override)); + MOCK_METHOD(int32_t, GetRow, (VBucket &data), (override)); + MOCK_METHOD(int32_t, Get, (int32_t col, Value &value), (override)); + MOCK_METHOD(int32_t, Get, (const std::string &col, Value &value), (override)); + MOCK_METHOD(int32_t, Close, (), (override)); + MOCK_METHOD(bool, IsEnd, (), (override)); +}; } // namespace DistributedData } // namespace OHOS #endif // OHOS_DISTRIBUTEDDATA_SERVICE_TEST_CURSOR_MOCK_H diff --git a/services/distributeddataservice/service/test/rdb_cloud_test.cpp b/services/distributeddataservice/service/test/rdb_cloud_test.cpp index f64e67f44e155d5a872dc82d5bb4bdeb6bb86604..d0c09e288a0b77cab27c70ac82a8d9bf15de1daa 100644 --- a/services/distributeddataservice/service/test/rdb_cloud_test.cpp +++ b/services/distributeddataservice/service/test/rdb_cloud_test.cpp @@ -16,27 +16,77 @@ #include "rdb_cloud.h" +#include "cloud_db_mock.h" +#include "cursor_mock.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" #include "log_print.h" using namespace testing::ext; +using namespace testing; using namespace OHOS::DistributedData; using namespace OHOS::DistributedRdb; using DBVBucket = DistributedDB::VBucket; using DBStatus = DistributedDB::DBStatus; -std::vector g_DBVBucket = { { { "#gid", { "0000000" } }, { "#flag", { true } }, +using DBAsset = DistributedDB::Asset; +using DBAssets = DistributedDB::Assets; +using AssetOpType = DistributedDB::AssetOpType; +using AssetStatus = DistributedDB::AssetStatus; +DBAsset assetValue1 = { .version = 1, + .name = "texture_diffuse", + .assetId = "123", + .subpath = "textures/environment", + .uri = "http://asset.com/textures/123.jpg", + .modifyTime = "2025-04-05T12:30:00Z", + .createTime = "2025-04-05T10:15:00Z", + .size = "1024", + .hash = "sha256-abc123", + .flag = static_cast(AssetOpType::INSERT), + .status = static_cast(AssetStatus::NORMAL), + .timestamp = std::time(nullptr) }; + +DBAsset assetValue2 = { .version = 2, + .name = "texture_diffuse", + .assetId = "456", + .subpath = "textures/environment", + .uri = "http://asset.com/textures/456.jpg", + .modifyTime = "2025-06-19T12:30:00Z", + .createTime = "2025-04-05T10:15:00Z", + .size = "1024", + .hash = "sha256-abc456", + .flag = static_cast(AssetOpType::UPDATE), + .status = static_cast(AssetStatus::NORMAL), + .timestamp = std::time(nullptr) }; + +DBAssets assetsValue = { assetValue1, assetValue2 }; +std::vector g_DBVBuckets = { { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, - { "#_query", { Bytes({ 1, 2, 3, 4 }) } } } }; + { "#_error", { "E_ERROR" } }, { "#_error", { "INVALID" } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } }, + { "#asset", assetValue1 }, { "#assets", assetsValue } } }; +DBVBucket g_DBVBucket = { { "#value", { int64_t(100) } } }; + namespace OHOS::Test { namespace DistributedRDBTest { class RdbCloudTest : public testing::Test { public: - static void SetUpTestCase(void){}; - static void TearDownTestCase(void){}; + static void SetUpTestCase(); + static void TearDownTestCase(); void SetUp(){}; void TearDown(){}; + static inline std::shared_ptr mockCloudDB = nullptr; + static constexpr int32_t COUNT = 2; }; +void RdbCloudTest::SetUpTestCase() +{ + mockCloudDB = std::make_shared(); +} + +void RdbCloudTest::TearDownTestCase() +{ + mockCloudDB = nullptr; +} + /** * @tc.name: RdbCloudTest001 * @tc.desc: RdbCloud BatchInsert BatchUpdate BatchDelete test. @@ -51,11 +101,11 @@ HWTEST_F(RdbCloudTest, RdbCloudTest001, TestSize.Level1) std::shared_ptr cloudDB = std::make_shared(); RdbCloud rdbCloud(cloudDB, &bindAssets); std::string tableName = "testTable"; - auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBucket), g_DBVBucket); + auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBuckets), g_DBVBuckets); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - result = rdbCloud.BatchUpdate(tableName, std::move(g_DBVBucket), g_DBVBucket); + result = rdbCloud.BatchUpdate(tableName, std::move(g_DBVBuckets), g_DBVBuckets); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - result = rdbCloud.BatchDelete(tableName, g_DBVBucket); + result = rdbCloud.BatchDelete(tableName, g_DBVBuckets); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); } @@ -75,18 +125,14 @@ HWTEST_F(RdbCloudTest, RdbCloudTest002, TestSize.Level1) rdbCloud.Lock(); std::string traceId = "id"; rdbCloud.SetPrepareTraceId(traceId); - auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBucket), g_DBVBucket); + auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBuckets), g_DBVBuckets); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - DBVBucket extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}}, {"#_query", {Bytes({ 1, 2, 3, 4 })}} - }; - result = rdbCloud.Query(tableName, extends, g_DBVBucket); + DBVBucket extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } }; + result = rdbCloud.Query(tableName, extends, g_DBVBuckets); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - std::vector vBuckets = { - {{"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}}, {"#_query", {Bytes({ 1, 2, 3, 4 })}}} - }; + std::vector vBuckets = { { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } } }; rdbCloud.PreSharing(tableName, vBuckets); result = rdbCloud.HeartBeat(); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); @@ -110,27 +156,20 @@ HWTEST_F(RdbCloudTest, RdbCloudTest003, TestSize.Level1) std::shared_ptr cloudDB = std::make_shared(); RdbCloud rdbCloud(cloudDB, &bindAssets); std::string tableName = "testTable"; - DBVBucket extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(1)}} - }; - std::vector data = { - {{"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}} - }; + DBVBucket extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(1) } } }; + std::vector data = { { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } } } }; auto result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_query", {Bytes({ 1, 2, 3, 4 })}} - }; + extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_query", { Bytes({ 1, 2, 3, 4 }) } } }; result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); - extends = { - {"#gid", {"0000000"}}, {"#flag", {true}}, {"#value", {int64_t(100)}}, {"#float", {double(100)}}, - {"#_type", {int64_t(0)}} - }; + extends = { { "#gid", { "0000000" } }, { "#flag", { true } }, { "#value", { int64_t(100) } }, + { "#float", { double(100) } }, { "#_type", { int64_t(0) } } }; result = rdbCloud.Query(tableName, extends, data); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); } @@ -209,27 +248,135 @@ HWTEST_F(RdbCloudTest, ConvertStatus, TestSize.Level1) HWTEST_F(RdbCloudTest, ConvertQuery, TestSize.Level1) { RdbCloud::DBQueryNodes nodes; - DistributedDB::QueryNode node = { DistributedDB::QueryNodeType::IN, "", {int64_t(1)} }; + DistributedDB::QueryNode node = { DistributedDB::QueryNodeType::IN, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::OR, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::OR, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::AND, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::AND, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::EQUAL_TO, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::EQUAL_TO, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::BEGIN_GROUP, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::BEGIN_GROUP, "", { int64_t(1) } }; nodes.push_back(node); - node = { DistributedDB::QueryNodeType::END_GROUP, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::END_GROUP, "", { int64_t(1) } }; nodes.push_back(node); - + auto result = RdbCloud::ConvertQuery(std::move(nodes)); EXPECT_EQ(result.size(), 6); nodes.clear(); - node = { DistributedDB::QueryNodeType::ILLEGAL, "", {int64_t(1)} }; + node = { DistributedDB::QueryNodeType::ILLEGAL, "", { int64_t(1) } }; nodes.push_back(node); result = RdbCloud::ConvertQuery(std::move(nodes)); EXPECT_EQ(result.size(), 0); } + +/** +* @tc.name: PostEvent002 +* @tc.desc: RdbCloud PostEvent test snapshots contains asset.uri. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent002, TestSize.Level1) +{ + BindAssets snapshots; + std::shared_ptr snapshot; + snapshots.bindAssets->insert_or_assign(assetValue1.uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), &snapshots); + std::string tableName = "testTable"; + auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBuckets), g_DBVBuckets); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: PostEvent003 +* @tc.desc: RdbCloud PostEvent test snapshots does not contains asset.uri. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent003, TestSize.Level1) +{ + BindAssets snapshots; + std::shared_ptr snapshot; + std::string uri = "testuri"; + snapshots.bindAssets->insert_or_assign(uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), &snapshots); + std::string tableName = "testTable"; + auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBuckets), g_DBVBuckets); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: PostEvent004 +* @tc.desc: RdbCloud PostEvent test the snapshot contained in the snapshots is nullpt. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, PostEvent004, TestSize.Level1) +{ + BindAssets snapshots; + std::shared_ptr snapshot = nullptr; + std::string uri = "testuri"; + snapshots.bindAssets->insert_or_assign(uri, snapshot); + RdbCloud rdbCloud(std::make_shared(), &snapshots); + std::string tableName = "testTable"; + auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBuckets), g_DBVBuckets); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} + +/** +* @tc.name: Query001 +* @tc.desc: RdbCloud Query test the cursor is nullptr and code is not E_OK. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query001, TestSize.Level1) +{ + std::shared_ptr cursor = nullptr; + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_SKIP_ASSET, cursor))); + BindAssets snapshots; + RdbCloud rdbCloud(std::make_shared(), &snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::SKIP_ASSET); +} + +/** +* @tc.name: Query002 +* @tc.desc: RdbCloud Query test code is QUERY_END. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query002, TestSize.Level1) +{ + std::shared_ptr mockCursor; + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_SKIP_ASSET, mockCursor))); + EXPECT_CALL(*mockCursor, GetCount()).WillOnce(Return(COUNT)); + EXPECT_CALL(*mockCursor, GetEntry(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockCursor, MoveToNext()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*mockCursor, IsEnd()).WillOnce(Return(true)); + + BindAssets snapshots; + RdbCloud rdbCloud(std::make_shared(), &snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::QUERY_END); +} + +/** +* @tc.name: Query003 +* @tc.desc: RdbCloud Query test code is CLOUD_ERROR. +* @tc.type: FUNC +*/ +HWTEST_F(RdbCloudTest, Query003, TestSize.Level1) +{ + std::shared_ptr mockCursor; + std::string tableName = "testTable"; + EXPECT_CALL(*mockCloudDB, Query(tableName, _)).WillOnce(Return(std::make_pair(E_SKIP_ASSET, mockCursor))); + EXPECT_CALL(*mockCursor, GetCount()).WillOnce(Return(COUNT)); + EXPECT_CALL(*mockCursor, GetEntry(_)).WillOnce(Return(E_OK)).WillOnce(Return(E_ERROR)); + EXPECT_CALL(*mockCursor, MoveToNext()).WillRepeatedly(Return(E_OK)); + EXPECT_CALL(*mockCursor, IsEnd()).WillOnce(Return(false)); + + BindAssets snapshots; + RdbCloud rdbCloud(std::make_shared(), &snapshots); + auto result = rdbCloud.Query(tableName, g_DBVBucket, g_DBVBuckets); + EXPECT_EQ(result, DBStatus::CLOUD_ERROR); +} } // namespace DistributedRDBTest } // namespace OHOS::Test \ No newline at end of file