diff --git a/services/distributeddataservice/app/src/kvstore_data_service.cpp b/services/distributeddataservice/app/src/kvstore_data_service.cpp index b598a653a38e6094d5def17c8f1388246dc9b805..40f7c39f70c88c6a5e934fcc7e985d2fb11bb9cb 100644 --- a/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -854,8 +854,8 @@ void KvStoreDataService::KvStoreClientDeathObserverImpl::Reset() bool KvStoreDataService::KvStoreClientDeathObserverImpl::Insert(sptr observer, const std::string &featureName) { - if (observerProxy_.size() < MAX_CLIENT_DEATH_OBSERVER_SIZE && - observerProxy_.insert_or_assign(featureName, observer).second) { + if (observer != nullptr && observerProxy_.size() < MAX_CLIENT_DEATH_OBSERVER_SIZE && + observerProxy_.insert({featureName, observer}).second) { observer->AddDeathRecipient(deathRecipient_); return true; } diff --git a/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp b/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp index 01c16a2390e7e71e399c2ca77ad720c2c12b3760..de8bb44d9b4ccfa33ccde01e246a7a938dffcd26 100644 --- a/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp +++ b/services/distributeddataservice/app/src/session_manager/route_head_handler_impl.cpp @@ -105,7 +105,7 @@ DistributedDB::DBStatus RouteHeadHandlerImpl::GetHeadDataSize(uint32_t &headSize ZLOGI("meta data permitted"); return DistributedDB::OK; } - if(!DmAdapter::GetInstance().IsOHOSType(session_.targetDeviceId)) { + if (!DmAdapter::GetInstance().IsOHOSType(session_.targetDeviceId)) { ZLOGD("devicdId:%{public}s is not oh type", Anonymous::Change(session_.targetDeviceId).c_str()); if (appId_.empty()) { diff --git a/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp b/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp index 8e761fdcb58b4ecc93fef43a2e10c17500fa77bd..65f8627e6d0a9b2c09ebb975a1e085a5665f0d4f 100644 --- a/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp +++ b/services/distributeddataservice/app/test/unittest/kvstore_data_service_test.cpp @@ -153,6 +153,29 @@ HWTEST_F(KvStoreDataServiceTest, RegisterClientDeathObserver001, TestSize.Level1 EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; } +/** +* @tc.name: RegisterClientDeathObserver002 +* @tc.desc: register client death observer +* @tc.type: FUNC +*/ +HWTEST_F(KvStoreDataServiceTest, RegisterClientDeathObserver002, TestSize.Level1) +{ + AppId appId; + appId.appId = "app0"; + KvStoreDataService kvDataService; + Bootstrap::GetInstance().LoadComponents(); + Bootstrap::GetInstance().LoadCheckers(); + KvStoreMetaManager::GetInstance().BindExecutor(std::make_shared(12, 5)); + KvStoreMetaManager::GetInstance().InitMetaParameter(); + Status status = kvDataService.RegisterClientDeathObserver(appId, nullptr, ""); + EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; + for (int i = 0; i < 17; i++) { + auto featureName = std::to_string(i); + status = kvDataService.RegisterClientDeathObserver(appId, new KvStoreClientDeathObserver(), featureName); + EXPECT_EQ(status, Status::SUCCESS) << "RegisterClientDeathObserver failed"; + } +} + /** * @tc.name: Exit001 * @tc.desc: feature Exit diff --git a/services/distributeddataservice/framework/include/serializable/serializable.h b/services/distributeddataservice/framework/include/serializable/serializable.h index 2fb72495ad79c445ee8d53502cc92585aa39a14e..a69eec77d1290190a7e3379efd251616f25c235c 100644 --- a/services/distributeddataservice/framework/include/serializable/serializable.h +++ b/services/distributeddataservice/framework/include/serializable/serializable.h @@ -33,7 +33,7 @@ namespace DistributedData { struct Serializable { public: class iterator; - class JSONWrapper final{ + class JSONWrapper final { public: friend iterator; enum class Type : uint8_t { @@ -100,7 +100,7 @@ public: API_EXPORT bool operator==(const std::vector& value) const; API_EXPORT bool empty() const; API_EXPORT JSONWrapper& operator=(const std::map& value); - API_EXPORT JSONWrapper &operator=(const std::map& value); + API_EXPORT JSONWrapper& operator=(const std::map& value); API_EXPORT bool erase(const std::string& key); API_EXPORT bool erase(int index); private: diff --git a/services/distributeddataservice/framework/serializable/serializable.cpp b/services/distributeddataservice/framework/serializable/serializable.cpp index 5cb4c926534ab3b91596ad723fd2a61f5d39430c..e3b10b4ecfbbda10aa350fa81b2074285e7fd843 100644 --- a/services/distributeddataservice/framework/serializable/serializable.cpp +++ b/services/distributeddataservice/framework/serializable/serializable.cpp @@ -291,7 +291,7 @@ Serializable::JSONWrapper &Serializable::JSONWrapper::operator=(JSONWrapper &&js jsonWrapper.root_ = nullptr; key_ = std::move(jsonWrapper.key_); children_ = std::move(jsonWrapper.children_); - needDel_ = jsonWrapper.needDel_; + needDel_ = jsonWrapper.needDel_; return *this; } @@ -377,8 +377,33 @@ Serializable::JSONWrapper &Serializable::JSONWrapper::operator=(int32_t value) Serializable::JSONWrapper &Serializable::JSONWrapper::operator=(uint32_t value) { - int32_t number = static_cast(value); - return operator=(number); + if (root_ == nullptr && cJSON_IsNull(json_)) { + cJSON_Delete(json_); + json_ = nullptr; + } + if (json_ == nullptr) { + json_ = cJSON_CreateNumber(static_cast(value)); + if (json_ == nullptr || root_ == nullptr) { + return *this; + } + AddToRoot(); + } + if (json_ == nullptr) { + return *this; + } + if (cJSON_IsNumber(json_)) { + cJSON_SetNumberValue(json_, static_cast(value)); + return *this; + } + cJSON *node = cJSON_CreateNumber(static_cast(value)); + if (node == nullptr) { + return *this; + } + if (!ReplaceNode(node)) { + ZLOGE("replace node failed."); + cJSON_Delete(node); + } + return *this; } Serializable::JSONWrapper &Serializable::JSONWrapper::operator=(int64_t value) @@ -496,7 +521,7 @@ Serializable::JSONWrapper &Serializable::JSONWrapper::operator=(const std::vecto auto node = cJSON_CreateNumber(value[i]); if (!node || !cJSON_AddItemToArray(json_, node)) { cJSON_Delete(json_); - cJSON_Delete(node); + cJSON_Delete(node); json_ = nullptr; children_.clear(); return *this; @@ -527,7 +552,7 @@ bool Serializable::JSONWrapper::ReplaceNode(cJSON *node) if (success) { json_ = node; - children_.clear(); + children_.clear(); } return success; } @@ -575,7 +600,8 @@ Serializable::JSONWrapper &Serializable::JSONWrapper::operator[](size_t index) if (!is_array()) { ZLOGE("cannot use operator[]."); } - int size = cJSON_GetArraySize(json_); + int rawSize = cJSON_GetArraySize(json_); + size_t size = (rawSize < 0) ? 0 : static_cast(rawSize); auto len = children_.size(); while (len < size) { auto item = cJSON_GetArrayItem(json_, len); @@ -583,11 +609,12 @@ Serializable::JSONWrapper &Serializable::JSONWrapper::operator[](size_t index) len++; } if (index > len) { - ZLOGE("cannot use operator[]."); + ZLOGE("index over limit."); } - if (index == len) { + while (len <= index) { auto item = cJSON_GetArrayItem(json_, len); children_.push_back(std::make_shared(item, json_)); + len++; } return *children_[index]; } @@ -597,7 +624,8 @@ Serializable::JSONWrapper &Serializable::JSONWrapper::operator[](size_t index) c if (!is_array()) { ZLOGE("invalid args."); } - int size = cJSON_GetArraySize(json_); + int rawSize = cJSON_GetArraySize(json_); + size_t size = (rawSize < 0) ? 0 : static_cast(rawSize); if (index >= size) { ZLOGE("invalid args."); } @@ -607,6 +635,14 @@ Serializable::JSONWrapper &Serializable::JSONWrapper::operator[](size_t index) c children_.push_back(std::make_shared(item, json_)); len++; } + if (index > len) { + ZLOGE("index over limit."); + } + while (len <= index) { + auto item = cJSON_GetArrayItem(json_, len); + children_.push_back(std::make_shared(item, json_)); + len++; + } return *children_[index]; } @@ -708,7 +744,8 @@ bool Serializable::JSONWrapper::get_to(uint32_t &values) const if (json_ == nullptr || !is_number_unsigned()) { return false; } - values = json_->valueint; + double num = cJSON_GetNumberValue(json_); + values = static_cast(num); return true; } @@ -717,7 +754,8 @@ bool Serializable::JSONWrapper::get_to(int64_t &values) const if (json_ == nullptr || !is_number_integer()) { return false; } - values = json_->valueint; + double num = cJSON_GetNumberValue(json_); + values = static_cast(num); return true; } @@ -726,7 +764,8 @@ bool Serializable::JSONWrapper::get_to(uint64_t &values) const if (json_ == nullptr || !is_number_unsigned()) { return false; } - values = json_->valueint; + double num = cJSON_GetNumberValue(json_); + values = static_cast(num); return true; } @@ -831,7 +870,8 @@ Serializable::iterator Serializable::JSONWrapper::end() const void Serializable::JSONWrapper::SyncChildren() const { - auto size = cJSON_GetArraySize(json_); + int rawSize = cJSON_GetArraySize(json_); + size_t size = (rawSize < 0) ? 0 : static_cast(rawSize); auto len = children_.size(); if (len != size) { children_.clear(); @@ -927,7 +967,7 @@ void Serializable::JSONWrapper::push_back(const JSONWrapper &value) if (is_array()) { cJSON *newJson = cJSON_Duplicate(value.json_, 1); cJSON_AddItemToArray(json_, newJson); - children_.push_back(std::make_shared(newJson, json_)); + children_.push_back(std::make_shared(newJson, json_)); } } @@ -941,7 +981,9 @@ bool Serializable::JSONWrapper::operator==(const std::map(rawSize); + if (size != value.size()) { return false; } for (const auto& pair : value) { @@ -958,7 +1000,9 @@ bool Serializable::JSONWrapper::operator==(const std::map if (!is_object()) { return false; } - if (cJSON_GetArraySize(json_) != value.size()) { + int rawSize = cJSON_GetArraySize(json_); + size_t size = (rawSize < 0) ? 0 : static_cast(rawSize); + if (size != value.size()) { return false; } for (const auto& pair : value) { @@ -975,7 +1019,9 @@ bool Serializable::JSONWrapper::operator==(const std::vector& value if (!is_array()) { return false; } - if (cJSON_GetArraySize(json_) != value.size()) { + int rawSize = cJSON_GetArraySize(json_); + size_t size = (rawSize < 0) ? 0 : static_cast(rawSize); + if (size != value.size()) { return false; } for (size_t i = 0; i < value.size(); ++i) { @@ -1046,7 +1092,8 @@ bool Serializable::JSONWrapper::erase(int index) return false; } - int size = cJSON_GetArraySize(json_); + int rawSize = cJSON_GetArraySize(json_); + size_t size = (rawSize < 0) ? 0 : static_cast(rawSize); auto len = children_.size(); while (len < size) { auto item = cJSON_GetArrayItem(json_, len); diff --git a/services/distributeddataservice/framework/test/serializable_test.cpp b/services/distributeddataservice/framework/test/serializable_test.cpp index a5992e84b59d44142f74d63ad9e2df03f7e9988d..913c745b6772b849f51dd4a269e351789e8613ba 100644 --- a/services/distributeddataservice/framework/test/serializable_test.cpp +++ b/services/distributeddataservice/framework/test/serializable_test.cpp @@ -128,10 +128,15 @@ HWTEST_F(SerializableTest, GetNormalVal, TestSize.Level2) normal.value = -56; normal.isClear = true; normal.cols = {"adfasdfas"}; - auto jstr = Serializable::JSONWrapper::to_string(normal.Marshall()); + auto json = normal.Marshall(); + auto jstr = Serializable::JSONWrapper::to_string(json); Normal normal1; normal1.Unmarshall(jstr); ASSERT_TRUE(normal == normal1) << normal1.name; + ASSERT_FALSE(normal1.Unmarshall("")); + ASSERT_FALSE(normal1.Unmarshall("{")); + std::vector testVec = {"adfasdfas", "banana"}; + ASSERT_FALSE(json["cols"] == testVec); } /** @@ -302,6 +307,82 @@ HWTEST_F(SerializableTest, SetPointerValue, TestSize.Level2) ASSERT_TRUE(in == out) << in.count; } +/** +* @tc.name: SetStringMapValue +* @tc.desc: set map value with string param. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, SetStringMapValue, TestSize.Level2) +{ + struct TestStringMap final : public Serializable { + public: + std::map testMap = { + {"name", "John"}, + {"email", "john@example.com"} + }; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(testMap)], testMap); + return true; + } + bool Unmarshal(const json &node) override + { + GetValue(node, GET_NAME(testMap), testMap); + return true; + } + bool operator==(const TestStringMap &other) const + { + return testMap == other.testMap; + } + }; + + TestStringMap in; + in.testMap["name"] = "New York"; + in.testMap["email"] = "john@sample.com"; + auto json = Serializable::JSONWrapper::to_string(in.Marshall()); + TestStringMap out; + out.Unmarshall(json); + ASSERT_TRUE(in == out); +} + +/** +* @tc.name: SetStringMapValue +* @tc.desc: set map value with int param. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, SetMapValue, TestSize.Level2) +{ + struct TestMap final : public Serializable { + public: + std::map testMap = { + {"id", 123456}, + {"version", 42} + }; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(testMap)], testMap); + return true; + } + bool Unmarshal(const json &node) override + { + GetValue(node, GET_NAME(testMap), testMap); + return true; + } + bool operator==(const TestMap &other) const + { + return testMap == other.testMap; + } + }; + + TestMap in; + in.testMap["version"] = 552; + auto json = Serializable::JSONWrapper::to_string(in.Marshall()); + + TestMap out; + out.Unmarshall(json); + ASSERT_TRUE(in == out); +} + /** * @tc.name: IsJson * @tc.desc: is json. @@ -329,8 +410,225 @@ HWTEST_F(SerializableTest, ToString, TestSize.Level1) wrapper["is_student"] = false; std::string result = wrapper; EXPECT_EQ(result, "{\"name\":\"Alice\",\"age\":30,\"height\":1.75,\"is_student\":false}"); + std::map testUintMap = { + {"id", 123456}, + {"version", 42} + }; + std::map testStringMap = { + {"name", "John"}, + {"email", "john@example.com"} + }; + wrapper["testUintMap"] = testUintMap; + wrapper["testStringMap"] = testStringMap; EXPECT_TRUE(wrapper["name"].is_string()); EXPECT_TRUE(wrapper["age"].is_number_float()); EXPECT_TRUE(wrapper["is_student"].is_boolean()); } + +/** +* @tc.name: OperatorTest +* @tc.desc: test operator. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, OperatorTest, TestSize.Level1) +{ + std::string name = "Alice"; + int32_t count = -30; + uint32_t status = 1; + uint64_t type = 5; + int64_t value = 2; + double test = 1.75; + bool isStudent = false; + Serializable::JSONWrapper wrapper; + wrapper["name"] = name; + wrapper["count"] = count; + wrapper["status"] = status; + wrapper["type"] = type; + wrapper["value"] = value; + wrapper["test"] = test; + wrapper["isStudent"] = isStudent; + EXPECT_TRUE(wrapper["name"].is_string()); + EXPECT_TRUE(wrapper["test"].is_number_float()); + EXPECT_TRUE(wrapper["count"].is_number_integer()); + EXPECT_TRUE(wrapper["status"].is_number_unsigned()); + EXPECT_TRUE(wrapper["isStudent"].is_boolean()); + std::string result = wrapper; + EXPECT_EQ(result, "{\"name\":\"Alice\",\"count\":-30,\"status\":1,\"type\":" + "5,\"value\":2,\"test\":1.75,\"isStudent\":false}"); + wrapper["name"] = isStudent; + EXPECT_TRUE(wrapper["name"].is_boolean()); + wrapper["count"] = status; + EXPECT_TRUE(wrapper["count"].is_number_unsigned()); + wrapper["status"] = count; + EXPECT_TRUE(wrapper["status"].is_number_integer()); + wrapper["isStudent"] = test; + result = wrapper; + EXPECT_EQ(result, "{\"name\":false,\"count\":1,\"status\":-30,\"type\":5," + "\"value\":2,\"test\":1.75,\"isStudent\":1.75}"); +} + +/** +* @tc.name: EraseTest +* @tc.desc: test erase. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, EraseTest, TestSize.Level2) +{ + Serializable::JSONWrapper wrapper; + wrapper = std::map{ + {"name", "John"}, {"age", "30"}, {"city", "New York"}}; + std::string res = wrapper.dump(); + EXPECT_EQ(res, "{\"age\":\"30\",\"city\":\"New York\",\"name\":\"John\"}"); + bool result = wrapper.erase("age"); + ASSERT_TRUE(result); + res = wrapper.dump(); + EXPECT_EQ(res, "{\"city\":\"New York\",\"name\":\"John\"}"); +} + +/** +* @tc.name: CompareUint +* @tc.desc: test compare. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, CompareUint, TestSize.Level2) +{ + Serializable::JSONWrapper wrapper; + wrapper = std::map{ + {"key1", 100}, + {"key2", 200}, + {"key3", 300} + }; + + std::map testMap1 = { + {"key1", 100}, + {"key2", 200} + }; + + bool result = wrapper == testMap1; + ASSERT_FALSE(result); + std::map testMap2 = { + {"key1", 100}, + {"key2", 200}, + {"key3", 300} + }; + result = wrapper == testMap2; + ASSERT_TRUE(result); +} + +/** +* @tc.name: CompareStringMap +* @tc.desc: test compare. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, CompareStringMap, TestSize.Level2) +{ + Serializable::JSONWrapper wrapper; + wrapper = std::map{ + {"name", "Bob"}, + {"age", "25"}, + {"job", "Engineer"} + }; + + std::map testMap1 = { + {"name", "Bob"}, + {"age", "25"} + }; + + bool result = wrapper == testMap1; + ASSERT_FALSE(result); + + std::map testMap2 = { + {"name", "Bob"}, + {"age", "25"}, + {"job", "Engineer"} + }; + result = wrapper == testMap2; + ASSERT_TRUE(result); +} + +/** +* @tc.name: BoundaryTest +* @tc.desc: test boundary. +* @tc.type: FUNC +*/ +HWTEST_F(SerializableTest, BoundaryTest, TestSize.Level1) +{ + struct TestBoundary : public Serializable { + int32_t int32Val; + uint32_t uint32Val; + int64_t int64Val; + uint64_t uint64Val; + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(int32Val)], int32Val); + SetValue(node[GET_NAME(uint32Val)], uint32Val); + SetValue(node[GET_NAME(int64Val)], int64Val); + SetValue(node[GET_NAME(uint64Val)], uint64Val); + return true; + } + bool Unmarshal(const json &node) override + { + bool success = true; + success = GetValue(node, GET_NAME(int32Val), int32Val) && success; + success = GetValue(node, GET_NAME(uint32Val), uint32Val) && success; + success = GetValue(node, GET_NAME(int64Val), int64Val) && success; + success = GetValue(node, GET_NAME(uint64Val), uint64Val) && success; + return success; + } + }; + TestBoundary in, out; + in.int32Val = INT32_MIN; + in.uint32Val = 0; + in.int64Val = -(1LL << 53) + 2; + in.uint64Val = 0; + + auto json = Serializable::JSONWrapper::to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); + + in.int32Val = INT32_MAX; + in.uint32Val = UINT32_MAX; + in.int64Val = (1LL << 53) - 2; + in.uint64Val = (1LL << 53) - 2; + + json = Serializable::JSONWrapper::to_string(in.Marshall()); + out.Unmarshall(json); + EXPECT_EQ(out.int32Val, in.int32Val); + EXPECT_EQ(out.uint32Val, in.uint32Val); + EXPECT_EQ(out.int64Val, in.int64Val); + EXPECT_EQ(out.uint64Val, in.uint64Val); +} + + +HWTEST_F(SerializableTest, ArrayTest, TestSize.Level1) +{ + struct TestBoundary : public Serializable { + std::vector vectorVal = {10, 20, 30, 40, 50}; + + bool Marshal(json &node) const override + { + SetValue(node[GET_NAME(vectorVal)], vectorVal); + return true; + } + + bool Unmarshal(const json &node) override + { + bool success = true; + success = GetValue(node, GET_NAME(vectorVal), vectorVal) && success; + return success; + } + }; + + TestBoundary in; + Serializable::JSONWrapper wrapper; + wrapper = in.Marshall(); + EXPECT_EQ(wrapper["vectorVal"][0].dump(), "10"); + EXPECT_EQ(wrapper["vectorVal"][1].dump(), "20"); + EXPECT_EQ(wrapper["vectorVal"][4].dump(), "50"); + EXPECT_EQ(wrapper["vectorVal"][5].dump(), ""); + EXPECT_EQ(wrapper["vectorVal"][10].dump(), ""); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/services/distributeddataservice/service/rdb/rdb_general_store.cpp index ba0299bddaf21e6f970eafa881b5f75cc9b772aa..3992cc45c2f727468a7d451852c4ac63268855d6 100644 --- a/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -965,6 +965,7 @@ void RdbGeneralStore::SetConfig(const StoreConfig &storeConfig) if (delegate_ == nullptr) { ZLOGE("database already closed!, tableMode is :%{public}d", storeConfig.tableMode.has_value() ? static_cast(storeConfig.tableMode.value()) : -1); + return; } if (storeConfig.tableMode.has_value()) { RelationalStoreDelegate::StoreConfig config;