diff --git a/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h b/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h index 788ea9c4da27c35270b2c42f3fcf3d9bfe6a7937..1218be2d24f867287be2c99d821829ae9cfe691f 100644 --- a/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h +++ b/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h @@ -58,6 +58,7 @@ public: static constexpr const char *CLOUD_KV_FIELD_ORI_DEVICE = "ori_device"; static constexpr const char *CLOUD_KV_FIELD_DEVICE_CREATE_TIME = "device_create_time"; static constexpr const char *CLOUD_KV_TABLE_NAME = "sync_data"; + static constexpr const char *CLOUD_KV_FIELD_USERID = "userid"; // data status changes to lock_change static constexpr const char *TO_LOCAL_CHANGE = "status = CASE WHEN status == 2 THEN 3 ELSE status END"; diff --git a/frameworks/libs/distributeddb/common/include/db_common.h b/frameworks/libs/distributeddb/common/include/db_common.h index abb9e1d0d2e99dc93d6010dff0249a69f9d1650c..31b1e2e7eb94340e1101d751b798fe75fa042ced 100644 --- a/frameworks/libs/distributeddb/common/include/db_common.h +++ b/frameworks/libs/distributeddb/common/include/db_common.h @@ -27,10 +27,6 @@ namespace DistributedDB { class DBCommon final { public: - enum FileControlType { - SET_FLAG, - CLEAR_FLAG - }; static int CreateDirectory(const std::string &directory); static void StringToVector(const std::string &src, std::vector &dst); @@ -148,8 +144,6 @@ public: static std::string GetCursorKey(const std::string &tableName); static void RemoveDuplicateAssetsData(std::vector &assets); - - static void SetOrClearFSMonitorFlag(const std::string &fileName, FileControlType fileControlType); private: static void InsertNodesByScore(const std::map> &graph, const std::vector &generateNodes, const std::map &scoreGraph, diff --git a/frameworks/libs/distributeddb/common/include/db_errno.h b/frameworks/libs/distributeddb/common/include/db_errno.h index 9de6910e91f3b6b83f4fafb8d09d6e1f2299964d..e8f136de1b27f999e435ea6dbefeab2a8d50b393 100644 --- a/frameworks/libs/distributeddb/common/include/db_errno.h +++ b/frameworks/libs/distributeddb/common/include/db_errno.h @@ -146,6 +146,7 @@ constexpr int E_CLOUD_GID_MISMATCH = (E_BASE + 125); // cloud gid cannot match i constexpr int E_WITH_INVENTORY_DATA = (E_BASE + 126); // inventory data exists when setTracker for the first time constexpr int E_WAIT_COMPENSATED_SYNC = (E_BASE + 127); // need to do compensated sync constexpr int E_CLOUD_SYNC_TASK_MERGED = (E_BASE + 128); // sync task is merged +constexpr int E_SQLITE_CANT_OPEN = (E_BASE + 129); // the sqlite cannot open // Num 150+ is reserved for schema related errno, since it may be added regularly constexpr int E_JSON_PARSE_FAIL = (E_BASE + 150); // Parse json fail in grammatical level constexpr int E_JSON_INSERT_PATH_EXIST = (E_BASE + 151); // Path already exist before insert diff --git a/frameworks/libs/distributeddb/common/include/db_types.h b/frameworks/libs/distributeddb/common/include/db_types.h index 28cdad4dd1215f801df68adb8b48b499ddcfd1a0..4e8e5171eef065194cf3fb2ed9e8ae4526900b2b 100644 --- a/frameworks/libs/distributeddb/common/include/db_types.h +++ b/frameworks/libs/distributeddb/common/include/db_types.h @@ -48,6 +48,7 @@ struct DataItem { Timestamp writeTimestamp = 0; std::string dev; bool neglect = false; + bool dataChanged = false; Key hashKey{}; Timestamp modifyTime = 0; Timestamp createTime = 0; diff --git a/frameworks/libs/distributeddb/common/include/relational/tracker_table.h b/frameworks/libs/distributeddb/common/include/relational/tracker_table.h index fe7251c2e417a0e9014a62fdff0c0b9f4674086c..65d12d595e9ca3f8a233ed4b22b63e86e9f1e951 100644 --- a/frameworks/libs/distributeddb/common/include/relational/tracker_table.h +++ b/frameworks/libs/distributeddb/common/include/relational/tracker_table.h @@ -42,12 +42,12 @@ public: const std::string GetExtendName() const; std::string ToString() const; const std::vector GetDropTempTriggerSql() const; - const std::string GetTempInsertTriggerSql() const; + const std::string GetTempInsertTriggerSql(bool incFlag = false) const; const std::string GetDropTempTriggerSql(TriggerMode::TriggerModeEnum mode) const; const std::string GetCreateTempTriggerSql(TriggerMode::TriggerModeEnum mode) const; const std::string GetTempTriggerName(TriggerMode::TriggerModeEnum mode) const; - const std::string GetTempUpdateTriggerSql() const; - const std::string GetTempDeleteTriggerSql() const; + const std::string GetTempUpdateTriggerSql(bool incFlag = false) const; + const std::string GetTempDeleteTriggerSql(bool incFlag = false) const; void SetTableName(const std::string &tableName); void SetExtendName(const std::string &colName); void SetTrackerNames(const std::set &trackerNames); diff --git a/frameworks/libs/distributeddb/common/src/auto_launch.cpp b/frameworks/libs/distributeddb/common/src/auto_launch.cpp index 1256c3eb6954ab53c3a97193f7a4a70bb7193d75..3a5056e2dba817750c58d9b69ef1f4cb7d67f8a1 100644 --- a/frameworks/libs/distributeddb/common/src/auto_launch.cpp +++ b/frameworks/libs/distributeddb/common/src/auto_launch.cpp @@ -1104,7 +1104,7 @@ int AutoLaunch::OpenRelationalConnection(AutoLaunchItem &autoLaunchItem) std::shared_ptr properties = std::static_pointer_cast(autoLaunchItem.propertiesPtr); int errCode = E_OK; - auto conn = RelationalStoreInstance::GetDatabaseConnection(*properties, errCode); + auto conn = RelationalStoreInstance::GetDatabaseConnection(*properties, errCode, false); if (errCode == -E_ALREADY_OPENED) { LOGI("[AutoLaunch] GetOneConnection user already openstore by self"); } else if (conn == nullptr) { diff --git a/frameworks/libs/distributeddb/common/src/db_common.cpp b/frameworks/libs/distributeddb/common/src/db_common.cpp index ca2d9418cd8d92e178064032108652f34a71af60..b505d9ff024f07fd2eafe5bc1f8ef8c55d5a1e83 100644 --- a/frameworks/libs/distributeddb/common/src/db_common.cpp +++ b/frameworks/libs/distributeddb/common/src/db_common.cpp @@ -21,11 +21,6 @@ #include #include #include -#ifndef OS_TYPE_WINDOWS -#include -#include -#include -#endif #include "cloud/cloud_db_constant.h" #include "cloud/cloud_db_types.h" @@ -36,14 +31,6 @@ #include "runtime_context.h" #include "value_hash_calc.h" -#ifndef OS_TYPE_WINDOWS -constexpr unsigned int HMFS_MONITOR_FL = 0x00000002; -// This ioctl cmd is used to get the flags' information of a file or folder. -#define HMFS_IOCTL_HW_GET_FLAGS _IOR(0xf5, 70, unsigned int) -// This ioctl cmd is used to set the flags' information of a file or folder. -#define HMFS_IOCTL_HW_SET_FLAGS _IOR(0xf5, 71, unsigned int) -#endif - namespace DistributedDB { namespace { void RemoveFiles(const std::list &fileList, OS::FileType type) @@ -803,56 +790,4 @@ void DBCommon::RemoveDuplicateAssetsData(std::vector &assets) arrIndex++; } } - -void DBCommon::SetOrClearFSMonitorFlag(const std::string &fileName, FileControlType fileControlType) -{ -#ifndef OS_TYPE_WINDOWS - int fd = open(fileName.c_str(), O_RDONLY, S_IRWXU | S_IRWXG); - if (fd < 0) { - LOGE("[SetOrClearFSMonitorFlag] Failed to open file, errno: %d, controlType: %d", errno, - fileControlType); - return; - } - unsigned int flags = 0u; - int ret = ioctl(fd, HMFS_IOCTL_HW_GET_FLAGS, &flags); - if (ret < 0) { - LOGE("[SetOrClearFSMonitorFlag] Failed to get flags, errno: %d, controlType: %d", errno, - fileControlType); - close(fd); - return; - } - - if (fileControlType == SET_FLAG && (flags & HMFS_MONITOR_FL)) { - LOGD("[SetOrClearFSMonitorFlag] Delete control flag is already set"); - close(fd); - return; - } - - if (fileControlType == CLEAR_FLAG && !(flags & HMFS_MONITOR_FL)) { - LOGD("[SetOrClearFSMonitorFlag] Delete control flag has been cleared"); - close(fd); - return; - } - - if (fileControlType == SET_FLAG) { - flags |= HMFS_MONITOR_FL; - } else { - flags &= ~HMFS_MONITOR_FL; - } - - ret = ioctl(fd, HMFS_IOCTL_HW_SET_FLAGS, &flags); - if (ret < 0) { - LOGE("[SetOrClearFSMonitorFlag] Failed to set flags, errno: %d, controlType: %d", errno, - fileControlType); - close(fd); - return; - } - - LOGD("[SetOrClearFSMonitorFlag] File control operation success type: %d", fileControlType); - close(fd); -#else - (void)fileName; - (void)fileControlType; -#endif -} } // namespace DistributedDB diff --git a/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp b/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp index 1bde0d9e864debf9cf69a89e5acb4cf75b28a7f6..ff608c703b5974062384a875213547f5c985484b 100644 --- a/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp +++ b/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp @@ -69,7 +69,11 @@ void DBDfxAdapter::Dump(int fd, const std::vector &args) } DBDumpHelper::Dump(fd, "DistributedDB Dump Message Info:\n\n"); DBDumpHelper::Dump(fd, "DistributedDB Database Basic Message Info:\n"); - KvDBManager::GetInstance()->Dump(fd); + auto kvDBManager = KvDBManager::GetInstance(); + if (kvDBManager == nullptr) { + return; + } + kvDBManager->Dump(fd); RelationalStoreInstance::GetInstance()->Dump(fd); DBDumpHelper::Dump(fd, "DistributedDB Common Message Info:\n"); RuntimeContext::GetInstance()->DumpCommonInfo(fd); diff --git a/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp b/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp index ea406582c3c71d7b8cfd154f2bb9769c8b68c5ee..5089cda515af312ae93ffdfeddd02054c4aa1c1c 100644 --- a/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp +++ b/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp @@ -145,7 +145,7 @@ const std::string TrackerTable::GetTempTriggerName(TriggerMode::TriggerModeEnum return DBConstant::RELATIONAL_PREFIX + tableName_ + "_ON_" + TriggerMode::GetTriggerModeString(mode) + "_TEMP"; } -const std::string TrackerTable::GetTempInsertTriggerSql() const +const std::string TrackerTable::GetTempInsertTriggerSql(bool incFlag) const { // This trigger is built on the log table std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; @@ -153,7 +153,11 @@ const std::string TrackerTable::GetTempInsertTriggerSql() const sql += " WHEN (SELECT 1 FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; sql += "BEGIN\n"; + if (incFlag) { + sql += CloudStorageUtils::GetCursorIncSqlWhenAllow(tableName_) + "\n"; + } else { sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + } sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; sql += " hash_key = NEW.hash_key;\n"; @@ -164,14 +168,18 @@ const std::string TrackerTable::GetTempInsertTriggerSql() const return sql; } -const std::string TrackerTable::GetTempUpdateTriggerSql() const +const std::string TrackerTable::GetTempUpdateTriggerSql(bool incFlag) const { std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; sql += "_ON_UPDATE_TEMP AFTER UPDATE ON " + tableName_; sql += " WHEN (SELECT 1 FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; sql += "BEGIN\n"; - sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + if (incFlag) { + sql += CloudStorageUtils::GetCursorIncSqlWhenAllow(tableName_) + "\n"; + } else { + sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + } sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; if (!IsEmpty()) { sql += "extend_field=" + GetAssignValSql() + ","; @@ -185,14 +193,18 @@ const std::string TrackerTable::GetTempUpdateTriggerSql() const return sql; } -const std::string TrackerTable::GetTempDeleteTriggerSql() const +const std::string TrackerTable::GetTempDeleteTriggerSql(bool incFlag) const { std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; sql += "_ON_DELETE_TEMP AFTER DELETE ON " + tableName_ + " WHEN (SELECT 1 FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; sql += "BEGIN\n"; - sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + if (incFlag) { + sql += CloudStorageUtils::GetCursorIncSqlWhenAllow(tableName_) + "\n"; + } else { + sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + } sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; if (!IsEmpty()) { sql += "extend_field=" + GetAssignValSql(true) + ","; diff --git a/frameworks/libs/distributeddb/common/src/runtime_context.cpp b/frameworks/libs/distributeddb/common/src/runtime_context.cpp index d47755e8b04b3f7f5d8ff576e8818b48351c5021..7c84bba70ebe22d9fa66f2e30d764964c44a52ad 100644 --- a/frameworks/libs/distributeddb/common/src/runtime_context.cpp +++ b/frameworks/libs/distributeddb/common/src/runtime_context.cpp @@ -20,14 +20,18 @@ namespace DistributedDB { RuntimeContext *RuntimeContext::GetInstance() { + const int MEMORY_MAX_SIZE = 4096; + static_assert(sizeof(RuntimeContextImpl) < MEMORY_MAX_SIZE); + static char instMemory[MEMORY_MAX_SIZE]; static std::mutex instLock_; static std::atomic instPtr = nullptr; // For Double-Checked Locking, we need check insPtr twice if (instPtr == nullptr) { std::lock_guard lock(instLock_); if (instPtr == nullptr) { - // Use instPtr to make sure this singleton not free before other object. - instPtr = new (std::nothrow) RuntimeContextImpl; + // Use instMemory to make sure this singleton not free before other object. + // This operation needn't to malloc memory, we needn't to check nullptr. + instPtr = new (instMemory) RuntimeContextImpl; LOGI("DistributedDB Version : %s", SOFTWARE_VERSION_STRING); } } diff --git a/frameworks/libs/distributeddb/include/types_export.h b/frameworks/libs/distributeddb/include/types_export.h index 10fd51a4d61482de2083c268c02ee47a66ebb25c..7f520c62dffa1cb5954812cc28bda734b343fe45 100644 --- a/frameworks/libs/distributeddb/include/types_export.h +++ b/frameworks/libs/distributeddb/include/types_export.h @@ -213,6 +213,11 @@ struct SecurityOption { { return securityLabel == rhs.securityLabel && securityFlag == rhs.securityFlag; } + + bool operator!=(const SecurityOption &rhs) const + { + return !(*this == rhs); + } }; enum class ResultSetCacheMode : int { diff --git a/frameworks/libs/distributeddb/interfaces/include/store_types.h b/frameworks/libs/distributeddb/interfaces/include/store_types.h index ae77b36b1ace25608b6def0a7737ec2187509a1c..806bd70e4262d5cc65b308b4cf994ce6c95701df 100644 --- a/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -88,6 +88,7 @@ enum DBStatus { CLOUD_SYNC_TASK_MERGED, // sync task is merged CLOUD_RECORD_NOT_FOUND, // this error happen in BatchUpdate/BatchDelete CLOUD_RECORD_ALREADY_EXISTED, // this error happen in BatchInsert + SQLITE_CANT_OPEN, // the sqlite cannot open BUTT_STATUS = 27394048 // end of status }; diff --git a/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp b/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp index e4e18c96ed6ec2f82b29be6e908524d236caead2..aef7e2c5c1b2643a4b3b0e86582079c283362c54 100644 --- a/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp +++ b/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp @@ -82,6 +82,7 @@ namespace { { -E_WITH_INVENTORY_DATA, WITH_INVENTORY_DATA }, { -E_WAIT_COMPENSATED_SYNC, WAIT_COMPENSATED_SYNC }, { -E_CLOUD_SYNC_TASK_MERGED, CLOUD_SYNC_TASK_MERGED }, + { -E_SQLITE_CANT_OPEN, SQLITE_CANT_OPEN }, }; } diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_instance.h b/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_instance.h index ac94a227a231a0c121fcba750471213d08e1c8d8..34b171b72b7de16ef13dbecbdf744152d35581a3 100644 --- a/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_instance.h +++ b/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_instance.h @@ -28,13 +28,15 @@ public: RelationalStoreInstance(); ~RelationalStoreInstance() = default; - static RelationalStoreConnection *GetDatabaseConnection(const RelationalDBProperties &properties, int &errCode); + static RelationalStoreConnection *GetDatabaseConnection(const RelationalDBProperties &properties, int &errCode, + bool isNeedIfOpened = true); static RelationalStoreInstance *GetInstance(); static int ReleaseDataBaseConnection(RelationalStoreConnection *connection); // public for test mock - static IRelationalStore *GetDataBase(const RelationalDBProperties &properties, int &errCode); + static IRelationalStore *GetDataBase(const RelationalDBProperties &properties, int &errCode, + bool isNeedIfOpened = true); void Dump(int fd); private: diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp b/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp index 9d3527abbb632d7e1f5d1f48a4e25fd217d4c360..dd965239ad9ee0bc0f375806858d939007623fe3 100644 --- a/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp +++ b/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp @@ -147,11 +147,23 @@ public: static int GetSysCurrentRawTime(uint64_t &curTime) { + static uint64_t lastCurTime = 0u; int errCode = GetCurrentSysTimeInMicrosecond(curTime); if (errCode != E_OK) { return errCode; } curTime *= TO_100_NS; + + std::lock_guard lock(systemTimeLock_); + int64_t timeDiff = static_cast(curTime) - static_cast(lastCurTime); + if (std::abs(timeDiff) > 1000u) { // 1000 is us + lastCurTime = curTime; + return E_OK; + } + if (curTime <= lastCurTime) { + curTime = lastCurTime + 1; + } + lastCurTime = curTime; return E_OK; } diff --git a/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h b/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h index d1d62dcf535d3453a0ef5c5806258c4cc9a15c3c..5a5cfda2ecc19d3f150cb9c3ac5cef4cd0aa3da8 100644 --- a/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h +++ b/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h @@ -175,6 +175,7 @@ public: int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isDownloadSuccess) override; int SetLogTriggerStatus(bool status) override; + int SetCursorIncFlag(bool flag) override; int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) override; @@ -208,7 +209,7 @@ public: int UpdateRecordFlag(const std::string &tableName, bool recordConflict, const LogInfo &logInfo) override; - int GetCompensatedSyncQuery(std::vector &syncQuery) override; + int GetCompensatedSyncQuery(std::vector &syncQuery, std::vector &users) override; int MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, const std::set &gidFilters) override; diff --git a/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h b/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h index 9e89b626fac4c013286118b4d17708449afa97f8..9146642e5b58ab0d2265db7afd779d64fb1b376a 100644 --- a/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h +++ b/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h @@ -104,6 +104,7 @@ public: std::vector &updateColName); static std::string GetSelectIncCursorSql(const std::string &tableName); static std::string GetCursorIncSql(const std::string &tableName); + static std::string GetCursorIncSqlWhenAllow(const std::string &tableName); static std::string GetCursorUpgradeSql(const std::string &tableName); static bool IsSharedTable(const TableSchema &tableSchema); diff --git a/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h b/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h index 72624574cabd59b259379fe19995d2dfd4294cae..28e6c6b312b0b3e525f19652d7be96b3742905f8 100644 --- a/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h +++ b/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h @@ -143,6 +143,10 @@ public: virtual int SetLogTriggerStatus(bool status) = 0; + virtual int SetCursorIncFlag(bool flag) + { + return E_OK; + }; virtual int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) = 0; virtual std::string GetIdentify() const = 0; @@ -187,7 +191,8 @@ public: return E_OK; } - virtual int GetCompensatedSyncQuery([[gnu::unused]] std::vector &syncQuery) + virtual int GetCompensatedSyncQuery([[gnu::unused]] std::vector &syncQuery, + std::vector &users) { return E_OK; } diff --git a/frameworks/libs/distributeddb/storage/include/storage_proxy.h b/frameworks/libs/distributeddb/storage/include/storage_proxy.h index 4238cbe160bb058bf96b75c09e6278a8e9fd5dbe..de4e013b320dbaaa2308fe471dce4bb0357928d6 100644 --- a/frameworks/libs/distributeddb/storage/include/storage_proxy.h +++ b/frameworks/libs/distributeddb/storage/include/storage_proxy.h @@ -97,9 +97,10 @@ public: int ReleaseContinueToken(ContinueToken &continueStmtToken); int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isDownloadSuccess); - int SetLogTriggerStatus(bool status); + int SetCursorIncFlag(bool flag); + int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data); std::string GetIdentify() const; @@ -125,7 +126,7 @@ public: int UpdateRecordFlag(const std::string &tableName, bool recordConflict, const LogInfo &logInfo); - int GetCompensatedSyncQuery(std::vector &syncQuery); + int GetCompensatedSyncQuery(std::vector &syncQuery, std::vector &users); int MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, const std::set &gidFilters); diff --git a/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp b/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp index 614db195d514908d3c72a3867c4762ad3c1662fd..79fcc62f2052f5da074cbbb7d560f2052fa2d98e 100644 --- a/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp @@ -1431,6 +1431,13 @@ std::string CloudStorageUtils::GetCursorUpgradeSql(const std::string &tableName) " NULL THEN 0 ELSE MAX(cursor) END FROM " + DBCommon::GetLogTableName(tableName) + "));"; } +std::string CloudStorageUtils::GetCursorIncSqlWhenAllow(const std::string &tableName) +{ + return "UPDATE " + DBConstant::RELATIONAL_PREFIX + "metadata" + " SET value= case when (select 1 from " + + DBConstant::RELATIONAL_PREFIX + "metadata" + " where key='cursor_inc_flag' AND value = 'true') then value + 1" + + " else value end WHERE key=x'" + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; +} + int CloudStorageUtils::GetSyncQueryByPk(const std::string &tableName, const std::vector &data, bool isKv, QuerySyncObject &querySyncObject) { diff --git a/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp b/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp index 6dbf7b6e5119c74f8b6bb131987a086ebdc51e2c..f43d53fe074156d9ae4fd0e518686037b1179f44 100644 --- a/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp +++ b/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp @@ -106,7 +106,7 @@ int RdSingleVerStorageEngine::GetExistedSecOption(SecurityOption &secOption) con int RdSingleVerStorageEngine::CheckDatabaseSecOpt(const SecurityOption &secOption) const { - if (!(secOption == option_.securityOpt) && + if (!(secOption == option_.securityOpt) && (secOption.securityLabel > option_.securityOpt.securityLabel) && secOption.securityLabel != SecurityLabel::NOT_SET && option_.securityOpt.securityLabel != SecurityLabel::NOT_SET) { LOGE("[RdSingleVerStorageEngine] SecurityOption mismatch, existed:[%d-%d] vs input:[%d-%d]", @@ -202,8 +202,6 @@ int RdSingleVerStorageEngine::OpenGrdDb(const OpenDbProperties &option, GRD_DB * LOGE("[RdSingleVerStorageEngine] database is corrupted"); return -E_INVALID_PASSWD_OR_CORRUPTED_DB; } - } else if (errCode == E_OK) { - DBCommon::SetOrClearFSMonitorFlag(option.uri, DBCommon::SET_FLAG); } return errCode; } diff --git a/frameworks/libs/distributeddb/storage/src/kv/kvdb_utils.cpp b/frameworks/libs/distributeddb/storage/src/kv/kvdb_utils.cpp index cfba63313aeb264ed170e408318599d4245689f5..4fb6451b004a61f9ea905b63aa73bee778dbe2e6 100644 --- a/frameworks/libs/distributeddb/storage/src/kv/kvdb_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/kv/kvdb_utils.cpp @@ -53,7 +53,6 @@ int KvDBUtils::RemoveKvDB(const std::string &dir, const std::string &dbName) dbFileName += DBConstant::DB_EXTENSION; int errCode = E_OK; if (OS::CheckPathExistence(dbFileName)) { - DBCommon::SetOrClearFSMonitorFlag(dbFileName, DBCommon::CLEAR_FLAG); errCode = DBCommon::RemoveAllFilesOfDirectory(dir, true); if (errCode != E_OK) { LOGE("Failed to delete the db file! errno[%d], errCode[%d]", errno, errCode); diff --git a/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp b/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp index 67cfce0af20e38d64cbe0c9c848c19d2055f9e09..5359c192ab2882b18637346c7d69c907c740a89d 100644 --- a/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp +++ b/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp @@ -128,10 +128,17 @@ IRelationalStore *RelationalStoreInstance::OpenDatabase(const RelationalDBProper return db; } -IRelationalStore *RelationalStoreInstance::GetDataBase(const RelationalDBProperties &properties, int &errCode) +IRelationalStore *RelationalStoreInstance::GetDataBase(const RelationalDBProperties &properties, int &errCode, + bool isNeedIfOpened) { auto *db = GetFromCache(properties, errCode); - if (db != nullptr) { + + if (db != nullptr && !isNeedIfOpened) { + RefObject::DecObjRef(db); + errCode = -E_ALREADY_OPENED; + LOGI("Database has already been opened."); + return nullptr; + } else if (db != nullptr) { LOGD("Get db from cache."); return db; } @@ -185,7 +192,7 @@ int CheckCompatibility(const RelationalDBProperties &prop, const RelationalDBPro } RelationalStoreConnection *RelationalStoreInstance::GetDatabaseConnection(const RelationalDBProperties &properties, - int &errCode) + int &errCode, bool isNeedIfOpened) { std::string identifier = properties.GetStringProp(DBProperties::IDENTIFIER_DATA, ""); LOGD("Begin to get [%s] database connection.", STR_MASK(DBCommon::TransferStringToHex(identifier))); @@ -196,7 +203,7 @@ RelationalStoreConnection *RelationalStoreInstance::GetDatabaseConnection(const } manager->EnterDBOpenCloseProcess(properties.GetStringProp(DBProperties::IDENTIFIER_DATA, "")); RelationalStoreConnection *connection = nullptr; - IRelationalStore *db = GetDataBase(properties, errCode); + IRelationalStore *db = GetDataBase(properties, errCode, isNeedIfOpened); if (db == nullptr) { DBDfxAdapter::ReportBehavior( {__func__, Scene::OPEN_CONN, State::BEGIN, Stage::GET_DB, StageResult::FAIL, errCode}); diff --git a/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp b/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp index bdf0cefd1ec7c5ea674d20aa21204f20fa33b0e6..865937cc16bedda3361228b893996f862dbfa031 100644 --- a/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp +++ b/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp @@ -1272,7 +1272,7 @@ int RelationalSyncAbleStorage::CleanCloudData(ClearMode mode, const std::vector< LOGE("the transaction has not been started"); return -E_INVALID_DB; } - transactionHandle_->SetLogicDelete(IsCurrentLogicDelete()); + transactionHandle_->SetLogicDelete(logicDelete_); std::vector notifyTableList; int errCode = transactionHandle_->DoCleanInner(mode, tableNameList, localSchema, assets, notifyTableList); if (!notifyTableList.empty()) { @@ -1334,6 +1334,20 @@ int RelationalSyncAbleStorage::SetLogTriggerStatus(bool status) return errCode; } +int RelationalSyncAbleStorage::SetCursorIncFlag(bool flag) +{ + int errCode = E_OK; + auto *handle = GetHandleExpectTransaction(false, errCode); + if (handle == nullptr) { + return errCode; + } + errCode = handle->SetCursorIncFlag(flag); + if (transactionHandle_ == nullptr) { + ReleaseHandle(handle); + } + return errCode; +} + int RelationalSyncAbleStorage::FillCloudLogAndAsset(const OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) { @@ -1867,7 +1881,8 @@ int RelationalSyncAbleStorage::UpdateRecordFlagAfterUpload(SQLiteSingleVerRelati return E_OK; } -int RelationalSyncAbleStorage::GetCompensatedSyncQuery(std::vector &syncQuery) +int RelationalSyncAbleStorage::GetCompensatedSyncQuery(std::vector &syncQuery, + std::vector &users) { std::vector tables; int errCode = GetCloudTableWithoutShared(tables); diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp index 12fa07a5891f804ae27c02798af9a6a017da9112..df208252604d0d826eb3504219afa5c7fb0f6f6d 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp @@ -28,6 +28,7 @@ #include "runtime_context.h" #include "sqlite_meta_executor.h" #include "sqlite_relational_utils.h" +#include "time_helper.h" #include "value_hash_calc.h" namespace DistributedDB { @@ -44,7 +45,7 @@ static constexpr const char *SET_FLAG_LOCAL_AND_CLEAN_WAIT_COMPENSATED_SYNC = "( "FLAG & 0x02 = 0x02 THEN (FLAG | 0x02) & (~0x10) & (~0x20) ELSE (FLAG | 0x02 | 0x20) & (~0x10) END)"; static constexpr const char *FLAG_IS_LOGIC_DELETE = "FLAG & 0x08 != 0"; // see if 3th bit of a flag is logic delete // set data logic delete and exist passport -static constexpr const char *SET_FLAG_LOGIC_DELETE = "FLAG | 0x08 | 0x800 | 0x01"; +static constexpr const char *SET_FLAG_LOGIC_DELETE = "(FLAG | 0x08 | 0x800 | 0x01) & (~0x02)"; static constexpr const char *DATA_IS_DELETE = "data_key = -1 AND FLAG & 0X08 = 0"; // see if data is delete static constexpr const char *UPDATE_CURSOR_SQL = "cursor=update_cursor()"; static constexpr const int SET_FLAG_ZERO_MASK = ~0x04; // clear 2th bit of flag @@ -559,8 +560,16 @@ static int GetLogData(sqlite3_stmt *logStatement, LogInfo &logInfo) namespace { void GetCloudLog(sqlite3_stmt *logStatement, VBucket &logInfo, uint32_t &totalSize) { - logInfo.insert_or_assign(CloudDbConstant::MODIFY_FIELD, - static_cast(sqlite3_column_int64(logStatement, TIMESTAMP_INDEX))); + int64_t modifyTime = static_cast(sqlite3_column_int64(logStatement, TIMESTAMP_INDEX)); + uint64_t curTime = 0; + if (TimeHelper::GetSysCurrentRawTime(curTime) == E_OK) { + if (modifyTime > static_cast(curTime)) { + modifyTime = static_cast(curTime); + } + } else { + LOGW("[Relational] get raw sys time failed."); + } + logInfo.insert_or_assign(CloudDbConstant::MODIFY_FIELD, modifyTime); logInfo.insert_or_assign(CloudDbConstant::CREATE_FIELD, static_cast(sqlite3_column_int64(logStatement, W_TIMESTAMP_INDEX))); totalSize += sizeof(int64_t) + sizeof(int64_t); @@ -1942,6 +1951,8 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateLogRecordStatement(const } else if (opType == OpType::LOCKED_NOT_HANDLE) { updateLogSql += std::string(CloudDbConstant::TO_LOCAL_CHANGE) + ", cloud_gid = ?"; updateColName.push_back(CloudDbConstant::GID_FIELD); + updateLogSql += ", version = ?"; + updateColName.push_back(CloudDbConstant::VERSION_FIELD); } else { updateLogSql += " device = 'cloud', timestamp = ?,"; updateColName.push_back(CloudDbConstant::MODIFY_FIELD); diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h index f57801bff46d2843954c3b3954e64acfefe1979f..b9fe0ccf52903f24d4b7c36536912851df20cf83 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h @@ -143,6 +143,7 @@ public: int FillCloudVersionForUpload(const OpType opType, const CloudSyncData &data); int SetLogTriggerStatus(bool status); + int SetCursorIncFlag(bool flag); int AnalysisTrackerTable(const TrackerTable &trackerTable, TableInfo &tableInfo); int CreateTrackerTable(const TrackerTable &trackerTable, bool isUpgrade); diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp index 6095558af335e74e1d7ff44c618df00ca6941518..b826bc4180f8650372d4175e31db4f1b30db3c39 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp @@ -359,10 +359,12 @@ void SQLiteSingleVerRelationalStorageExecutor::UpdateCursor(sqlite3_context *ctx return; } auto context = static_cast(sqlite3_user_data(ctx)); + if (context == nullptr) { + LOGW("[SqlSinRDBExe][UpdateCursor] invalid context"); + return; + } context->cursor++; - Value cursor; - DBCommon::StringToVector(std::to_string(context->cursor), cursor); - sqlite3_result_blob(ctx, cursor.data(), static_cast(cursor.size()), SQLITE_TRANSIENT); + sqlite3_result_int64(ctx, static_cast(context->cursor)); } int SQLiteSingleVerRelationalStorageExecutor::CreateFuncUpdateCursor(UpdateCursorContext &context, @@ -583,6 +585,23 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudAssets(const std::string & return errCode; } +int SQLiteSingleVerRelationalStorageExecutor::SetCursorIncFlag(bool flag) +{ + std::string sql = "INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "metadata" + + " VALUES ('cursor_inc_flag', "; + if (flag) { + sql += "'true'"; + } else { + sql += "'false'"; + } + sql += ");"; + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + LOGE("set cursor inc flag fail, errCode = %d", errCode); + } + return errCode; +} + int SQLiteSingleVerRelationalStorageExecutor::PutCloudSyncData(const std::string &tableName, const TableSchema &tableSchema, const TrackerTable &trackerTable, DownloadData &downloadData) { diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp index 30b8a3743b6e8a30d3611cd150fc9a9da39c2f20..ae038bc00086437f3c1474cfc9665af26765cbc0 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp @@ -522,17 +522,17 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateTempSyncTrigger(const Tracke return errCode; } } - errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempInsertTriggerSql()); + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempInsertTriggerSql(true)); if (errCode != E_OK) { LOGE("[RDBExecutor] create temp insert trigger failed %d.", errCode); return errCode; } - errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempUpdateTriggerSql()); + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempUpdateTriggerSql(true)); if (errCode != E_OK) { LOGE("[RDBExecutor] create temp update trigger failed %d.", errCode); return errCode; } - errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempDeleteTriggerSql()); + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempDeleteTriggerSql(true)); if (errCode != E_OK) { LOGE("[RDBExecutor] create temp delete trigger failed %d.", errCode); } diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp index 3fbca864d404066f16af5ff1ad9839b8bf3bb5de..c4372d16c85406398e06cfd68dce1317894c2175 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp @@ -21,6 +21,7 @@ #include "res_finalizer.h" #include "runtime_context.h" #include "sqlite_single_ver_storage_executor_sql.h" +#include "time_helper.h" namespace DistributedDB { int SqliteCloudKvExecutorUtils::GetCloudData(const CloudSyncConfig &config, const DBParam ¶m, @@ -133,8 +134,16 @@ int SqliteCloudKvExecutorUtils::GetCloudDataForSync(const CloudSyncConfig &confi void SqliteCloudKvExecutorUtils::GetCloudLog(sqlite3_stmt *stmt, VBucket &logInfo, uint32_t &totalSize) { - logInfo.insert_or_assign(CloudDbConstant::MODIFY_FIELD, - static_cast(sqlite3_column_int64(stmt, CLOUD_QUERY_MODIFY_TIME_INDEX))); + int64_t modifyTime = static_cast(sqlite3_column_int64(stmt, CLOUD_QUERY_MODIFY_TIME_INDEX)); + uint64_t curTime = 0; + if (TimeHelper::GetSysCurrentRawTime(curTime) == E_OK) { + if (modifyTime > static_cast(curTime)) { + modifyTime = static_cast(curTime); + } + } else { + LOGW("[SqliteCloudKvExecutorUtils] get raw sys time failed."); + } + logInfo.insert_or_assign(CloudDbConstant::MODIFY_FIELD, modifyTime); logInfo.insert_or_assign(CloudDbConstant::CREATE_FIELD, static_cast(sqlite3_column_int64(stmt, CLOUD_QUERY_CREATE_TIME_INDEX))); totalSize += sizeof(int64_t) + sizeof(int64_t); @@ -219,7 +228,7 @@ int SqliteCloudKvExecutorUtils::GetCloudKvBlobData(const std::string &keyStr, in } std::pair SqliteCloudKvExecutorUtils::GetLogInfo(sqlite3 *db, bool isMemory, - const VBucket &cloudData) + const VBucket &cloudData, const std::string &userId) { std::pair res; int &errCode = res.first; @@ -237,7 +246,7 @@ std::pair SqliteCloudKvExecutorUtils::GetLogInfo(sqlite3 * Bytes hashKey; DBCommon::CalcValueHash(key, hashKey); sqlite3_stmt *stmt = nullptr; - std::tie(errCode, stmt) = GetLogInfoStmt(db, cloudData, !hashKey.empty()); + std::tie(errCode, stmt) = GetLogInfoStmt(db, cloudData, !hashKey.empty(), userId.empty()); if (errCode != E_OK) { LOGE("[SqliteCloudKvExecutorUtils] Get stmt failed %d", errCode); return res; @@ -248,27 +257,33 @@ std::pair SqliteCloudKvExecutorUtils::GetLogInfo(sqlite3 * LOGE("[SqliteCloudKvExecutorUtils] Get gid failed %d", errCode); return res; } - return GetLogInfoInner(stmt, isMemory, gid, hashKey); + return GetLogInfoInner(stmt, isMemory, gid, hashKey, userId); } std::pair SqliteCloudKvExecutorUtils::GetLogInfoStmt(sqlite3 *db, const VBucket &cloudData, - bool existKey) + bool existKey, bool emptyUserId) { std::pair res; auto &[errCode, stmt] = res; std::string sql = QUERY_CLOUD_SYNC_DATA_LOG; sql += " WHERE cloud_gid = ?"; + if (!emptyUserId) { + sql += " AND (userid = ? OR userid IS NULL)"; + } if (existKey) { sql += " UNION "; sql += QUERY_CLOUD_SYNC_DATA_LOG; sql += " WHERE sync_data.hash_key = ?"; + if (!emptyUserId) { + sql += " AND (userid = ? OR userid IS NULL)"; + } } errCode = SQLiteUtils::GetStatement(db, sql, stmt); return res; } std::pair SqliteCloudKvExecutorUtils::GetLogInfoInner(sqlite3_stmt *stmt, bool isMemory, - const std::string &gid, const Bytes &key) + const std::string &gid, const Bytes &key, const std::string &userId) { ResFinalizer finalizer([stmt]() { sqlite3_stmt *statement = stmt; @@ -286,12 +301,26 @@ std::pair SqliteCloudKvExecutorUtils::GetLogInfoInner(sqli LOGE("[SqliteCloudKvExecutorUtils] Bind gid failed %d", errCode); return res; } + if (!userId.empty()) { + errCode = SQLiteUtils::BindTextToStatement(stmt, index++, userId); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvExecutorUtils] Bind userId failed %d", errCode); + return res; + } + } if (!key.empty()) { - errCode = SQLiteUtils::BindBlobToStatement(stmt, index, key); + errCode = SQLiteUtils::BindBlobToStatement(stmt, index++, key); if (errCode != E_OK) { LOGE("[SqliteCloudKvExecutorUtils] Bind key failed %d", errCode); return res; } + if (!userId.empty()) { + errCode = SQLiteUtils::BindTextToStatement(stmt, index++, userId); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvExecutorUtils] Bind userId failed %d", errCode); + return res; + } + } } errCode = SQLiteUtils::StepNext(stmt, isMemory); if (errCode == -E_FINISHED) { @@ -841,6 +870,7 @@ int SqliteCloudKvExecutorUtils::FillCloudGid(const FillGidParam ¶m, const Cl } CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::VERSION_FIELD, data.extend[i], dataItem.version); dataItem.hashKey = data.hashKey[i]; + dataItem.dataChanged = CheckDataChanged(param, data, i); errCode = BindFillGidLogStmt(logStmt, user, dataItem, data.extend[i], type); if (errCode != E_OK) { return errCode; @@ -854,7 +884,7 @@ int SqliteCloudKvExecutorUtils::FillCloudGid(const FillGidParam ¶m, const Cl return errCode; } SQLiteUtils::ResetStatement(logStmt, false, errCode); - MarkUploadSuccess(param, data, user, i); + MarkUploadSuccess(param, data, user, i, dataItem.dataChanged); // ignored version record if (i >= data.timestamp.size()) { continue; @@ -1294,6 +1324,58 @@ int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataPk(sqlite3 *db, bool i return errCode; } +int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataUserId(sqlite3 *db, bool isMemory, + std::vector &users) +{ + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, SELECT_COMPENSATE_SYNC_USERID_SQL, stmt); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvExecutorUtils] Get compensate key stmt failed %d", errCode); + return errCode; + } + ResFinalizer finalizerData([stmt]() { + int ret = E_OK; + sqlite3_stmt *statement = stmt; + SQLiteUtils::ResetStatement(statement, true, ret); + if (ret != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] Reset compensate key stmt failed %d", ret); + } + }); + uint32_t totalSize = 0; + do { + errCode = SQLiteUtils::StepWithRetry(stmt, isMemory); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("[SqliteCloudKvExecutorUtils] Get key from compensate key stmt failed. %d", errCode); + break; + } + VBucket key; + errCode = GetCloudKvBlobData(CloudDbConstant::CLOUD_KV_FIELD_USERID, CLOUD_QUERY_KEY_INDEX, stmt, key, totalSize); + if (errCode != E_OK) { + return errCode; + } + users.push_back(key); + } while (errCode == E_OK); + return errCode; +} + +int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncData(sqlite3 *db, bool isMemory, std::vector &data, + std::vector &users) +{ + int errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataPk(db, isMemory, data); + if (errCode != E_OK) { + LOGE("[GetWaitCompensatedSyncData] Get wait compensate sync data failed! errCode=%d", errCode); + return errCode; + } + errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataUserId(db, isMemory, users); + if (errCode != E_OK) { + LOGE("[GetWaitCompensatedSyncData] Get wait compensate sync data failed! errCode=%d", errCode); + } + return errCode; +} + int SqliteCloudKvExecutorUtils::QueryCloudGid(sqlite3 *db, bool isMemory, const std::string &user, QuerySyncObject &querySyncObject, std::vector &cloudGid) { @@ -1330,7 +1412,7 @@ int SqliteCloudKvExecutorUtils::BindFillGidLogStmt(sqlite3_stmt *logStmt, const const DataItem &dataItem, const VBucket &uploadExtend, const CloudWaterType &type) { DataItem wItem = dataItem; - if (DBCommon::IsNeedCompensatedForUpload(uploadExtend, type)) { + if (DBCommon::IsNeedCompensatedForUpload(uploadExtend, type) && !wItem.dataChanged) { wItem.cloud_flag |= static_cast(LogInfoFlag::FLAG_WAIT_COMPENSATED_SYNC); } if (DBCommon::IsCloudRecordNotFound(uploadExtend) && @@ -1353,7 +1435,7 @@ int SqliteCloudKvExecutorUtils::BindFillGidLogStmt(sqlite3_stmt *logStmt, const } void SqliteCloudKvExecutorUtils::MarkUploadSuccess(const FillGidParam ¶m, const CloudSyncBatch &data, - const std::string &user, size_t dataIndex) + const std::string &user, size_t dataIndex, bool dataChanged) { if (data.extend.size() <= dataIndex || data.hashKey.size() <= dataIndex || data.timestamp.size() <= dataIndex) { LOGW("[SqliteCloudKvExecutorUtils] invalid index %zu when mark upload success", dataIndex); @@ -1362,7 +1444,7 @@ void SqliteCloudKvExecutorUtils::MarkUploadSuccess(const FillGidParam ¶m, co if (!DBCommon::IsRecordSuccess(data.extend[dataIndex])) { return; } - if (CheckDataChanged(param, data, dataIndex)) { + if (dataChanged) { LOGW("[SqliteCloudKvExecutorUtils] %zu data changed when mark upload success", dataIndex); return; } @@ -1383,15 +1465,19 @@ bool SqliteCloudKvExecutorUtils::CheckDataChanged(const FillGidParam ¶m, } }); int index = 1; - errCode = SQLiteUtils::BindInt64ToStatement(checkStmt, index++, data.timestamp[dataIndex]); - if (errCode != E_OK) { - LOGW("[SqliteCloudKvExecutorUtils] bind modify time failed %d when check data changed", errCode); - return true; + if (data.timestamp.size() > 0) { + errCode = SQLiteUtils::BindInt64ToStatement(checkStmt, index++, data.timestamp[dataIndex]); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] bind modify time failed %d when check data changed", errCode); + return true; + } } - errCode = SQLiteUtils::BindBlobToStatement(checkStmt, index++, data.hashKey[dataIndex]); - if (errCode != E_OK) { - LOGW("[SqliteCloudKvExecutorUtils] bind hashKey failed %d when check data changed", errCode); - return true; + if (data.hashKey.size() > 0) { + errCode = SQLiteUtils::BindBlobToStatement(checkStmt, index++, data.hashKey[dataIndex]); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] bind hashKey failed %d when check data changed", errCode); + return true; + } } errCode = SQLiteUtils::StepNext(checkStmt); if (errCode != E_OK) { diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h index 00e7bc7269fe546944425870b04301b3edb2049f..bef051c7ff9f0ecb438eae064fbd47c89fbe7be7 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h @@ -33,7 +33,8 @@ public: static int GetCloudData(const CloudSyncConfig &config, const DBParam ¶m, const CloudUploadRecorder &recorder, SQLiteSingleVerContinueToken &token, CloudSyncData &data); - static std::pair GetLogInfo(sqlite3 *db, bool isMemory, const VBucket &cloudData); + static std::pair GetLogInfo(sqlite3 *db, bool isMemory, const VBucket &cloudData, + const std::string &userId); static int PutCloudData(sqlite3 *db, bool isMemory, DownloadData &downloadData); @@ -53,6 +54,11 @@ public: static int GetWaitCompensatedSyncDataPk(sqlite3 *db, bool isMemory, std::vector &data); + static int GetWaitCompensatedSyncDataUserId(sqlite3 *db, bool isMemory, std::vector &users); + + static int GetWaitCompensatedSyncData(sqlite3 *db, bool isMemory, std::vector &data, + std::vector &users); + static int QueryCloudGid(sqlite3 *db, bool isMemory, const std::string &user, QuerySyncObject &querySyncObject, std::vector &cloudGid); private: @@ -69,10 +75,11 @@ private: static int GetCloudKvBlobData(const std::string &keyStr, int index, sqlite3_stmt *stmt, VBucket &data, uint32_t &totalSize); - static std::pair GetLogInfoStmt(sqlite3 *db, const VBucket &cloudData, bool existKey); + static std::pair GetLogInfoStmt(sqlite3 *db, const VBucket &cloudData, bool existKey, + bool emptyUserId); static std::pair GetLogInfoInner(sqlite3_stmt *stmt, bool isMemory, const std::string &gid, - const Bytes &key); + const Bytes &key, const std::string &userId); static DataInfoWithLog FillLogInfoWithStmt(sqlite3_stmt *stmt); @@ -152,7 +159,7 @@ private: const DataItem &dataItem, const VBucket &uploadExtend, const CloudWaterType &type); private: static void MarkUploadSuccess(const FillGidParam ¶m, const CloudSyncBatch &data, const std::string &user, - size_t dataIndex); + size_t dataIndex, bool dataChanged); static bool CheckDataChanged(const FillGidParam ¶m, const CloudSyncBatch &data, size_t dataIndex); diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp index 71d27673f78582d3367b49e00525fe9a8a2b0e48..e767851905b0b85781a300080cd398503d6edaba 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp @@ -180,8 +180,7 @@ int SqliteCloudKvStore::GetCloudData(const TableSchema &tableSchema, const Query const Timestamp &beginTime, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { SyncTimeRange timeRange; - // memory db use watermark - timeRange.beginTime = GetTransactionDbHandleAndMemoryStatus().second ? beginTime : 0; + timeRange.beginTime = 0; auto token = new (std::nothrow) SQLiteSingleVerContinueToken(timeRange, object); if (token == nullptr) { LOGE("[SqliteCloudKvStore] create token failed"); @@ -245,7 +244,7 @@ int SqliteCloudKvStore::GetInfoByPrimaryKeyOrGid([[gnu::unused]] const std::stri return -E_INTERNAL_ERROR; } int errCode = E_OK; - std::tie(errCode, dataInfoWithLog) = SqliteCloudKvExecutorUtils::GetLogInfo(db, isMemory, vBucket); + std::tie(errCode, dataInfoWithLog) = SqliteCloudKvExecutorUtils::GetLogInfo(db, isMemory, vBucket, user_); return errCode; } @@ -374,6 +373,11 @@ int SqliteCloudKvStore::SetLogTriggerStatus(bool status) return E_OK; } +int SqliteCloudKvStore::SetCursorIncFlag(bool status) +{ + return E_OK; +} + int SqliteCloudKvStore::CheckQueryValid(const QuerySyncObject &query) { return E_OK; @@ -566,7 +570,8 @@ bool SqliteCloudKvStore::IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localI return localInfoDev == cloudInfoDev && localInfoDev != device; } -int SqliteCloudKvStore::GetCompensatedSyncQuery(std::vector &syncQuery) +int SqliteCloudKvStore::GetCompensatedSyncQuery(std::vector &syncQuery, + std::vector &users) { std::shared_ptr cloudSchema; (void)GetCloudDbSchema(cloudSchema); @@ -584,8 +589,9 @@ int SqliteCloudKvStore::GetCompensatedSyncQuery(std::vector &sy (void)transactionHandle_->GetDbHandle(db); for (const auto &table: cloudSchema->tables) { std::vector syncDataPk; - int errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataPk(db, transactionHandle_->IsMemory(), - syncDataPk); + std::vector syncDataUserId; + int errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncData(db, transactionHandle_->IsMemory(), + syncDataPk, syncDataUserId); if (errCode != E_OK) { LOGW("[SqliteCloudKvStore] Get wait compensated sync date failed, continue! errCode=%d", errCode); continue; @@ -600,6 +606,15 @@ int SqliteCloudKvStore::GetCompensatedSyncQuery(std::vector &sy continue; } syncQuery.push_back(syncObject); + for (auto &oneRow : syncDataUserId) { + std::string user; + errCode = CloudStorageUtils::GetStringFromCloudData(CloudDbConstant::CLOUD_KV_FIELD_USERID, oneRow, user); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvStore] Get compensated sync query happen error, ignore it! errCode = %d", errCode); + continue; + } + users.push_back(user); + } } return Commit(); } diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h index b0b2284974e0801aacae6569324fdda5b5a147b6..76075c858b37fffe39ea380a06a0c127d2cc1907 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h @@ -69,6 +69,7 @@ public: int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isDownloadSuccess) override; int SetLogTriggerStatus(bool status) override; + int SetCursorIncFlag(bool status) override; int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) override; @@ -100,7 +101,7 @@ public: bool IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localInfo, const LogInfo &cloudInfo) override; - int GetCompensatedSyncQuery(std::vector &syncQuery) override; + int GetCompensatedSyncQuery(std::vector &syncQuery, std::vector &users) override; private: std::pair GetTransactionDbHandleAndMemoryStatus(); diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp index 3897c8b27c505e24a4b9d12e8689dab26fa11309..2e5f65dde364cc3b40cd0376da8176db95a2ef3b 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp @@ -288,17 +288,12 @@ int SQLiteSingleVerDatabaseUpgrader::SetPathSecOptWithCheck(const std::string &p if (!OS::CheckPathExistence(dbItemFilePath)) { continue; } - if (OS::CheckPathExistence(dbItemFilePath) && dbOpt.securityLabel == NOT_SET) { + if (OS::CheckPathExistence(dbItemFilePath) && dbOpt != secOption) { int errCode = RuntimeContext::GetInstance()->SetSecurityOption(dbItemFilePath, secOption); if (errCode != E_OK) { LOGE("[SetPathSecOptWithCheck] SetSecurityOption failed."); return errCode; } - } else if (dbOpt == secOption) { - LOGI("[SetPathSecOptWithCheck] already set secoption"); - } else { - LOGE("[SetPathSecOptWithCheck] already set secoption,but different from early option."); - return -E_INVALID_ARGS; } } return E_OK; diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp index 82f3e3d8750d1a3f95e7a6a327c7e33843092316..9b76d8e15e026cb326c5eeb8bd334c012ed2b55f 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp @@ -556,6 +556,13 @@ StorageExecutor *SQLiteSingleVerStorageEngine::NewSQLiteStorageExecutor(sqlite3 return executor; } executor->SetConflictResolvePolicy(option_.conflictReslovePolicy); + + int errCode = executor->CreateCloudLogTable(); + if (errCode != E_OK) { + LOGE("[SQLiteSingleVerStorageEngine] create cloud log table failed, errCode = [%d]", errCode); + delete executor; + executor = nullptr; + } return executor; } @@ -691,7 +698,7 @@ int SQLiteSingleVerStorageEngine::GetCacheDbHandle(sqlite3 *&db) int SQLiteSingleVerStorageEngine::CheckDatabaseSecOpt(const SecurityOption &secOption) const { - if (!(secOption == option_.securityOpt) && + if (!(secOption == option_.securityOpt) && (secOption.securityLabel > option_.securityOpt.securityLabel) && secOption.securityLabel != SecurityLabel::NOT_SET && option_.securityOpt.securityLabel != SecurityLabel::NOT_SET) { LOGE("[SQLiteSingleVerStorageEngine] SecurityOption mismatch, existed:[%d-%d] vs input:[%d-%d]", @@ -1003,7 +1010,12 @@ void SQLiteSingleVerStorageEngine::InitConflictNotifiedFlag(SingleVerNaturalStor return; } auto identifier = GetIdentifier(); - auto kvdb = KvDBManager::GetInstance()->FindKvDB(identifier); + auto kvDBManager = KvDBManager::GetInstance(); + if (kvDBManager == nullptr) { + LOGE("[SQLiteSingleVerStorageEngine::InitConflictNotifiedFlag] kvDBManager is null."); + return; + } + auto kvdb = kvDBManager->FindKvDB(identifier); if (kvdb == nullptr) { LOGE("[SQLiteSingleVerStorageEngine::InitConflictNotifiedFlag] kvdb is null."); return; @@ -1096,6 +1108,9 @@ bool SQLiteSingleVerStorageEngine::IsUseExistedSecOption(const SecurityOption &e existedSecOpt.securityLabel == SecurityLabel::NOT_SET) { return false; } + if (existedSecOpt.securityLabel < openSecOpt.securityLabel) { + return false; + } return true; } diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp index 35c9ab7503497cb515ad6f100da9bb0514620996..861ae3edd4da1b6ee1c136137ce85d2dde8f6e55 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp @@ -247,7 +247,7 @@ int SQLiteSingleVerStorageExecutor::RemoveDeviceData(const std::string &deviceNa { if (mode == ClearMode::DEFAULT) { return CheckCorruptedStatus(deviceName.empty() ? - RemoveDeviceDataInner(deviceName, mode) : RemoveDeviceDataInner(mode)); + RemoveDeviceDataInner(mode) : RemoveDeviceDataInner(deviceName, mode)); } int errCode = E_OK; bool isDataExist = false; diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h index 219a744dfbd9c5f8d12581b46cde2a4f7ca4cb2d..6561608f9c208744bbea0fdc503819400b642534 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h @@ -374,6 +374,10 @@ namespace DistributedDB { "SELECT key FROM sync_data left join naturalbase_kv_aux_sync_data_log as log_table on sync_data.hash_key" "= log_table.hash_key WHERE log_table.cloud_flag=log_table.cloud_flag|0x10"; + constexpr const char *SELECT_COMPENSATE_SYNC_USERID_SQL = + "SELECT userid FROM sync_data left join naturalbase_kv_aux_sync_data_log as log_table on sync_data.hash_key" + "= log_table.hash_key WHERE log_table.cloud_flag=log_table.cloud_flag|0x10"; + constexpr const char *SELECT_CLOUD_GID_SQL = "SELECT cloud_gid FROM sync_data left join naturalbase_kv_aux_sync_data_log as log_table" " on sync_data.hash_key = log_table.hash_key WHERE log_table.userid=?"; diff --git a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index 537e0830f03ede6032860bb08147c3d01732c100..de8da22e611583d61946b4a4a6d8c37567cb2cae 100644 --- a/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -170,7 +170,6 @@ int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&db LOGE("[SQLite] SetDataBaseProperty failed: %d", errCode); goto END; } - DBCommon::SetOrClearFSMonitorFlag(properties.uri, DBCommon::SET_FLAG); END: if (errCode != E_OK && dbTemp != nullptr) { @@ -1142,6 +1141,8 @@ int SQLiteUtils::MapSQLiteErrno(int errCode) return -E_DENIED_SQL; case SQLITE_CONSTRAINT: return -E_CONSTRAINT; + case SQLITE_CANTOPEN: + return -E_SQLITE_CANT_OPEN; default: break; } diff --git a/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp b/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp index e6455d83b9b66cfc06cc41a75df3147aac1b4621..6088440bb898c27514d1cbd41554f55d5f9bc851 100644 --- a/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp +++ b/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp @@ -297,6 +297,15 @@ int StorageProxy::GetInfoByPrimaryKeyOrGid(const std::string &tableName, const V return errCode; } +int StorageProxy::SetCursorIncFlag(bool flag) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return -E_INVALID_DB; + } + return store_->SetCursorIncFlag(flag); +} + int StorageProxy::PutCloudSyncData(const std::string &tableName, DownloadData &downloadData) { std::shared_lock readLock(storeMutex_); @@ -569,13 +578,13 @@ int StorageProxy::UpdateRecordFlag(const std::string &tableName, bool recordConf return store_->UpdateRecordFlag(tableName, recordConflict, logInfo); } -int StorageProxy::GetCompensatedSyncQuery(std::vector &syncQuery) +int StorageProxy::GetCompensatedSyncQuery(std::vector &syncQuery, std::vector &users) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - return store_->GetCompensatedSyncQuery(syncQuery); + return store_->GetCompensatedSyncQuery(syncQuery, users); } int StorageProxy::MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp index 7a7b0455827995b19378e6b29641298452846c00..60c01a668ddc00ff8a0cd8ce9d66b149796d6b93 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp @@ -245,8 +245,8 @@ int CloudDBProxy::RemoveLocalAssets(const std::vector &assets) } std::shared_lock readLock(assetLoaderMutex_); if (iAssetLoader_ == nullptr) { - LOGE("Asset loader has not been set %d", -E_NOT_SET); - return -E_NOT_SET; + LOGW("Asset loader has not been set"); + return E_OK; } DBStatus status = iAssetLoader_->RemoveLocalAssets(assets); if (status != OK) { @@ -312,17 +312,20 @@ DBStatus CloudDBProxy::DMLActionTask(const std::shared_ptr & switch (action) { case INSERT: { status = cloudDb->BatchInsert(context->GetTableName(), std::move(record), extend); - context->MoveInExtend(extend); + context->MoveInRecordAndExtend(record, extend); + context->SetInfo(CloudWaterType::INSERT, status); break; } case UPDATE: { status = cloudDb->BatchUpdate(context->GetTableName(), std::move(record), extend); - context->MoveInExtend(extend); + context->MoveInRecordAndExtend(record, extend); + context->SetInfo(CloudWaterType::UPDATE, status); break; } case DELETE: { status = cloudDb->BatchDelete(context->GetTableName(), extend); - context->MoveInExtend(extend); + context->MoveInRecordAndExtend(record, extend); + context->SetInfo(CloudWaterType::DELETE, status); break; } default: { @@ -330,7 +333,6 @@ DBStatus CloudDBProxy::DMLActionTask(const std::shared_ptr & return INVALID_ARGS; } } - context->SetInfo(action == INSERT); if (status == CLOUD_VERSION_CONFLICT) { LOGI("[CloudSyncer] Version conflict during cloud batch upload."); } else if (status != OK) { @@ -417,7 +419,7 @@ DBStatus CloudDBProxy::InnerActionGetEmptyCursor(const std::shared_ptr BUTT_STATUS) { + if (status < DB_ERROR || status >= BUTT_STATUS) { return static_cast(status); } switch (status) { @@ -566,13 +568,17 @@ bool CloudDBProxy::CloudActionContext::IsEmptyAssetId(const Assets &assets) return false; } -bool CloudDBProxy::CloudActionContext::IsRecordActionFail(const VBucket &extend, bool isInsert) +bool CloudDBProxy::CloudActionContext::IsRecordActionFail(const VBucket &extend, bool isInsert, DBStatus status) { - if (extend.count(CloudDbConstant::GID_FIELD) == 0 || DBCommon::IsRecordError(extend) || - (!DBCommon::IsRecordSuccess(extend) && !DBCommon::IsRecordIgnored(extend) && - !DBCommon::IsRecordVersionConflict(extend))) { + if (extend.count(CloudDbConstant::GID_FIELD) == 0) { return true; } + if (status != OK) { + if (DBCommon::IsRecordError(extend) || + (!DBCommon::IsRecordSuccess(extend) && !DBCommon::IsRecordVersionConflict(extend))) { + return true; + } + } auto gid = std::get_if(&extend.at(CloudDbConstant::GID_FIELD)); if (gid == nullptr || (isInsert && (*gid).empty())) { return true; @@ -590,11 +596,20 @@ bool CloudDBProxy::CloudActionContext::IsRecordActionFail(const VBucket &extend, return false; } -void CloudDBProxy::CloudActionContext::SetInfo(bool isInsert) +void CloudDBProxy::CloudActionContext::SetInfo(const CloudWaterType &type, DBStatus status) { - totalCount_ = extend_.size(); + totalCount_ = record_.size(); + + // records_ size should be equal to extend_ or batch data failed. + if (record_.size() != extend_.size()) { + failedCount_ += record_.size(); + return; + } for (auto &extend : extend_) { - if (IsRecordActionFail(extend, isInsert)) { + if (DBCommon::IsNeedCompensatedForUpload(extend, type) || DBCommon::IsRecordIgnored(extend)) { + continue; + } + if (IsRecordActionFail(extend, type == CloudWaterType::INSERT, status)) { failedCount_++; } else { successCount_++; diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h index 703172ad53cf0450e7808e8c4875532cbbfba9f9..c84cca427a5e9a3af8fd3662e530c0b97b5a5676 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h @@ -19,6 +19,7 @@ #include #include #include +#include "cloud_db_types.h" #include "cloud/icloud_db.h" #include "cloud/iAssetLoader.h" @@ -106,7 +107,7 @@ protected: Info GetInfo(); - void SetInfo(bool isInsert); + void SetInfo(const CloudWaterType &type, DBStatus status); void SetTableName(const std::string &tableName); @@ -114,7 +115,7 @@ protected: private: static bool IsEmptyAssetId(const Assets &assets); - static bool IsRecordActionFail(const VBucket &extend, bool isInsert); + static bool IsRecordActionFail(const VBucket &extend, bool isInsert, DBStatus status); std::mutex actionMutex_; std::condition_variable actionCv_; diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.cpp index a144131d5ed01f42fc126bb19fe6d488ae41c5dc..5048082931967af17712715312b332cf4a1e38c0 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.cpp @@ -65,8 +65,12 @@ bool CloudSyncStrategy::IsIgnoreUpdate(const LogInfo &localInfo) const if (policy_ == SingleVerConflictResolvePolicy::DEFAULT_LAST_WIN) { return false; } + if ((localInfo.flag & static_cast(LogInfoFlag::FLAG_LOCAL)) == 0 && IsDelete(localInfo)) { + LOGW("[CloudSyncStrategy] dont ignore %.6s", localInfo.cloudGid.c_str()); + return false; + } if (localInfo.originDev.empty() && localInfo.device.empty()) { - LOGW("[CloudSyncStrategy] %.3s was ignored override", localInfo.cloudGid.c_str()); + LOGW("[CloudSyncStrategy] %.6s was ignored override", localInfo.cloudGid.c_str()); return true; } return false; diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp index 8241a255172b3d010896f025f267c7d8834747c9..f7d7daa0f901ccd0b1ecaff4afb8feb3ae151c6d 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp @@ -397,6 +397,7 @@ int CloudSyncUtils::SaveChangedData(ICloudSyncer::SyncParam ¶m, size_t dataI } // INSERT: for no primary key or composite primary key situation if (!param.isSinglePrimaryKey && opType == OpType::INSERT) { + param.info.downLoadInfo.insertCount++; param.withoutRowIdData.insertData.push_back(dataIndex); return E_OK; } @@ -429,7 +430,7 @@ void CloudSyncUtils::ClearWithoutData(ICloudSyncer::SyncParam ¶m) param.withoutRowIdData.assetInsertData.clear(); } -int CloudSyncUtils::FillAssetIdToAssets(CloudSyncBatch &data, int errorCode) +int CloudSyncUtils::FillAssetIdToAssets(CloudSyncBatch &data, int errorCode, const CloudWaterType &type) { if (data.extend.size() != data.assets.size()) { LOGE("[CloudSyncUtils] size not match, extend:%zu assets:%zu.", data.extend.size(), data.assets.size()); @@ -437,13 +438,9 @@ int CloudSyncUtils::FillAssetIdToAssets(CloudSyncBatch &data, int errorCode) } int errCode = E_OK; for (size_t i = 0; i < data.assets.size(); i++) { - if (data.assets[i].empty()) { - continue; - } - if (errorCode != E_OK && DBCommon::IsRecordError(data.extend[i])) { - continue; - } - if (DBCommon::IsRecordIgnored(data.extend[i])) { + if (data.assets[i].empty() || DBCommon::IsRecordIgnored(data.extend[i]) || + (errorCode != E_OK && DBCommon::IsRecordError(data.extend[i])) || + DBCommon::IsNeedCompensatedForUpload(data.extend[i], type)) { continue; } for (auto it = data.assets[i].begin(); it != data.assets[i].end();) { diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h index 8a17825828df51b6f07eaf997496ab0b6aba07b1..a7aff59f3cc4d7c726eda1dc699159d4e8616b35 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h @@ -83,7 +83,7 @@ public: static void ClearWithoutData(ICloudSyncer::SyncParam ¶m); - static int FillAssetIdToAssets(CloudSyncBatch &data, int errorCode); + static int FillAssetIdToAssets(CloudSyncBatch &data, int errorCode, const CloudWaterType &type); static int FillAssetIdToAssetData(const Type &extend, Type &assetData); diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp index 9714afc7905c7a73dd66c58692aab5863ef0700f..da44de5925a897ba34787fecdb55d774c39dac1f 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp @@ -999,7 +999,9 @@ int CloudSyncer::SaveDataInTransaction(CloudSyncer::TaskId taskId, SyncParam &pa param.changedData.field = param.pkColNames; param.changedData.type = ChangedDataType::DATA; } + (void)storageProxy_->SetCursorIncFlag(true); ret = SaveData(taskId, param); + (void)storageProxy_->SetCursorIncFlag(false); param.insertPk.clear(); if (ret != E_OK) { LOGE("[CloudSyncer] cannot save data: %d.", ret); @@ -1064,9 +1066,7 @@ int CloudSyncer::SaveDataNotifyProcess(CloudSyncer::TaskId taskId, SyncParam &pa param.downloadData.opType.resize(param.downloadData.data.size()); param.downloadData.existDataKey.resize(param.downloadData.data.size()); param.downloadData.existDataHashKey.resize(param.downloadData.data.size()); - (void)storageProxy_->CreateTempSyncTrigger(param.tableName); ret = SaveDataInTransaction(taskId, param); - (void)storageProxy_->ClearAllTempSyncTrigger(); if (ret != E_OK) { return ret; } @@ -1109,8 +1109,15 @@ int CloudSyncer::DoDownload(CloudSyncer::TaskId taskId, bool isFirstDownload) LOGE("[CloudSyncer] get sync param for download failed %d", errCode); return errCode; } + (void)storageProxy_->CreateTempSyncTrigger(param.tableName); errCode = DoDownloadInner(taskId, param, isFirstDownload); + (void)storageProxy_->ClearAllTempSyncTrigger(); if (errCode == -E_TASK_PAUSED) { + // No need to handle ret. + int ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); + if (ret != E_OK) { + LOGE("[DoDownload] Cannot get cloud watermark : %d.", ret); + } std::lock_guard autoLock(dataLock_); resumeTaskInfos_[taskId].syncParam = std::move(param); } diff --git a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp index 6acf328ef925b4eea29ec51a059052748e6c771c..bf20cb985295071df5c72a03e00fb10e1bdc6b0a 100644 --- a/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp +++ b/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp @@ -150,6 +150,7 @@ int CloudSyncer::BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerP uploadData.insData.extend, insertInfo); innerProcessInfo.upLoadInfo.successCount += insertInfo.successCount; innerProcessInfo.upLoadInfo.insertCount += insertInfo.successCount; + innerProcessInfo.upLoadInfo.total -= insertInfo.total - insertInfo.successCount - insertInfo.failCount; if (uploadData.isCloudVersionRecord) { return errCode; } @@ -160,7 +161,7 @@ int CloudSyncer::BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerP return ret; } if (!isSharedTable) { - ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.insData, errCode); + ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.insData, errCode, CloudWaterType::INSERT); } if (errCode != E_OK) { storageProxy_->FillCloudGidIfSuccess(OpType::INSERT, uploadData); @@ -181,6 +182,7 @@ int CloudSyncer::BatchUpdate(Info &updateInfo, CloudSyncData &uploadData, InnerP uploadData.updData.extend, updateInfo); innerProcessInfo.upLoadInfo.successCount += updateInfo.successCount; innerProcessInfo.upLoadInfo.updateCount += updateInfo.successCount; + innerProcessInfo.upLoadInfo.total -= updateInfo.total - updateInfo.successCount - updateInfo.failCount; if (uploadData.isCloudVersionRecord) { return errCode; } @@ -191,7 +193,7 @@ int CloudSyncer::BatchUpdate(Info &updateInfo, CloudSyncData &uploadData, InnerP return ret; } if (!isSharedTable) { - ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.updData, errCode); + ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.updData, errCode, CloudWaterType::UPDATE); } if (errCode != E_OK) { storageProxy_->FillCloudGidIfSuccess(OpType::UPDATE, uploadData); @@ -424,7 +426,8 @@ int CloudSyncer::CommitDownloadAssets(const DownloadItem &downloadItem, const st void CloudSyncer::GenerateCompensatedSync(CloudTaskInfo &taskInfo) { std::vector syncQuery; - int errCode = storageProxy_->GetCompensatedSyncQuery(syncQuery); + std::vector users; + int errCode = storageProxy_->GetCompensatedSyncQuery(syncQuery, users); if (errCode != E_OK) { LOGW("[CloudSyncer] Generate compensated sync failed by get query! errCode = %d", errCode); return; @@ -433,6 +436,14 @@ void CloudSyncer::GenerateCompensatedSync(CloudTaskInfo &taskInfo) LOGD("[CloudSyncer] Not need generate compensated sync"); return; } + taskInfo.users.clear(); + auto cloudDBs = cloudDB_.GetCloudDB(); + for (auto &[user, cloudDb] : cloudDBs) { + auto it = std::find(users.begin(), users.end(), user); + if (it != users.end()) { + taskInfo.users.push_back(user); + } + } for (const auto &query : syncQuery) { taskInfo.table.push_back(query.GetRelationTableName()); taskInfo.queryList.push_back(query); diff --git a/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp b/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp index 0605b0985dc59a0f7086d4ebc0047c9bfc017c89..f991cfcf65322d0bffc1b7595eabe32df4140a02 100644 --- a/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp +++ b/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp @@ -211,7 +211,7 @@ int GenericSyncer::CancelSync(uint32_t syncId) if (iter == syncOperationMap_.end()) { LOGE("[Syncer] Non-existent syncId %" PRIu32 "", syncId); RefObject::DecObjRef(engine); - return -E_NOT_SUPPORT; + return -E_NOT_FOUND; } else if (iter->second->CanCancel() == false) { RefObject::DecObjRef(engine); LOGE("[Syncer] Can't cancel syncId %" PRIu32 " %" PRIu32 "", syncId, iter->second->CanCancel()); diff --git a/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp b/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp index b40bea20b8560ea10cdbd33b1c8e04db36b0e204..c09f9f2281454ffe6954b59f4b4a64d2cce67f9c 100644 --- a/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp +++ b/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp @@ -509,6 +509,11 @@ std::pair SingleVerDataSyncUtils::GetTimeOffsetFromReque std::pair res; auto &[systemOffset, senderLocalOffset] = res; const DataRequestPacket *packet = message->GetObject(); + if (packet == nullptr) { + systemOffset = 0; + senderLocalOffset = 0; + return res; + } systemOffset = packet->GetSystemTimeOffset(); senderLocalOffset = packet->GetSenderTimeOffset(); return res; diff --git a/frameworks/libs/distributeddb/test/BUILD.gn b/frameworks/libs/distributeddb/test/BUILD.gn index 1b496084c2c8653f3d5888fd85962f9cb3216f75..fc9596cdffec8919ae84116e2e3aeb6a274bf6d8 100644 --- a/frameworks/libs/distributeddb/test/BUILD.gn +++ b/frameworks/libs/distributeddb/test/BUILD.gn @@ -1005,6 +1005,8 @@ group("distributeddatamgr_fuzztest") { "fuzztest/fileoper_fuzzer:fuzztest", "fuzztest/importfile_fuzzer:fuzztest", "fuzztest/iprocesscommunicator_fuzzer:fuzztest", + "fuzztest/json_fuzzer:fuzztest", + "fuzztest/jsoninner_fuzzer:fuzztest", "fuzztest/kvdelegatemanager_fuzzer:fuzztest", "fuzztest/kvstoreresultset_fuzzer:fuzztest", "fuzztest/nbdelegate_fuzzer:fuzztest", diff --git a/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..b2adbb3594d9cbf48fb83060e3da9a7c7a4c9d05 --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/BUILD.gn @@ -0,0 +1,148 @@ +# Copyright (c) 2024 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/config/features.gni") +import("//build/test.gni") + +module_output_path = "kv_store/distributeddb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "../../../gaussdb_rd/include", + "../../../gaussdb_rd/src/common/include", + "../../../gaussdb_rd/src/executor/include", + "../../../gaussdb_rd/src/executor/document", + "../../../gaussdb_rd/src/oh_adapter/include", + "../../../gaussdb_rd/src/oh_adapter/src", + "../../../gaussdb_rd/src/interface/include", + ] + + 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 = [ + "../../../gaussdb_rd/src/common/src/collection_option.cpp", + "../../../gaussdb_rd/src/common/src/db_config.cpp", + "../../../gaussdb_rd/src/common/src/grd_api_manager.cpp", + "../../../gaussdb_rd/src/common/src/json_common.cpp", + "../../../gaussdb_rd/src/common/src/os_api.cpp", + "../../../gaussdb_rd/src/common/src/rd_log_print.cpp", + "../../../gaussdb_rd/src/executor/base/grd_db_api.cpp", + "../../../gaussdb_rd/src/executor/base/grd_db_api_inner.cpp", + "../../../gaussdb_rd/src/executor/document/check_common.cpp", + "../../../gaussdb_rd/src/executor/document/grd_document_api.cpp", + "../../../gaussdb_rd/src/executor/document/grd_document_api_inner.cpp", + "../../../gaussdb_rd/src/executor/document/grd_resultset_api.cpp", + "../../../gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp", + "../../../gaussdb_rd/src/executor/kv/grd_kv_api.cpp", + "../../../gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp", + "../../../gaussdb_rd/src/interface/src/collection.cpp", + "../../../gaussdb_rd/src/interface/src/doc_errno.cpp", + "../../../gaussdb_rd/src/interface/src/document_key.cpp", + "../../../gaussdb_rd/src/interface/src/document_store.cpp", + "../../../gaussdb_rd/src/interface/src/document_store_manager.cpp", + "../../../gaussdb_rd/src/interface/src/projection_tree.cpp", + "../../../gaussdb_rd/src/interface/src/result_set.cpp", + "../../../gaussdb_rd/src/interface/src/result_set_common.cpp", + "../../../gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp", + "../../../gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp", + "../../../gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp", + "../../../gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ "//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", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + ] + + subsystem_name = "distributeddatamgr" + part_name = "kv_store" +} + +ohos_fuzztest("JsonFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "../json_fuzzer" + + if (!defined(deps)) { + deps = [] + } + if (!defined(external_deps)) { + external_deps = [] + } + configs = [ ":module_private_config" ] + deps += [ + ":src_file", + "//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", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "--coverage", + ] + + ldflags += [ "--coverage" ] + + cflags_cc = [ "--coverage" ] + + sources = [ "json_fuzzer.cpp" ] +} + +############################################################################### + +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":JsonFuzzTest", + ] +} +############################################################################### diff --git a/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/corpus/init b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..e7c3fecd8d4d4816e40088113a2316bb9eb2e13f --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2024 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. + +FUZZ \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8a1c6435530ab6650a4bf1b9c849630056ab24e4 --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp @@ -0,0 +1,1678 @@ +/* + * Copyright (c) 2024 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. + */ +#include "json_fuzzer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "grd_base/grd_db_api.h" +#include "grd_base/grd_error.h" +#include "grd_base/grd_resultset_api.h" +#include "grd_document/grd_document_api.h" +#include "grd_kv/grd_kv_api.h" +#include "grd_resultset_inner.h" +#include "securec.h" + +const char *TEST_DB = "./data"; +const char *TEST_DB_FILE = "./data/testfile"; +const char *COLLECTION_NAME = "collectionname"; +const char *OPTION_STR = "{ \"maxdoc\" : 1000}"; +const char *CONFIG_STR = "{}"; +const char *DB_DIR_PATH = "./data/"; +const char *NO_EXIST_COLLECTION_NAME = "no_exisit"; +const int NUM_THREE = 3; +const int SMALL_PREFIX_LEN = 5; +const int NUM_FIFTEEN = 15; +const int NUM_NINETY_EIGHT = 98; +const int BATCH_COUNT = 100; +const int HALF_HALF_BYTES = 256; +const int MORE_HALF_HALF_BYTES = 257; +const int LESS_HALF_BYTES = 511; +const int MORE_HALF_BYTES = 513; +const int HALF_BYTES = 512; +const int MAX_LEN_NUM = 600; +const int LESS_MIDDLE_SIZE = 899; +const int MIDDLE_SIZE = 900; +const int MAX_SIZE_NUM = 1000; +const int ONE_BYTES = 1024; +const int CURSOR_COUNT = 50000; +const int VECTOR_SIZE = 100000; + +static GRD_DB *g_db = nullptr; + +namespace OHOS { +namespace { +int RemoveDir(const char *dir) +{ + if (dir == nullptr) { + return -1; + } + if (access(dir, F_OK) != 0) { + return 0; + } + struct stat dirStat; + if (stat(dir, &dirStat) < 0) { + return -1; + } + + char dirName[PATH_MAX]; + DIR *dirPtr = nullptr; + struct dirent *dr = nullptr; + if (S_ISREG(dirStat.st_mode)) { // normal file + remove(dir); + } else if (S_ISDIR(dirStat.st_mode)) { + dirPtr = opendir(dir); + while ((dr = readdir(dirPtr)) != nullptr) { + // ignore . and .. + if ((strcmp(".", dr->d_name) == 0) || (strcmp("..", dr->d_name) == 0)) { + continue; + } + if (sprintf_s(dirName, sizeof(dirName), "%s / %s", dir, dr->d_name) < 0) { + return -1; + } + (void)RemoveDir(dirName); + } + closedir(dirPtr); + rmdir(dir); // remove empty dir + } else { + return -1; + } + return 0; +} + +void MakeDir(const char *dir) +{ + std::string tmpPath; + const char *pcur = dir; + + while (*pcur++ != '\0') { + tmpPath.push_back(*(pcur - 1)); + if ((*pcur == '/' || *pcur == '\0') && access(tmpPath.c_str(), 0) != 0 && !tmpPath.empty()) { + if (mkdir(tmpPath.c_str(), (S_IRUSR | S_IWUSR | S_IXUSR)) != 0) { + return; + } + } + } +} + +std::string getMaxString() +{ + std::string str = "{"; + for (int i = 0; i <= MAX_SIZE_NUM; i++) { + for (int j = 0; j <= MAX_LEN_NUM; j++) { + str += "a"; + } + } + return str + "}"; +} +} // namespace + +void InsertDocOneFuzz(std::string documentData) +{ + std::string document2 = "{\"_id\":2,\"field\":\"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document2.c_str(), 0); + std::string document3 = "{\"_id\":true,\"field\":\"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document3.c_str(), 0); + std::string document4 = "{\"_id\" : null, \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document4.c_str(), 0); + std::string document5 = "{\"_id\" : [\"2\"], \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document5.c_str(), 0); + std::string document6 = "{\"_id\" : {\"val\" : \"2\"}, \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document6.c_str(), 0); + std::string document7 = "{\"_id\" : \"3\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document7.c_str(), 0); + std::string document9 = "{\"_id\" : \"4\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(NULL, COLLECTION_NAME, document9.c_str(), 0); + std::string document10 = "{\"_id\" : \"5\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, NULL, document10.c_str(), 0); + std::string document12 = "{\"_id\" : \"6\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document12.c_str(), 1); + std::string document13 = "{\"_id\" : \"7\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document13.c_str(), INT_MAX); + std::string document14 = "{\"_id\" : \"8\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document14.c_str(), INT_MIN); + GRD_InsertDoc(g_db, NULL, NULL, 0); + std::string document15 = "{\"_id\" : \"9\", \"name\" : \"" + documentData + "\"}"; + std::string collectionName2(HALF_BYTES, 'a'); + GRD_InsertDoc(g_db, collectionName2.c_str(), document15.c_str(), 0); + const char *collectionName = "collection@!#"; + std::string document16 = "{\"_id\" : \"10\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, collectionName, document16.c_str(), GRD_OK); + std::string collectionName1(MORE_HALF_HALF_BYTES, 'k'); + std::string document17 = "{\"_id\" : \"10\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, collectionName1.c_str(), document17.c_str(), GRD_OK); + std::string document18 = "({\"level1\" : {\"level2\" : {\"level3\" : {\"level4\": {\"level5\" : 1}},\ + \"level3_2\" : \"" + + documentData + "\"}},\"_id\":\"14\"})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document18.c_str(), 0); + std::string document19 = "({\"level1\" : {\"level2\" : {\"level3\" : [{ \"level5\" : \"" + documentData + "\",\ + \"level5_2\":\"" + + documentData + "\"}, \"" + documentData + "\",\"" + documentData + "\"], \"level3_2\":\ + \"" + + documentData + "\"}}, \"_id\":\"14\"})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document19.c_str(), 0); + std::string document20 = "({\"level1\" : {\"level2\" : {\"level3\" : { \"level4\" : \"" + documentData + "\"},\ + \"level3_2\" : \"" + + documentData + "\"}}, \"_id\":\"14\"})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document20.c_str(), 0); +} + +void InsertDocTwoFuzz(std::string documentData) +{ + std::string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; + std::string documentPart2 = "\" }"; + std::string jsonVal = std::string(HALF_BYTES * ONE_BYTES - documentPart1.size() - documentPart2.size(), 'k'); + std::string document = documentPart1 + jsonVal + documentPart2; + std::string jsonVal2 = std::string(HALF_BYTES * ONE_BYTES - 1 - documentPart1.size() - documentPart2.size(), 'k'); + std::string document21 = documentPart1 + jsonVal2 + documentPart2; + GRD_InsertDoc(g_db, COLLECTION_NAME, document21.c_str(), 0); + std::string document22 = "{\"_id\" : \"16\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document22.c_str(), 0); + std::string document23 = + "{\"_id\" : \"17\", \"level1\" : {\"level2\" : {\"level3\" : {\"level4\" : " + documentData + "\ + } } }, \"level1_2\" : \"" + + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document23.c_str(), 0); + std::string document24 = documentData; + GRD_InsertDoc(g_db, COLLECTION_NAME, document24.c_str(), 0); + std::string document25 = "{\"name\" : \"" + documentData + "\", \"age\" : " + documentData + ",\ + \"friend\" : {\"name\" : \" " + + documentData + "\"}, \"_id\" : \"19\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document25.c_str(), 0); + std::string collectionName3 = std::string(HALF_HALF_BYTES, 'k'); + std::string document26 = "{\"_id\" : \"22\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, collectionName3.c_str(), document26.c_str(), GRD_OK); + std::string collectionName4 = "Aads_sd__23Asb_"; + std::string document27 = "{\"_id\" : \"23\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, collectionName4.c_str(), document27.c_str(), GRD_OK); + std::string collectionName5 = "GRD_collectionName"; + std::string document28 = "{\"_id\" : \"24\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollection(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDoc(g_db, collectionName5.c_str(), document28.c_str(), 0); + collectionName5 = "GM_SYS__collectionName"; + std::string document29 = "{\"_id\" : \"24_2\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollection(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDoc(g_db, collectionName5.c_str(), document29.c_str(), 0); + + collectionName5 = "grd_collectionName"; + std::string document30 = "{\"_id\" : \"24_3\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollection(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDoc(g_db, collectionName5.c_str(), document30.c_str(), 0); +} + +void InsertDocThreeFuzz(std::string documentData) +{ + std::string collectionName5 = "gm_sys_collectionName"; + std::string document31 = "{\"_id\" : \"24_4\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollection(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDoc(g_db, collectionName5.c_str(), document31.c_str(), 0); + + collectionName5 = "gM_sYs_collectionName"; + std::string document32 = "{\"_id\" : \"24_5\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollection(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDoc(g_db, collectionName5.c_str(), document32.c_str(), 0); + + collectionName5 = "gRd_collectionName"; + std::string document33 = "{\"_id\" : \"24_6\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollection(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDoc(g_db, collectionName5.c_str(), document33.c_str(), 0); + + collectionName5 = "gRd@collectionName"; + std::string document34 = "{\"_id\" : \"24_7\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollection(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDoc(g_db, collectionName5.c_str(), document34.c_str(), 0); + + std::string document35 = "{\"_id\" : \"25_0\", \"level1\" : {\"level2\" : {\"level3\" :\ + {\"level4\" : \"" + + documentData + "\"}}} , \"level1_2\" : \"" + documentData + "\" }"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document35.c_str(), 0); + + std::string document36 = "{\"_id\" : \"25_1\", \"class_name\" : \"" + documentData + + "\", \"signed_info\" : true, \ + \"student_info\" : [{\"name\":\"" + + documentData + "\", \"age\" : " + documentData + ", \"sex\" : \"male\"}, \ + { \"newName1\" : [\"" + + documentData + "\", \"" + documentData + "\", 0, \"" + documentData + "\"] }]}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document36.c_str(), 0); + + std::string document37 = "{\"_id\" : \"25_2\", \"class_name\" : \"" + documentData + + "\", \"signed_info\" : true, \ + \"student_info\" : [{\"name\":\"" + + documentData + "\", \"age\" : " + documentData + ", \"sex\" : \"male\"}, \ + [\"" + + documentData + "\", \"" + documentData + "\", 0, \"" + documentData + "\", {\"0ab\" : null}]]}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document37.c_str(), 0); + + std::string document38 = "{\"_id\" : \"25_3\", \"class_name\" : \"" + documentData + + "\", \"signed_info\" : true, \ + \"student_info\" : [{\"name\":\"" + + documentData + "\", \"age\" : " + documentData + ", \"sex\" : \"male\"}, \ + { \"newName1\" : [\"" + + documentData + "\", \"" + documentData + "\", 0, \"" + documentData + "\", {\"level5\" : 1}] }]}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document38.c_str(), 0); +} + +void InsertDocFourFuzz(std::string longId, std::string documentData) +{ + std::string document39 = + "{\"_id\" : \"35\", \"A_aBdk_324_\" : \"" + documentData + "\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document39.c_str(), 0); + + std::string document40 = "{\"_id\" : \"35_2\", \"1A_aBdk_324_\" : \"" + documentData + + "\", " + "\"name\" : \"" + + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document40.c_str(), 0); + std::string document41 = "{\"_id\" : \"36_0\", \"stringType\" : \"" + documentData + + "\", \"numType\" : " + documentData + ", \"BoolType\" : true,\ + \"nullType\" : null, \"arrayType\" : " + + documentData + ", \"objectType\" : {\"A\" : 3}}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document41.c_str(), 0); + + std::string document42 = "({\"_id\" : \"38_0\", \"field2\" : 1.797693" + longId + "13486232e308})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document42.c_str(), 0); + std::string document43 = "({\"_id\" : \"38_1\", \"t1\" : {\"field2\" : 1.797" + longId + "69313486232e308}})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document43.c_str(), 0); + std::string document44 = "({\"_id\" : \"38_2\", \"t1\" : [1, 2, 1.79769313486" + longId + "232e308]})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document44.c_str(), 0); + std::string document45 = "({\"_id\" : \"38_3\", \"t1\" : [1, 2, -1.7976931348623167" + longId + "E+308]})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document45.c_str(), 0); + std::string document46 = "({\"_id\" : \"38_4\", \"t1\" : [1, 2, -1." + longId + "79769313486231570E+308]})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document46.c_str(), 0); + std::string document47 = "({\"_id\" : \"38_5\", \"t1\" : [1, 2, 1.79769313486" + longId + "231570E+308]})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document47.c_str(), 0); + + std::string doc1 = "{\"_id\" : "; + std::string doc2 = "\""; + std::string doc4 = "\""; + std::string doc5 = ", \"name\" : \"" + documentData + "\"}"; + std::string documentMiddle(MIDDLE_SIZE, 'k'); + std::string document48 = doc1 + doc2 + documentMiddle + doc4 + doc5; + GRD_InsertDoc(g_db, COLLECTION_NAME, document48.c_str(), 0); + std::string documentMiddle2(MAX_SIZE_NUM, 'k'); + document48 = doc1 + doc2 + documentMiddle2 + doc4 + doc5; + GRD_InsertDoc(g_db, COLLECTION_NAME, document48.c_str(), 0); + + std::string document49 = "({\"_id\":\"0123\", \"num\":\"" + documentData + "\"})"; + std::string document50 = "({\"_id\":\"0123\", \"NUM\":\"" + documentData + "\"})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document49.c_str(), 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, document50.c_str(), 0); + + std::string document51 = "({\"_id\":\"0123\", \"num.\":\"" + documentData + "\"})"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document51.c_str(), 0); + + const char *document52 = R""({})""; + GRD_InsertDoc(g_db, COLLECTION_NAME, document52, 0); +} + +void InsertDocFuzz(const uint8_t *data, size_t size) +{ + std::string collectionNameData(reinterpret_cast(data), size); + const char *collectionNameVal = collectionNameData.data(); + std::string optionStrData(reinterpret_cast(data), size); + const char *optionStrVal = optionStrData.data(); + GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); + std::string documentData(reinterpret_cast(data), size); + const char *documentVal = documentData.data(); + GRD_InsertDoc(g_db, collectionNameVal, documentVal, 0); + GRD_InsertDoc(g_db, collectionNameVal, documentVal, 0); + std::string stringJson = "{" + documentData + "}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, stringJson.c_str(), 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, stringJson.c_str(), 0); + std::string stringJson2 = "{\"_id\":\"1\",\"field\":\"" + documentData + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, stringJson2.c_str(), 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, stringJson2.c_str(), 0); + std::string longId = "1"; + for (int i = 0; i < MAX_SIZE_NUM; i++) { + longId += "1"; + } + longId = "{\"_id\":\"" + longId + "\",\"field\":\"field_id\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, longId.c_str(), 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, "{\"_id\":123}", 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, "{\"field1.field2.field&*^&3\":\"anc\"}", 0); + InsertDocOneFuzz(documentData); + InsertDocTwoFuzz(documentData); + InsertDocThreeFuzz(documentData); + InsertDocFourFuzz(longId, documentData); + + const char *document53 = R""({"empty" : null})""; + GRD_InsertDoc(g_db, COLLECTION_NAME, document53, 0); + GRD_DropCollection(g_db, collectionNameVal, 0); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + + std::string documentNew1 = "{\"_id\" : "; + std::string documentNew2 = "\""; + std::string documentNew3 = "\""; + std::string documentNew4 = ", \"name\" : \"Ori\"}"; + std::string document = documentNew1 + documentNew2 + documentData + documentNew3 + documentNew4; + GRD_InsertDoc(g_db, COLLECTION_NAME, document.c_str(), 0); +} + +static const char *DOCUMENT1 = "{\"_id\" : \"1\", \"name\":\"doc1\",\"item\":\"journal\",\"personInfo\":\ + {\"school\":\"AB\", \"age\" : 51}}"; +static const char *DOCUMENT2 = "{\"_id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"personInfo\":\ + [1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; +static const char *DOCUMENT3 = "{\"_id\" : \"3\", \"name\":\"doc3\",\"item\":\"notebook\",\"personInfo\":\ + [{\"school\":\"C\", \"age\" : 5}]}"; +static const char *DOCUMENT4 = "{\"_id\" : \"4\", \"name\":\"doc4\",\"item\":\"paper\",\"personInfo\":\ + {\"grade\" : 1, \"school\":\"A\", \"age\" : 18}}"; +static const char *DOCUMENT5 = "{\"_id\" : \"5\", \"name\":\"doc5\",\"item\":\"journal\",\"personInfo\":\ + [{\"sex\" : \"woma\", \"school\" : \"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *DOCUMENT6 = "{\"_id\" : \"6\", \"name\":\"doc6\",\"item\":false,\"personInfo\":\ + [{\"school\":\"B\", \"teacher\" : \"mike\", \"age\" : 15},\ + {\"school\":\"C\", \"teacher\" : \"moon\", \"age\" : 20}]}"; + +static const char *DOCUMENT7 = "{\"_id\" : \"7\", \"name\":\"doc7\",\"item\":\"fruit\",\"other_Info\":\ + [{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *DOCUMENT8 = "{\"_id\" : \"8\", \"name\":\"doc8\",\"item\":true,\"personInfo\":\ + [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *DOCUMENT9 = "{\"_id\" : \"9\", \"name\":\"doc9\",\"item\": true}"; +static const char *DOCUMENT10 = "{\"_id\" : \"10\", \"name\":\"doc10\", \"parent\" : \"kate\"}"; +static const char *DOCUMENT11 = "{\"_id\" : \"11\", \"name\":\"doc11\", \"other\" : \"null\"}"; +static const char *DOCUMENT12 = "{\"_id\" : \"12\", \"name\":\"doc12\",\"other\" : null}"; +static const char *DOCUMENT13 = "{\"_id\" : \"13\", \"name\":\"doc13\",\"item\" : \"shoes\",\"personInfo\":\ + {\"school\":\"AB\", \"age\" : 15}}"; +static const char *DOCUMENT14 = "{\"_id\" : \"14\", \"name\":\"doc14\",\"item\" : true,\"personInfo\":\ + [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 85}]}"; +static const char *DOCUMENT15 = "{\"_id\" : \"15\", \"name\":\"doc15\",\"personInfo\":[{\"school\":\"C\", \"age\" : " + "5}]}"; +static const char *DOCUMENT16 = "{\"_id\" : \"16\", \"name\":\"doc16\", \"nested1\":{\"nested2\":{\"nested3\":\ + {\"nested4\":\"ABC\", \"field2\":\"CCC\"}}}}"; +static const char *DOCUMENT17 = "{\"_id\" : \"17\", \"name\":\"doc17\",\"personInfo\":\"oh,ok\"}"; +static const char *DOCUMENT18 = "{\"_id\" : \"18\", \"name\":\"doc18\",\"item\" : \"mobile phone\",\"personInfo\":\ + {\"school\":\"DD\", \"age\":66}, \"color\":\"blue\"}"; +static const char *DOCUMENT19 = "{\"_id\" : \"19\", \"name\":\"doc19\",\"ITEM\" : true,\"PERSONINFO\":\ + {\"school\":\"AB\", \"age\":15}}"; +static const char *DOCUMENT20 = "{\"_id\" : \"20\", \"name\":\"doc20\",\"ITEM\" : true,\"personInfo\":\ + [{\"SCHOOL\":\"B\", \"AGE\":15}, {\"SCHOOL\":\"C\", \"AGE\":35}]}"; +static const char *DOCUMENT23 = "{\"_id\" : \"23\", \"name\":\"doc22\",\"ITEM\" : " + "true,\"personInfo\":[{\"school\":\"b\", \"age\":15}, [{\"school\":\"doc23\"}, 10, " + "{\"school\":\"doc23\"}, true, {\"school\":\"y\"}], {\"school\":\"b\"}]}"; +static std::vector g_data = { DOCUMENT1, DOCUMENT2, DOCUMENT3, DOCUMENT4, DOCUMENT5, + DOCUMENT6, DOCUMENT7, DOCUMENT8, DOCUMENT9, DOCUMENT10, DOCUMENT11, DOCUMENT12, DOCUMENT13, + DOCUMENT14, DOCUMENT15, DOCUMENT16, DOCUMENT17, DOCUMENT18, DOCUMENT19, DOCUMENT20, DOCUMENT23 }; + +namespace { +static void InsertData(GRD_DB *g_db, const char *collectionName) +{ + for (const auto &item : g_data) { + GRD_InsertDoc(g_db, collectionName, item, 0); + } +} + +void SetUpTestCase() +{ + (void)RemoveDir(TEST_DB); + MakeDir(TEST_DB); + GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &g_db); + InsertData(g_db, COLLECTION_NAME); + GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); +} + +void TearDownTestCase() +{ + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + GRD_DBClose(g_db, GRD_DB_CLOSE); + (void)RemoveDir(TEST_DB); + g_db = nullptr; +} + +void FindDocResultSetFuzz(const char *collName, std::string filter, std::string projectionInfo) +{ + GRD_ResultSet *resultSet = nullptr; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, collName, query, 1, &resultSet); + if (resultSet != nullptr) { + GRD_Next(resultSet); + char *valueResultSet = nullptr; + GRD_GetValue(resultSet, &valueResultSet); + } + GRD_FreeResultSet(resultSet); +} + +void FindDocWithFlagFuzz(std::string filter, std::string projectionInfo, int flag) +{ + GRD_ResultSet *resultSet = nullptr; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet); + GRD_Next(resultSet); + char *value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); +} + +void FindDocNextTwiceFuzz(std::string filter, std::string projectionInfo) +{ + GRD_ResultSet *resultSet = nullptr; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + char *value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); +} + +void FindDocZeroFuzz(const std::string &input) +{ + std::string filter = "{\"_id\" : \"6\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : \"6\", \"name\":\"" + input + "\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"name\":\"" + input + "\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : \"" + input + "\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : 1}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : [\"" + input + "\", 1]}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : {\"" + input + "\" : \"1\"}}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : true}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : null}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + const char *collName1 = "grd_type"; + const char *collName2 = "GM_SYS_sysfff"; + filter = "{\"_id\" : \"1\"}"; + FindDocResultSetFuzz(collName1, filter, R"({})"); + FindDocResultSetFuzz(collName2, filter, R"({})"); + + filter = "{\"_id\" : \"100\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); +} + +void FindDocOneFuzz() +{ + std::string filter = "{\"_id\" : \"6\"}"; + GRD_ResultSet *resultSet = nullptr; + GRD_ResultSet *resultSet2 = nullptr; + Query query = { filter.c_str(), "{}" }; + const char *collectionName = "DocumentDBFindTest024"; + GRD_CreateCollection(g_db, collectionName, "", 0); + InsertData(g_db, collectionName); + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FindDoc(g_db, collectionName, query, 1, &resultSet2); + + GRD_Next(resultSet); + char *value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + + GRD_Next(resultSet2); + char *value2 = nullptr; + GRD_GetValue(resultSet2, &value2); + GRD_FreeValue(value2); + + GRD_Next(resultSet); + GRD_Next(resultSet2); + GRD_GetValue(resultSet, &value); + GRD_GetValue(resultSet2, &value); + GRD_FreeResultSet(resultSet); + GRD_FreeResultSet(resultSet2); + GRD_DropCollection(g_db, collectionName, 0); + + filter = "{\"_id\" : \"16\"}"; + resultSet = nullptr; + std::string projectionInfo = "{\"name\": true, \"nested1.nested2.nested3.nested4\":true}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_Next(resultSet); + value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + GRD_FreeResultSet(resultSet); + + projectionInfo = "{\"name\": true, \"nested1\":{\"nested2\":{\"nested3\":{\"nested4\":true}}}}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + GRD_FreeResultSet(resultSet); +} + +void FindDocTwoFuzz(const std::string &input) +{ + GRD_ResultSet *resultSet = nullptr; + std::string projectionInfo = "{\"name\": 0, \"nested1.nested2.nested3.nested4\":0}"; + std::string filter = "{\"_id\" : \"16\"}"; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_Next(resultSet); + char *value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); + + projectionInfo = "{\"name\": \"" + input + "\", \"nested1.nested2.nested3.nested4\":\"" + input + "\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); + + filter = "{\"_id\" : \"7\"}"; + resultSet = nullptr; + projectionInfo = "{\"name\": true, \"other_Info\":true, \"non_exist_field\":true}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_Next(resultSet); + value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); + + projectionInfo = "{\"name\": true, \"other_Info\":true, \" item \":true}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); +} + +void FindDocThreeFuzz(const std::string &input) +{ + std::string filter = "{\"_id\" : \"7\"}"; + GRD_ResultSet *resultSet = nullptr; + std::string projectionInfo = "{\"name\": true, \"other_Info.non_exist_field\":true}"; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_Next(resultSet); + char *value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); + projectionInfo = "{\"name\": true, \"other_Info\":{\"non_exist_field\":true}}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); + projectionInfo = "{\"name\": true, \"other_Info.0\": true}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); + filter = "{\"_id\" : \"4\"}"; + resultSet = nullptr; + projectionInfo = "{\"personInfo\": true, \"personInfo.grade\": true}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + + filter = "{\"_id\" : \"7\"}"; + projectionInfo = "{\"non_exist_field\":true}"; + int flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + flag = 1; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + filter = "{\"_id\" : \"7\"}"; + projectionInfo = "{\"name\":true, \"item\":true}"; + flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + flag = 1; + projectionInfo = "{\"name\": " + input + ", \"item\": " + input + "}"; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + filter = "{\"_id\" : \"7\"}"; + projectionInfo = "{\"name\":false, \"item\":false}"; + flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + flag = 1; + projectionInfo = "{\"name\": " + input + ", \"item\": " + input + "}"; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + filter = "{\"_id\" : \"4\"}"; + projectionInfo = "{\"name\": " + input + ", \"personInfo.grade1\": " + input + ", \ + \"personInfo.shool1\": " + + input + ", \"personInfo.age1\": " + input + "}"; + flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + projectionInfo = "{\"name\": false, \"personInfo.grade1\": false, \ + \"personInfo.shool1\": false, \"personInfo.age1\": false}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); +} + +void FindDocFourFuzz(const std::string &input) +{ + std::string filter = "{\"_id\" : \"4\"}"; + std::string projectionInfo = + "{\"name\": " + input + ", \"personInfo.school\": " + input + ", \"personInfo.age\": " + input + "}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); + + filter = "{\"_id\" : \"17\"}"; + GRD_ResultSet *resultSet = nullptr; + Query query = { filter.c_str(), "{}" }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, GRD_DOC_ID_DISPLAY, &resultSet); + GRD_Next(resultSet); + char *value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + GRD_FreeResultSet(resultSet); + + resultSet = nullptr; + query = { filter.c_str(), "{}" }; + GRD_FindDoc(g_db, "", query, 0, &resultSet); + GRD_FindDoc(g_db, nullptr, query, 0, &resultSet); + + filter = "{\"_id\" : \"4\"}"; + resultSet = nullptr; + projectionInfo = "{\"name\":" + input + ", \"personInfo\":0, \"item\":" + input + "}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":true, \"personInfo\":0, \"item\":true}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":\"\", \"personInfo\":0, \"item\":\"\"}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":false, \"personInfo\":1, \"item\":false"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":false, \"personInfo\":-1.123, \"item\":false"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":false, \"personInfo\":true, \"item\":false"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); +} + +void FindDocFiveFuzz(const std::string &input) +{ + std::string filter = "{\"_id\" : \"6\"}"; + std::string projectionInfo = "{\"name\":false, \"personInfo\": 0, \"item\":0}"; + int flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + + filter = "{\"_id\" : \"18\"}"; + projectionInfo = "{\"name\":true, \"personInfo.age\": \"\", \"item\":1, \"color\":10, \"nonExist\" : " + "-100}"; + flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + + GRD_ResultSet *resultSet = nullptr; + projectionInfo = "{\"personInfo\":[true, " + input + "]}"; + flag = 1; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet); + projectionInfo = "{\"personInfo\":null}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet); + resultSet = nullptr; + projectionInfo = "{\"Name\":true, \"personInfo.age\": \"\", \"item\":" + input + ", \"COLOR\":" + input + + ", \"nonExist\" : " + "" + + input + "}"; + flag = 0; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet); + GRD_Next(resultSet); + GRD_FreeResultSet(resultSet); + + resultSet = nullptr; + projectionInfo = "{\"Name\":" + input + ", \"personInfo.age\": false, \"personInfo.SCHOOL\": false, \"item\":\ + false, \"COLOR\":false, \"nonExist\" : false}"; + query = { filter.c_str(), projectionInfo.c_str() }; + char *value = nullptr; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_Next(resultSet); + GRD_FreeResultSet(resultSet); + + filter = "{\"_id\" : \"18\"}"; + resultSet = nullptr; + query = { filter.c_str(), "{}" }; + std::string collectionName1(LESS_HALF_BYTES, 'a'); + GRD_FindDoc(g_db, collectionName1.c_str(), query, 1, &resultSet); + GRD_FreeResultSet(resultSet); +} + +void FindDocSixFuzz(const std::string &input) +{ + std::string collectionName2(HALF_BYTES, 'a'); + std::string filter = "{\"_id\" : \"18\"}"; + Query query = { filter.c_str(), "{}" }; + GRD_ResultSet *resultSet = nullptr; + GRD_FindDoc(g_db, collectionName2.c_str(), query, 1, &resultSet); + GRD_FindDoc(g_db, "", query, 1, &resultSet); + + resultSet = nullptr; + std::string projectionInfo = "{}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, NUM_THREE, &resultSet); + GRD_FindDoc(g_db, COLLECTION_NAME, query, INT_MAX, &resultSet); + GRD_FindDoc(g_db, COLLECTION_NAME, query, INT_MIN, &resultSet); + GRD_FindDoc(nullptr, COLLECTION_NAME, query, 0, &resultSet); + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, nullptr); + query = { nullptr, nullptr }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + + std::string document1 = "{\"_id\" : "; + std::string document2 = "\""; + std::string document4 = "\""; + std::string document5 = "}"; + std::string documentMiddle(MIDDLE_SIZE, 'k'); + filter = document1 + document2 + documentMiddle + document4 + document5; + resultSet = nullptr; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + std::string documentMiddle2(LESS_MIDDLE_SIZE, 'k'); + filter = document1 + document2 + documentMiddle2 + document4 + document5; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_FreeResultSet(resultSet); + + filter = "{\"personInfo\" : {\"school\":\"" + input + "\"}}"; + FindDocNextTwiceFuzz(filter, R"({})"); + + projectionInfo = "{\"version\": " + input + "}"; + FindDocNextTwiceFuzz(filter, projectionInfo); + + projectionInfo = "({\"a00001\":" + input + ", \"a00001\":" + input + "})"; + FindDocNextTwiceFuzz(filter, projectionInfo); + + projectionInfo = "({\"abc123_.\":" + input + "})"; + FindDocNextTwiceFuzz(filter, projectionInfo); + + filter = "({\"abc123_.\":" + input + "})"; + FindDocNextTwiceFuzz(filter, projectionInfo); +} + +void FindDocSevenFuzz(const std::string &input) +{ + std::string document064 = "{\"_id\" : \"64\", \"a\":" + input + ", \"doc64\" : " + input + "}"; + std::string document063 = "{\"_id\" : \"63\", \"a\":" + input + ", \"doc63\" : " + input + "}"; + std::string document062 = "{\"_id\" : \"62\", \"a\":" + input + ", \"doc62\" : " + input + "}"; + std::string document061 = "{\"_id\" : \"61\", \"a\":" + input + ", \"doc61\" : " + input + "}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document064.c_str(), 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, document063.c_str(), 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, document062.c_str(), 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, document061.c_str(), 0); + std::string filter = "{\"a\":" + input + "}"; + GRD_ResultSet *resultSet = nullptr; + std::string projectionInfo = R"({})"; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_Next(resultSet); + char *value = nullptr; + GRD_GetValue(resultSet, &value); + + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); +} + +void FindDocFuzzPlus(const std::string &input) +{ + FindDocZeroFuzz(input); + std::string filter = "{\"_id\" : \"6\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + FindDocOneFuzz(); + FindDocTwoFuzz(input); + FindDocThreeFuzz(input); + FindDocFourFuzz(input); + FindDocFiveFuzz(input); + FindDocSixFuzz(input); + FindDocSevenFuzz(input); + + std::string document = "{\"a\":" + input + ", \"doc64\" : " + input + "}"; + filter = "{\"b\":" + input + "}"; + GRD_UpsertDoc(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + filter = "{\"a\":" + input + "}"; + GRD_ResultSet *resultSet = nullptr; + std::string projectionInfo = R"({})"; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + GRD_Next(resultSet); + GRD_FreeResultSet(resultSet); + filter = "{\"a\":" + input + "}"; + resultSet = nullptr; + projectionInfo = R"({})"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + GRD_Next(resultSet); + char *valueNew = nullptr; + GRD_GetValue(resultSet, &valueNew); + GRD_FreeValue(valueNew); + GRD_FreeResultSet(resultSet); + filter = "{\"personInfo\" : {\"school\":" + input + "}" + "}"; + FindDocNextTwiceFuzz(filter, R"({})"); +} +} // namespace + +void FindDocFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{\"field\":\"" + input + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + Query query = { inputJson.c_str(), inputJson.c_str() }; + GRD_ResultSet *resultSet = nullptr; + // ResultSet conflict + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSet(resultSet); + resultSet = nullptr; + GRD_FindDoc(g_db, input.c_str(), query, size, &resultSet); + GRD_FreeResultSet(resultSet); + GRD_FindDoc(nullptr, input.c_str(), query, 1, &resultSet); + query.filter = nullptr; + GRD_FindDoc(g_db, input.c_str(), query, 1, &resultSet); + inputJson = "{\"field\": 0, \"field2\":" + input + "}"; + query.filter = "{}"; + query.projection = inputJson.c_str(); + resultSet = nullptr; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSet(resultSet); + inputJson = "{\"" + input + "\": 0}"; + query.projection = inputJson.c_str(); + resultSet = nullptr; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSet(resultSet); + inputJson = "{\"field\":[\"aaa\"," + input + "]}"; + resultSet = nullptr; + query.projection = inputJson.c_str(); + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSet(resultSet); + query.filter = "{\"field\": false}"; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSet(resultSet); + FindDocFuzzPlus(input); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); +} + +void UpdateDocOneFuzz(std::string s, std::string input) +{ + std::string inputJson = "{\"field5\": \"" + s + "\"}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field5\": \"" + s + s + "\"}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); + inputJson = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); + inputJson = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); + + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDoc(g_db, inputJson.c_str(), "{}", "{}", 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, input.c_str(), "{}", 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{}", input.c_str(), 0); + GRD_UpdateDoc(nullptr, COLLECTION_NAME, "{}", "{}", 0); + inputJson = "{\"_id\":\"2\", \"field\":" + input + "}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; + inputJson = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + s.clear(); + for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { + s += 'a'; + } + inputJson = "{\"field5\": \"" + s + "\"}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field5\": \"" + s + s + "\"}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); + inputJson = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); + inputJson = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); +} + +void UpdateDocTwoFuzz(const char *newCollName, std::string s, std::string input) +{ + std::string inputJson = "{\"field5\": \"" + s + "\"}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field5\": \"" + s + s + "\"}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; + GRD_UpdateDoc(g_db, newCollName, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); + inputJson = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; + GRD_UpdateDoc(g_db, newCollName, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); + inputJson = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + GRD_UpdateDoc(g_db, newCollName, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); + + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDoc(g_db, inputJson.c_str(), "{}", "{}", 0); + GRD_UpdateDoc(g_db, newCollName, input.c_str(), "{}", 0); + GRD_UpdateDoc(g_db, newCollName, "{}", input.c_str(), 0); + GRD_UpdateDoc(nullptr, newCollName, "{}", "{}", 0); + inputJson = "{\"_id\":\"2\", \"field\":" + input + "}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; + inputJson = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + s.clear(); + for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { + s += 'a'; + } + inputJson = "{\"field5\": \"" + s + "\"}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field5\": \"" + s + s + "\"}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; + GRD_InsertDoc(g_db, newCollName, inputJson.c_str(), 0); + GRD_UpdateDoc(g_db, newCollName, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); + inputJson = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; + GRD_InsertDoc(g_db, newCollName, inputJson.c_str(), 0); + GRD_UpdateDoc(g_db, newCollName, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); + inputJson = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + GRD_InsertDoc(g_db, newCollName, inputJson.c_str(), 0); + GRD_UpdateDoc(g_db, newCollName, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); +} + +void UpdateDocFilterFuzz() +{ + const char *filter = "{\"_id\" : \"1\"}"; + const char *updata2 = "{\"objectInfo.child.child\" : {\"child\":{\"child\":null}}}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, filter, updata2, 0); + + const char *filter1 = "{\"_id\" : \"1\"}"; + const char *updata1 = "{\"_id\" : \"6\"}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, filter1, updata1, 0); + + const char *filter2 = "{\"_id\" : \"1\"}"; + const char *updata3 = "{\"age$\" : \"21\"}"; + const char *updata4 = "{\"bonus..traffic\" : 100}"; + const char *updata5 = "{\"0item\" : 100}"; + const char *updata6 = "{\"item\" : 1.79769313486232e308}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, filter2, updata3, 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, filter2, updata4, 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, filter2, updata5, 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, filter2, updata6, 0); + + const char *filter3 = "{\"_id\" : \"1\"}"; + const char *updata7 = "{\"age\" : 21}"; + GRD_UpdateDoc(g_db, NULL, filter3, updata7, 0); + GRD_UpdateDoc(g_db, "", filter3, updata7, 0); + GRD_UpdateDoc(NULL, COLLECTION_NAME, filter3, updata7, 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, NULL, updata7, 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, filter3, NULL, 0); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); +} + +void UpdateDocFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{\"_id\":\"2\", \"field\": \"aaa\", " + "\"subject\":\"aaaaaaaaaaa\", \"test1\": true, " + "\"test2\": null}"; + + GRD_UpdateDoc(g_db, inputJson.c_str(), "{}", "{}", 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, input.c_str(), "{}", 0); + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{}", input.c_str(), 0); + GRD_UpdateDoc(nullptr, COLLECTION_NAME, "{}", "{}", 0); + inputJson = "{\"_id\":\"2\", \"field\":" + input + "}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; + inputJson = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; + GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + std::string s; + for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { + s += 'a'; + } + UpdateDocOneFuzz(s, input); + + const char *newCollName = "./student"; + GRD_UpdateDoc(g_db, inputJson.c_str(), "{}", "{}", 0); + GRD_UpdateDoc(g_db, newCollName, input.c_str(), "{}", 0); + GRD_UpdateDoc(g_db, newCollName, "{}", input.c_str(), 0); + GRD_UpdateDoc(nullptr, newCollName, "{}", "{}", 0); + inputJson = "{\"_id\":\"2\", \"field\":" + input + "}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; + inputJson = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; + GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + s.clear(); + for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { + s += 'a'; + } + + UpdateDocTwoFuzz(newCollName, s, input); + UpdateDocFilterFuzz(); +} + +void UpsertDocNewFuzz(std::string input, GRD_DB *db1) +{ + GRD_CreateCollection(g_db, "student", "", 0); + std::string documentNew = + "{\"name\": {\"first\":[\"XXX\", \"BBB\", \"CCC\"], \"last\":\"moray\", \"field\":" + input + "}"; + std::string updateDocNew = R""({"name.last.AA.B":"Mnado"})""; + GRD_UpsertDoc(g_db, "student", R""({"_id":"10001"})"", documentNew.c_str(), 0); + GRD_UpsertDoc(db1, "student", R""({"_id":"10001"})"", updateDocNew.c_str(), 1); + GRD_DropCollection(g_db, "student", 0); + + GRD_CreateCollection(g_db, "student", "", 0); + documentNew = "{\"name\":[\"Tmn\", \"BB\", \"Alice\"], \"field\":" + input + "}"; + updateDocNew = R""({"name.first":"GG"})""; + GRD_UpsertDoc(g_db, "student", R""({"_id":"10002"})"", documentNew.c_str(), 0); + GRD_UpsertDoc(db1, "student", R""({"_id":"10002"})"", updateDocNew.c_str(), 1); +} + +void UpsertDocFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJsonNoId = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + std::string inputJson = "{\"_id\":\"1\", \"field\": " + input + "}"; + + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpsertDoc(g_db, input.c_str(), "{}", "{}", 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), "{}", 0); + inputJson = "{\"_id\":\"1\", \"field\":" + input + "}"; + GRD_UpsertDoc(g_db, COLLECTION_NAME, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + inputJson = "{\"_id\":\"1\", \"field\":\"" + input + "\"}"; + GRD_UpsertDoc(g_db, COLLECTION_NAME, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpsertDoc(g_db, COLLECTION_NAME, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + GRD_UpsertDoc(g_db, COLLECTION_NAME, "{\"_id\":\"1\"}", inputJson.c_str(), 1); + GRD_UpsertDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 1); + GRD_UpsertDoc(nullptr, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 1); + GRD_UpsertDoc(g_db, COLLECTION_NAME, nullptr, inputJson.c_str(), 1); + GRD_UpsertDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), BATCH_COUNT); + + const char *newCollName = "./student"; + GRD_DB *db1 = nullptr; + GRD_CreateCollection(db1, newCollName, "", 0); + GRD_InsertDoc(db1, newCollName, inputJson.c_str(), 0); + GRD_UpsertDoc(db1, input.c_str(), "{}", "{}", 0); + GRD_UpsertDoc(db1, newCollName, inputJson.c_str(), "{}", 0); + inputJson = "{\"_id\":\"1\", \"field\":" + input + "}"; + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + inputJson = "{\"_id\":\"1\", \"field\":\"" + input + "\"}"; + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"1\"}", inputJson.c_str(), 1); + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 1); + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"newID1999\"}", inputJsonNoId.c_str(), 0); + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"newID1999a\"}", inputJsonNoId.c_str(), 1); + GRD_UpsertDoc(nullptr, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 1); + GRD_UpsertDoc(db1, newCollName, nullptr, inputJson.c_str(), 1); + GRD_UpsertDoc(db1, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), BATCH_COUNT); + GRD_DropCollection(db1, newCollName, 0); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + + UpsertDocNewFuzz(input, db1); +} + +void DeleteDocResultFuzz(std::string input) +{ + const char *filter = "{\"age\" : 15}"; + GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0); + const char *filter1 = "{\"_id\" : \"1\", \"age\" : 15}"; + GRD_DeleteDoc(g_db, COLLECTION_NAME, filter1, 0); + std::string filter2 = "{\"_id\" : \"1\", \"name\" : " + input + "}"; + GRD_DeleteDoc(g_db, COLLECTION_NAME, filter2.c_str(), 1); + GRD_DeleteDoc(g_db, NULL, filter2.c_str(), 0); + GRD_DeleteDoc(g_db, "", filter2.c_str(), 1); + GRD_DeleteDoc(g_db, COLLECTION_NAME, filter2.c_str(), 0); + + const char *filter3 = "{\"_id\" : \"1\"}"; + GRD_ResultSet *resultSet = nullptr; + Query query = { filter3, "{}" }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_DeleteDoc(g_db, COLLECTION_NAME, filter3, 0); + + const char *filter4 = "{\"_id\" : \"1\"}"; + std::string collectionName1(LESS_HALF_BYTES, 'a'); + GRD_CreateCollection(g_db, collectionName1.c_str(), "", 0); + GRD_DeleteDoc(g_db, collectionName1.c_str(), filter4, 0); + GRD_DropCollection(g_db, collectionName1.c_str(), 0); + GRD_FreeResultSet(resultSet); + + GRD_DeleteDoc(NULL, COLLECTION_NAME, filter2.c_str(), 0); + GRD_DeleteDoc(g_db, NULL, filter2.c_str(), 0); + GRD_DeleteDoc(g_db, "", filter2.c_str(), 0); + GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL, 0); + GRD_DeleteDoc(g_db, COLLECTION_NAME, "", 0); + GRD_DeleteDoc(g_db, "notExisted", filter2.c_str(), 0); + + std::vector filterVec = { R"({"_id" : 1})", R"({"_id":[1, 2]})", R"({"_id" : {"t1" : 1}})", + R"({"_id":null})", R"({"_id":true})", R"({"_id" : 1.333})", R"({"_id" : -2.0})" }; + for (const auto &item : filterVec) { + GRD_DeleteDoc(g_db, COLLECTION_NAME, item.c_str(), 0); + } + GRD_DeleteDoc(g_db, COLLECTION_NAME, filter2.c_str(), 0); + + std::string filter5 = "{\"subject.info\" : \"" + input + "\"}"; + resultSet = nullptr; + query = { filter2.c_str(), "{}" }; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_DeleteDoc(g_db, COLLECTION_NAME, filter5.c_str(), 0); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + GRD_FreeResultSet(resultSet); +} + +void DeleteDocFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{\"field\":" + input + "}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_DeleteDoc(g_db, input.c_str(), "{}", 0); + GRD_DeleteDoc(g_db, nullptr, "{}", 0); + std::string longName = ""; + for (int i = 0; i < MORE_HALF_BYTES; i++) { + longName += 'a'; + } + GRD_DeleteDoc(g_db, "grd_name", "{}", 0); + GRD_DeleteDoc(g_db, longName.c_str(), "{}", 0); + GRD_DeleteDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + inputJson = "{\"field1\":" + input + "}"; + GRD_DeleteDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + inputJson = "{\"field\":\"" + input + "\"}"; + GRD_DeleteDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + inputJson = "{\"field1\":\"" + input + "\"}"; + GRD_DeleteDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + + const char *document1 = "{ \ + \"_id\" : \"1\", \ + \"name\": \"xiaoming\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"math\", \"English\", \"music\", {\"info\" : \"exam\"}] \ + }"; + const char *document2 = "{ \ + \"_id\" : \"2\", \ + \"name\": \"ori\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"math\", \"English\", \"music\"] \ + }"; + const char *document3 = "{ \ + \"_id\" : \"3\", \ + \"name\": \"David\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"Sing\", \"Jump\", \"Rap\", \"BasketBall\"] \ + }"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document1, 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, document2, 0); + GRD_InsertDoc(g_db, COLLECTION_NAME, document3, 0); + GRD_DeleteDoc(g_db, COLLECTION_NAME, "{}", 0); + + DeleteDocResultFuzz(input); +} + +namespace { +void FindAndRelease(Query query) +{ + GRD_ResultSet *resultSet = nullptr; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_Next(resultSet); + char *value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); + resultSet = nullptr; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_Next(resultSet); + value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); + + const char *newCollName = "./student"; + resultSet = nullptr; + GRD_FindDoc(g_db, newCollName, query, 1, &resultSet); + GRD_Next(resultSet); + value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); + resultSet = nullptr; + GRD_FindDoc(g_db, newCollName, query, 0, &resultSet); + GRD_Next(resultSet); + value = nullptr; + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); +} +} // namespace + +void FindAndReleaseFuzz(std::string document, std::string filter, Query query, std::string input) +{ + GRD_InsertDoc(g_db, COLLECTION_NAME, document.c_str(), 0); + query.filter = filter.c_str(); + query.projection = "{\"field\": 0}"; + FindAndRelease(query); + document = "{\"field1.field2\" [false], \"field1.field2.field3\": [3], " + "\"field1.field4\": [null]}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document.c_str(), 0); + query.filter = document.c_str(); + query.projection = "{\"field\": 0}"; + FindAndRelease(query); + query.projection = "{\"field\": 1}"; + FindAndRelease(query); + query.projection = "{\"field.field2\": 1}"; + FindAndRelease(query); + document = "{\"field1\": {\"field2\": [{\"field3\":\"" + input + "\"}]}}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, document.c_str(), 0); + filter = "{\"field1.field2.field3\":\"" + input + "\"}"; + query.filter = filter.c_str(); + query.projection = "{\"field1.field2\": 1}"; + FindAndRelease(query); + query.projection = "{\"field1.field2\": 0}"; + FindAndRelease(query); + query.projection = "{\"field1.field3\": 1}"; + FindAndRelease(query); + query.projection = "{\"field1.field3\": 0}"; + FindAndRelease(query); + query.projection = "{\"field1.field2.field3\": 0, \"field1.field2.field3\": 0}"; + FindAndRelease(query); + std::string projection = "{\"field1\": \"" + input + "\"}"; + query.projection = projection.c_str(); + FindAndRelease(query); + projection = "{\"" + input + "\": true, \"" + input + "\": false}"; + query.projection = projection.c_str(); + FindAndRelease(query); +} + +void NextFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{" + input + "}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + Query query = { inputJson.c_str(), "{}" }; + FindAndRelease(query); + std::string stringJson2 = "{ \"_id\":\"1\", \"field\":\"" + input + "\"}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, stringJson2.c_str(), 0); + query.filter = "{\"_id\": \"1\"}"; + FindAndRelease(query); + std::string filter2 = "{ \"_id\":\"1\", \"field\":\"" + input + " invalid\"}"; + query.filter = filter2.c_str(); + FindAndRelease(query); + query.filter = "{\"_id\": \"3\"}"; + FindAndRelease(query); + std::string stringJson3 = "{ \"_id\":\"2\", \"field\": [\"field2\", null, \"abc\", 123]}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, stringJson3.c_str(), 0); + query.filter = "{\"field\": [\"field2\", null, \"abc\", 123]}"; + FindAndRelease(query); + std::string document = "{\"field\": [\"" + input + "\",\"" + input + "\",\"" + input + "\"]}"; + std::string filter = "{\"field." + std::to_string(size) + "\":\"" + input + "\"}"; + FindAndReleaseFuzz(document, filter, query, input); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); +} + +void GetValueFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollection(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{" + input + "}"; + GRD_InsertDoc(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + char *value = nullptr; + Query query = { inputJson.c_str(), "{}" }; + GRD_ResultSet *resultSet = nullptr; + GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_GetValue(resultSet, &value); + GRD_Next(resultSet); + GRD_GetValue(resultSet, &value); + GRD_FreeValue(value); + GRD_FreeResultSet(resultSet); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); +} + +void FreeResultSetFuzz() +{ + GRD_ResultSet *resultSet = nullptr; + GRD_FreeResultSet(resultSet); + resultSet = new GRD_ResultSet; + resultSet->resultSet_ = DocumentDB::ResultSet(); + GRD_FreeResultSet(resultSet); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); +} + +void DbOpenOneFuzz(GRD_DB *dbVal) +{ + std::string path = "./documentFuzz.db"; + GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_ONLY, &dbVal); + (void)remove(path.c_str()); + + path = "./document.db"; + GRD_DBOpen(path.c_str(), R""({"pageSize":64, "redopubbufsize":4033})"", GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBClose(dbVal, 0); + GRD_DBOpen(path.c_str(), R""({"pageSize":64, "redopubbufsize":4032})"", GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBOpen(path.c_str(), R""({"redopubbufsize":255})"", GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBOpen(path.c_str(), R""({"redopubbufsize":16385})"", GRD_DB_OPEN_CREATE, &dbVal); +} + +void DbOpenFuzz(const uint8_t *data, size_t size) +{ + std::string dbFileData(reinterpret_cast(data), size); + std::string realDbFileData = DB_DIR_PATH + dbFileData; + const char *dbFileVal = realDbFileData.data(); + std::string configStrData(reinterpret_cast(data), size); + const char *configStrVal = configStrData.data(); + GRD_DB *dbVal = nullptr; + + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + std::string stringMax = getMaxString(); + const char *configStrMaxLen = stringMax.data(); + GRD_DBOpen(dbFileVal, configStrMaxLen, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValue = "{\"bufferPoolSize\": \"1024.5\"}"; + const char *configStrStringValue = fieldStringValue.data(); + GRD_DBOpen(dbFileVal, configStrStringValue, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldBoolValue = "{\"bufferPoolSize\":}"; + const char *configStrBool = fieldBoolValue.data(); + GRD_DBOpen(dbFileVal, configStrBool, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValueAppend = "{\"bufferPoolSize\":\"8192\"}"; + const char *configStrStr = fieldStringValueAppend.data(); + GRD_DBOpen(dbFileVal, configStrStr, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValueFlush = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\"}"; + const char *configStrFlush = fieldStringValueFlush.data(); + GRD_DBOpen(dbFileVal, configStrFlush, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValueRedoBufsize = "{\"bufferPoolSize\":\"8192\",\"redoBufSize\":\"16384\"}"; + const char *configStrBs = fieldStringValueRedoBufsize.data(); + GRD_DBOpen(dbFileVal, configStrBs, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValueMaxConnNum = "{\"bufferPoolSize\":\"8192\",\"maxConnNum\":\"1024\"}"; + const char *configStrMcn = fieldStringValueMaxConnNum.data(); + GRD_DBOpen(dbFileVal, configStrMcn, GRD_DB_OPEN_CREATE, &dbVal); + + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + std::string fieldStringValueAll = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\",\"redoBufSize\":" + "\"16384\",\"maxConnNum\":\"1024\"}"; + const char *configStrAll = fieldStringValueAll.data(); + GRD_DBOpen(dbFileVal, configStrAll, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldLowNumber = "{\"bufferPoolSize\": 102}"; + const char *configStrLowNumber = fieldLowNumber.data(); + GRD_DBOpen(dbFileVal, configStrLowNumber, GRD_DB_OPEN_CREATE, &dbVal); + + GRD_DBOpen(nullptr, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBOpen(dbFileVal, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBClose(nullptr, GRD_DB_CLOSE); + GRD_DBClose(dbVal, GRD_DB_CLOSE); + + DbOpenOneFuzz(dbVal); +} + +void DbCloseFuzz(const uint8_t *data, size_t size) +{ + std::string dbFileData(reinterpret_cast(data), size); + std::string realDbFileData = DB_DIR_PATH + dbFileData; + const char *dbFileVal = realDbFileData.data(); + std::string configStrData(reinterpret_cast(data), size); + const char *configStrVal = configStrData.data(); + GRD_DB *dbVal = nullptr; + GRD_DBOpen(dbFileVal, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBClose(dbVal, GRD_DB_CLOSE); +} + +void DbCloseResultSetFuzz() +{ + GRD_DB *db = nullptr; + GRD_DB *db2 = nullptr; + GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); + GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db2); + GRD_CreateCollection(db, "collection1", "{\"maxdoc\" : 5}", 0); + + GRD_ResultSet *resultSet = nullptr; + Query query = { "{}", "{}" }; + GRD_FindDoc(db, "collection1", query, 0, &resultSet); + + GRD_FreeResultSet(resultSet); + + GRD_DBClose(db, GRD_DB_CLOSE); + + GRD_DBClose(db2, GRD_DB_CLOSE); +} + +void CreateCollectionFuzz(const uint8_t *data, size_t size) +{ + std::string collectionNameData(reinterpret_cast(data), size); + const char *collectionNameVal = collectionNameData.data(); + std::string optionStrData(reinterpret_cast(data), size); + const char *optionStrVal = optionStrData.data(); + GRD_CreateCollection(nullptr, collectionNameVal, optionStrVal, 0); + GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); + const char *optionStr = nullptr; + GRD_CreateCollection(g_db, COLLECTION_NAME, optionStr, 0); + GRD_CreateCollection(g_db, COLLECTION_NAME, "{\"maxdoc\":5, \"unexpected_max_doc\":32}", 0); + GRD_CreateCollection(g_db, COLLECTION_NAME, "{}", 0); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + std::string optStr = "{\"maxdoc\":" + optionStrData + "}"; + GRD_CreateCollection(g_db, COLLECTION_NAME, optStr.c_str(), 0); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + GRD_CreateCollection(g_db, COLLECTION_NAME, optStr.c_str(), MAX_SIZE_NUM); + optStr = "{\"maxdoc\": 5}"; + GRD_CreateCollection(g_db, COLLECTION_NAME, optStr.c_str(), 0); + GRD_CreateCollection(g_db, COLLECTION_NAME, optStr.c_str(), 1); + GRD_DropCollection(g_db, COLLECTION_NAME, 0); + GRD_DropCollection(g_db, COLLECTION_NAME, MAX_SIZE_NUM); + GRD_DropCollection(g_db, collectionNameVal, 0); +} + +void DropCollectionFuzz(const uint8_t *data, size_t size) +{ + std::string collectionNameData(reinterpret_cast(data), size); + const char *collectionNameVal = collectionNameData.data(); + std::string optionStrData(reinterpret_cast(data), size); + const char *optionStrVal = optionStrData.data(); + GRD_CreateCollection(g_db, collectionNameVal, optionStrVal, 0); + GRD_DropCollection(nullptr, collectionNameVal, 0); + GRD_DropCollection(g_db, collectionNameVal, 0); +} + +void DbFlushFuzz(const uint8_t *data, size_t size) +{ + GRD_DB *db = nullptr; + GRD_DB *db2 = nullptr; + GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); + GRD_Flush(db, 0); + GRD_Flush(db, 1); + GRD_Flush(db2, 0); + GRD_Flush(db2, 1); + GRD_DBClose(db, GRD_DB_CLOSE); +} + +void TestGrdDbApGrdGetItem002Fuzz() +{ + const char *config = CONFIG_STR; + GRD_DB *db = nullptr; + GRD_DBOpen(TEST_DB_FILE, config, GRD_DB_OPEN_CREATE, &db); + GRD_IndexPreload(nullptr, COLLECTION_NAME); + GRD_IndexPreload(nullptr, "invalid_name"); + GRD_IndexPreload(g_db, COLLECTION_NAME); + std::string smallPrefix = std::string(SMALL_PREFIX_LEN, 'a'); + for (uint32_t i = 0; i < NUM_NINETY_EIGHT; ++i) { + std::string v = smallPrefix + std::to_string(i); + GRD_KVItemT key = { &i, sizeof(uint32_t) }; + GRD_KVItemT value = { (void *)v.data(), (uint32_t)v.size() + 1 }; + GRD_KVPut(g_db, COLLECTION_NAME, &key, &value); + + GRD_KVItemT getValue = { nullptr, 0 }; + GRD_KVGet(g_db, COLLECTION_NAME, &key, &getValue); + GRD_KVFreeItem(&getValue); + + GRD_KVDel(g_db, COLLECTION_NAME, &key); + } + GRD_Flush(g_db, 1); + + uint32_t begin = 0, end = MAX_SIZE_NUM; + GRD_FilterOptionT option = {}; + option.mode = KV_SCAN_RANGE; + option.begin = { &begin, sizeof(uint32_t) }; + option.end = { &end, sizeof(uint32_t) }; + GRD_ResultSet *resultSet = nullptr; + GRD_KVFilter(g_db, COLLECTION_NAME, &option, &resultSet); + + uint32_t keySize, valueSize; + GRD_KVGetSize(resultSet, &keySize, &valueSize); + + resultSet = nullptr; + uint32_t i = 32; + GRD_KVItemT key = { &i, sizeof(uint32_t) }; + GRD_KVScan(g_db, COLLECTION_NAME, &key, KV_SCAN_EQUAL_OR_LESS_KEY, &resultSet); + + GRD_Prev(resultSet); + GRD_Next(resultSet); + + GRD_FreeResultSet(resultSet); +} + +void TestGrdKvBatchCoupling003Fuzz() +{ + const char *config = CONFIG_STR; + GRD_DB *db = nullptr; + GRD_DBOpen(TEST_DB_FILE, config, GRD_DB_OPEN_CREATE, &db); + + GRD_ResultSet *resultSet = nullptr; + GRD_KVScan(g_db, COLLECTION_NAME, nullptr, KV_SCAN_PREFIX, &resultSet); + + for (uint32_t i = 0; i < CURSOR_COUNT; i++) { + GRD_Next(resultSet); + } + + GRD_KVBatchT *batchDel = nullptr; + std::vector keySet; + std::vector valueSet; + for (uint32_t i = 0; i < VECTOR_SIZE; i++) { + std::string key(MAX_SIZE_NUM, 'a'); + key += std::to_string(i); + keySet.emplace_back(key); + std::string value = std::to_string(i); + valueSet.emplace_back(value); + } + + for (int j = 0; j < BATCH_COUNT; j++) { + GRD_KVBatchPrepare(BATCH_COUNT, &batchDel); + GRD_KVBatchPut(g_db, COLLECTION_NAME, batchDel); + for (uint16_t i = 0; i < BATCH_COUNT; i++) { + GRD_KVBatchPushback((void *)keySet[CURSOR_COUNT + j * BATCH_COUNT + i].c_str(), + (uint32_t)keySet[CURSOR_COUNT + j * BATCH_COUNT + i].length() + 1, + (void *)valueSet[CURSOR_COUNT + j * BATCH_COUNT + i].c_str(), + (uint32_t)valueSet[CURSOR_COUNT + j * BATCH_COUNT + i].length() + 1, + batchDel); + } + + GRD_KVBatchDel(g_db, COLLECTION_NAME, batchDel); + + GRD_KVBatchDestroy(batchDel); + } + + GRD_Next(resultSet); + GRD_KVItemT keyItem = { nullptr, 0 }; + GRD_KVItemT valueItem = { nullptr, 0 }; + GRD_Fetch(resultSet, &keyItem, &valueItem); + GRD_KVFreeItem(&keyItem); + GRD_KVFreeItem(&valueItem); + GRD_FreeResultSet(resultSet); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" { +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + OHOS::SetUpTestCase(); + + OHOS::DbOpenFuzz(data, size); + OHOS::CreateCollectionFuzz(data, size); + OHOS::DropCollectionFuzz(data, size); + OHOS::InsertDocFuzz(data, size); + OHOS::FindDocFuzz(data, size); + OHOS::UpdateDocFuzz(data, size); + OHOS::UpsertDocFuzz(data, size); + OHOS::DeleteDocFuzz(data, size); + OHOS::NextFuzz(data, size); + OHOS::GetValueFuzz(data, size); + OHOS::FreeResultSetFuzz(); + OHOS::TestGrdDbApGrdGetItem002Fuzz(); + OHOS::TestGrdKvBatchCoupling003Fuzz(); + OHOS::DbCloseFuzz(data, size); + OHOS::DbCloseResultSetFuzz(); + OHOS::DbFlushFuzz(data, size); + + OHOS::TearDownTestCase(); + return 0; +} +} \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.h b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..af5feb8c9cef1cfedaea4faa2da7f8a02d0e38e7 --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 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 JSON_FUZZER_H +#define JSON_FUZZER_H + +#define FUZZ_PROJECT_NAME "Json_fuzzer" + +#endif // JSON_FUZZER_H \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/project.xml b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..73736f01a8820f5deb20590a5655e6fbe62b6aa6 --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 1800 + + 4096 + + diff --git a/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..71a6e13514da63b32bfd808a69944fa3b9fda41d --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/BUILD.gn @@ -0,0 +1,148 @@ +# Copyright (c) 2024 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/config/features.gni") +import("//build/test.gni") + +module_output_path = "kv_store/distributeddb" + +############################################################################### +config("module_private_config") { + visibility = [ ":*" ] + + include_dirs = [ + "../../../gaussdb_rd/include", + "../../../gaussdb_rd/src/common/include", + "../../../gaussdb_rd/src/executor/include", + "../../../gaussdb_rd/src/executor/document", + "../../../gaussdb_rd/src/oh_adapter/include", + "../../../gaussdb_rd/src/oh_adapter/src", + "../../../gaussdb_rd/src/interface/include", + ] + + 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 = [ + "../../../gaussdb_rd/src/common/src/collection_option.cpp", + "../../../gaussdb_rd/src/common/src/db_config.cpp", + "../../../gaussdb_rd/src/common/src/grd_api_manager.cpp", + "../../../gaussdb_rd/src/common/src/json_common.cpp", + "../../../gaussdb_rd/src/common/src/os_api.cpp", + "../../../gaussdb_rd/src/common/src/rd_log_print.cpp", + "../../../gaussdb_rd/src/executor/base/grd_db_api.cpp", + "../../../gaussdb_rd/src/executor/base/grd_db_api_inner.cpp", + "../../../gaussdb_rd/src/executor/document/check_common.cpp", + "../../../gaussdb_rd/src/executor/document/grd_document_api.cpp", + "../../../gaussdb_rd/src/executor/document/grd_document_api_inner.cpp", + "../../../gaussdb_rd/src/executor/document/grd_resultset_api.cpp", + "../../../gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp", + "../../../gaussdb_rd/src/executor/kv/grd_kv_api.cpp", + "../../../gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp", + "../../../gaussdb_rd/src/interface/src/collection.cpp", + "../../../gaussdb_rd/src/interface/src/doc_errno.cpp", + "../../../gaussdb_rd/src/interface/src/document_key.cpp", + "../../../gaussdb_rd/src/interface/src/document_store.cpp", + "../../../gaussdb_rd/src/interface/src/document_store_manager.cpp", + "../../../gaussdb_rd/src/interface/src/projection_tree.cpp", + "../../../gaussdb_rd/src/interface/src/result_set.cpp", + "../../../gaussdb_rd/src/interface/src/result_set_common.cpp", + "../../../gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp", + "../../../gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp", + "../../../gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp", + "../../../gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp", + ] + + configs = [ ":module_private_config" ] + + deps = [ "//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", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + ] + + subsystem_name = "distributeddatamgr" + part_name = "kv_store" +} + +ohos_fuzztest("JsonInnerFuzzTest") { + module_out_path = module_output_path + fuzz_config_file = "../jsoninner_fuzzer" + + if (!defined(deps)) { + deps = [] + } + if (!defined(external_deps)) { + external_deps = [] + } + configs = [ ":module_private_config" ] + deps += [ + ":src_file", + "//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", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + ] + + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + "--coverage", + ] + + ldflags += [ "--coverage" ] + + cflags_cc = [ "--coverage" ] + + sources = [ "jsoninner_fuzzer.cpp" ] +} + +############################################################################### + +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":JsonInnerFuzzTest", + ] +} +############################################################################### diff --git a/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/corpus/init b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/corpus/init new file mode 100644 index 0000000000000000000000000000000000000000..e7c3fecd8d4d4816e40088113a2316bb9eb2e13f --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/corpus/init @@ -0,0 +1,14 @@ +# Copyright (c) 2024 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. + +FUZZ \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7e9dd016b440e9a746a39a7a4f2bba8009aa750 --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp @@ -0,0 +1,1687 @@ +/* + * Copyright (c) 2024 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. + */ +#include "jsoninner_fuzzer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "grd_base/grd_db_api.h" +#include "grd_base/grd_error.h" +#include "grd_base/grd_resultset_api.h" +#include "grd_document/grd_document_api.h" +#include "grd_kv/grd_kv_api.h" +#include "grd_resultset_inner.h" + +#include "grd_db_api_inner.h" +#include "grd_document_api_inner.h" +#include "grd_kv_api_inner.h" +#include "grd_resultset_api_inner.h" +#include "grd_sequence_api_inner.h" +#include "grd_type_inner.h" +#include "securec.h" + +using namespace DocumentDB; + +const char *TEST_DB = "./data"; +const char *TEST_DB_FILE = "./data/testfile"; +const char *COLLECTION_NAME = "collectionname"; +const char *OPTION_STR = "{ \"maxdoc\" : 1000}"; +const char *CONFIG_STR = "{}"; +const char *DB_DIR_PATH = "./data/"; +const char *NO_EXIST_COLLECTION_NAME = "no_exisit"; +const int NUM_THREE = 3; +const int SMALL_PREFIX_LEN = 5; +const int NUM_FIFTEEN = 15; +const int NUM_NINETY_EIGHT = 98; +const int BATCH_COUNT = 100; +const int HALF_HALF_BYTES = 256; +const int MORE_HALF_HALF_BYTES = 257; +const int LESS_HALF_BYTES = 511; +const int MORE_HALF_BYTES = 513; +const int HALF_BYTES = 512; +const int MAX_LEN_NUM = 600; +const int LESS_MIDDLE_SIZE = 899; +const int MIDDLE_SIZE = 900; +const int MAX_SIZE_NUM = 1000; +const int ONE_BYTES = 1024; +const int CURSOR_COUNT = 50000; +const int VECTOR_SIZE = 100000; + +static GRD_DB *g_db = nullptr; + +namespace OHOS { +namespace { +int RemoveDir(const char *dir) +{ + if (dir == nullptr) { + return -1; + } + if (access(dir, F_OK) != 0) { + return 0; + } + struct stat dirStat; + if (stat(dir, &dirStat) < 0) { + return -1; + } + + char dirName[PATH_MAX]; + DIR *dirPtr = nullptr; + struct dirent *dr = nullptr; + if (S_ISREG(dirStat.st_mode)) { // normal file + remove(dir); + } else if (S_ISDIR(dirStat.st_mode)) { + dirPtr = opendir(dir); + while ((dr = readdir(dirPtr)) != nullptr) { + // ignore . and .. + if ((strcmp(".", dr->d_name) == 0) || (strcmp("..", dr->d_name) == 0)) { + continue; + } + if (sprintf_s(dirName, sizeof(dirName), "%s / %s", dir, dr->d_name) < 0) { + return -1; + } + (void)RemoveDir(dirName); + } + closedir(dirPtr); + rmdir(dir); // remove empty dir + } else { + return -1; + } + return 0; +} + +void MakeDir(const char *dir) +{ + std::string tmpPath; + const char *pcur = dir; + + while (*pcur++ != '\0') { + tmpPath.push_back(*(pcur - 1)); + if ((*pcur == '/' || *pcur == '\0') && access(tmpPath.c_str(), 0) != 0 && !tmpPath.empty()) { + if (mkdir(tmpPath.c_str(), (S_IRUSR | S_IWUSR | S_IXUSR)) != 0) { + return; + } + } + } +} + +std::string getMaxString() +{ + std::string str = "{"; + for (int i = 0; i <= MAX_SIZE_NUM; i++) { + for (int j = 0; j <= MAX_LEN_NUM; j++) { + str += "a"; + } + } + return str + "}"; +} +} // namespace + +void InsertDocOneFuzz(std::string documentData) +{ + std::string document2 = "{\"_id\":2,\"field\":\"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document2.c_str(), 0); + std::string document3 = "{\"_id\":true,\"field\":\"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document3.c_str(), 0); + std::string document4 = "{\"_id\" : null, \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document4.c_str(), 0); + std::string document5 = "{\"_id\" : [\"2\"], \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document5.c_str(), 0); + std::string document6 = "{\"_id\" : {\"val\" : \"2\"}, \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document6.c_str(), 0); + std::string document7 = "{\"_id\" : \"3\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document7.c_str(), 0); + std::string document9 = "{\"_id\" : \"4\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(NULL, COLLECTION_NAME, document9.c_str(), 0); + std::string document10 = "{\"_id\" : \"5\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, NULL, document10.c_str(), 0); + std::string document12 = "{\"_id\" : \"6\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document12.c_str(), 1); + std::string document13 = "{\"_id\" : \"7\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document13.c_str(), INT_MAX); + std::string document14 = "{\"_id\" : \"8\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document14.c_str(), INT_MIN); + GRD_InsertDocInner(g_db, NULL, NULL, 0); + std::string document15 = "{\"_id\" : \"9\", \"name\" : \"" + documentData + "\"}"; + std::string collectionName2(HALF_BYTES, 'a'); + GRD_InsertDocInner(g_db, collectionName2.c_str(), document15.c_str(), 0); + const char *collectionName = "collection@!#"; + std::string document16 = "{\"_id\" : \"10\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, collectionName, document16.c_str(), GRD_OK); + std::string collectionName1(MORE_HALF_HALF_BYTES, 'k'); + std::string document17 = "{\"_id\" : \"10\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, collectionName1.c_str(), document17.c_str(), GRD_OK); + std::string document18 = "({\"level1\" : {\"level2\" : {\"level3\" : {\"level4\": {\"level5\" : 1}},\ + \"level3_2\" : \"" + + documentData + "\"}},\"_id\":\"14\"})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document18.c_str(), 0); + std::string document19 = "({\"level1\" : {\"level2\" : {\"level3\" : [{ \"level5\" : \"" + documentData + "\",\ + \"level5_2\":\"" + + documentData + "\"}, \"" + documentData + "\",\"" + documentData + "\"], \"level3_2\":\ + \"" + + documentData + "\"}}, \"_id\":\"14\"})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document19.c_str(), 0); + std::string document20 = "({\"level1\" : {\"level2\" : {\"level3\" : { \"level4\" : \"" + documentData + "\"},\ + \"level3_2\" : \"" + + documentData + "\"}}, \"_id\":\"14\"})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document20.c_str(), 0); +} + +void InsertDocTwoFuzz(std::string documentData) +{ + std::string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; + std::string documentPart2 = "\" }"; + std::string jsonVal = std::string(HALF_BYTES * ONE_BYTES - documentPart1.size() - documentPart2.size(), 'k'); + std::string document = documentPart1 + jsonVal + documentPart2; + std::string jsonVal2 = std::string(HALF_BYTES * ONE_BYTES - 1 - documentPart1.size() - documentPart2.size(), 'k'); + std::string document21 = documentPart1 + jsonVal2 + documentPart2; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document21.c_str(), 0); + std::string document22 = "{\"_id\" : \"16\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document22.c_str(), 0); + std::string document23 = + "{\"_id\" : \"17\", \"level1\" : {\"level2\" : {\"level3\" : {\"level4\" : " + documentData + "\ + } } }, \"level1_2\" : \"" + + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document23.c_str(), 0); + std::string document24 = documentData; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document24.c_str(), 0); + std::string document25 = "{\"name\" : \"" + documentData + "\", \"age\" : " + documentData + ",\ + \"friend\" : {\"name\" : \" " + + documentData + "\"}, \"_id\" : \"19\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document25.c_str(), 0); + std::string collectionName3 = std::string(HALF_HALF_BYTES, 'k'); + std::string document26 = "{\"_id\" : \"22\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, collectionName3.c_str(), document26.c_str(), GRD_OK); + std::string collectionName4 = "Aads_sd__23Asb_"; + std::string document27 = "{\"_id\" : \"23\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, collectionName4.c_str(), document27.c_str(), GRD_OK); + std::string collectionName5 = "GRD_collectionName"; + std::string document28 = "{\"_id\" : \"24\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollectionInner(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDocInner(g_db, collectionName5.c_str(), document28.c_str(), 0); + collectionName5 = "GM_SYS__collectionName"; + std::string document29 = "{\"_id\" : \"24_2\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollectionInner(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDocInner(g_db, collectionName5.c_str(), document29.c_str(), 0); + + collectionName5 = "grd_collectionName"; + std::string document30 = "{\"_id\" : \"24_3\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollectionInner(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDocInner(g_db, collectionName5.c_str(), document30.c_str(), 0); +} + +void InsertDocThreeFuzz(std::string documentData) +{ + std::string collectionName5 = "gm_sys_collectionName"; + std::string document31 = "{\"_id\" : \"24_4\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollectionInner(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDocInner(g_db, collectionName5.c_str(), document31.c_str(), 0); + + collectionName5 = "gM_sYs_collectionName"; + std::string document32 = "{\"_id\" : \"24_5\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollectionInner(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDocInner(g_db, collectionName5.c_str(), document32.c_str(), 0); + + collectionName5 = "gRd_collectionName"; + std::string document33 = "{\"_id\" : \"24_6\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollectionInner(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDocInner(g_db, collectionName5.c_str(), document33.c_str(), 0); + + collectionName5 = "gRd@collectionName"; + std::string document34 = "{\"_id\" : \"24_7\", \"name\" : \"" + documentData + "\"}"; + GRD_CreateCollectionInner(g_db, collectionName5.c_str(), "", 0); + GRD_InsertDocInner(g_db, collectionName5.c_str(), document34.c_str(), 0); + + std::string document35 = "{\"_id\" : \"25_0\", \"level1\" : {\"level2\" : {\"level3\" :\ + {\"level4\" : \"" + + documentData + "\"}}} , \"level1_2\" : \"" + documentData + "\" }"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document35.c_str(), 0); + + std::string document36 = "{\"_id\" : \"25_1\", \"class_name\" : \"" + documentData + + "\", \"signed_info\" : true, \ + \"student_info\" : [{\"name\":\"" + + documentData + "\", \"age\" : " + documentData + ", \"sex\" : \"male\"}, \ + { \"newName1\" : [\"" + + documentData + "\", \"" + documentData + "\", 0, \"" + documentData + "\"] }]}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document36.c_str(), 0); + + std::string document37 = "{\"_id\" : \"25_2\", \"class_name\" : \"" + documentData + + "\", \"signed_info\" : true, \ + \"student_info\" : [{\"name\":\"" + + documentData + "\", \"age\" : " + documentData + ", \"sex\" : \"male\"}, \ + [\"" + + documentData + "\", \"" + documentData + "\", 0, \"" + documentData + "\", {\"0ab\" : null}]]}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document37.c_str(), 0); + + std::string document38 = "{\"_id\" : \"25_3\", \"class_name\" : \"" + documentData + + "\", \"signed_info\" : true, \ + \"student_info\" : [{\"name\":\"" + + documentData + "\", \"age\" : " + documentData + ", \"sex\" : \"male\"}, \ + { \"newName1\" : [\"" + + documentData + "\", \"" + documentData + "\", 0, \"" + documentData + "\", {\"level5\" : 1}] }]}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document38.c_str(), 0); +} + +void InsertDocFourFuzz(std::string longId, std::string documentData) +{ + std::string document39 = + "{\"_id\" : \"35\", \"A_aBdk_324_\" : \"" + documentData + "\", \"name\" : \"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document39.c_str(), 0); + + std::string document40 = "{\"_id\" : \"35_2\", \"1A_aBdk_324_\" : \"" + documentData + + "\", " + "\"name\" : \"" + + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document40.c_str(), 0); + std::string document41 = "{\"_id\" : \"36_0\", \"stringType\" : \"" + documentData + + "\", \"numType\" : " + documentData + ", \"BoolType\" : true,\ + \"nullType\" : null, \"arrayType\" : " + + documentData + ", \"objectType\" : {\"A\" : 3}}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document41.c_str(), 0); + + std::string document42 = "({\"_id\" : \"38_0\", \"field2\" : 1.797693" + longId + "13486232e308})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document42.c_str(), 0); + std::string document43 = "({\"_id\" : \"38_1\", \"t1\" : {\"field2\" : 1.797" + longId + "69313486232e308}})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document43.c_str(), 0); + std::string document44 = "({\"_id\" : \"38_2\", \"t1\" : [1, 2, 1.79769313486" + longId + "232e308]})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document44.c_str(), 0); + std::string document45 = "({\"_id\" : \"38_3\", \"t1\" : [1, 2, -1.7976931348623167" + longId + "E+308]})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document45.c_str(), 0); + std::string document46 = "({\"_id\" : \"38_4\", \"t1\" : [1, 2, -1." + longId + "79769313486231570E+308]})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document46.c_str(), 0); + std::string document47 = "({\"_id\" : \"38_5\", \"t1\" : [1, 2, 1.79769313486" + longId + "231570E+308]})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document47.c_str(), 0); + + std::string doc1 = "{\"_id\" : "; + std::string doc2 = "\""; + std::string doc4 = "\""; + std::string doc5 = ", \"name\" : \"" + documentData + "\"}"; + std::string documentMiddle(MIDDLE_SIZE, 'k'); + std::string document48 = doc1 + doc2 + documentMiddle + doc4 + doc5; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document48.c_str(), 0); + std::string documentMiddle2(MAX_SIZE_NUM, 'k'); + document48 = doc1 + doc2 + documentMiddle2 + doc4 + doc5; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document48.c_str(), 0); + + std::string document49 = "({\"_id\":\"0123\", \"num\":\"" + documentData + "\"})"; + std::string document50 = "({\"_id\":\"0123\", \"NUM\":\"" + documentData + "\"})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document49.c_str(), 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, document50.c_str(), 0); + + std::string document51 = "({\"_id\":\"0123\", \"num.\":\"" + documentData + "\"})"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document51.c_str(), 0); + + const char *document52 = R""({})""; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document52, 0); +} + +void InsertDocFuzz(const uint8_t *data, size_t size) +{ + std::string collectionNameData(reinterpret_cast(data), size); + const char *collectionNameVal = collectionNameData.data(); + std::string optionStrData(reinterpret_cast(data), size); + const char *optionStrVal = optionStrData.data(); + GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); + std::string documentData(reinterpret_cast(data), size); + const char *documentVal = documentData.data(); + GRD_InsertDocInner(g_db, collectionNameVal, documentVal, 0); + GRD_InsertDocInner(g_db, collectionNameVal, documentVal, 0); + std::string stringJson = "{" + documentData + "}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, stringJson.c_str(), 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, stringJson.c_str(), 0); + std::string stringJson2 = "{\"_id\":\"1\",\"field\":\"" + documentData + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, stringJson2.c_str(), 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, stringJson2.c_str(), 0); + std::string longId = "1"; + for (int i = 0; i < MAX_SIZE_NUM; i++) { + longId += "1"; + } + longId = "{\"_id\":\"" + longId + "\",\"field\":\"field_id\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, longId.c_str(), 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, "{\"_id\":123}", 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, "{\"field1.field2.field&*^&3\":\"anc\"}", 0); + InsertDocOneFuzz(documentData); + InsertDocTwoFuzz(documentData); + InsertDocThreeFuzz(documentData); + InsertDocFourFuzz(longId, documentData); + + const char *document53 = R""({"empty" : null})""; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document53, 0); + GRD_DropCollectionInner(g_db, collectionNameVal, 0); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + + std::string documentNew1 = "{\"_id\" : "; + std::string documentNew2 = "\""; + std::string documentNew3 = "\""; + std::string documentNew4 = ", \"name\" : \"Ori\"}"; + std::string document = documentNew1 + documentNew2 + documentData + documentNew3 + documentNew4; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document.c_str(), 0); +} + +static const char *DOCUMENT1 = "{\"_id\" : \"1\", \"name\":\"doc1\",\"item\":\"journal\",\"personInfo\":\ + {\"school\":\"AB\", \"age\" : 51}}"; +static const char *DOCUMENT2 = "{\"_id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"personInfo\":\ + [1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; +static const char *DOCUMENT3 = "{\"_id\" : \"3\", \"name\":\"doc3\",\"item\":\"notebook\",\"personInfo\":\ + [{\"school\":\"C\", \"age\" : 5}]}"; +static const char *DOCUMENT4 = "{\"_id\" : \"4\", \"name\":\"doc4\",\"item\":\"paper\",\"personInfo\":\ + {\"grade\" : 1, \"school\":\"A\", \"age\" : 18}}"; +static const char *DOCUMENT5 = "{\"_id\" : \"5\", \"name\":\"doc5\",\"item\":\"journal\",\"personInfo\":\ + [{\"sex\" : \"woma\", \"school\" : \"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *DOCUMENT6 = "{\"_id\" : \"6\", \"name\":\"doc6\",\"item\":false,\"personInfo\":\ + [{\"school\":\"B\", \"teacher\" : \"mike\", \"age\" : 15},\ + {\"school\":\"C\", \"teacher\" : \"moon\", \"age\" : 20}]}"; + +static const char *DOCUMENT7 = "{\"_id\" : \"7\", \"name\":\"doc7\",\"item\":\"fruit\",\"other_Info\":\ + [{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *DOCUMENT8 = "{\"_id\" : \"8\", \"name\":\"doc8\",\"item\":true,\"personInfo\":\ + [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *DOCUMENT9 = "{\"_id\" : \"9\", \"name\":\"doc9\",\"item\": true}"; +static const char *DOCUMENT10 = "{\"_id\" : \"10\", \"name\":\"doc10\", \"parent\" : \"kate\"}"; +static const char *DOCUMENT11 = "{\"_id\" : \"11\", \"name\":\"doc11\", \"other\" : \"null\"}"; +static const char *DOCUMENT12 = "{\"_id\" : \"12\", \"name\":\"doc12\",\"other\" : null}"; +static const char *DOCUMENT13 = "{\"_id\" : \"13\", \"name\":\"doc13\",\"item\" : \"shoes\",\"personInfo\":\ + {\"school\":\"AB\", \"age\" : 15}}"; +static const char *DOCUMENT14 = "{\"_id\" : \"14\", \"name\":\"doc14\",\"item\" : true,\"personInfo\":\ + [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 85}]}"; +static const char *DOCUMENT15 = "{\"_id\" : \"15\", \"name\":\"doc15\",\"personInfo\":[{\"school\":\"C\", \"age\" : " + "5}]}"; +static const char *DOCUMENT16 = "{\"_id\" : \"16\", \"name\":\"doc16\", \"nested1\":{\"nested2\":{\"nested3\":\ + {\"nested4\":\"ABC\", \"field2\":\"CCC\"}}}}"; +static const char *DOCUMENT17 = "{\"_id\" : \"17\", \"name\":\"doc17\",\"personInfo\":\"oh,ok\"}"; +static const char *DOCUMENT18 = "{\"_id\" : \"18\", \"name\":\"doc18\",\"item\" : \"mobile phone\",\"personInfo\":\ + {\"school\":\"DD\", \"age\":66}, \"color\":\"blue\"}"; +static const char *DOCUMENT19 = "{\"_id\" : \"19\", \"name\":\"doc19\",\"ITEM\" : true,\"PERSONINFO\":\ + {\"school\":\"AB\", \"age\":15}}"; +static const char *DOCUMENT20 = "{\"_id\" : \"20\", \"name\":\"doc20\",\"ITEM\" : true,\"personInfo\":\ + [{\"SCHOOL\":\"B\", \"AGE\":15}, {\"SCHOOL\":\"C\", \"AGE\":35}]}"; +static const char *DOCUMENT23 = "{\"_id\" : \"23\", \"name\":\"doc22\",\"ITEM\" : " + "true,\"personInfo\":[{\"school\":\"b\", \"age\":15}, [{\"school\":\"doc23\"}, 10, " + "{\"school\":\"doc23\"}, true, {\"school\":\"y\"}], {\"school\":\"b\"}]}"; +static std::vector g_data = { DOCUMENT1, DOCUMENT2, DOCUMENT3, DOCUMENT4, DOCUMENT5, + DOCUMENT6, DOCUMENT7, DOCUMENT8, DOCUMENT9, DOCUMENT10, DOCUMENT11, DOCUMENT12, DOCUMENT13, + DOCUMENT14, DOCUMENT15, DOCUMENT16, DOCUMENT17, DOCUMENT18, DOCUMENT19, DOCUMENT20, DOCUMENT23 }; + +namespace { +static void InsertData(GRD_DB *g_db, const char *collectionName) +{ + for (const auto &item : g_data) { + GRD_InsertDocInner(g_db, collectionName, item, 0); + } +} + +void SetUpTestCase() +{ + (void)RemoveDir(TEST_DB); + MakeDir(TEST_DB); + GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &g_db); + InsertData(g_db, COLLECTION_NAME); + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); +} + +void TearDownTestCase() +{ + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + GRD_DBCloseInner(g_db, GRD_DB_CLOSE); + (void)RemoveDir(TEST_DB); + g_db = nullptr; +} + +void FindDocResultSetFuzz(const char *collName, std::string filter, std::string projectionInfo) +{ + GRD_ResultSet *resultSet = nullptr; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, collName, query, 1, &resultSet); + if (resultSet != nullptr) { + GRD_NextInner(resultSet); + char *valueResultSet = nullptr; + GRD_GetValueInner(resultSet, &valueResultSet); + } + GRD_FreeResultSetInner(resultSet); +} + +void FindDocWithFlagFuzz(std::string filter, std::string projectionInfo, int flag) +{ + GRD_ResultSet *resultSet = nullptr; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, flag, &resultSet); + GRD_NextInner(resultSet); + char *value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); +} + +void FindDocNextTwiceFuzz(std::string filter, std::string projectionInfo) +{ + GRD_ResultSet *resultSet = nullptr; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + char *value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); +} + +void FindDocZeroFuzz(const std::string &input) +{ + std::string filter = "{\"_id\" : \"6\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : \"6\", \"name\":\"" + input + "\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"name\":\"" + input + "\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : \"" + input + "\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : 1}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : [\"" + input + "\", 1]}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : {\"" + input + "\" : \"1\"}}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : true}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + filter = "{\"_id\" : null}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + + const char *collName1 = "grd_type"; + const char *collName2 = "GM_SYS_sysfff"; + filter = "{\"_id\" : \"1\"}"; + FindDocResultSetFuzz(collName1, filter, R"({})"); + FindDocResultSetFuzz(collName2, filter, R"({})"); + + filter = "{\"_id\" : \"100\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); +} + +void FindDocOneFuzz() +{ + std::string filter = "{\"_id\" : \"6\"}"; + GRD_ResultSet *resultSet = nullptr; + GRD_ResultSet *resultSet2 = nullptr; + Query query = { filter.c_str(), "{}" }; + const char *collectionName = "DocumentDBFindTest024"; + GRD_CreateCollectionInner(g_db, collectionName, "", 0); + InsertData(g_db, collectionName); + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FindDocInner(g_db, collectionName, query, 1, &resultSet2); + + GRD_NextInner(resultSet); + char *value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + + GRD_NextInner(resultSet2); + char *value2 = nullptr; + GRD_GetValueInner(resultSet2, &value2); + GRD_FreeValueInner(value2); + + GRD_NextInner(resultSet); + GRD_NextInner(resultSet2); + GRD_GetValueInner(resultSet, &value); + GRD_GetValueInner(resultSet2, &value); + GRD_FreeResultSetInner(resultSet); + GRD_FreeResultSetInner(resultSet2); + GRD_DropCollectionInner(g_db, collectionName, 0); + + filter = "{\"_id\" : \"16\"}"; + resultSet = nullptr; + std::string projectionInfo = "{\"name\": true, \"nested1.nested2.nested3.nested4\":true}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_NextInner(resultSet); + value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + GRD_FreeResultSetInner(resultSet); + + projectionInfo = "{\"name\": true, \"nested1\":{\"nested2\":{\"nested3\":{\"nested4\":true}}}}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + GRD_FreeResultSetInner(resultSet); +} + +void FindDocTwoFuzz(const std::string &input) +{ + GRD_ResultSet *resultSet = nullptr; + std::string projectionInfo = "{\"name\": 0, \"nested1.nested2.nested3.nested4\":0}"; + std::string filter = "{\"_id\" : \"16\"}"; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_NextInner(resultSet); + char *value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); + + projectionInfo = "{\"name\": \"" + input + "\", \"nested1.nested2.nested3.nested4\":\"" + input + "\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); + + filter = "{\"_id\" : \"7\"}"; + resultSet = nullptr; + projectionInfo = "{\"name\": true, \"other_Info\":true, \"non_exist_field\":true}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_NextInner(resultSet); + value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); + + projectionInfo = "{\"name\": true, \"other_Info\":true, \" item \":true}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); +} + +void FindDocThreeFuzz(const std::string &input) +{ + std::string filter = "{\"_id\" : \"7\"}"; + GRD_ResultSet *resultSet = nullptr; + std::string projectionInfo = "{\"name\": true, \"other_Info.non_exist_field\":true}"; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_NextInner(resultSet); + char *value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); + projectionInfo = "{\"name\": true, \"other_Info\":{\"non_exist_field\":true}}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); + projectionInfo = "{\"name\": true, \"other_Info.0\": true}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); + filter = "{\"_id\" : \"4\"}"; + resultSet = nullptr; + projectionInfo = "{\"personInfo\": true, \"personInfo.grade\": true}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + + filter = "{\"_id\" : \"7\"}"; + projectionInfo = "{\"non_exist_field\":true}"; + int flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + flag = 1; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + filter = "{\"_id\" : \"7\"}"; + projectionInfo = "{\"name\":true, \"item\":true}"; + flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + flag = 1; + projectionInfo = "{\"name\": " + input + ", \"item\": " + input + "}"; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + filter = "{\"_id\" : \"7\"}"; + projectionInfo = "{\"name\":false, \"item\":false}"; + flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + flag = 1; + projectionInfo = "{\"name\": " + input + ", \"item\": " + input + "}"; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + filter = "{\"_id\" : \"4\"}"; + projectionInfo = "{\"name\": " + input + ", \"personInfo.grade1\": " + input + ", \ + \"personInfo.shool1\": " + + input + ", \"personInfo.age1\": " + input + "}"; + flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + projectionInfo = "{\"name\": false, \"personInfo.grade1\": false, \ + \"personInfo.shool1\": false, \"personInfo.age1\": false}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); +} + +void FindDocFourFuzz(const std::string &input) +{ + std::string filter = "{\"_id\" : \"4\"}"; + std::string projectionInfo = + "{\"name\": " + input + ", \"personInfo.school\": " + input + ", \"personInfo.age\": " + input + "}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, projectionInfo); + + filter = "{\"_id\" : \"17\"}"; + GRD_ResultSet *resultSet = nullptr; + Query query = { filter.c_str(), "{}" }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, GRD_DOC_ID_DISPLAY, &resultSet); + GRD_NextInner(resultSet); + char *value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + GRD_FreeResultSetInner(resultSet); + + resultSet = nullptr; + query = { filter.c_str(), "{}" }; + GRD_FindDocInner(g_db, "", query, 0, &resultSet); + GRD_FindDocInner(g_db, nullptr, query, 0, &resultSet); + + filter = "{\"_id\" : \"4\"}"; + resultSet = nullptr; + projectionInfo = "{\"name\":" + input + ", \"personInfo\":0, \"item\":" + input + "}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":true, \"personInfo\":0, \"item\":true}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":\"\", \"personInfo\":0, \"item\":\"\"}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":false, \"personInfo\":1, \"item\":false"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":false, \"personInfo\":-1.123, \"item\":false"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + + projectionInfo = "{\"name\":false, \"personInfo\":true, \"item\":false"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); +} + +void FindDocFiveFuzz(const std::string &input) +{ + std::string filter = "{\"_id\" : \"6\"}"; + std::string projectionInfo = "{\"name\":false, \"personInfo\": 0, \"item\":0}"; + int flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + + filter = "{\"_id\" : \"18\"}"; + projectionInfo = "{\"name\":true, \"personInfo.age\": \"\", \"item\":1, \"color\":10, \"nonExist\" : " + "-100}"; + flag = 0; + FindDocWithFlagFuzz(filter, projectionInfo, flag); + + GRD_ResultSet *resultSet = nullptr; + projectionInfo = "{\"personInfo\":[true, " + input + "]}"; + flag = 1; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, flag, &resultSet); + projectionInfo = "{\"personInfo\":null}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, flag, &resultSet); + resultSet = nullptr; + projectionInfo = "{\"Name\":true, \"personInfo.age\": \"\", \"item\":" + input + ", \"COLOR\":" + input + + ", \"nonExist\" : " + "" + + input + "}"; + flag = 0; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, flag, &resultSet); + GRD_NextInner(resultSet); + GRD_FreeResultSetInner(resultSet); + + resultSet = nullptr; + projectionInfo = "{\"Name\":" + input + ", \"personInfo.age\": false, \"personInfo.SCHOOL\": false, \"item\":\ + false, \"COLOR\":false, \"nonExist\" : false}"; + query = { filter.c_str(), projectionInfo.c_str() }; + char *value = nullptr; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_NextInner(resultSet); + GRD_FreeResultSetInner(resultSet); + + filter = "{\"_id\" : \"18\"}"; + resultSet = nullptr; + query = { filter.c_str(), "{}" }; + std::string collectionName1(LESS_HALF_BYTES, 'a'); + GRD_FindDocInner(g_db, collectionName1.c_str(), query, 1, &resultSet); + GRD_FreeResultSetInner(resultSet); +} + +void FindDocSixFuzz(const std::string &input) +{ + std::string collectionName2(HALF_BYTES, 'a'); + std::string filter = "{\"_id\" : \"18\"}"; + Query query = { filter.c_str(), "{}" }; + GRD_ResultSet *resultSet = nullptr; + GRD_FindDocInner(g_db, collectionName2.c_str(), query, 1, &resultSet); + GRD_FindDocInner(g_db, "", query, 1, &resultSet); + + resultSet = nullptr; + std::string projectionInfo = "{}"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, NUM_THREE, &resultSet); + GRD_FindDocInner(g_db, COLLECTION_NAME, query, INT_MAX, &resultSet); + GRD_FindDocInner(g_db, COLLECTION_NAME, query, INT_MIN, &resultSet); + GRD_FindDocInner(nullptr, COLLECTION_NAME, query, 0, &resultSet); + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, nullptr); + query = { nullptr, nullptr }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + + std::string document1 = "{\"_id\" : "; + std::string document2 = "\""; + std::string document4 = "\""; + std::string document5 = "}"; + std::string documentMiddle(MIDDLE_SIZE, 'k'); + filter = document1 + document2 + documentMiddle + document4 + document5; + resultSet = nullptr; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + std::string documentMiddle2(LESS_MIDDLE_SIZE, 'k'); + filter = document1 + document2 + documentMiddle2 + document4 + document5; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_FreeResultSetInner(resultSet); + + filter = "{\"personInfo\" : {\"school\":\"" + input + "\"}}"; + FindDocNextTwiceFuzz(filter, R"({})"); + + projectionInfo = "{\"version\": " + input + "}"; + FindDocNextTwiceFuzz(filter, projectionInfo); + + projectionInfo = "({\"a00001\":" + input + ", \"a00001\":" + input + "})"; + FindDocNextTwiceFuzz(filter, projectionInfo); + + projectionInfo = "({\"abc123_.\":" + input + "})"; + FindDocNextTwiceFuzz(filter, projectionInfo); + + filter = "({\"abc123_.\":" + input + "})"; + FindDocNextTwiceFuzz(filter, projectionInfo); +} + +void FindDocSevenFuzz(const std::string &input) +{ + std::string document064 = "{\"_id\" : \"64\", \"a\":" + input + ", \"doc64\" : " + input + "}"; + std::string document063 = "{\"_id\" : \"63\", \"a\":" + input + ", \"doc63\" : " + input + "}"; + std::string document062 = "{\"_id\" : \"62\", \"a\":" + input + ", \"doc62\" : " + input + "}"; + std::string document061 = "{\"_id\" : \"61\", \"a\":" + input + ", \"doc61\" : " + input + "}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document064.c_str(), 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, document063.c_str(), 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, document062.c_str(), 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, document061.c_str(), 0); + std::string filter = "{\"a\":" + input + "}"; + GRD_ResultSet *resultSet = nullptr; + std::string projectionInfo = R"({})"; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_NextInner(resultSet); + char *value = nullptr; + GRD_GetValueInner(resultSet, &value); + + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); +} + +void FindDocFuzzPlus(const std::string &input) +{ + FindDocZeroFuzz(input); + std::string filter = "{\"_id\" : \"6\"}"; + FindDocResultSetFuzz(COLLECTION_NAME, filter, R"({})"); + FindDocOneFuzz(); + FindDocTwoFuzz(input); + FindDocThreeFuzz(input); + FindDocFourFuzz(input); + FindDocFiveFuzz(input); + FindDocSixFuzz(input); + FindDocSevenFuzz(input); + + std::string document = "{\"a\":" + input + ", \"doc64\" : " + input + "}"; + filter = "{\"b\":" + input + "}"; + GRD_UpsertDocInner(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, filter.c_str(), document.c_str(), 0); + filter = "{\"a\":" + input + "}"; + GRD_ResultSet *resultSet = nullptr; + std::string projectionInfo = R"({})"; + Query query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + GRD_NextInner(resultSet); + GRD_FreeResultSetInner(resultSet); + filter = "{\"a\":" + input + "}"; + resultSet = nullptr; + projectionInfo = R"({})"; + query = { filter.c_str(), projectionInfo.c_str() }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + GRD_NextInner(resultSet); + char *valueNew = nullptr; + GRD_GetValueInner(resultSet, &valueNew); + GRD_FreeValueInner(valueNew); + GRD_FreeResultSetInner(resultSet); + filter = "{\"personInfo\" : {\"school\":" + input + "}" + "}"; + FindDocNextTwiceFuzz(filter, R"({})"); +} +} // namespace + +void FindDocFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{\"field\":\"" + input + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + Query query = { inputJson.c_str(), inputJson.c_str() }; + GRD_ResultSet *resultSet = nullptr; + // ResultSet conflict + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSetInner(resultSet); + resultSet = nullptr; + GRD_FindDocInner(g_db, input.c_str(), query, size, &resultSet); + GRD_FreeResultSetInner(resultSet); + GRD_FindDocInner(nullptr, input.c_str(), query, 1, &resultSet); + query.filter = nullptr; + GRD_FindDocInner(g_db, input.c_str(), query, 1, &resultSet); + inputJson = "{\"field\": 0, \"field2\":" + input + "}"; + query.filter = "{}"; + query.projection = inputJson.c_str(); + resultSet = nullptr; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSetInner(resultSet); + inputJson = "{\"" + input + "\": 0}"; + query.projection = inputJson.c_str(); + resultSet = nullptr; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSetInner(resultSet); + inputJson = "{\"field\":[\"aaa\"," + input + "]}"; + resultSet = nullptr; + query.projection = inputJson.c_str(); + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSetInner(resultSet); + query.filter = "{\"field\": false}"; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_FreeResultSetInner(resultSet); + FindDocFuzzPlus(input); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); +} + +void UpdateDocOneFuzz(std::string s, std::string input) +{ + std::string inputJson = "{\"field5\": \"" + s + "\"}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field5\": \"" + s + s + "\"}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); + inputJson = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); + inputJson = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); + + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDocInner(g_db, inputJson.c_str(), "{}", "{}", 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, input.c_str(), "{}", 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{}", input.c_str(), 0); + GRD_UpdateDocInner(nullptr, COLLECTION_NAME, "{}", "{}", 0); + inputJson = "{\"_id\":\"2\", \"field\":" + input + "}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; + inputJson = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + s.clear(); + for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { + s += 'a'; + } + inputJson = "{\"field5\": \"" + s + "\"}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field5\": \"" + s + s + "\"}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); + inputJson = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); + inputJson = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); +} + +void UpdateDocTwoFuzz(const char *newCollName, std::string s, std::string input) +{ + std::string inputJson = "{\"field5\": \"" + s + "\"}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field5\": \"" + s + s + "\"}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; + GRD_UpdateDocInner(g_db, newCollName, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); + inputJson = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; + GRD_UpdateDocInner(g_db, newCollName, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); + inputJson = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); + + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpdateDocInner(g_db, inputJson.c_str(), "{}", "{}", 0); + GRD_UpdateDocInner(g_db, newCollName, input.c_str(), "{}", 0); + GRD_UpdateDocInner(g_db, newCollName, "{}", input.c_str(), 0); + GRD_UpdateDocInner(nullptr, newCollName, "{}", "{}", 0); + inputJson = "{\"_id\":\"2\", \"field\":" + input + "}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; + inputJson = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + s.clear(); + for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { + s += 'a'; + } + inputJson = "{\"field5\": \"" + s + "\"}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field5\": \"" + s + s + "\"}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1\": [\"field2\", {\"field3\":\"" + input + "\"}]}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"name\":\"doc6\", \"c0\" : {\"c1\" : true } }"; + GRD_InsertDocInner(g_db, newCollName, inputJson.c_str(), 0); + GRD_UpdateDocInner(g_db, newCollName, "{\"name\":\"doc6\"}", "{\"c0.c1\":false}", 1); + inputJson = "{\"name\":\"doc7\", \"c0\" : {\"c1\" : null } }"; + GRD_InsertDocInner(g_db, newCollName, inputJson.c_str(), 0); + GRD_UpdateDocInner(g_db, newCollName, "{\"name\":\"doc7\"}", "{\"c0.c1\":null}", 1); + inputJson = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + GRD_InsertDocInner(g_db, newCollName, inputJson.c_str(), 0); + GRD_UpdateDocInner(g_db, newCollName, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); +} + +void UpdateDocFilterFuzz() +{ + const char *filter = "{\"_id\" : \"1\"}"; + const char *updata2 = "{\"objectInfo.child.child\" : {\"child\":{\"child\":null}}}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, filter, updata2, 0); + + const char *filter1 = "{\"_id\" : \"1\"}"; + const char *updata1 = "{\"_id\" : \"6\"}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, filter1, updata1, 0); + + const char *filter2 = "{\"_id\" : \"1\"}"; + const char *updata3 = "{\"age$\" : \"21\"}"; + const char *updata4 = "{\"bonus..traffic\" : 100}"; + const char *updata5 = "{\"0item\" : 100}"; + const char *updata6 = "{\"item\" : 1.79769313486232e308}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, filter2, updata3, 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, filter2, updata4, 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, filter2, updata5, 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, filter2, updata6, 0); + + const char *filter3 = "{\"_id\" : \"1\"}"; + const char *updata7 = "{\"age\" : 21}"; + GRD_UpdateDocInner(g_db, NULL, filter3, updata7, 0); + GRD_UpdateDocInner(g_db, "", filter3, updata7, 0); + GRD_UpdateDocInner(NULL, COLLECTION_NAME, filter3, updata7, 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, NULL, updata7, 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, filter3, NULL, 0); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); +} + +void UpdateDocFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{\"_id\":\"2\", \"field\": \"aaa\", " + "\"subject\":\"aaaaaaaaaaa\", \"test1\": true, " + "\"test2\": null}"; + + GRD_UpdateDocInner(g_db, inputJson.c_str(), "{}", "{}", 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, input.c_str(), "{}", 0); + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{}", input.c_str(), 0); + GRD_UpdateDocInner(nullptr, COLLECTION_NAME, "{}", "{}", 0); + inputJson = "{\"_id\":\"2\", \"field\":" + input + "}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; + inputJson = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; + GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + std::string s; + for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { + s += 'a'; + } + UpdateDocOneFuzz(s, input); + + const char *newCollName = "./student"; + GRD_UpdateDocInner(g_db, inputJson.c_str(), "{}", "{}", 0); + GRD_UpdateDocInner(g_db, newCollName, input.c_str(), "{}", 0); + GRD_UpdateDocInner(g_db, newCollName, "{}", input.c_str(), 0); + GRD_UpdateDocInner(nullptr, newCollName, "{}", "{}", 0); + inputJson = "{\"_id\":\"2\", \"field\":" + input + "}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + inputJson = "{\"field1.field2.field3.field4.field5.field6\":" + input + "}"; + inputJson = "{\"field1\": {\"field2\": {\"field3\": {\"field4\": {\"field5\":" + input + "}}}}}"; + GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + s.clear(); + for (int i = 0; i < ((ONE_BYTES * ONE_BYTES) - 1) - NUM_FIFTEEN; i++) { + s += 'a'; + } + + UpdateDocTwoFuzz(newCollName, s, input); + UpdateDocFilterFuzz(); +} + +void UpsertDocNewFuzz(std::string input, GRD_DB *db1) +{ + GRD_CreateCollectionInner(g_db, "student", "", 0); + std::string documentNew = + "{\"name\": {\"first\":[\"XXX\", \"BBB\", \"CCC\"], \"last\":\"moray\", \"field\":" + input + "}"; + std::string updateDocNew = R""({"name.last.AA.B":"Mnado"})""; + GRD_UpsertDocInner(g_db, "student", R""({"_id":"10001"})"", documentNew.c_str(), 0); + GRD_UpsertDocInner(db1, "student", R""({"_id":"10001"})"", updateDocNew.c_str(), 1); + GRD_DropCollectionInner(g_db, "student", 0); + + GRD_CreateCollectionInner(g_db, "student", "", 0); + documentNew = "{\"name\":[\"Tmn\", \"BB\", \"Alice\"], \"field\":" + input + "}"; + updateDocNew = R""({"name.first":"GG"})""; + GRD_UpsertDocInner(g_db, "student", R""({"_id":"10002"})"", documentNew.c_str(), 0); + GRD_UpsertDocInner(db1, "student", R""({"_id":"10002"})"", updateDocNew.c_str(), 1); +} + +void UpsertDocFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJsonNoId = "{\"name\":\"doc8\", \"c0\" : [\"" + input + "\", 123]}"; + std::string inputJson = "{\"_id\":\"1\", \"field\": " + input + "}"; + + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_UpsertDocInner(g_db, input.c_str(), "{}", "{}", 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), "{}", 0); + inputJson = "{\"_id\":\"1\", \"field\":" + input + "}"; + GRD_UpsertDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + inputJson = "{\"_id\":\"1\", \"field\":\"" + input + "\"}"; + GRD_UpsertDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpsertDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"1\"}", inputJson.c_str(), 1); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 1); + GRD_UpsertDocInner(nullptr, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 1); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, nullptr, inputJson.c_str(), 1); + GRD_UpsertDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), BATCH_COUNT); + + const char *newCollName = "./student"; + GRD_DB *db1 = nullptr; + GRD_CreateCollectionInner(db1, newCollName, "", 0); + GRD_InsertDocInner(db1, newCollName, inputJson.c_str(), 0); + GRD_UpsertDocInner(db1, input.c_str(), "{}", "{}", 0); + GRD_UpsertDocInner(db1, newCollName, inputJson.c_str(), "{}", 0); + inputJson = "{\"_id\":\"1\", \"field\":" + input + "}"; + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + inputJson = "{\"_id\":\"1\", \"field\":\"" + input + "\"}"; + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + inputJson = "{\"field\":" + input + "}"; + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"1\"}", inputJson.c_str(), 0); + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"1\"}", inputJson.c_str(), 1); + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 1); + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"newID1999\"}", inputJsonNoId.c_str(), 0); + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"newID1999a\"}", inputJsonNoId.c_str(), 1); + GRD_UpsertDocInner(nullptr, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 1); + GRD_UpsertDocInner(db1, newCollName, nullptr, inputJson.c_str(), 1); + GRD_UpsertDocInner(db1, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), BATCH_COUNT); + GRD_DropCollectionInner(db1, newCollName, 0); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + + UpsertDocNewFuzz(input, db1); +} + +void DeleteDocResultFuzz(std::string input) +{ + const char *filter = "{\"age\" : 15}"; + GRD_DeleteDocInner(g_db, COLLECTION_NAME, filter, 0); + const char *filter1 = "{\"_id\" : \"1\", \"age\" : 15}"; + GRD_DeleteDocInner(g_db, COLLECTION_NAME, filter1, 0); + std::string filter2 = "{\"_id\" : \"1\", \"name\" : " + input + "}"; + GRD_DeleteDocInner(g_db, COLLECTION_NAME, filter2.c_str(), 1); + GRD_DeleteDocInner(g_db, NULL, filter2.c_str(), 0); + GRD_DeleteDocInner(g_db, "", filter2.c_str(), 1); + GRD_DeleteDocInner(g_db, COLLECTION_NAME, filter2.c_str(), 0); + + const char *filter3 = "{\"_id\" : \"1\"}"; + GRD_ResultSet *resultSet = nullptr; + Query query = { filter3, "{}" }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_DeleteDocInner(g_db, COLLECTION_NAME, filter3, 0); + + const char *filter4 = "{\"_id\" : \"1\"}"; + std::string collectionName1(LESS_HALF_BYTES, 'a'); + GRD_CreateCollectionInner(g_db, collectionName1.c_str(), "", 0); + GRD_DeleteDocInner(g_db, collectionName1.c_str(), filter4, 0); + GRD_DropCollectionInner(g_db, collectionName1.c_str(), 0); + GRD_FreeResultSetInner(resultSet); + + GRD_DeleteDocInner(NULL, COLLECTION_NAME, filter2.c_str(), 0); + GRD_DeleteDocInner(g_db, NULL, filter2.c_str(), 0); + GRD_DeleteDocInner(g_db, "", filter2.c_str(), 0); + GRD_DeleteDocInner(g_db, COLLECTION_NAME, NULL, 0); + GRD_DeleteDocInner(g_db, COLLECTION_NAME, "", 0); + GRD_DeleteDocInner(g_db, "notExisted", filter2.c_str(), 0); + + std::vector filterVec = { R"({"_id" : 1})", R"({"_id":[1, 2]})", R"({"_id" : {"t1" : 1}})", + R"({"_id":null})", R"({"_id":true})", R"({"_id" : 1.333})", R"({"_id" : -2.0})" }; + for (const auto &item : filterVec) { + GRD_DeleteDocInner(g_db, COLLECTION_NAME, item.c_str(), 0); + } + GRD_DeleteDocInner(g_db, COLLECTION_NAME, filter2.c_str(), 0); + + std::string filter5 = "{\"subject.info\" : \"" + input + "\"}"; + resultSet = nullptr; + query = { filter2.c_str(), "{}" }; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_DeleteDocInner(g_db, COLLECTION_NAME, filter5.c_str(), 0); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + GRD_FreeResultSetInner(resultSet); +} + +void DeleteDocFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{\"field\":" + input + "}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + GRD_DeleteDocInner(g_db, input.c_str(), "{}", 0); + GRD_DeleteDocInner(g_db, nullptr, "{}", 0); + std::string longName = ""; + for (int i = 0; i < MORE_HALF_BYTES; i++) { + longName += 'a'; + } + GRD_DeleteDocInner(g_db, "grd_name", "{}", 0); + GRD_DeleteDocInner(g_db, longName.c_str(), "{}", 0); + GRD_DeleteDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + inputJson = "{\"field1\":" + input + "}"; + GRD_DeleteDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + inputJson = "{\"field\":\"" + input + "\"}"; + GRD_DeleteDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + inputJson = "{\"field1\":\"" + input + "\"}"; + GRD_DeleteDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + + const char *document1 = "{ \ + \"_id\" : \"1\", \ + \"name\": \"xiaoming\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"math\", \"English\", \"music\", {\"info\" : \"exam\"}] \ + }"; + const char *document2 = "{ \ + \"_id\" : \"2\", \ + \"name\": \"ori\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"math\", \"English\", \"music\"] \ + }"; + const char *document3 = "{ \ + \"_id\" : \"3\", \ + \"name\": \"David\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"Sing\", \"Jump\", \"Rap\", \"BasketBall\"] \ + }"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document1, 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, document2, 0); + GRD_InsertDocInner(g_db, COLLECTION_NAME, document3, 0); + GRD_DeleteDocInner(g_db, COLLECTION_NAME, "{}", 0); + + DeleteDocResultFuzz(input); +} + +namespace { +void FindAndRelease(Query query) +{ + GRD_ResultSet *resultSet = nullptr; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_NextInner(resultSet); + char *value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); + resultSet = nullptr; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 0, &resultSet); + GRD_NextInner(resultSet); + value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); + + const char *newCollName = "./student"; + resultSet = nullptr; + GRD_FindDocInner(g_db, newCollName, query, 1, &resultSet); + GRD_NextInner(resultSet); + value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); + resultSet = nullptr; + GRD_FindDocInner(g_db, newCollName, query, 0, &resultSet); + GRD_NextInner(resultSet); + value = nullptr; + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); +} +} // namespace + +void FindAndReleaseFuzz(std::string document, std::string filter, Query query, std::string input) +{ + GRD_InsertDocInner(g_db, COLLECTION_NAME, document.c_str(), 0); + query.filter = filter.c_str(); + query.projection = "{\"field\": 0}"; + FindAndRelease(query); + document = "{\"field1.field2\" [false], \"field1.field2.field3\": [3], " + "\"field1.field4\": [null]}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document.c_str(), 0); + query.filter = document.c_str(); + query.projection = "{\"field\": 0}"; + FindAndRelease(query); + query.projection = "{\"field\": 1}"; + FindAndRelease(query); + query.projection = "{\"field.field2\": 1}"; + FindAndRelease(query); + document = "{\"field1\": {\"field2\": [{\"field3\":\"" + input + "\"}]}}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, document.c_str(), 0); + filter = "{\"field1.field2.field3\":\"" + input + "\"}"; + query.filter = filter.c_str(); + query.projection = "{\"field1.field2\": 1}"; + FindAndRelease(query); + query.projection = "{\"field1.field2\": 0}"; + FindAndRelease(query); + query.projection = "{\"field1.field3\": 1}"; + FindAndRelease(query); + query.projection = "{\"field1.field3\": 0}"; + FindAndRelease(query); + query.projection = "{\"field1.field2.field3\": 0, \"field1.field2.field3\": 0}"; + FindAndRelease(query); + std::string projection = "{\"field1\": \"" + input + "\"}"; + query.projection = projection.c_str(); + FindAndRelease(query); + projection = "{\"" + input + "\": true, \"" + input + "\": false}"; + query.projection = projection.c_str(); + FindAndRelease(query); +} + +void NextFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{" + input + "}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + Query query = { inputJson.c_str(), "{}" }; + FindAndRelease(query); + std::string stringJson2 = "{ \"_id\":\"1\", \"field\":\"" + input + "\"}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, stringJson2.c_str(), 0); + query.filter = "{\"_id\": \"1\"}"; + FindAndRelease(query); + std::string filter2 = "{ \"_id\":\"1\", \"field\":\"" + input + " invalid\"}"; + query.filter = filter2.c_str(); + FindAndRelease(query); + query.filter = "{\"_id\": \"3\"}"; + FindAndRelease(query); + std::string stringJson3 = "{ \"_id\":\"2\", \"field\": [\"field2\", null, \"abc\", 123]}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, stringJson3.c_str(), 0); + query.filter = "{\"field\": [\"field2\", null, \"abc\", 123]}"; + FindAndRelease(query); + std::string document = "{\"field\": [\"" + input + "\",\"" + input + "\",\"" + input + "\"]}"; + std::string filter = "{\"field." + std::to_string(size) + "\":\"" + input + "\"}"; + FindAndReleaseFuzz(document, filter, query, input); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); +} + +void GetValueFuzz(const uint8_t *data, size_t size) +{ + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, OPTION_STR, 0); + std::string input(reinterpret_cast(data), size); + std::string inputJson = "{" + input + "}"; + GRD_InsertDocInner(g_db, COLLECTION_NAME, inputJson.c_str(), 0); + char *value = nullptr; + Query query = { inputJson.c_str(), "{}" }; + GRD_ResultSet *resultSet = nullptr; + GRD_FindDocInner(g_db, COLLECTION_NAME, query, 1, &resultSet); + GRD_GetValueInner(resultSet, &value); + GRD_NextInner(resultSet); + GRD_GetValueInner(resultSet, &value); + GRD_FreeValueInner(value); + GRD_FreeResultSetInner(resultSet); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); +} + +void FreeResultSetFuzz() +{ + GRD_ResultSet *resultSet = nullptr; + GRD_FreeResultSetInner(resultSet); + resultSet = new GRD_ResultSet; + resultSet->resultSet_ = DocumentDB::ResultSet(); + GRD_FreeResultSetInner(resultSet); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); +} + +void DbOpenOneFuzz(GRD_DB *dbVal) +{ + std::string path = "./documentFuzz.db"; + GRD_DBOpenInner(path.c_str(), "", GRD_DB_OPEN_ONLY, &dbVal); + (void)remove(path.c_str()); + + path = "./document.db"; + GRD_DBOpenInner(path.c_str(), R""({"pageSize":64, "redopubbufsize":4033})"", GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBCloseInner(dbVal, 0); + GRD_DBOpenInner(path.c_str(), R""({"pageSize":64, "redopubbufsize":4032})"", GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBOpenInner(path.c_str(), R""({"redopubbufsize":255})"", GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBOpenInner(path.c_str(), R""({"redopubbufsize":16385})"", GRD_DB_OPEN_CREATE, &dbVal); +} + +void DbOpenFuzz(const uint8_t *data, size_t size) +{ + std::string dbFileData(reinterpret_cast(data), size); + std::string realDbFileData = DB_DIR_PATH + dbFileData; + const char *dbFileVal = realDbFileData.data(); + std::string configStrData(reinterpret_cast(data), size); + const char *configStrVal = configStrData.data(); + GRD_DB *dbVal = nullptr; + + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + std::string stringMax = getMaxString(); + const char *configStrMaxLen = stringMax.data(); + GRD_DBOpenInner(dbFileVal, configStrMaxLen, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValue = "{\"bufferPoolSize\": \"1024.5\"}"; + const char *configStrStringValue = fieldStringValue.data(); + GRD_DBOpenInner(dbFileVal, configStrStringValue, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldBoolValue = "{\"bufferPoolSize\":}"; + const char *configStrBool = fieldBoolValue.data(); + GRD_DBOpenInner(dbFileVal, configStrBool, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValueAppend = "{\"bufferPoolSize\":\"8192\"}"; + const char *configStrStr = fieldStringValueAppend.data(); + GRD_DBOpenInner(dbFileVal, configStrStr, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValueFlush = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\"}"; + const char *configStrFlush = fieldStringValueFlush.data(); + GRD_DBOpenInner(dbFileVal, configStrFlush, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValueRedoBufsize = "{\"bufferPoolSize\":\"8192\",\"redoBufSize\":\"16384\"}"; + const char *configStrBs = fieldStringValueRedoBufsize.data(); + GRD_DBOpenInner(dbFileVal, configStrBs, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldStringValueMaxConnNum = "{\"bufferPoolSize\":\"8192\",\"maxConnNum\":\"1024\"}"; + const char *configStrMcn = fieldStringValueMaxConnNum.data(); + GRD_DBOpenInner(dbFileVal, configStrMcn, GRD_DB_OPEN_CREATE, &dbVal); + + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + std::string fieldStringValueAll = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\",\"redoBufSize\":" + "\"16384\",\"maxConnNum\":\"1024\"}"; + const char *configStrAll = fieldStringValueAll.data(); + GRD_DBOpenInner(dbFileVal, configStrAll, GRD_DB_OPEN_CREATE, &dbVal); + + std::string fieldLowNumber = "{\"bufferPoolSize\": 102}"; + const char *configStrLowNumber = fieldLowNumber.data(); + GRD_DBOpenInner(dbFileVal, configStrLowNumber, GRD_DB_OPEN_CREATE, &dbVal); + + GRD_DBOpenInner(nullptr, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBOpenInner(dbFileVal, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBCloseInner(nullptr, GRD_DB_CLOSE); + GRD_DBCloseInner(dbVal, GRD_DB_CLOSE); + + DbOpenOneFuzz(dbVal); +} + +void DbCloseFuzz(const uint8_t *data, size_t size) +{ + std::string dbFileData(reinterpret_cast(data), size); + std::string realDbFileData = DB_DIR_PATH + dbFileData; + const char *dbFileVal = realDbFileData.data(); + std::string configStrData(reinterpret_cast(data), size); + const char *configStrVal = configStrData.data(); + GRD_DB *dbVal = nullptr; + GRD_DBOpenInner(dbFileVal, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); + GRD_DBCloseInner(dbVal, GRD_DB_CLOSE); +} + +void DbCloseResultSetFuzz() +{ + GRD_DB *db = nullptr; + GRD_DB *db2 = nullptr; + GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); + GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db2); + GRD_CreateCollectionInner(db, "collection1", "{\"maxdoc\" : 5}", 0); + + GRD_ResultSet *resultSet = nullptr; + Query query = { "{}", "{}" }; + GRD_FindDocInner(db, "collection1", query, 0, &resultSet); + + GRD_FreeResultSetInner(resultSet); + + GRD_DBCloseInner(db, GRD_DB_CLOSE); + + GRD_DBCloseInner(db2, GRD_DB_CLOSE); +} + +void CreateCollectionFuzz(const uint8_t *data, size_t size) +{ + std::string collectionNameData(reinterpret_cast(data), size); + const char *collectionNameVal = collectionNameData.data(); + std::string optionStrData(reinterpret_cast(data), size); + const char *optionStrVal = optionStrData.data(); + GRD_CreateCollectionInner(nullptr, collectionNameVal, optionStrVal, 0); + GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); + const char *optionStr = nullptr; + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, optionStr, 0); + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, "{\"maxdoc\":5, \"unexpected_max_doc\":32}", 0); + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, "{}", 0); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + std::string optStr = "{\"maxdoc\":" + optionStrData + "}"; + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, optStr.c_str(), 0); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, optStr.c_str(), MAX_SIZE_NUM); + optStr = "{\"maxdoc\": 5}"; + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, optStr.c_str(), 0); + GRD_CreateCollectionInner(g_db, COLLECTION_NAME, optStr.c_str(), 1); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); + GRD_DropCollectionInner(g_db, COLLECTION_NAME, MAX_SIZE_NUM); + GRD_DropCollectionInner(g_db, collectionNameVal, 0); +} + +void DropCollectionFuzz(const uint8_t *data, size_t size) +{ + std::string collectionNameData(reinterpret_cast(data), size); + const char *collectionNameVal = collectionNameData.data(); + std::string optionStrData(reinterpret_cast(data), size); + const char *optionStrVal = optionStrData.data(); + GRD_CreateCollectionInner(g_db, collectionNameVal, optionStrVal, 0); + GRD_DropCollectionInner(nullptr, collectionNameVal, 0); + GRD_DropCollectionInner(g_db, collectionNameVal, 0); +} + +void DbFlushFuzz(const uint8_t *data, size_t size) +{ + GRD_DB *db = nullptr; + GRD_DB *db2 = nullptr; + GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); + GRD_FlushInner(db, 0); + GRD_FlushInner(db, 1); + GRD_FlushInner(db2, 0); + GRD_FlushInner(db2, 1); + GRD_DBCloseInner(db, GRD_DB_CLOSE); +} + +void TestGrdDbApGrdGetItem002Fuzz() +{ + const char *config = CONFIG_STR; + GRD_DB *db = nullptr; + GRD_DBOpenInner(TEST_DB_FILE, config, GRD_DB_OPEN_CREATE, &db); + GRD_IndexPreloadInner(nullptr, COLLECTION_NAME); + GRD_IndexPreloadInner(nullptr, "invalid_name"); + GRD_IndexPreloadInner(g_db, COLLECTION_NAME); + std::string smallPrefix = std::string(SMALL_PREFIX_LEN, 'a'); + for (uint32_t i = 0; i < NUM_NINETY_EIGHT; ++i) { + std::string v = smallPrefix + std::to_string(i); + GRD_KVItemT key = { &i, sizeof(uint32_t) }; + GRD_KVItemT value = { (void *)v.data(), (uint32_t)v.size() + 1 }; + GRD_KVPutInner(g_db, COLLECTION_NAME, &key, &value); + + GRD_KVItemT getValue = { nullptr, 0 }; + GRD_KVGetInner(g_db, COLLECTION_NAME, &key, &getValue); + GRD_KVFreeItemInner(&getValue); + + GRD_KVDelInner(g_db, COLLECTION_NAME, &key); + } + GRD_FlushInner(g_db, 1); + + uint32_t begin = 0, end = MAX_SIZE_NUM; + GRD_FilterOptionT option = {}; + option.mode = KV_SCAN_RANGE; + option.begin = { &begin, sizeof(uint32_t) }; + option.end = { &end, sizeof(uint32_t) }; + GRD_ResultSet *resultSet = nullptr; + GRD_KVFilterInner(g_db, COLLECTION_NAME, &option, &resultSet); + + uint32_t keySize, valueSize; + GRD_KVGetSizeInner(resultSet, &keySize, &valueSize); + + resultSet = nullptr; + uint32_t i = 32; + GRD_KVItemT key = { &i, sizeof(uint32_t) }; + GRD_KVScanInner(g_db, COLLECTION_NAME, &key, KV_SCAN_EQUAL_OR_LESS_KEY, &resultSet); + + GRD_PrevInner(resultSet); + GRD_NextInner(resultSet); + + GRD_FreeResultSetInner(resultSet); +} + +void TestGrdKvBatchCoupling003Fuzz() +{ + const char *config = CONFIG_STR; + GRD_DB *db = nullptr; + GRD_DBOpenInner(TEST_DB_FILE, config, GRD_DB_OPEN_CREATE, &db); + + GRD_ResultSet *resultSet = nullptr; + GRD_KVScanInner(g_db, COLLECTION_NAME, nullptr, KV_SCAN_PREFIX, &resultSet); + + for (uint32_t i = 0; i < CURSOR_COUNT; i++) { + GRD_NextInner(resultSet); + } + + GRD_KVBatchT *batchDel = nullptr; + std::vector keySet; + std::vector valueSet; + for (uint32_t i = 0; i < VECTOR_SIZE; i++) { + std::string key(MAX_SIZE_NUM, 'a'); + key += std::to_string(i); + keySet.emplace_back(key); + std::string value = std::to_string(i); + valueSet.emplace_back(value); + } + + for (int j = 0; j < BATCH_COUNT; j++) { + GRD_KVBatchPrepareInner(BATCH_COUNT, &batchDel); + GRD_KVBatchPutInner(g_db, COLLECTION_NAME, batchDel); + for (uint16_t i = 0; i < BATCH_COUNT; i++) { + GRD_KVBatchPushbackInner((void *)keySet[CURSOR_COUNT + j * BATCH_COUNT + i].c_str(), + (uint32_t)keySet[CURSOR_COUNT + j * BATCH_COUNT + i].length() + 1, + (void *)valueSet[CURSOR_COUNT + j * BATCH_COUNT + i].c_str(), + (uint32_t)valueSet[CURSOR_COUNT + j * BATCH_COUNT + i].length() + 1, + batchDel); + } + + GRD_KVBatchDelInner(g_db, COLLECTION_NAME, batchDel); + + GRD_KVBatchDestroyInner(batchDel); + } + + GRD_NextInner(resultSet); + GRD_KVItemT keyItem = { nullptr, 0 }; + GRD_KVItemT valueItem = { nullptr, 0 }; + GRD_FetchInner(resultSet, &keyItem, &valueItem); + GRD_KVFreeItemInner(&keyItem); + GRD_KVFreeItemInner(&valueItem); + GRD_FreeResultSetInner(resultSet); +} +} // namespace OHOS + +/* Fuzzer entry point */ +extern "C" { +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + /* Run your code on data */ + OHOS::SetUpTestCase(); + + OHOS::DbOpenFuzz(data, size); + OHOS::CreateCollectionFuzz(data, size); + OHOS::DropCollectionFuzz(data, size); + OHOS::InsertDocFuzz(data, size); + OHOS::FindDocFuzz(data, size); + OHOS::UpdateDocFuzz(data, size); + OHOS::UpsertDocFuzz(data, size); + OHOS::DeleteDocFuzz(data, size); + OHOS::NextFuzz(data, size); + OHOS::GetValueFuzz(data, size); + OHOS::FreeResultSetFuzz(); + OHOS::TestGrdDbApGrdGetItem002Fuzz(); + OHOS::TestGrdKvBatchCoupling003Fuzz(); + OHOS::DbCloseFuzz(data, size); + OHOS::DbCloseResultSetFuzz(); + OHOS::DbFlushFuzz(data, size); + + OHOS::TearDownTestCase(); + return 0; +} +} \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.h b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..1e69bc3bd9678b45a2a8c99dc5962ec87c07e746 --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 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 JSON_INNER_FUZZER_H +#define JSON_INNER_FUZZER_H + +#define FUZZ_PROJECT_NAME "JsonInner_fuzzer" + +#endif // JSON_INNER_FUZZER_H \ No newline at end of file diff --git a/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/project.xml b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..73736f01a8820f5deb20590a5655e6fbe62b6aa6 --- /dev/null +++ b/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 1800 + + 4096 + + diff --git a/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp index ed5d6d40d88e3eeef85f4e84404adf6275cb08ec..c84c7cf72de807c664cd8bdc15c0bb5b846cb79e 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp @@ -541,7 +541,11 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, Fragment004, TestSize.Level2) std::this_thread::sleep_for(std::chrono::seconds(1)); // Wait 1s to make sure send done g_envDeviceA.adapterHandle->SimulateSendRetry(DEVICE_NAME_B); g_envDeviceA.adapterHandle->SimulateSendRetryClear(DEVICE_NAME_B); - std::this_thread::sleep_for(std::chrono::seconds(5)); // Wait 5s to make sure send done + int reTryTimes = 5; + while (recvMsgForBB == nullptr && reTryTimes > 0) { + std::this_thread::sleep_for(std::chrono::seconds(3)); + reTryTimes--; + } ASSERT_NE(recvMsgForBB, nullptr); ASSERT_EQ(recvMsgForBB->GetMessageId(), REGED_GIANT_MSG_ID); /** diff --git a/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp index eb0ee96e98effb10699c2b1bd21295f11591e2f9..8cda98e645ef16d4e08deefd4cfb42ae963dba9d 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_test.cpp @@ -473,7 +473,11 @@ void TestRemoteRestart() * @tc.expected: step6. communicatorE has callback; */ AdapterStub::ConnectAdapterStub(envDeviceD.adapterHandle, envDeviceE.adapterHandle); - std::this_thread::sleep_for(std::chrono::seconds(1)); + int reTryTimes = 5; + while (onlineForEE.onlineDevices.size() != 1 && reTryTimes > 0) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + reTryTimes--; + } EXPECT_EQ(onlineForEE.onlineDevices.size(), static_cast(1)); // Clean up and disconnect envDeviceD.commAggrHandle->ReleaseCommunicator(commDD); diff --git a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp index e57e5a60a3a8fbbb4e4d2eaa7194495c89c2b13b..02a04224f532f07445dd116beb70973936a205fc 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp @@ -531,6 +531,7 @@ namespace { void CloseDb() { + g_delegate->UnRegisterObserver(g_observer); delete g_observer; g_virtualCloudDb = nullptr; if (g_delegate != nullptr) { diff --git a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp index 2c66de2fc50a2c21d7b29385a901a2965443edb1..1406c6d9aca8ceb64022b932ce9619c7b9b8c40d 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp @@ -277,6 +277,8 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes g_mgr.GetKvStore("corrupt5", nbOption, g_kvNbDelegateCallback); ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; /** * @tc.steps: step4. Modify the database file. @@ -309,13 +311,13 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes EXPECT_EQ(g_mgr.DeleteKvStore("corrupt4"), OK); infoSize++; #endif // OMIT_MULTI_VER + g_mgr.GetKvStore("corrupt5", nbOption, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); ASSERT_NE(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); infoSize++; std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME)); EXPECT_TRUE(corruptInfo.GetDatabaseInfoSize() >= infoSize); // 2 more callback EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt5"), true); - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; EXPECT_EQ(g_mgr.DeleteKvStore("corrupt5"), OK); } @@ -343,6 +345,8 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes g_mgr.GetKvStore("corrupt7", nbOption, g_kvNbDelegateCallback); ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; /** * @tc.steps: step4. Modify the database file. @@ -364,6 +368,8 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.steps: step5. Re-obtain the kvStore. * @tc.expected: step5. Returns null kvstore. */ + g_mgr.GetKvStore("corrupt7", nbOption, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); size_t infoSize = 0; ASSERT_NE(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); infoSize++; @@ -371,8 +377,6 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes EXPECT_EQ(corruptInfo.GetDatabaseInfoSize(), 0UL); // no callback EXPECT_TRUE(corruptInfoNew.GetDatabaseInfoSize() >= infoSize); // 2 more callback EXPECT_EQ(corruptInfoNew.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt7"), true); - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; EXPECT_EQ(g_mgr.DeleteKvStore("corrupt7"), OK); } diff --git a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp index 6676d063de645def7730046a36b7e60efd79d875..f86972bcfcd476c4fa7ce463892fc14a7195bd92 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp @@ -361,7 +361,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore007, TestSize.Le option.storageEngineType = GAUSSDB_RD; option.rdconfig.readOnly = true; g_mgr.GetKvStore("distributed_getkvstore_007", option, g_kvNbDelegateCallback); - EXPECT_EQ(g_kvDelegateStatus, INVALID_ARGS); + EXPECT_EQ(g_kvDelegateStatus, DB_ERROR); ASSERT_EQ(g_kvNbDelegatePtr, nullptr); } diff --git a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp index d2e28ae87021da367587ecd8950d071dda68d79e..4409ae99d881d0ea915d412ee2ae17e34e350a5d 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp @@ -1071,7 +1071,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, SeparaDbExportAndImport, Te RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); std::string singleExportFileName = g_exportFileDir + "/SeparaDbExportAndImport.$$"; - std::string singleStoreId = "distributed_ExportSingle_010"; + std::string singleStoreId = "distributed_ExportSingle_0101"; KvStoreNbDelegate::Option option = {true, false, false}; SecurityOption secOption{SecurityLabel::S3, SecurityFlag::SECE}; option.secOption = secOption; diff --git a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp index 3c26c7f23cd9ccd0a1c3f75bd99629ca0f6aced9..9083987f9c75ec6855dd6c132a806d54197b15d2 100755 --- a/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp @@ -3533,7 +3533,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, OptionModeValidCheck001, TestSiz * @tc.require: DTS2024042521804 * @tc.author: zhujinlin */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, DISABLED_InvalidOption001, TestSize.Level3) +HWTEST_F(DistributedDBInterfacesNBDelegateTest, InvalidOption001, TestSize.Level3) { /** * @tc.steps:step1. Get the nb delegate. diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp index bd48bb7a5f7c7aca09d7efe59e14e2c5bc347477..424b1ce65aa00a933ba5497c2bb512d7afe6751d 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp @@ -808,7 +808,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest001, TestSiz Asset asset; Assets assets; switch (recordIndex) { - case 0: // record[0] fail. + case 0: // record[0] is successful because ERROR_FIELD is not verified when BatchInsert returns OK status. extend[std::string(CloudDbConstant::ERROR_FIELD)] = static_cast(DBStatus::CLOUD_ERROR); break; case 1: // record[1] is considered successful because it is a conflict. @@ -816,7 +816,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest001, TestSiz static_cast(DBStatus::CLOUD_RECORD_EXIST_CONFLICT); break; case 2: // record[2] fail because of empty gid. - extend[std::string(CloudDbConstant::GID_FIELD)] = ""; + extend[std::string(CloudDbConstant::GID_FIELD)] = std::string(""); break; case 3: // record[3] fail because of empty assetId. asset = tempAsset; @@ -828,8 +828,8 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest001, TestSiz assets[0].assetId = ""; extend[std::string(CloudDbConstant::ASSETS)] = assets; break; - case 5: // record[5] fail because of error. - extend[std::string(CloudDbConstant::ERROR_FIELD)] = ""; + case 5: // record[5] is successful because ERROR_FIELD is not verified when BatchInsert returns OK status. + extend[std::string(CloudDbConstant::ERROR_FIELD)] = std::string(""); break; default: break; @@ -843,9 +843,9 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest001, TestSiz Query query = Query::Select().FromTable({ tableName_ }); BlockSync(query, delegate_); for (const auto &table : lastProcess_.tableProcess) { - EXPECT_EQ(table.second.upLoadInfo.total, 10u); - EXPECT_EQ(table.second.upLoadInfo.failCount, 5u); - EXPECT_EQ(table.second.upLoadInfo.successCount, 5u); + EXPECT_EQ(table.second.upLoadInfo.total, 9u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 3u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 6u); } virtualCloudDb_->ForkUpload(nullptr); } @@ -888,5 +888,44 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest002, TestSiz } virtualCloudDb_->ForkUpload(nullptr); } + +/** + * @tc.name: UploadAssetsTest003 + * @tc.desc: Test upload asset with error CLOUD_RECORD_ALREADY_EXISTED. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSize.Level0) +{ + /** + * @tc.steps:step1. Insert 100 records. + * @tc.expected: step1. ok. + */ + const int actualCount = 100; + InsertUserTableRecord(tableName_, 0, actualCount); + /** + * @tc.steps:step2. Set callback function to return CLOUD_RECORD_ALREADY_EXISTED in 1st batch. + * @tc.expected: step2. ok. + */ + int uploadCount = 0; + virtualCloudDb_->ForkUpload([&uploadCount](const std::string &tableName, VBucket &extend) { + if (uploadCount < 30) { // There are a total of 30 pieces of data in one batch of upstream data + extend[std::string(CloudDbConstant::ERROR_FIELD)] = + static_cast(DBStatus::CLOUD_RECORD_ALREADY_EXISTED); + } + uploadCount++; + }); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.batchIndex, 4u); + EXPECT_EQ(table.second.upLoadInfo.total, 70u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 70u); + EXPECT_EQ(table.second.process, ProcessStatus::FINISHED); + } + virtualCloudDb_->ForkUpload(nullptr); +} } #endif diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp index f6105966c95ec6e830db8cc3394d71122c11261b..91c3687b69113d22d9f97c9641cc57e623611acf 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp @@ -387,19 +387,17 @@ void DistributedDBCloudCheckSyncTest::PriorityAndNormalSync(const Query &normalQ const std::map &process) { for (const auto &item: process) { if (item.second.process == DistributedDB::FINISHED) { - { - std::lock_guard autoLock(dataMutex); - normalFinish = true; - } + normalFinish = true; ASSERT_EQ(priorityFinish, true); cv.notify_one(); } } }; - auto priorityCallback = [&priorityFinish](const std::map &process) { + auto priorityCallback = [&cv, &priorityFinish](const std::map &process) { for (const auto &item: process) { if (item.second.process == DistributedDB::FINISHED) { priorityFinish = true; + cv.notify_one(); } } }; @@ -408,6 +406,7 @@ void DistributedDBCloudCheckSyncTest::PriorityAndNormalSync(const Query &normalQ virtualCloudDb_->SetBlockTime(500); // 500 ms ASSERT_EQ(delegate->Sync(option, normalCallback), OK); PrepareOption(option, priorityQuery, true); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 50 ms ASSERT_EQ(delegate->Sync(option, priorityCallback), OK); std::unique_lock uniqueLock(dataMutex); cv.wait(uniqueLock, [&normalFinish]() { @@ -888,11 +887,10 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Lev std::vector idValue = {"0", "1", "2"}; Query priorityQuery = Query::Select().From(tableName_).In("id", idValue); PriorityAndNormalSync(normalQuery, priorityQuery, delegate_); - CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records EXPECT_EQ(virtualCloudDb_->GetLockCount(), 2); virtualCloudDb_->Reset(); EXPECT_EQ(virtualCloudDb_->GetLockCount(), 0); - EXPECT_EQ(virtualCloudDb_->GetQueryTimes(tableName_), 3u); // 3 = normal query 2 times + priority 1 times + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records } /** diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp index adf0ce80e14e654d5389085cc946716b127baa88..773df39ae35ed365478c86d332a31726f96d70fe 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp @@ -285,7 +285,8 @@ namespace { const CloudTaskConfig config; proxyObj.SetCloudTaskConfig(config); std::vector syncQuery; - EXPECT_EQ(proxyObj.GetCompensatedSyncQuery(syncQuery), -E_INVALID_DB); + std::vector users; + EXPECT_EQ(proxyObj.GetCompensatedSyncQuery(syncQuery, users), -E_INVALID_DB); proxyObj.OnSyncFinish(); proxyObj.OnUploadStart(); std::shared_ptr cloudSchema; diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp index 6d1f8bfd731552f56dc2c3ebd1fc5e0b670601f2..355e40b38de318507caa954e28c4b1e01634ebb9 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp @@ -396,6 +396,11 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData1, TestSize.Level1) EXPECT_TRUE(errCode == E_OK || errCode == -E_UNFINISHED); } EXPECT_EQ(count, RECORD_COUNT); + + RelationalDBProperties properties; + InitStoreProp(g_storePath, APP_ID, USER_ID, properties); + auto db = RelationalStoreInstance::GetDataBase(properties, errCode, false); + EXPECT_EQ(db, nullptr); RefObject::DecObjRef(g_store); } diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_executor_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_executor_test.cpp index 724d5ea321dd5724215cc29240f3545097bd49fb..3b479946ce96c4aa7c29c294b1ebe3cd1acfc5fe 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_executor_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_executor_test.cpp @@ -443,8 +443,8 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, PragmaTest003, Test EXPECT_EQ(emptyConn->CheckIntegrity(), -E_NOT_INIT); int limit = 0; - EXPECT_EQ(emptyConn->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, &limit), -E_NOT_SUPPORT); - EXPECT_EQ(emptyConn->Pragma(PRAGMA_RM_DEVICE_DATA, nullptr), -E_NOT_SUPPORT); + EXPECT_EQ(emptyConn->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, &limit), -E_INVALID_DB); + EXPECT_EQ(emptyConn->Pragma(PRAGMA_RM_DEVICE_DATA, nullptr), -E_INVALID_DB); CipherPassword pw; EXPECT_EQ(emptyConn->Import("/a.b", pw), -E_NOT_SUPPORT); EXPECT_EQ(emptyConn->Export("/a.b", pw), -E_NOT_SUPPORT); diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp index 6e75a96357ba7a54bc8807747a65a0756858225f..02425f1c349cb7ce61fb9b62638c81cdffa92e3f 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp @@ -255,7 +255,7 @@ HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, ExportBusy001, TestSiz ASSERT_NE(g_store, nullptr); ASSERT_EQ(g_store->TryToDisableConnection(OperatePerm::NORMAL_WRITE), E_OK); CipherPassword password; - EXPECT_EQ(g_store->Export(g_testDir, password), -E_NOT_SUPPORT); + EXPECT_EQ(g_store->Export(g_testDir, password), -E_READ_ONLY); g_store->ReEnableConnection(OperatePerm::NORMAL_WRITE); } } diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp index 62354fc6d47ffe405e6c2e033c739e4f019d815e..f90b2bb6ef1843a6bfd900c6b0e6ddc023161859 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp @@ -61,8 +61,8 @@ namespace { bool newIsDeleted = false; bool oldIsNative = false; bool newIsNative = false; - int getoldValueErrCode = 0; - int getNewValueErrCode = 0; + DBStatus getoldValueErrCode = DBStatus::OK; + DBStatus getNewValueErrCode = DBStatus::OK; bool operator==(const SingleVerConflictData &comparedData) const { if (this->type == comparedData.type && diff --git a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp index 9da40f841c093df2cab53377cc51756917f5888d..5fa3c9829447111e5fe16d4d2f958b6f65540228 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp @@ -90,7 +90,7 @@ void PreSetData(uint8_t dataNum) validJsonData = R"({"field_name1":false,"field_name2":false,"field_name3":100})"; } value.assign(validJsonData.begin(), validJsonData.end()); - EXPECT_EQ(g_kvNbDelegatePtr->Put(keyA, value), E_OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(keyA, value), OK); } } @@ -163,7 +163,7 @@ void CheckDataNumByKey(const std::string &storeId, const Key& key, size_t expSiz EXPECT_TRUE(g_kvNbDelegatePtr != nullptr); EXPECT_TRUE(g_kvDelegateStatus == OK); std::vector entries; - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(key, entries), E_OK); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(key, entries), OK); EXPECT_TRUE(entries.size() == expSize); EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); } diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp index 583d15fefdff232887611f5079bb7819407c3c11..8b4342f4451a6a0b74edeec2827d61ac30f6b872 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp @@ -849,7 +849,7 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest013, TestSize.Level0) EXPECT_EQ(ret, -E_OK); assets = {{}}; ret = proxy.RemoveLocalAssets(assets); - EXPECT_EQ(ret, -E_NOT_SET); + EXPECT_EQ(ret, -E_OK); } /** @@ -897,7 +897,7 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudSyncUtilsTest, TestSize.Level0) EXPECT_EQ(ret, -E_INTERNAL_ERROR); CloudSyncBatch data; data.assets = {{}}; - ret = utilsObj.FillAssetIdToAssets(data, 0); + ret = utilsObj.FillAssetIdToAssets(data, 0, CloudWaterType::UPDATE); EXPECT_EQ(ret, -E_CLOUD_ERROR); /** diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp index bbdb42672c478fbead96085fceedf791d3d266cc..da834a5c762c1b51afc53f5e44f1f8e9866428af 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp @@ -484,7 +484,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level0) * @tc.steps:step1. Device A inserts data and synchronizes * @tc.expected: step1 errCode outside DBStatus should be kept. */ - int errCode = 27394049; + int errCode = 27394048; virtualCloudDb_->SetActionStatus(static_cast(errCode)); Key key = {'k'}; Value value = {'v'}; diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp index 67feaa1645b2f415283683774d7db120bb1fe600..13c2c5208a95d7f27522ad8a4f6da6e375c71253 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp @@ -1939,6 +1939,45 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level0) } } +/** + * @tc.name: NormalSync045 + * @tc.desc: Test some record upload fail in 1 batch and extend size greater than record size + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangtao + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level0) +{ + /** + * @tc.steps:step1. put 10 records. + * @tc.expected: step1 ok. + */ + vector entries; + int count = 10; // put 10 records. + for (int i = 0; i < count; i++) { + std::string keyStr = "k_" + std::to_string(i); + std::string valueStr = "v_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + Value value(valueStr.begin(), valueStr.end()); + entries.push_back({key, value}); + } + EXPECT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); + /** + * @tc.steps:step2. sync and add one empty extend as result + * @tc.expected: step2 sync fail and upLoadInfo.failCount is 10. 1 batch failed. + */ + std::atomic missCount = -1; + virtualCloudDb_->SetClearExtend(missCount); + BlockSync(kvDelegatePtrS1_, CLOUD_ERROR, g_CloudSyncoption); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 10u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 10u); + } + virtualCloudDb_->ForkUpload(nullptr); +} + /** * @tc.name: SyncOptionCheck001 * @tc.desc: Test sync without user. diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp index 7f513215d3972658d8bdb5b7080a217fc9e6c4ba..dfdf72caf04bf6a9bf87e090b0a2951e29d7b378 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp @@ -946,7 +946,7 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest004, TestSize.Level0) * @tc.expected: step3. return ok. */ std::string sql = "select count(*) from " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + - " where data_key='0' and extend_field='name10' and cursor='31';"; + " where data_key='0' and extend_field='name10' and cursor='32';"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(1), nullptr), SQLITE_OK); } diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp index 01701a653a56a7dbf5f23f3f1c6c64a1071d76ed..db184edd60251c2ba3a7509858213527578e470a 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp @@ -716,7 +716,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser003, TestSize.Level3) * @tc.expected: step6. success. */ Query query = Query::Select(g_tableName); - EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), OK); + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); /** * @tc.steps: step7. deviceA have {k1,v1} diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index 52d7351e36a456e4ba6e6e38949b12c4d079117e..0091095f9ca04feef11b73a7317829c4d5ed9d8c 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -735,7 +735,7 @@ namespace { } RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); LOGD("CloseStore Start"); - EXPECT_EQ(g_rdbDelegatePtr->RemoveDeviceData(), E_OK); + EXPECT_EQ(g_rdbDelegatePtr->RemoveDeviceData(), OK); ASSERT_EQ(g_mgr.CloseStore(g_rdbDelegatePtr), OK); g_rdbDelegatePtr = nullptr; OpenStore(); @@ -1819,7 +1819,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer006, TestSize.Level3) } return true; }; - EXPECT_EQ(RuntimeConfig::SetPermissionCheckCallback(callback), E_OK); + EXPECT_EQ(RuntimeConfig::SetPermissionCheckCallback(callback), OK); /** * @tc.steps: step3. device A check observer @@ -2032,6 +2032,11 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer008, TestSize.Level3) * @tc.steps: step6. Call sync expect sync successful and device A check observer */ EXPECT_EQ(autoObserver->GetCallCount(), 1u); + int reTry = 5; + while (observer1->GetCallCount() != 1u && reTry > 0) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + reTry--; + } EXPECT_EQ(observer1->GetCallCount(), 1u); EXPECT_EQ(autoObserver->GetDataChangeDevice(), DEVICE_B); CheckIdentify(autoObserver); diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp index 173c6bb9c59bd7f68032d9d5e13be945b09ea62b..afd2320a1b4433f82a30c8552bea5db9aabaa2f6 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp @@ -480,12 +480,12 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser003, TestSize.Level3) Value value = {'1'}; Timestamp currentTime; (void)OS::GetCurrentSysTimeInMicrosecond(currentTime); - EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == OK); + EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == E_OK); /** * @tc.steps: step4. device B push sync to A * @tc.expected: step4. success. */ - EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == OK); + EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); EXPECT_TRUE(observer->GetCallCount() == 1); // only A /** diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp index c02cdb5514f512cac57beb21d40d6bf0be8df0a4..323304cc91ebfb2eddbc1eb51bc36eb6bfab6fdd 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp @@ -461,7 +461,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync002, TestSize.Lev LOGD("Begin PUSH"); EXPECT_EQ(g_kvDelegatePtr->Sync(devices, DistributedDB::SYNC_MODE_PUSH_ONLY, callback, query, true), OK); ASSERT_TRUE(result.size() == devices.size()); - EXPECT_TRUE(result[DEVICE_A] == OK); + EXPECT_TRUE(result[DEVICE_B] == OK); }); /** * @tc.steps: step3. B pull to A when A is in push task @@ -851,11 +851,11 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, EncryptedAlgoUpgrade001, Test std::string hashDir = DBCommon::TransferHashString(identifier); std::string hexHashDir = DBCommon::TransferStringToHex(hashDir); std::string dbPath = g_testDir + "/" + hexHashDir + "/single_ver"; - ASSERT_TRUE(DBCommon::CreateDirectory(g_testDir + "/" + hexHashDir) == OK); - ASSERT_TRUE(DBCommon::CreateDirectory(dbPath) == OK); + ASSERT_TRUE(DBCommon::CreateDirectory(g_testDir + "/" + hexHashDir) == E_OK); + ASSERT_TRUE(DBCommon::CreateDirectory(dbPath) == E_OK); std::vector dbDir {DBConstant::MAINDB_DIR, DBConstant::METADB_DIR, DBConstant::CACHEDB_DIR}; for (const auto &item : dbDir) { - ASSERT_TRUE(DBCommon::CreateDirectory(dbPath + "/" + item) == OK); + ASSERT_TRUE(DBCommon::CreateDirectory(dbPath + "/" + item) == E_OK); } uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; sqlite3 *db; @@ -1377,6 +1377,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync001, TestSize.Leve (void)OS::GetCurrentSysTimeInMicrosecond(currentTime); EXPECT_EQ(g_deviceB->PutData(key2, value, currentTime, 0), E_OK); EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, true), E_OK); + std::this_thread::sleep_for(std::chrono::seconds(1)); Value actualValue; EXPECT_EQ(g_kvDelegatePtr->Get(key1, actualValue), OK); @@ -1403,6 +1404,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync001, TestSize.Leve (void)OS::GetCurrentSysTimeInMicrosecond(currentTime); EXPECT_EQ(g_deviceB->PutData(key1, value, currentTime, 0), E_OK); EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, true), E_OK); + std::this_thread::sleep_for(std::chrono::seconds(1)); /** * @tc.steps: step4. check data in device A * * @tc.expected: step4. check ok diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp index c23af4efa979142ff0bdda891100fbf098d12f83..c1d575e67a4c1579a047b30b07f080353380933a 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subscribe_sync_test.cpp @@ -202,6 +202,7 @@ void DistributedDBSingleVerP2PSubscribeSyncTest::WaitUntilNotify(KvVirtualDevice LOGI("End wait notify"); } virtualDevice.SetPushNotifier(nullptr); + std::this_thread::sleep_for(std::chrono::seconds(1)); } void InitSubSchemaDb() diff --git a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp index a33256decaa7a0f4d09dce3f4b17a048589a05c0..f2f2cfc6acd151cd0dea8c5e4da2177635341ec8 100644 --- a/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp +++ b/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp @@ -686,7 +686,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess003, TestSize.Level1 /** * @tc.expected: step3. onProcess should be called, DeviceB have all bigData */ - for (const auto &entry : entries) { + for (const auto &entry : std::vector(entries.begin(), entries.begin() + 5)) { VirtualDataItem item; EXPECT_EQ(g_deviceB->GetData(entry.key, item), E_OK); EXPECT_EQ(item.value, entry.value); @@ -808,6 +808,130 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, BigDataSync002, TestSize.Level1 } } +void DistributedDBSingleVerP2PSyncCheckTest::CancelTestInit(DeviceSyncOption &option, std::vector &entries, + const uint32_t mtuSize) +{ + option.devices.push_back(g_deviceB->GetDeviceId()); + option.devices.push_back(g_deviceC->GetDeviceId()); + option.mode = SYNC_MODE_PULL_ONLY; + option.isQuery = false; + option.isWait = false; + + std::vector keys; + const uint32_t entriesSize = 14000u; + DistributedDBUnitTest::GenerateRecords(entriesSize, entries, keys, KEY_LEN, mtuSize); + for (uint32_t i = 0; i < entries.size(); i++) { + if (i % option.devices.size() == 0) { + g_deviceB->PutData(entries[i].key, entries[i].value, 0, 0); + } else { + g_deviceC->PutData(entries[i].key, entries[i].value, 0, 0); + } + } + + g_communicatorAggregator->SetDeviceMtuSize("real_device", mtuSize); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_C, mtuSize); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_B, mtuSize); +} + +void DistributedDBSingleVerP2PSyncCheckTest::CancelTestEnd(std::vector &entries, const uint32_t mtuSize) +{ + size_t syncSuccCount = 0; + for (uint32_t i = 0; i < entries.size(); i++) { + Value value; + if (g_kvDelegatePtr->Get(entries[i].key, value) == OK) { + syncSuccCount++; + EXPECT_EQ(value, entries[i].value); + } + } + EXPECT_GT(syncSuccCount, static_cast(0)); + EXPECT_LT(syncSuccCount, entries.size()); + uint32_t mtu = 5u; + g_communicatorAggregator->SetDeviceMtuSize("real_device", mtu * mtuSize * mtuSize); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_C, mtu * mtuSize * mtuSize); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_B, mtu * mtuSize * mtuSize); + g_communicatorAggregator->RegBeforeDispatch(nullptr); +} + +/** + * @tc.name: CancelSyncProcess001 + * @tc.desc: cancel data sync process pull mode. + * @tc.type: FUNC + * @tc.require: AR.SR.IR-20075207.007.001 + * @tc.author: lijun + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcessCancel001, TestSize.Level1) +{ + DeviceSyncOption option; + std::vector entries; + const uint32_t mtuSize = 1024u; + /** + * @tc.steps: step1. deviceB deviceC put data + */ + CancelTestInit(option, entries, mtuSize); + uint32_t syncId; + std::mutex tempMutex; + bool isFirst = true; + g_communicatorAggregator->RegBeforeDispatch([&](const std::string &dstTarget, const Message *msg) { + if (dstTarget == "real_device" && msg->GetMessageType() == TYPE_REQUEST && + msg->GetMessageId() == DATA_SYNC_MESSAGE) { + tempMutex.lock(); + if (isFirst == true) { + isFirst = false; + /** + * @tc.steps: step3. cancel sync + * @tc.expected: step3. should return OK. + */ + ASSERT_TRUE(g_kvDelegatePtr->CancelSync(syncId) == OK); + tempMutex.unlock(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + return; + } + tempMutex.unlock(); + } + }); + + std::mutex cancelMtx; + std::condition_variable cancelCv; + bool cancalFinished = false; + + DeviceSyncProcessCallback onProcess = [&](const std::map &processMap) { + bool isAllCancel = true; + for (auto &process: processMap) { + syncId = process.second.syncId; + if (process.second.errCode != COMM_FAILURE) { + isAllCancel = false; + } + } + if (isAllCancel) { + std::unique_lock lock(cancelMtx); + cancalFinished = true; + cancelCv.notify_all(); + } + }; + /** + * @tc.steps: step2. deviceA call pull sync + * @tc.expected: step2. sync should return OK. + */ + ASSERT_TRUE(g_kvDelegatePtr->Sync(option, onProcess) == OK); + + // Wait onProcess complete. + { + std::unique_lock lock2(cancelMtx); + cancelCv.wait(lock2, [&cancalFinished]() {return cancalFinished;}); + } + // Wait until all the packets arrive. + std::this_thread::sleep_for(std::chrono::seconds(2)); + + /** + * @tc.steps: step4. Cancel abnormal syncId. + * @tc.expected: step4. return NOT_FOUND. + */ + ASSERT_TRUE(g_kvDelegatePtr->CancelSync(syncId) == NOT_FOUND); + ASSERT_TRUE(g_kvDelegatePtr->CancelSync(0) == NOT_FOUND); + ASSERT_TRUE(g_kvDelegatePtr->CancelSync(4294967295) == NOT_FOUND); // uint32_t max value 4294967295 + CancelTestEnd(entries, mtuSize); +} + /** * @tc.name: BigDataSync003 * @tc.desc: big data sync pushAndPull mode. @@ -1132,7 +1256,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, AckSessionCheck001, TestSize.Le * @tc.steps: step1. deviceB sync to deviceA just for timeSync and abilitySync * @tc.expected: step1. should return OK. */ - ASSERT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == OK); + ASSERT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK); /** * @tc.steps: step2. deviceA StartTransaction for prevent other sync action deviceB sync will fail @@ -1149,7 +1273,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, AckSessionCheck001, TestSize.Le Timestamp currentTime; (void)OS::GetCurrentSysTimeInMicrosecond(currentTime); EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == E_OK); - EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == OK); + EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK); Value outValue; EXPECT_TRUE(g_kvDelegatePtr->Get(key, outValue) == NOT_FOUND); @@ -1159,9 +1283,9 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, AckSessionCheck001, TestSize.Le * @tc.expected: step3. should return OK. */ EXPECT_TRUE(g_kvDelegatePtr->Commit() == OK); - EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == OK); + EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK); - EXPECT_TRUE(g_kvDelegatePtr->Get(key, outValue) == E_OK); + EXPECT_TRUE(g_kvDelegatePtr->Get(key, outValue) == OK); EXPECT_EQ(outValue, value); }