193a4c0abSBrandon Kim // Copyright 2024 Google LLC
293a4c0abSBrandon Kim //
393a4c0abSBrandon Kim // Licensed under the Apache License, Version 2.0 (the "License");
493a4c0abSBrandon Kim // you may not use this file except in compliance with the License.
593a4c0abSBrandon Kim // You may obtain a copy of the License at
693a4c0abSBrandon Kim //
793a4c0abSBrandon Kim // http://www.apache.org/licenses/LICENSE-2.0
893a4c0abSBrandon Kim //
993a4c0abSBrandon Kim // Unless required by applicable law or agreed to in writing, software
1093a4c0abSBrandon Kim // distributed under the License is distributed on an "AS IS" BASIS,
1193a4c0abSBrandon Kim // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1293a4c0abSBrandon Kim // See the License for the specific language governing permissions and
1393a4c0abSBrandon Kim // limitations under the License.
1493a4c0abSBrandon Kim
1593a4c0abSBrandon Kim #include "bios_setting.hpp"
1693a4c0abSBrandon Kim #include "commands.hpp"
1793a4c0abSBrandon Kim #include "helper.hpp"
1893a4c0abSBrandon Kim
1993a4c0abSBrandon Kim #include <stdplus/gtest/tmp.hpp>
2093a4c0abSBrandon Kim
2193a4c0abSBrandon Kim #include <fstream>
2293a4c0abSBrandon Kim #include <ios>
2393a4c0abSBrandon Kim #include <iostream>
2493a4c0abSBrandon Kim #include <string>
2593a4c0abSBrandon Kim #include <vector>
2693a4c0abSBrandon Kim
2793a4c0abSBrandon Kim #include <gtest/gtest.h>
2893a4c0abSBrandon Kim
2993a4c0abSBrandon Kim namespace google
3093a4c0abSBrandon Kim {
3193a4c0abSBrandon Kim namespace ipmi
3293a4c0abSBrandon Kim {
3393a4c0abSBrandon Kim
3493a4c0abSBrandon Kim using testing::_;
3593a4c0abSBrandon Kim using ::testing::ElementsAre;
3693a4c0abSBrandon Kim
3793a4c0abSBrandon Kim class BiosSettingTest : public stdplus::gtest::TestWithTmp
3893a4c0abSBrandon Kim {
3993a4c0abSBrandon Kim public:
4093a4c0abSBrandon Kim std::string filename = std::format("{}/oem_bios_setting", CaseTmpDir());
4193a4c0abSBrandon Kim
writeTmpFile(std::vector<uint8_t> payload)4293a4c0abSBrandon Kim void writeTmpFile(std::vector<uint8_t> payload)
4393a4c0abSBrandon Kim {
4493a4c0abSBrandon Kim std::ofstream ofs;
4593a4c0abSBrandon Kim ofs.open(filename, std::ios::trunc | std::ios::binary);
4693a4c0abSBrandon Kim ofs.write(reinterpret_cast<char*>(payload.data()), payload.size());
4793a4c0abSBrandon Kim ofs.close();
4893a4c0abSBrandon Kim }
4993a4c0abSBrandon Kim };
5093a4c0abSBrandon Kim
TEST_F(BiosSettingTest,NoOrEmptyFileRead)5193a4c0abSBrandon Kim TEST_F(BiosSettingTest, NoOrEmptyFileRead)
5293a4c0abSBrandon Kim {
5393a4c0abSBrandon Kim std::vector<uint8_t> request = {};
5493a4c0abSBrandon Kim
5593a4c0abSBrandon Kim HandlerMock hMock;
5693a4c0abSBrandon Kim EXPECT_EQ(::ipmi::responseRetBytesUnavailable(),
5793a4c0abSBrandon Kim readBiosSetting(request, &hMock));
5893a4c0abSBrandon Kim
5993a4c0abSBrandon Kim // Create an empty file
6093a4c0abSBrandon Kim writeTmpFile({});
6193a4c0abSBrandon Kim EXPECT_EQ(::ipmi::responseRetBytesUnavailable(),
6293a4c0abSBrandon Kim readBiosSetting(request, &hMock, filename));
6393a4c0abSBrandon Kim std::remove(filename.c_str());
6493a4c0abSBrandon Kim }
6593a4c0abSBrandon Kim
TEST_F(BiosSettingTest,SuccessfulRead)6693a4c0abSBrandon Kim TEST_F(BiosSettingTest, SuccessfulRead)
6793a4c0abSBrandon Kim {
6893a4c0abSBrandon Kim std::vector<uint8_t> request = {};
6993a4c0abSBrandon Kim // Ensure 0x0A which is a new line character '\n', is read properly
7093a4c0abSBrandon Kim std::vector<uint8_t> payload = {0x0A, 0xDE, 0xAD, 0xBE, 0xEF, 0x0A};
7193a4c0abSBrandon Kim std::vector<uint8_t> expectedReply = {6, 0x0A, 0xDE, 0xAD,
7293a4c0abSBrandon Kim 0xBE, 0xEF, 0x0A};
7393a4c0abSBrandon Kim
7493a4c0abSBrandon Kim writeTmpFile(payload);
7593a4c0abSBrandon Kim
7693a4c0abSBrandon Kim HandlerMock hMock;
7793a4c0abSBrandon Kim auto reply = readBiosSetting(request, &hMock, filename);
7893a4c0abSBrandon Kim auto result = ValidateReply(reply);
7993a4c0abSBrandon Kim auto& data = result.second;
8093a4c0abSBrandon Kim
8193a4c0abSBrandon Kim EXPECT_EQ(SysOEMCommands::SysReadBiosSetting, result.first);
8293a4c0abSBrandon Kim EXPECT_EQ(expectedReply.size() - 1, data.front());
8393a4c0abSBrandon Kim EXPECT_EQ(expectedReply, data);
8493a4c0abSBrandon Kim std::remove(filename.c_str());
8593a4c0abSBrandon Kim }
8693a4c0abSBrandon Kim
TEST_F(BiosSettingTest,InvalidRequestWrite)87*e8929699SBrandon Kim TEST_F(BiosSettingTest, InvalidRequestWrite)
88*e8929699SBrandon Kim {
89*e8929699SBrandon Kim // Empty request
90*e8929699SBrandon Kim std::vector<uint8_t> request = {};
91*e8929699SBrandon Kim
92*e8929699SBrandon Kim HandlerMock hMock;
93*e8929699SBrandon Kim EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
94*e8929699SBrandon Kim writeBiosSetting(request, &hMock));
95*e8929699SBrandon Kim
96*e8929699SBrandon Kim // Request with payload size 1 but no payload
97*e8929699SBrandon Kim request = {0x01};
98*e8929699SBrandon Kim EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
99*e8929699SBrandon Kim writeBiosSetting(request, &hMock));
100*e8929699SBrandon Kim
101*e8929699SBrandon Kim // Request with payload size 1 but actual payload size of 2 bytes
102*e8929699SBrandon Kim request = {0x01, 0x02, 0x03};
103*e8929699SBrandon Kim EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
104*e8929699SBrandon Kim writeBiosSetting(request, &hMock));
105*e8929699SBrandon Kim
106*e8929699SBrandon Kim // Request with payload size 2 but actual payload of 1 byte
107*e8929699SBrandon Kim request = {0x02, 0x02};
108*e8929699SBrandon Kim EXPECT_EQ(::ipmi::responseReqDataLenInvalid(),
109*e8929699SBrandon Kim writeBiosSetting(request, &hMock));
110*e8929699SBrandon Kim }
111*e8929699SBrandon Kim
TEST_F(BiosSettingTest,SuccessfulWrite)112*e8929699SBrandon Kim TEST_F(BiosSettingTest, SuccessfulWrite)
113*e8929699SBrandon Kim {
114*e8929699SBrandon Kim std::vector<uint8_t> request = {0x02, 0xDE, 0xAD};
115*e8929699SBrandon Kim
116*e8929699SBrandon Kim // Write a dummy file to get around permission issues with CI
117*e8929699SBrandon Kim // (Not needed in local CI)
118*e8929699SBrandon Kim writeTmpFile({});
119*e8929699SBrandon Kim HandlerMock hMock;
120*e8929699SBrandon Kim auto reply = writeBiosSetting(request, &hMock, filename);
121*e8929699SBrandon Kim auto result = ValidateReply(reply);
122*e8929699SBrandon Kim auto& data = result.second;
123*e8929699SBrandon Kim
124*e8929699SBrandon Kim EXPECT_EQ(SysOEMCommands::SysWriteBiosSetting, result.first);
125*e8929699SBrandon Kim EXPECT_EQ(std::vector<uint8_t>{2}, data);
126*e8929699SBrandon Kim
127*e8929699SBrandon Kim // Validate the payload is correct
128*e8929699SBrandon Kim reply = readBiosSetting(request, &hMock, filename);
129*e8929699SBrandon Kim result = ValidateReply(reply);
130*e8929699SBrandon Kim data = result.second;
131*e8929699SBrandon Kim
132*e8929699SBrandon Kim EXPECT_EQ(SysOEMCommands::SysReadBiosSetting, result.first);
133*e8929699SBrandon Kim EXPECT_EQ(request.size() - 1, data.front());
134*e8929699SBrandon Kim EXPECT_EQ(request, data);
135*e8929699SBrandon Kim
136*e8929699SBrandon Kim // Verify that we can write a shorter string and it'll replace the original
137*e8929699SBrandon Kim // content of the file
138*e8929699SBrandon Kim request = {0x01, 0x0A};
139*e8929699SBrandon Kim
140*e8929699SBrandon Kim reply = writeBiosSetting(request, &hMock, filename);
141*e8929699SBrandon Kim result = ValidateReply(reply);
142*e8929699SBrandon Kim data = result.second;
143*e8929699SBrandon Kim
144*e8929699SBrandon Kim EXPECT_EQ(SysOEMCommands::SysWriteBiosSetting, result.first);
145*e8929699SBrandon Kim EXPECT_EQ(std::vector<uint8_t>{1}, data);
146*e8929699SBrandon Kim
147*e8929699SBrandon Kim // Validate the payload is correct
148*e8929699SBrandon Kim reply = readBiosSetting(request, &hMock, filename);
149*e8929699SBrandon Kim result = ValidateReply(reply);
150*e8929699SBrandon Kim data = result.second;
151*e8929699SBrandon Kim
152*e8929699SBrandon Kim EXPECT_EQ(SysOEMCommands::SysReadBiosSetting, result.first);
153*e8929699SBrandon Kim EXPECT_EQ(request.size() - 1, data.front());
154*e8929699SBrandon Kim EXPECT_EQ(request, data);
155*e8929699SBrandon Kim // Cleanup the settings file
156*e8929699SBrandon Kim std::remove(filename.c_str());
157*e8929699SBrandon Kim }
158*e8929699SBrandon Kim
15993a4c0abSBrandon Kim } // namespace ipmi
16093a4c0abSBrandon Kim } // namespace google
161