| #include "libpldmresponder/pdr_file.hpp" |
| #include "libpldmresponder/pdr_utils.hpp" |
| |
| #include <libpldm/platform.h> |
| |
| #include <nlohmann/json.hpp> |
| |
| #include <filesystem> |
| #include <fstream> |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| using namespace pldm::responder::pdr_file; |
| using namespace pldm::responder::pdr_utils; |
| using ::testing::_; |
| using ::testing::Return; |
| using Json = nlohmann::json; |
| namespace fs = std::filesystem; |
| |
| class MockRepo : public RepoInterface |
| { |
| public: |
| MockRepo() : RepoInterface(nullptr) {} |
| |
| MOCK_METHOD(pldm_pdr*, getPdr, (), (const, override)); |
| MOCK_METHOD(RecordHandle, addRecord, (const PdrEntry&), (override)); |
| MOCK_METHOD(const pldm_pdr_record*, getFirstRecord, (PdrEntry&), |
| (override)); |
| MOCK_METHOD(const pldm_pdr_record*, getNextRecord, |
| (const pldm_pdr_record*, PdrEntry&), (override)); |
| MOCK_METHOD(uint32_t, getRecordHandle, (const pldm_pdr_record*), |
| (const, override)); |
| MOCK_METHOD(uint32_t, getRecordCount, (), (override)); |
| MOCK_METHOD(bool, empty, (), (override)); |
| MOCK_METHOD(uint32_t, getRepositorySize, (), (override)); |
| MOCK_METHOD(uint32_t, getLargestRecordSize, (), (override)); |
| }; |
| |
| class GenerateFileDescriptorPDRTest : public ::testing::Test |
| { |
| protected: |
| void SetUp() override |
| { |
| // Create a temporary directory for test files. |
| char tmppldm[] = "/tmp/pldm_file_pdr_test.XXXXXX"; |
| dir = fs::path(mkdtemp(tmppldm)); |
| |
| // Create a dummy file for the success case. |
| testFilePath = dir / "test_dir"; |
| fs::create_directory(testFilePath); |
| std::ofstream(testFilePath / "test_file.bin").close(); |
| } |
| |
| void TearDown() override |
| { |
| for (const auto& pair : fileIdentifierToFileInfo) |
| { |
| if (pair.second.fp) |
| { |
| fclose(pair.second.fp); |
| } |
| } |
| fs::remove_all(dir); |
| } |
| |
| fs::path dir; |
| fs::path testFilePath; |
| MockRepo repo; |
| std::map<uint16_t, FileInfo> fileIdentifierToFileInfo; |
| std::map<uint32_t, FileInfo> recordHandleToFileInfo; |
| }; |
| |
| TEST_F(GenerateFileDescriptorPDRTest, SuccessCase) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "placeholder", |
| "Files": [ |
| { |
| "FileIdentifier": 1, |
| "FileName": "test_file.bin", |
| "FileSize": 1234 |
| } |
| ] |
| } |
| ] |
| })"_json; |
| |
| auto modifiedJson = json; |
| modifiedJson["entries"][0]["Path"] = testFilePath.string(); |
| |
| EXPECT_CALL(repo, addRecord(_)).WillOnce(Return(1)); |
| |
| generateFileDescriptorPDR(modifiedJson, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| |
| EXPECT_EQ(fileIdentifierToFileInfo.size(), 1); |
| EXPECT_EQ(recordHandleToFileInfo.size(), 1); |
| EXPECT_TRUE(fileIdentifierToFileInfo.contains(1)); |
| EXPECT_TRUE(recordHandleToFileInfo.contains(1)); |
| |
| const auto& fileInfo = fileIdentifierToFileInfo.at(1); |
| EXPECT_EQ(fileInfo.fileIdentifier, 1); |
| EXPECT_EQ(fileInfo.fileSize, 1234); |
| EXPECT_EQ(fileInfo.recordHandle, 1); |
| EXPECT_EQ(fileInfo.filePath, testFilePath / "test_file.bin"); |
| EXPECT_NE(fileInfo.fp, nullptr); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureMissingEntityType) |
| { |
| const Json json = R"({ "entries": [{ "Path": "p" }]})"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureEntityTypeNotNumber) |
| { |
| const Json json = |
| R"({ "entries": [{ "EntityType": "abc", "Path": "p" }]})"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureInvalidEntityType) |
| { |
| const Json json = |
| R"({ "entries": [{ "EntityType": 8, "Path": "p" }]})"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureMissingPath) |
| { |
| const Json json = R"({ "entries": [{ "EntityType": 9 }]})"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailurePathNotString) |
| { |
| const Json json = |
| R"({ "entries": [{ "EntityType": 9, "Path": 123 }]})"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureMissingFileIdentifier) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "p", |
| "Files": [ { "FileName": "f", "FileSize": 0 } ] |
| } |
| ] |
| })"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureFileIdentifierNotNumber) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "p", |
| "Files": [ { "FileIdentifier": "abc", "FileName": "f", "FileSize": 0 } ] |
| } |
| ] |
| })"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureMissingFileName) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "p", |
| "Files": [ { "FileIdentifier": 1, "FileSize": 0 } ] |
| } |
| ] |
| })"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureFileNameNotString) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "p", |
| "Files": [ { "FileIdentifier": 1, "FileName": 123, "FileSize": 0 } ] |
| } |
| ] |
| })"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureMissingFileSize) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "p", |
| "Files": [ { "FileIdentifier": 1, "FileName": "f" } ] |
| } |
| ] |
| })"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureFileSizeNotNumber) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "p", |
| "Files": [ { "FileIdentifier": 1, "FileName": "f", "FileSize": "abc" } ] |
| } |
| ] |
| })"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureFileNameTooLong) |
| { |
| std::string longName(255, 'a'); |
| Json json = {{"entries", |
| {{{"EntityType", 9}, |
| {"Path", "p"}, |
| {"Files", |
| {{{"FileIdentifier", 1}, |
| {"FileName", longName}, |
| {"FileSize", 0}}}}}}}}; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, FailureCannotOpenFile) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "nonexistent_dir", |
| "Files": [ |
| { |
| "FileIdentifier": 1, |
| "FileName": "nonexistent_file.bin", |
| "FileSize": 0 |
| } |
| ] |
| } |
| ] |
| })"_json; |
| |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, CornerCaseEmptyEntries) |
| { |
| const Json json = R"({ "entries": [] })"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |
| |
| TEST_F(GenerateFileDescriptorPDRTest, CornerCaseEmptyFiles) |
| { |
| const Json json = R"( |
| { |
| "entries": [ |
| { |
| "EntityType": 9, |
| "Path": "p", |
| "Files": [] |
| } |
| ] |
| })"_json; |
| generateFileDescriptorPDR(json, "", {}, fileIdentifierToFileInfo, |
| recordHandleToFileInfo, repo); |
| EXPECT_TRUE(fileIdentifierToFileInfo.empty()); |
| EXPECT_TRUE(recordHandleToFileInfo.empty()); |
| } |