* -------------------------------------------------------------------------
* This file is part of the MindStudio project.
* Copyright (c) 2026 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*/
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <memory>
#include <cstdint>
#include "DataBaseManager.h"
#include "ParserStatusManager.h"
#include "DbClusterDataBase.h"
#include "ClusterDef.h"
#include "ClusterFileParser.h"
#include "ClusterFileParserInterfaces.h"
using ::testing::_;
using ::testing::Return;
using ::testing::NiceMock;
namespace Dic {
namespace Module {
namespace Timeline {
class MockFileUtil : public IFileUtil {
public:
MOCK_METHOD(bool, IsFolder, (const std::string &path), (override));
MOCK_METHOD(std::string, GetParentPath, (const std::string &filePath), (override));
MOCK_METHOD(std::vector<std::string>, FindFilesWithFilter, (const std::string &path, const std::regex &fileRegex),
(override));
};
class MockParserStatusManager : public IParserStatusManager {
public:
MOCK_METHOD(void, SetClusterParseStatus, (const std::string &uniqueKey, ParserStatus status), (override));
MOCK_METHOD(ParserStatus, GetClusterParseStatus, (const std::string &uniqueKey), (override));
};
class MockDataBaseManager : public IDataBaseManager {
public:
MOCK_METHOD(void, CreateClusterConnectionPool,
(const std::string &projectPath, const std::string &dbPath, DataType type), (override));
MOCK_METHOD(std::shared_ptr<IDbClusterDataBase>, GetClusterDatabase, (const std::string &uniqueKey), (override));
};
class MockDbClusterDataBase : public IDbClusterDataBase {
public:
MOCK_METHOD(bool, IsDatabaseVersionChange, (), (const, override));
MOCK_METHOD(bool, SetDataBaseVersion, (const std::string &targetVersion), (override));
MOCK_METHOD(bool, QueryExtremumTimestamp, (uint64_t & min, uint64_t &max), (override));
MOCK_METHOD(bool, CreateTable, (), (override));
MOCK_METHOD(bool, DropTable, (), (override));
MOCK_METHOD(bool, HasFinishedParseLastTime, (), (override));
MOCK_METHOD(bool, UpdatesClusterParseStatus, (const std::string &status), (override));
MOCK_METHOD(void, InsertClusterBaseInfo, (ClusterBaseInfo & info), (override));
};
class MockTraceTime : public ITraceTime {
public:
MOCK_METHOD(void, UpdateTime, (uint64_t min, uint64_t max), (override));
};
class TestableClusterFileParser {
public:
TestableClusterFileParser(const std::string &filePath, const std::string &uniqueKey,
std::shared_ptr<IFileUtil> fileUtil, std::shared_ptr<IParserStatusManager> statusManager,
std::shared_ptr<IDataBaseManager> dbManager, std::shared_ptr<ITraceTime> traceTime)
: filePath_(filePath), uniqueKey_(uniqueKey), fileUtil_(fileUtil), statusManager_(statusManager),
dbManager_(dbManager), traceTime_(traceTime) {}
bool ParserClusterOfDb() {
statusManager_->SetClusterParseStatus(uniqueKey_, ParserStatus::INIT);
std::string tempPath(filePath_);
if (!fileUtil_->IsFolder(filePath_)) {
tempPath = fileUtil_->GetParentPath(filePath_);
}
std::string clusterDBReg = "cluster_analysis\\.db$";
std::vector<std::string> clusterPath = fileUtil_->FindFilesWithFilter(tempPath, std::regex(clusterDBReg));
if (clusterPath.empty()) {
statusManager_->SetClusterParseStatus(uniqueKey_, ParserStatus::FINISH);
return false;
}
std::string clusterDbPath = clusterPath[0];
dbManager_->CreateClusterConnectionPool(filePath_, clusterDbPath, DataType::DB);
auto clusterDatabase = dbManager_->GetClusterDatabase(filePath_);
if (clusterDatabase == nullptr) {
statusManager_->SetClusterParseStatus(uniqueKey_, ParserStatus::FINISH);
return false;
}
if (!clusterDatabase->IsDatabaseVersionChange() && clusterDatabase->HasFinishedParseLastTime()) {
statusManager_->SetClusterParseStatus(uniqueKey_, ParserStatus::FINISH);
UpdateTraceTimeOfDb(clusterDatabase);
return true;
}
if (!clusterDatabase->DropTable() || !clusterDatabase->CreateTable() ||
!clusterDatabase->SetDataBaseVersion("") || !clusterDatabase->UpdatesClusterParseStatus("NOT_FINISH")) {
statusManager_->SetClusterParseStatus(uniqueKey_, ParserStatus::FINISH);
return false;
}
ClusterBaseInfo baseInfo;
clusterDatabase->InsertClusterBaseInfo(baseInfo);
clusterDatabase->UpdatesClusterParseStatus("FINISH");
statusManager_->SetClusterParseStatus(uniqueKey_, ParserStatus::FINISH);
UpdateTraceTimeOfDb(clusterDatabase);
return true;
}
private:
void UpdateTraceTimeOfDb(std::shared_ptr<IDbClusterDataBase> clusterDatabase) {
uint64_t min = UINT64_MAX;
uint64_t max = 0;
if (clusterDatabase->QueryExtremumTimestamp(min, max)) {
if (min != UINT64_MAX && max != 0) {
traceTime_->UpdateTime(min, max);
}
}
}
std::string filePath_;
std::string uniqueKey_;
std::shared_ptr<IFileUtil> fileUtil_;
std::shared_ptr<IParserStatusManager> statusManager_;
std::shared_ptr<IDataBaseManager> dbManager_;
std::shared_ptr<ITraceTime> traceTime_;
};
class UpdateTraceTimeOfDbTest : public ::testing::Test {
protected:
void SetUp() override {
mockFileUtil_ = std::make_shared<NiceMock<MockFileUtil>>();
mockStatusManager_ = std::make_shared<NiceMock<MockParserStatusManager>>();
mockDbManager_ = std::make_shared<NiceMock<MockDataBaseManager>>();
mockTraceTime_ = std::make_shared<NiceMock<MockTraceTime>>();
mockDb_ = std::make_shared<NiceMock<MockDbClusterDataBase>>();
}
void TearDown() override {
mockFileUtil_.reset();
mockStatusManager_.reset();
mockDbManager_.reset();
mockTraceTime_.reset();
mockDb_.reset();
}
std::shared_ptr<MockFileUtil> mockFileUtil_;
std::shared_ptr<MockParserStatusManager> mockStatusManager_;
std::shared_ptr<MockDataBaseManager> mockDbManager_;
std::shared_ptr<MockTraceTime> mockTraceTime_;
std::shared_ptr<MockDbClusterDataBase> mockDb_;
};
TEST_F(UpdateTraceTimeOfDbTest, ParserClusterOfDb_CallsUpdateTraceTime_VersionNotChanged) {
std::string filePath = "/test/path/to/file.db";
std::string uniqueKey = "test_unique_key";
std::string clusterDbPath = "/test/path/to/cluster_analysis.db";
std::vector<std::string> clusterPaths = {clusterDbPath};
TestableClusterFileParser parser(
filePath, uniqueKey, mockFileUtil_, mockStatusManager_, mockDbManager_, mockTraceTime_);
EXPECT_CALL(*mockStatusManager_, SetClusterParseStatus(uniqueKey, ParserStatus::INIT));
EXPECT_CALL(*mockFileUtil_, IsFolder(filePath)).WillOnce(Return(false));
EXPECT_CALL(*mockFileUtil_, GetParentPath(filePath)).WillOnce(Return("/test/path/to"));
EXPECT_CALL(*mockFileUtil_, FindFilesWithFilter("/test/path/to", _)).WillOnce(Return(clusterPaths));
EXPECT_CALL(*mockDbManager_, CreateClusterConnectionPool(filePath, clusterDbPath, DataType::DB));
EXPECT_CALL(*mockDbManager_, GetClusterDatabase(filePath)).WillOnce(Return(mockDb_));
EXPECT_CALL(*mockDb_, IsDatabaseVersionChange()).WillOnce(Return(false));
EXPECT_CALL(*mockDb_, HasFinishedParseLastTime()).WillOnce(Return(true));
EXPECT_CALL(*mockDb_, QueryExtremumTimestamp(_, _)).WillOnce([](uint64_t &min, uint64_t &max) -> bool {
min = 1000;
max = 5000;
return true;
});
EXPECT_CALL(*mockTraceTime_, UpdateTime(1000, 5000));
EXPECT_CALL(*mockStatusManager_, SetClusterParseStatus(uniqueKey, ParserStatus::FINISH));
bool result = parser.ParserClusterOfDb();
EXPECT_TRUE(result);
}
TEST_F(UpdateTraceTimeOfDbTest, ParserClusterOfDb_CallsUpdateTraceTime_VersionChanged) {
std::string filePath = "/test/path/to/folder";
std::string uniqueKey = "test_unique_key";
std::string clusterDbPath = "/test/path/to/folder/cluster_analysis.db";
std::vector<std::string> clusterPaths = {clusterDbPath};
TestableClusterFileParser parser(
filePath, uniqueKey, mockFileUtil_, mockStatusManager_, mockDbManager_, mockTraceTime_);
EXPECT_CALL(*mockStatusManager_, SetClusterParseStatus(uniqueKey, ParserStatus::INIT));
EXPECT_CALL(*mockFileUtil_, IsFolder(filePath)).WillOnce(Return(true));
EXPECT_CALL(*mockFileUtil_, FindFilesWithFilter(filePath, _)).WillOnce(Return(clusterPaths));
EXPECT_CALL(*mockDbManager_, CreateClusterConnectionPool(filePath, clusterDbPath, DataType::DB));
EXPECT_CALL(*mockDbManager_, GetClusterDatabase(filePath)).WillOnce(Return(mockDb_));
EXPECT_CALL(*mockDb_, IsDatabaseVersionChange()).WillOnce(Return(true));
EXPECT_CALL(*mockDb_, DropTable()).WillOnce(Return(true));
EXPECT_CALL(*mockDb_, CreateTable()).WillOnce(Return(true));
EXPECT_CALL(*mockDb_, SetDataBaseVersion(_)).WillOnce(Return(true));
EXPECT_CALL(*mockDb_, UpdatesClusterParseStatus(_)).WillRepeatedly(Return(true));
EXPECT_CALL(*mockDb_, InsertClusterBaseInfo(_));
EXPECT_CALL(*mockDb_, QueryExtremumTimestamp(_, _)).WillOnce([](uint64_t &min, uint64_t &max) -> bool {
min = 2000;
max = 6000;
return true;
});
EXPECT_CALL(*mockTraceTime_, UpdateTime(2000, 6000));
EXPECT_CALL(*mockStatusManager_, SetClusterParseStatus(uniqueKey, ParserStatus::FINISH));
bool result = parser.ParserClusterOfDb();
EXPECT_TRUE(result);
}
TEST_F(UpdateTraceTimeOfDbTest, ParserClusterOfDb_NoCallUpdateTraceTime_InvalidTimestamp) {
std::string filePath = "/test/path/to/folder";
std::string uniqueKey = "test_unique_key";
std::string clusterDbPath = "/test/path/to/folder/cluster_analysis.db";
std::vector<std::string> clusterPaths = {clusterDbPath};
TestableClusterFileParser parser(
filePath, uniqueKey, mockFileUtil_, mockStatusManager_, mockDbManager_, mockTraceTime_);
EXPECT_CALL(*mockStatusManager_, SetClusterParseStatus(uniqueKey, ParserStatus::INIT));
EXPECT_CALL(*mockFileUtil_, IsFolder(filePath)).WillOnce(Return(true));
EXPECT_CALL(*mockFileUtil_, FindFilesWithFilter(filePath, _)).WillOnce(Return(clusterPaths));
EXPECT_CALL(*mockDbManager_, CreateClusterConnectionPool(filePath, clusterDbPath, DataType::DB));
EXPECT_CALL(*mockDbManager_, GetClusterDatabase(filePath)).WillOnce(Return(mockDb_));
EXPECT_CALL(*mockDb_, IsDatabaseVersionChange()).WillOnce(Return(false));
EXPECT_CALL(*mockDb_, HasFinishedParseLastTime()).WillOnce(Return(true));
EXPECT_CALL(*mockDb_, QueryExtremumTimestamp(_, _)).WillOnce([](uint64_t &min, uint64_t &max) -> bool {
min = UINT64_MAX;
max = 0;
return true;
});
EXPECT_CALL(*mockTraceTime_, UpdateTime(_, _)).Times(0);
EXPECT_CALL(*mockStatusManager_, SetClusterParseStatus(uniqueKey, ParserStatus::FINISH));
bool result = parser.ParserClusterOfDb();
EXPECT_TRUE(result);
}
}
}
}