1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "kv_general_ut.h"
17 #include "kv_store_errno.h"
18 #include "storage_engine_manager.h"
19 #include "virtual_cloud_db.h"
20
21 namespace DistributedDB {
SetUp()22 void KVGeneralUt::SetUp()
23 {
24 virtualCloudDb_ = std::make_shared<VirtualCloudDb>();
25 CloseAllDelegate();
26 BasicUnitTest::SetUp();
27 }
28
TearDown()29 void KVGeneralUt::TearDown()
30 {
31 CloseAllDelegate();
32 virtualCloudDb_ = nullptr;
33 BasicUnitTest::TearDown();
34 }
35
InitDelegate(const StoreInfo & info)36 int KVGeneralUt::InitDelegate(const StoreInfo &info)
37 {
38 KvStoreDelegateManager manager(info.appId, info.userId);
39 manager.SetKvStoreConfig(GetKvStoreConfig());
40 KvStoreNbDelegate::Option option;
41 std::lock_guard<std::mutex> autoLock(storeMutex_);
42 if (option_.has_value()) {
43 option = option_.value();
44 }
45 KvStoreNbDelegate *store = nullptr;
46 DBStatus status = DBStatus::OK;
47 manager.GetKvStore(info.storeId, option, [&status, &store](DBStatus ret, KvStoreNbDelegate *delegate) {
48 status = ret;
49 store = delegate;
50 });
51 if (status != DBStatus::OK) {
52 LOGE("[KVGeneralUt] Init delegate failed %d", static_cast<int>(status));
53 return -E_INTERNAL_ERROR;
54 }
55 if (processCommunicator_ != nullptr) {
56 manager.SetProcessCommunicator(processCommunicator_);
57 }
58 stores_[info] = store;
59 LOGI("[KVGeneralUt] Init delegate app %s store %s user %s success", info.appId.c_str(),
60 info.storeId.c_str(), info.userId.c_str());
61 return E_OK;
62 }
63
CloseDelegate(const StoreInfo & info)64 int KVGeneralUt::CloseDelegate(const StoreInfo &info)
65 {
66 std::lock_guard<std::mutex> autoLock(storeMutex_);
67 auto iter = stores_.find(info);
68 if (iter == stores_.end()) {
69 LOGW("[KVGeneralUt] Close not exist delegate app %s store %s user %s", info.appId.c_str(),
70 info.storeId.c_str(), info.userId.c_str());
71 return E_OK;
72 }
73 KvStoreDelegateManager manager(info.appId, info.userId);
74 manager.SetKvStoreConfig(GetKvStoreConfig());
75 auto ret = manager.CloseKvStore(iter->second);
76 if (ret != DBStatus::OK) {
77 LOGI("[KVGeneralUt] Close delegate app %s store %s user %s failed %d", info.appId.c_str(),
78 info.storeId.c_str(), info.userId.c_str(), static_cast<int>(ret));
79 return -E_INTERNAL_ERROR;
80 }
81 LOGI("[KVGeneralUt] Close delegate app %s store %s user %s success", info.appId.c_str(),
82 info.storeId.c_str(), info.userId.c_str());
83 stores_.erase(iter);
84 return E_OK;
85 }
86
CloseAllDelegate()87 void KVGeneralUt::CloseAllDelegate()
88 {
89 std::vector<StoreInfo> infoList;
90 {
91 std::lock_guard<std::mutex> autoLock(storeMutex_);
92 for (const auto &item : stores_) {
93 infoList.push_back(item.first);
94 }
95 }
96 for (const auto &info : infoList) {
97 (void)CloseDelegate(info);
98 }
99 }
100
SetOption(const KvStoreNbDelegate::Option & option)101 void KVGeneralUt::SetOption(const KvStoreNbDelegate::Option &option)
102 {
103 std::lock_guard<std::mutex> autoLock(storeMutex_);
104 option_ = option;
105 }
106
GetKvStoreConfig()107 KvStoreConfig KVGeneralUt::GetKvStoreConfig()
108 {
109 KvStoreConfig config;
110 config.dataDir = GetTestDir();
111 return config;
112 }
113
GetDelegate(const DistributedDB::StoreInfo & info) const114 KvStoreNbDelegate *KVGeneralUt::GetDelegate(const DistributedDB::StoreInfo &info) const
115 {
116 std::lock_guard<std::mutex> autoLock(storeMutex_);
117 auto iter = stores_.find(info);
118 if (iter == stores_.end()) {
119 LOGW("[KVGeneralUt] Not exist delegate app %s store %s user %s", info.appId.c_str(),
120 info.storeId.c_str(), info.userId.c_str());
121 return nullptr;
122 }
123 return iter->second;
124 }
125
BlockPush(const StoreInfo & from,const StoreInfo & to,DBStatus expectRet)126 void KVGeneralUt::BlockPush(const StoreInfo &from, const StoreInfo &to, DBStatus expectRet)
127 {
128 auto fromStore = GetDelegate(from);
129 ASSERT_NE(fromStore, nullptr);
130 auto toDevice = GetDevice(to);
131 ASSERT_FALSE(toDevice.empty());
132 std::map<std::string, DBStatus> syncRet;
133 tool_.SyncTest(fromStore, {toDevice}, SyncMode::SYNC_MODE_PUSH_ONLY, syncRet);
134 for (const auto &item : syncRet) {
135 EXPECT_EQ(item.second, expectRet);
136 }
137 }
138
GetDataBaseSchema(bool invalidSchema)139 DataBaseSchema KVGeneralUt::GetDataBaseSchema(bool invalidSchema)
140 {
141 DataBaseSchema schema;
142 TableSchema tableSchema;
143 tableSchema.name = invalidSchema ? "invalid_schema_name" : CloudDbConstant::CLOUD_KV_TABLE_NAME;
144 Field field;
145 field.colName = CloudDbConstant::CLOUD_KV_FIELD_KEY;
146 field.type = TYPE_INDEX<std::string>;
147 field.primary = true;
148 tableSchema.fields.push_back(field);
149 field.colName = CloudDbConstant::CLOUD_KV_FIELD_DEVICE;
150 field.primary = false;
151 tableSchema.fields.push_back(field);
152 field.colName = CloudDbConstant::CLOUD_KV_FIELD_ORI_DEVICE;
153 tableSchema.fields.push_back(field);
154 field.colName = CloudDbConstant::CLOUD_KV_FIELD_VALUE;
155 tableSchema.fields.push_back(field);
156 field.colName = CloudDbConstant::CLOUD_KV_FIELD_DEVICE_CREATE_TIME;
157 field.type = TYPE_INDEX<int64_t>;
158 tableSchema.fields.push_back(field);
159 schema.tables.push_back(tableSchema);
160 return schema;
161 }
162
SetCloud(KvStoreNbDelegate * & delegate,bool invalidSchema)163 DBStatus KVGeneralUt::SetCloud(KvStoreNbDelegate *&delegate, bool invalidSchema)
164 {
165 std::lock_guard<std::mutex> autoLock(storeMutex_);
166 std::map<std::string, std::shared_ptr<ICloudDb>> cloudDbs;
167 cloudDbs[DistributedDBUnitTest::USER_ID] = virtualCloudDb_;
168 delegate->SetCloudDB(cloudDbs);
169 std::map<std::string, DataBaseSchema> schemas;
170 schemas[DistributedDBUnitTest::USER_ID] = GetDataBaseSchema(invalidSchema);
171 return delegate->SetCloudDbSchema(schemas);
172 }
173
GetDeviceEntries(KvStoreNbDelegate * delegate,const std::string & deviceId,bool isSelfDevice,std::vector<Entry> & entries)174 DBStatus KVGeneralUt::GetDeviceEntries(KvStoreNbDelegate *delegate, const std::string &deviceId, bool isSelfDevice,
175 std::vector<Entry> &entries)
176 {
177 if (isSelfDevice) {
178 communicatorAggregator_->SetLocalDeviceId(deviceId);
179 } else {
180 communicatorAggregator_->SetLocalDeviceId(deviceId + "_");
181 }
182 return delegate->GetDeviceEntries(deviceId, entries);
183 }
184
BlockCloudSync(const StoreInfo & from,const std::string & deviceId,DBStatus expectRet)185 void KVGeneralUt::BlockCloudSync(const StoreInfo &from, const std::string &deviceId, DBStatus expectRet)
186 {
187 auto fromStore = GetDelegate(from);
188 ASSERT_NE(fromStore, nullptr);
189
190 communicatorAggregator_->SetLocalDeviceId(deviceId);
191 CloudSyncOption syncOption;
192 syncOption.mode = SyncMode::SYNC_MODE_CLOUD_MERGE;
193 syncOption.users.push_back(DistributedDBUnitTest::USER_ID);
194 syncOption.devices.push_back("cloud");
195 tool_.BlockSync(fromStore, DBStatus::OK, syncOption, expectRet);
196 }
197
GetRemoteSoftwareVersion(const StoreInfo & info,const std::string & dev,const std::string & user)198 std::pair<DBStatus, uint64_t> KVGeneralUt::GetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev,
199 const std::string &user)
200 {
201 uint64_t version = 0;
202 int errCode = QueryMetaValue(info, dev, user,
203 [&version](const std::shared_ptr<Metadata> &metadata, const std::string &device,
204 const std::string &userId) {
205 version = metadata->GetRemoteSoftwareVersion(device, userId);
206 return E_OK;
207 });
208 return {TransferDBErrno(errCode), version};
209 }
210
GetRemoteSchemaVersion(const StoreInfo & info,const std::string & dev,const std::string & user)211 std::pair<DBStatus, uint64_t> KVGeneralUt::GetRemoteSchemaVersion(const StoreInfo &info, const std::string &dev,
212 const std::string &user)
213 {
214 uint64_t version = 0;
215 int errCode = QueryMetaValue(info, dev, user,
216 [&version](const std::shared_ptr<Metadata> &metadata, const std::string &device,
217 const std::string &userId) {
218 version = metadata->GetRemoteSchemaVersion(device, userId);
219 return E_OK;
220 });
221 return {TransferDBErrno(errCode), version};
222 }
223
SetRemoteSoftwareVersion(const StoreInfo & info,const std::string & dev,const std::string & user,uint64_t version)224 DBStatus KVGeneralUt::SetRemoteSoftwareVersion(const StoreInfo &info, const std::string &dev, const std::string &user,
225 uint64_t version)
226 {
227 int errCode = QueryMetaValue(info, dev, user,
228 [version](const std::shared_ptr<Metadata> &metadata, const std::string &device,
229 const std::string &userId) {
230 return metadata->SetRemoteSoftwareVersion(device, userId, version);
231 });
232 return TransferDBErrno(errCode);
233 }
234
GetLocalSchemaVersion(const DistributedDB::StoreInfo & info)235 std::pair<DBStatus, uint64_t> KVGeneralUt::GetLocalSchemaVersion(const DistributedDB::StoreInfo &info)
236 {
237 uint64_t version = 0;
238 int errCode = QueryMetaValue(info, "", "",
239 [&version](const std::shared_ptr<Metadata> &metadata, const std::string &device,
240 const std::string &userId) {
241 auto [ret, schemaVersion] = metadata->GetLocalSchemaVersion();
242 version = schemaVersion;
243 return ret;
244 });
245 return {TransferDBErrno(errCode), version};
246 }
247
QueryMetaValue(const StoreInfo & info,const std::string & dev,const std::string & user,const std::function<int (const std::shared_ptr<Metadata> &,const std::string &,const std::string &)> & queryFunc)248 int KVGeneralUt::QueryMetaValue(const StoreInfo &info, const std::string &dev, const std::string &user,
249 const std::function<int(const std::shared_ptr<Metadata> &, const std::string &, const std::string &)> &queryFunc)
250 {
251 int errCode = E_OK;
252 auto properties = GetDBProperties(info);
253 auto store = new(std::nothrow) SQLiteSingleVerNaturalStore;
254 if (store == nullptr) {
255 errCode = -E_INVALID_ARGS;
256 LOGI("[KVGeneralUt] create natural store failed with oom");
257 return errCode;
258 }
259 errCode = store->Open(properties);
260 if (errCode != E_OK) {
261 RefObject::KillAndDecObjRef(store);
262 return errCode;
263 }
264 auto meta = std::make_shared<Metadata>();
265 errCode = meta->Initialize(store);
266 if (errCode != E_OK) {
267 store->Close();
268 RefObject::KillAndDecObjRef(store);
269 return errCode;
270 }
271 if (queryFunc) {
272 errCode = queryFunc(meta, dev, user);
273 }
274 meta = nullptr;
275 store->Close();
276 RefObject::KillAndDecObjRef(store);
277 return errCode;
278 }
279
GetDBProperties(const StoreInfo & info)280 KvDBProperties KVGeneralUt::GetDBProperties(const StoreInfo &info)
281 {
282 KvDBProperties properties;
283 properties.SetStringProp(KvDBProperties::DATA_DIR, GetTestDir());
284 properties.SetStringProp(KvDBProperties::STORE_ID, info.storeId);
285 KvStoreNbDelegate::Option option;
286 std::lock_guard<std::mutex> autoLock(storeMutex_);
287 if (option_.has_value()) {
288 option = option_.value();
289 }
290 auto idDir = DBCommon::TransferStringToHex(DBCommon::GetStoreIdentifier(info, "", option.syncDualTupleMode, false));
291 properties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, idDir);
292 properties.SetStringProp(KvDBProperties::IDENTIFIER_DATA, idDir + "KVGeneralUt");
293 properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE);
294 return properties;
295 }
296 }