diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/BUILD.gn b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/BUILD.gn index bf1a5b8fc72d85936a2f667b614f582a6b071e55..6536f8057bde122d5c804d156105d54b5ee5fe45 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/BUILD.gn +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/BUILD.gn @@ -1,14 +1,86 @@ -/* -* Copyright (c) 2023 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. -*/ \ No newline at end of file +# Copyright (c) 2021 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. +import("//build/ohos.gni") + +config("distrdb_config") { + visibility = [ ":*" ] + include_dirs = [ + "src/common/include", + "src/executor/include", + "src/oh_adapter/include", + "src/oh_adapter/src", + "src/interface/include", + ] + + defines = [ + "SQLITE_ENABLE_SNAPSHOT", + "SQLITE_HAS_CODEC", + "SQLITE_ENABLE_JSON1", + "USING_HILOG_LOGGER", + "USE_SQLITE_SYMBOLS", + "SQLITE_ENABLE_DROPTABLE_CALLBACK", + ] + if (is_debug) { + defines += [ "TRACE_SQLITE_EXECUTE" ] + } +} + +config("distrdb_public_config") { + visibility = [ "*:*" ] + include_dirs = [ "include" ] +} + +group("build_module") { + deps = [ ":documentdb" ] +} + +ohos_shared_library("documentdb") { + sources = [ + "src/common/src/collection_option.cpp", + "src/common/src/db_config.cpp", + "src/common/src/doc_common.cpp", + "src/common/src/json_common.cpp", + "src/common/src/log_print.cpp", + "src/common/src/os_api.cpp", + "src/executor/base/grd_db_api.cpp", + "src/executor/document/grd_document_api.cpp", + "src/interface/src/collection.cpp", + "src/interface/src/doc_errno.cpp", + "src/interface/src/document_store.cpp", + "src/interface/src/document_store_manager.cpp", + "src/oh_adapter/src/json_object.cpp", + "src/oh_adapter/src/kv_store_manager.cpp", + "src/oh_adapter/src/sqlite_store_executor_impl.cpp", + "src/oh_adapter/src/sqlite_utils.cpp", + ] + + configs = [ ":distrdb_config" ] + public_configs = [ ":distrdb_public_config" ] + + deps = [ "//third_party/sqlite:sqlite" ] + + configs += [ "//third_party/cJSON:cJSON_config" ] + ldflags = [ "-Wl,--exclude-libs,ALL" ] + cflags_cc = [ "-fvisibility=hidden" ] + deps += [ "//third_party/cJSON:cjson" ] + + external_deps = [ + "c_utils:utils", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "hiviewdfx_hilog_native:libhilog", + ] + + subsystem_name = "distributeddatamgr" + part_name = "datamgr_service" +} diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_db_api.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_db_api.h index e607b0f5b1bfda71d69f1a972b168768bba08a2d..4ec0fc88c2b2c3b441d33861b9f48c3e9643bb42 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_db_api.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_db_api.h @@ -26,6 +26,8 @@ int GRD_DBOpen(const char *dbPath, const char *configStr, unsigned int flags, GR int GRD_DBClose(GRD_DB *db, unsigned int flags); +int GRD_Flush(GRD_DB *db, unsigned int flags); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_document/grd_document_api.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_document/grd_document_api.h index 96ad01e3b0a7f4bac02fa77e3861bf317d6489eb..a38ff58124385e9d8b4d85aa561781f13c8ddf33 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_document/grd_document_api.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_document/grd_document_api.h @@ -33,7 +33,7 @@ int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned in int GRD_UpdateDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *update, unsigned int flags); -int GRD_UpSertDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *document, unsigned int flags); +int GRD_UpsertDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *document, unsigned int flags); int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, unsigned int flags); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp index e6c954e339ba961dc628a31631de76c587d56ab8..4870da28bf1e0077f0d1760868e41657bfbf9bb0 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp @@ -63,3 +63,14 @@ int GRD_DBClose(GRD_DB *db, unsigned int flags) delete db; return GRD_OK; } + +int GRD_Flush(GRD_DB *db, unsigned int flags) +{ + if (db == nullptr || db->store_ == nullptr) { + return GRD_INVALID_ARGS; + } + if (flags != GRD_DB_FLUSH_ASYNC && flags != GRD_DB_FLUSH_SYNC) { + return GRD_INVALID_ARGS; + } + return GRD_OK; +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index 61f50633eb9f8452b0624bb6a4641330316f9288..5ffaabe73e59468afa876d63bba51edd9393e7d4 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -55,7 +55,7 @@ int GRD_UpdateDoc(GRD_DB *db, const char *collectionName, const char *filter, co return TrasnferDocErr(ret); } -int GRD_UpSertDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *document, unsigned int flags) +int GRD_UpsertDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *document, unsigned int flags) { if (db == nullptr || db->store_ == nullptr) { return GRD_INVALID_ARGS; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/collection.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/collection.h index b71feaae45a66196a305e3cc6e8e11800b8f0c2d..0b73e613d3ad2cfc4c05754587090178984a798d 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/collection.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/collection.h @@ -31,7 +31,7 @@ public: int DeleteDocument(const Key &key); int UpsertDocument(const std::string &id, const std::string &document, bool isReplace = true); - int UpdateDocument(const Key &key, Value &update); + int UpdateDocument(const std::string &id, const std::string &document); private: std::string name_; KvStoreExecutor *executor_ = nullptr; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h index b1fa3c39ae693e125d3fb8c846ba299d82f953b8..b4d1c3b66f8ce80427170fb844f9458229ac3a05 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h @@ -32,7 +32,7 @@ public: int CreateCollection(const std::string &name, const std::string &option, int flags); int DropCollection(const std::string &name, int flags); - int UpdateDocument(const std::string &collection, const std::string &filter, const std::string &update, int flag); + int UpdateDocument(const std::string &collection, const std::string &filter, const std::string &update, int flags); int UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, int flags); private: diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/collection.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/collection.cpp index d04eb8022ac7fb77f4fb400d1fe0eca2251340d4..c5c045ad73b3b6c898595fb14a34643fb3bfeff0 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/collection.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/collection.cpp @@ -101,14 +101,62 @@ int Collection::UpsertDocument(const std::string &id, const std::string &documen GLOGD("Append value failed. %d", errCode); return errCode; } + + std::string valStr = originValue.Print(); + valSet = {valStr.begin(), valStr.end()}; } } return executor_->PutData(name_, keyId, valSet); } -int Collection::UpdateDocument(const Key &key, Value &update) +int Collection::UpdateDocument(const std::string &id, const std::string &update) { - return E_OK; + if (executor_ == nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = E_OK; + bool isCollExist = executor_->IsCollectionExists(name_, errCode); + if (errCode != E_OK) { + GLOGE("Check collection failed. %d", errCode); + return -errCode; + } + if (!isCollExist) { + GLOGE("Collection not created."); + return -E_NO_DATA; + } + + JsonObject updateValue = JsonObject::Parse(update, errCode); + if (errCode != E_OK) { + GLOGD("Parse upsert value failed. %d", errCode); + return errCode; + } + + Key keyId(id.begin(), id.end()); + Value valueGot; + errCode = executor_->GetData(name_, keyId, valueGot); + std::string valueGotStr = std::string(valueGot.begin(), valueGot.end()); + if (errCode != E_OK) { + GLOGE("Get original document failed. %d", errCode); + return errCode; + } + + GLOGD("Update document value."); + JsonObject originValue = JsonObject::Parse(valueGotStr, errCode); + if (errCode != E_OK) { + GLOGD("Parse original value failed. %d %s", errCode, valueGotStr.c_str()); + return errCode; + } + + errCode = JsonCommon::Append(originValue, updateValue); + if (errCode != E_OK) { + GLOGD("Append value failed. %d", errCode); + return errCode; + } + + std::string valStr = originValue.Print(); + Value valSet(valStr.begin(), valStr.end()); + return executor_->PutData(name_, keyId, valSet); } } // namespace DocumentDB diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp index 9cedce6ac0faa3c89e7949a3fb89f720e125aef3..7b80110bb81a4647e2e5102f520779bec8aa6451 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp @@ -27,6 +27,10 @@ int GetErrorCategory(int errCode) int TrasnferDocErr(int err) { + if(err > 0) { + return err; + } + int outErr = GRD_OK; switch (err) { case E_OK: @@ -53,6 +57,7 @@ int TrasnferDocErr(int err) outErr = GRD_COLLECTION_CONFLICT; break; case -E_NO_DATA: + case -E_NOT_FOUND: outErr = GRD_NO_DATA; break; case -E_INVALID_COLL_NAME_FORMAT: diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store.cpp index 98b7031131e4c0706d89208885a9cea3b9b6dd72..c15fe200eb819a8e32940aab58e9d338d4165f6c 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store.cpp @@ -105,10 +105,90 @@ int DocumentStore::DropCollection(const std::string &name, int flags) return errCode; } +namespace { +bool CheckFilter(const std::string &filter, std::string &idStr, int &errCode) +{ + if (filter.empty()) { + errCode = -E_INVALID_ARGS; + GLOGE("Check filter invalid. %d", errCode); + return false; + } + + JsonObject filterObject = JsonObject::Parse(filter, errCode, true); + if (errCode != E_OK) { + GLOGE("Parse filter failed. %d", errCode); + return false; + } + + JsonObject filterId = filterObject.GetObjectItem("_id", errCode); + if (errCode != E_OK || filterId.GetItemValue().GetValueType() != ValueObject::ValueType::VALUE_STRING) { + GLOGE("Check filter '_id' not found or type not string."); + errCode = -E_INVALID_ARGS; + return false; + } + + idStr = filterId.GetItemValue().GetStringValue(); + return true; +} + +bool CheckDocument(const std::string &updateStr, int &errCode) +{ + if (updateStr.empty()) { + errCode = -E_INVALID_ARGS; + return false; + } + + JsonObject updateObj = JsonObject::Parse(updateStr, errCode); + if (updateObj.IsNull() || errCode != E_OK) { + GLOGE("Parse update document failed. %d", errCode); + return false; + } + + JsonObject filterId = updateObj.GetObjectItem("_id", errCode); + if (errCode != -E_NOT_FOUND) { + GLOGE("Can not change '_id' with update document failed."); + return false; + } + + return true; +} +} + int DocumentStore::UpdateDocument(const std::string &collection, const std::string &filter, const std::string &update, - int flag) + int flags) { - return E_OK; + std::string lowerCaseCollName; + int errCode = E_OK; + if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) { + GLOGE("Check collection name invalid. %d", errCode); + return errCode; + } + + std::string idStr; + if (!CheckFilter(filter, idStr, errCode)) { + GLOGE("Check update filter failed. %d", errCode); + return errCode; + } + + if (!CheckDocument(update, errCode)) { + GLOGE("Check update document failed. %d", errCode); + return errCode; + } + + if (flags != 0) { + GLOGE("Check flags invalid."); + return -E_INVALID_ARGS; + } + + std::string docId(idStr.begin(), idStr.end()); + + std::lock_guard lock(dbMutex_); + auto coll = Collection(lowerCaseCollName, executor_); + errCode = coll.UpdateDocument(docId, update); + if (errCode == E_OK) { + errCode = 1; // update one record. + } + return errCode; } int DocumentStore::UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, @@ -121,21 +201,31 @@ int DocumentStore::UpsertDocument(const std::string &collection, const std::stri return errCode; } - // TODO:: check filter + std::string idStr; + if (!CheckFilter(filter, idStr, errCode)) { + GLOGE("Check upsert filter failed. %d", errCode); + return errCode; + } - // TODO:: check document + if (!CheckDocument(document, errCode)) { + GLOGE("Check upsert document failed. %d", errCode); + return errCode; + } if (flags != GRD_DOC_APPEND && flags != GRD_DOC_REPLACE) { GLOGE("Check flags invalid."); return -E_INVALID_ARGS; } - auto coll = Collection(lowerCaseCollName, executor_); - - std::string docId(filter.begin(), filter.end()); - bool isReplace = (flags & GRD_DOC_REPLACE == GRD_DOC_REPLACE); + std::string docId(idStr.begin(), idStr.end()); + bool isReplace = ((flags & GRD_DOC_REPLACE) == GRD_DOC_REPLACE); std::lock_guard lock(dbMutex_); - return coll.UpsertDocument(docId, document, isReplace); + auto coll = Collection(lowerCaseCollName, executor_); + errCode = coll.UpsertDocument(docId, document, isReplace); + if (errCode == E_OK) { + errCode = 1; // upsert one record. + } + return errCode; } } // namespace DocumentDB \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/json_object.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/json_object.cpp index 661dfeeb336a927c683b439e0066ce50f1b0d245..4cff475c7706e9adcfd3cce49fd8b29452719720 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/json_object.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/json_object.cpp @@ -425,7 +425,6 @@ int JsonObject::DeleteItemOnTarget(const JsonFieldPath &path) JsonFieldPath patherPath = path; patherPath.pop_back(); - int errCode = E_OK; cJSON *nodeFather = MoveToPath(cjson_, patherPath, caseSensitive_); if (nodeFather == nullptr) { GLOGE("Delete item failed, json field path not found."); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp index fedc5197a8c0a0160442e89c72dacb429d937812..ac45c871767caf64653c08718cc08306aa4dc4ac 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp @@ -20,10 +20,6 @@ #include "sqlite_utils.h" namespace DocumentDB { -constexpr const char *APP_ID = "APP_ID"; -constexpr const char *USER_ID = "USER_ID"; -constexpr const char *STORE_ID = "STORE_ID"; - int KvStoreManager::GetKvStore(const std::string &path, const DBConfig &config, KvStoreExecutor *&executor) { if (executor != nullptr) { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/BUILD.gn b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/BUILD.gn index bf1a5b8fc72d85936a2f667b614f582a6b071e55..6c6ff3c64d1280e30b2d8ccc3c3d5ba106219223 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/BUILD.gn +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/BUILD.gn @@ -1,14 +1,156 @@ -/* -* Copyright (c) 2023 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. -*/ \ No newline at end of file +# Copyright (c) 2021 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. +import("//build/test.gni") + +module_output_path = "datamgr_service/documentdb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "../src/common/include", + "../src/executor/include", + "../src/oh_adapter/include", + "../src/oh_adapter/src", + "../src/interface/include", + "unittest/common", + ] + + defines = [ + "SQLITE_ENABLE_SNAPSHOT", + "SQLITE_HAS_CODEC", + "SQLITE_ENABLE_JSON1", + "USING_HILOG_LOGGER", + "USE_SQLITE_SYMBOLS", + "SQLITE_ENABLE_DROPTABLE_CALLBACK", + ] +} + +############################################################################### +ohos_source_set("src_file") { + testonly = true + + sources = [ + "../src/common/src/collection_option.cpp", + "../src/common/src/db_config.cpp", + "../src/common/src/doc_common.cpp", + "../src/common/src/json_common.cpp", + "../src/common/src/log_print.cpp", + "../src/common/src/os_api.cpp", + "../src/executor/base/grd_db_api.cpp", + "../src/executor/document/grd_document_api.cpp", + "../src/interface/src/collection.cpp", + "../src/interface/src/doc_errno.cpp", + "../src/interface/src/document_store.cpp", + "../src/interface/src/document_store_manager.cpp", + "../src/oh_adapter/src/json_object.cpp", + "../src/oh_adapter/src/kv_store_manager.cpp", + "../src/oh_adapter/src/sqlite_store_executor_impl.cpp", + "../src/oh_adapter/src/sqlite_utils.cpp", + "unittest/common/documentdb_test_utils.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ + "//third_party/googletest:gtest_main", + "//third_party/sqlite:sqlite", + ] + + configs += [ "//third_party/cJSON:cJSON_config" ] + ldflags = [ "-Wl,--exclude-libs,ALL" ] + deps += [ "//third_party/cJSON:cjson" ] + external_deps = [ + "c_utils:utils", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "hiviewdfx_hilog_native:libhilog", + ] + part_name = "kv_store" +} + +template("documentdb_unittest") { + ohos_unittest(target_name) { + forward_variables_from(invoker, "*") + module_out_path = module_output_path + if (!defined(deps)) { + deps = [] + } + if (!defined(external_deps)) { + external_deps = [] + } + configs = [ ":module_private_config" ] + deps += [ + ":src_file", + "//third_party/googletest:gmock_main", + "//third_party/googletest:gtest_main", + "//third_party/sqlite:sqlite", + ] + configs += [ "//third_party/cJSON:cJSON_config" ] + ldflags = [ "-Wl,--exclude-libs,ALL" ] + deps += [ + "//third_party/cJSON:cjson", + "//third_party/openssl:libcrypto_shared", + ] + external_deps = [ + "c_utils:utils", + "hisysevent_native:libhisysevent", + "hitrace_native:hitrace_meter", + "hiviewdfx_hilog_native:libhilog", + ] + } +} + +documentdb_unittest("DocumentDBApiTest") { + sources = [ "unittest/api/documentdb_api_test.cpp" ] +} + +documentdb_unittest("DocumentDBCollectionTest") { + sources = [ "unittest/api/documentdb_collection_test.cpp" ] +} + +documentdb_unittest("DocumentDBDataTest") { + sources = [ "unittest/api/documentdb_data_test.cpp" ] +} + +documentdb_unittest("DocumentDBJsonCommonTest") { + sources = [ "unittest/oh_adapter/documentdb_json_common_test.cpp" ] +} + +documentdb_unittest("DocumentDBJsonObjectTest") { + sources = [ "unittest/oh_adapter/documentdb_jsonobject_test.cpp" ] +} + +############################################################################### +group("unittest") { + testonly = true + deps = [ "//third_party/googletest:gmock" ] + + deps += [ + ":DocumentDBApiTest", + ":DocumentDBCollectionTest", + ":DocumentDBDataTest", + ":DocumentDBJsonCommonTest", + ":DocumentDBJsonObjectTest", + ] +} + +############################################################################### + +group("document_fuzztest") { + testonly = true + deps = [] + deps += [] +} +############################################################################### diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp index 382fe5ef71dd3a0cd036b1b37e1141412748e7f2..b36dd2e11f19d590550a829baa07f2a156dc52b9 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp @@ -70,8 +70,8 @@ HWTEST_F(DocumentDBApiTest, OpenDBTest001, TestSize.Level0) EXPECT_EQ(GRD_CreateCollection(db, "student", "", 0), GRD_OK); - EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", R""({"name":"Tom","age":23})"", 0), GRD_OK); - EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", R""({"name":"Tom","age":23})"", 0), GRD_OK); + EXPECT_EQ(GRD_UpsertDoc(db, "student", R""({"_id":"10001"})"", R""({"name":"Tom","age":23})"", 0), 1); + EXPECT_EQ(GRD_UpsertDoc(db, "student", R""({"_id":"10001"})"", R""({"name":"Tom","age":23})"", 0), 1); EXPECT_EQ(GRD_DropCollection(db, "student", 0), GRD_OK); @@ -291,6 +291,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest004, TestSize.Level1) GRD_DB *db = nullptr; int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); EXPECT_EQ(status, GRD_OK); + EXPECT_NE(db, nullptr); dbList.push_back(db); } @@ -298,6 +299,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest004, TestSize.Level1) int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); EXPECT_EQ(status, GRD_OK); EXPECT_NE(db, nullptr); + dbList.push_back(db); for (auto *it : dbList) { status = GRD_DBClose(it, GRD_DB_CLOSE); @@ -616,5 +618,37 @@ HWTEST_F(DocumentDBApiTest, CloseDBFlagTest003, TestSize.Level0) EXPECT_EQ(status, GRD_OK); db = nullptr; + DocumentDBTestUtils::RemoveTestDbFiles(path); +} + +/** + * @tc.name: FlushDBTest001 + * @tc.desc: Test flush document db + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, FlushDBTest001, TestSize.Level0) +{ + EXPECT_EQ(GRD_Flush(nullptr, GRD_DB_FLUSH_ASYNC), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_Flush(nullptr, GRD_DB_FLUSH_SYNC), GRD_INVALID_ARGS); + + GRD_DB *db = nullptr; + std::string path= "./document.db"; + int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + ASSERT_NE(db, nullptr); + + EXPECT_EQ(GRD_Flush(db, GRD_DB_FLUSH_ASYNC), GRD_OK); + EXPECT_EQ(GRD_Flush(db, GRD_DB_FLUSH_SYNC), GRD_OK); + std::vector invalidFlags = {2, 4, 8, 512, 1024, UINT32_MAX}; + for (auto flags : invalidFlags) { + EXPECT_EQ(GRD_Flush(db, flags), GRD_INVALID_ARGS); + } + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + DocumentDBTestUtils::RemoveTestDbFiles(path); } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp index 6f61aac7140255144b53f867dd924d534b5a4168..228978ba824e9bb241f7d184e494a684161d86cf 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp @@ -76,7 +76,13 @@ void DocumentDBDataTest::TearDown(void) HWTEST_F(DocumentDBDataTest, UpsertDataTest001, TestSize.Level0) { std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; - EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, "1234", document.c_str(), GRD_DOC_REPLACE), GRD_OK); + EXPECT_EQ(GRD_UpsertDoc(g_db, g_coll, R""({"_id":"1234"})"", document.c_str(), GRD_DOC_REPLACE), 1); + + std::string update = R""({"CC":"AAAA"})""; + EXPECT_EQ(GRD_UpdateDoc(g_db, g_coll, R""({"_id":"1234"})"", update.c_str(), 0), 1); + + std::string append = R""({"addr.city":"DDDD"})""; + EXPECT_EQ(GRD_UpsertDoc(g_db, g_coll, R""({"_id":"1234"})"", append.c_str(), GRD_DOC_APPEND), 1); } /** @@ -89,7 +95,7 @@ HWTEST_F(DocumentDBDataTest, UpsertDataTest001, TestSize.Level0) HWTEST_F(DocumentDBDataTest, UpsertDataTest002, TestSize.Level0) { std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; - EXPECT_EQ(GRD_UpSertDoc(nullptr, g_coll, "1234", document.c_str(), GRD_DOC_REPLACE), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_UpsertDoc(nullptr, g_coll, "1234", document.c_str(), GRD_DOC_REPLACE), GRD_INVALID_ARGS); } /** @@ -102,17 +108,17 @@ HWTEST_F(DocumentDBDataTest, UpsertDataTest002, TestSize.Level0) HWTEST_F(DocumentDBDataTest, UpsertDataTest003, TestSize.Level0) { std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; - std::vector invalidName = { - nullptr, - "", - "GRD_123", - "grd_123", - "GM_SYS_123", - "gm_sys_123", + std::vector> invalidName = { + {nullptr, GRD_INVALID_ARGS}, + {"", GRD_INVALID_ARGS}, + {"GRD_123", GRD_INVALID_FORMAT}, + {"grd_123", GRD_INVALID_FORMAT}, + {"GM_SYS_123", GRD_INVALID_FORMAT}, + {"gm_sys_123", GRD_INVALID_FORMAT}, }; - for (auto name : invalidName) { - GLOGD("UpsertDataTest003: upsert data with collectionname: %s", name); - EXPECT_EQ(GRD_UpSertDoc(g_db, name, "1234", document.c_str(), GRD_DOC_REPLACE), GRD_INVALID_ARGS); + for (auto it : invalidName) { + GLOGD("UpsertDataTest003: upsert data with collectionname: %s", it.first); + EXPECT_EQ(GRD_UpsertDoc(g_db, it.first, "1234", document.c_str(), GRD_DOC_REPLACE), it.second); } } @@ -127,23 +133,22 @@ HWTEST_F(DocumentDBDataTest, UpsertDataTest004, TestSize.Level0) R""({"_id":1234})"", }; for (auto filter : invalidFilter) { - EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter, document.c_str(), GRD_DOC_REPLACE), GRD_INVALID_ARGS); + GLOGD("UpsertDataTest004: upsert data with filter: %s", filter); + EXPECT_EQ(GRD_UpsertDoc(g_db, g_coll, filter, document.c_str(), GRD_DOC_REPLACE), GRD_INVALID_ARGS); } } HWTEST_F(DocumentDBDataTest, UpsertDataTest005, TestSize.Level0) { - std::string filter = R""({"_id":1234})""; - std::vector invalidDocument = { - nullptr, - "", - "GRD_123", - "grd_123", - "GM_SYS_123", - "gm_sys_123", + std::string filter = R""({"_id":"1234"})""; + std::vector> invalidDocument = { + {"", GRD_INVALID_ARGS}, + {nullptr, GRD_INVALID_ARGS}, + {R""({invalidJsonFormat})"", GRD_INVALID_FORMAT}, }; - for (auto document : invalidDocument) { - EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), document, GRD_DOC_REPLACE), GRD_INVALID_FORMAT); + for (auto it : invalidDocument) { + GLOGD("UpsertDataTest005: upsert data with document: %s", it.first); + EXPECT_EQ(GRD_UpsertDoc(g_db, g_coll, filter.c_str(), it.first, GRD_DOC_REPLACE), it.second); } } @@ -156,11 +161,11 @@ HWTEST_F(DocumentDBDataTest, UpsertDataTest005, TestSize.Level0) */ HWTEST_F(DocumentDBDataTest, UpsertDataTest006, TestSize.Level0) { - std::string filter = R""({"_id":1234})""; + std::string filter = R""({"_id":"1234"})""; std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; for (auto flags : std::vector {2, 4, 8, 64, 1024, UINT32_MAX}) { - EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), document.c_str(), flags), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_UpsertDoc(g_db, g_coll, filter.c_str(), document.c_str(), flags), GRD_INVALID_ARGS); } } @@ -173,8 +178,9 @@ HWTEST_F(DocumentDBDataTest, UpsertDataTest006, TestSize.Level0) */ HWTEST_F(DocumentDBDataTest, UpsertDataTest007, TestSize.Level0) { + std::string filter = R""({"_id":"1234"})""; std::string val = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; - EXPECT_EQ(GRD_UpSertDoc(g_db, "collection_not_exists", "1234", val.c_str(), GRD_DOC_REPLACE), GRD_NO_DATA); + EXPECT_EQ(GRD_UpsertDoc(g_db, "collection_not_exists", filter.c_str(), val.c_str(), GRD_DOC_REPLACE), GRD_NO_DATA); } /** @@ -186,10 +192,127 @@ HWTEST_F(DocumentDBDataTest, UpsertDataTest007, TestSize.Level0) */ HWTEST_F(DocumentDBDataTest, UpsertDataTest008, TestSize.Level0) { - std::string filter = R""({"_id":1234})""; + std::string filter = R""({"_id":"1234"})""; std::string document = R""({"name":"Tmn","age":18,"addr":{"city":"shanghai","postal":200001}})""; - EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), document.c_str(), GRD_DOC_REPLACE), GRD_OK); + EXPECT_EQ(GRD_UpsertDoc(g_db, g_coll, filter.c_str(), document.c_str(), GRD_DOC_REPLACE), 1); std::string updateDoc = R""({"name":"Xue","case":2,"age":28,"addr":{"city":"shenzhen","postal":518000}})""; - EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), updateDoc.c_str(), GRD_DOC_APPEND), GRD_OK); + EXPECT_EQ(GRD_UpsertDoc(g_db, g_coll, filter.c_str(), updateDoc.c_str(), GRD_DOC_APPEND), 1); +} + +/** + * @tc.name: UpdateDataTest001 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpdateDataTest001, TestSize.Level0) +{ + std::string filter = R""({"_id":"1234"})""; + std::string updateDoc = R""({"name":"Xue"})""; + EXPECT_EQ(GRD_UpdateDoc(g_db, g_coll, filter.c_str(), updateDoc.c_str(), 0), GRD_NO_DATA); +} + +/** + * @tc.name: UpdateDataTest002 + * @tc.desc: Test update data with db is nullptr + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpdateDataTest002, TestSize.Level0) +{ + std::string filter = R""({"_id":"1234"})""; + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + EXPECT_EQ(GRD_UpdateDoc(nullptr, g_coll, filter.c_str(), document.c_str(), 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: UpdateDataTest003 + * @tc.desc: Test update data with invalid collection name + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpdateDataTest003, TestSize.Level0) +{ + std::string filter = R""({"_id":"1234"})""; + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + std::vector> invalidName = { + {nullptr, GRD_INVALID_ARGS}, + {"", GRD_INVALID_ARGS}, + {"GRD_123", GRD_INVALID_FORMAT}, + {"grd_123", GRD_INVALID_FORMAT}, + {"GM_SYS_123", GRD_INVALID_FORMAT}, + {"gm_sys_123", GRD_INVALID_FORMAT}, + }; + for (auto it : invalidName) { + GLOGD("UpdateDataTest003: update data with collectionname: %s", it.first); + EXPECT_EQ(GRD_UpdateDoc(g_db, it.first, filter.c_str(), document.c_str(), 0), it.second); + } +} + +/** + * @tc.name: UpdateDataTest004 + * @tc.desc: Test update data with invalid filter + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpdateDataTest004, TestSize.Level0) +{ + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + std::vector invalidFilter = { + nullptr, + "", + R""({"name":"Tmono"})"", + R""({"value":{"_id":"1234"}})"", + R""({"_id":1234})"", + }; + for (auto filter : invalidFilter) { + GLOGD("UpdateDataTest004: update data with filter: %s", filter); + EXPECT_EQ(GRD_UpdateDoc(g_db, g_coll, filter, document.c_str(), 0), GRD_INVALID_ARGS); + } +} + +/** + * @tc.name: UpdateDataTest005 + * @tc.desc: Test update data with invalid doc + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpdateDataTest005, TestSize.Level0) +{ + std::string filter = R""({"_id":"1234"})""; + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + std::vector> invalidUpdate = { + {"", GRD_INVALID_ARGS}, + {nullptr, GRD_INVALID_ARGS}, + {R""({invalidJsonFormat})"", GRD_INVALID_FORMAT}, + }; + + for (auto it : invalidUpdate) { + GLOGD("UpdateDataTest005: update data with doc: %s", it.first); + EXPECT_EQ(GRD_UpdateDoc(g_db, g_coll, filter.c_str(), it.first, 0), it.second); + } +} + +/** + * @tc.name: UpdateDataTest006 + * @tc.desc: Test update data with invalid flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpdateDataTest006, TestSize.Level0) +{ + std::string filter = R""({"_id":"1234"})""; + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + std::vector invalidFlags = {1, 2, 4, 8, 1024, UINT32_MAX}; + for (auto flag : invalidFlags) { + GLOGD("UpdateDataTest006: update data with flag: %u", flag); + EXPECT_EQ(GRD_UpdateDoc(g_db, g_coll, filter.c_str(), document.c_str(), flag), GRD_INVALID_ARGS); + } } \ No newline at end of file