blob: 692cabd44c216bebe4d586fe8882d8c8ae57c0e5 [file] [log] [blame]
Ratan Guptaed123a32017-06-15 09:07:31 +05301#include "config_parser.hpp"
Ratan Guptaed123a32017-06-15 09:07:31 +05302
Gunnar Mills57d9c502018-09-14 14:42:34 -05003#include <phosphor-logging/elog-errors.hpp>
William A. Kennington IIId9e2d722022-08-18 15:21:08 -07004#include <stdplus/fd/atomic.hpp>
5#include <stdplus/fd/fmt.hpp>
William A. Kennington III84bfe672022-07-13 14:15:30 -07006#include <stdplus/gtest/tmp.hpp>
William A. Kennington IIIb7401962023-07-21 16:36:11 -07007#include <stdplus/print.hpp>
Patrick Venturea9733402019-01-07 13:27:01 -08008#include <xyz/openbmc_project/Common/error.hpp>
Gunnar Mills57d9c502018-09-14 14:42:34 -05009
Patrick Williams89d734b2023-05-10 07:50:25 -050010#include <exception>
William A. Kennington IIIcafc1512023-07-25 02:22:32 -070011#include <format>
Patrick Williams89d734b2023-05-10 07:50:25 -050012#include <fstream>
13#include <stdexcept>
14
William A. Kennington III25511a12022-08-04 16:32:28 -070015#include <gmock/gmock.h>
Gunnar Mills57d9c502018-09-14 14:42:34 -050016#include <gtest/gtest.h>
Ratan Guptaed123a32017-06-15 09:07:31 +053017
18namespace phosphor
19{
20namespace network
21{
William A. Kennington III25511a12022-08-04 16:32:28 -070022namespace config
23{
24
25using testing::ElementsAre;
William A. Kennington III86642522023-07-24 17:55:55 -070026using std::literals::string_view_literals::operator""sv;
Ratan Guptaed123a32017-06-15 09:07:31 +053027
William A. Kennington III150753f2022-08-05 15:20:54 -070028TEST(TestConvert, iCaseEq)
29{
30 EXPECT_TRUE(icaseeq("VaL", "val"));
31 EXPECT_TRUE(icaseeq("[ab1", "[ab1"));
32}
33
34TEST(TestConvert, ParseBool)
35{
36 EXPECT_TRUE(parseBool("tRue").value());
37 EXPECT_FALSE(parseBool("tru").has_value());
38 EXPECT_TRUE(parseBool("t").value());
39 EXPECT_TRUE(parseBool("Yes").value());
40 EXPECT_FALSE(parseBool("ye").has_value());
41 EXPECT_TRUE(parseBool("y").value());
42 EXPECT_TRUE(parseBool("oN").value());
43
44 EXPECT_FALSE(parseBool("fAlse").value());
45 EXPECT_FALSE(parseBool("fal").has_value());
46 EXPECT_FALSE(parseBool("f").value());
47 EXPECT_FALSE(parseBool("No").value());
48 EXPECT_FALSE(parseBool("n").value());
49 EXPECT_FALSE(parseBool("oFf").value());
50}
51
William A. Kennington III0dd09372022-08-18 14:57:07 -070052TEST(TestTypeChecking, Section)
53{
54 Section("");
55 Section("fds#1!'\"");
56 EXPECT_THROW(Section("fds]sf"), std::invalid_argument);
57 EXPECT_THROW(Section("g\ng"), std::invalid_argument);
58}
59
60TEST(TestTypeChecking, Value)
61{
62 Value("");
63 Value("=fds1!'\"#=");
64 Value("fds]sf'' #");
65 EXPECT_THROW(Value("g\ng"), std::invalid_argument);
66}
67
68TEST(TestTypeChecking, Key)
69{
70 Key("");
71 Key("fds1!'\"#");
72 Key("fds]sf'' #");
73 EXPECT_THROW(Key("fds]sf'='"), std::invalid_argument);
74 EXPECT_THROW(Key("g\ng"), std::invalid_argument);
75}
76
William A. Kennington III84bfe672022-07-13 14:15:30 -070077class TestConfigParser : public stdplus::gtest::TestWithTmp
Ratan Guptaed123a32017-06-15 09:07:31 +053078{
Gunnar Mills57d9c502018-09-14 14:42:34 -050079 public:
William A. Kennington IIIcafc1512023-07-25 02:22:32 -070080 std::string filename = std::format("{}/eth0.network", CaseTmpDir());
William A. Kennington III25511a12022-08-04 16:32:28 -070081 Parser parser;
82
83 void WriteSampleFile()
Gunnar Mills57d9c502018-09-14 14:42:34 -050084 {
William A. Kennington III84bfe672022-07-13 14:15:30 -070085 std::ofstream filestream(filename);
William A. Kennington III25511a12022-08-04 16:32:28 -070086 filestream << "\n\n\n\nBad=key\n[Match]\n # K=v \nName =eth0\n"
87 << "[Network\nDHCP=true\n[DHCP]\nClientIdentifier= mac\n"
88 << "[Network] a\nDHCP=false #hi\n\n\nDHCP = yes \n"
89 << " [ SEC ] \n'DHCP#'=\"#hi\"\nDHCP#=ho\n[Network]\n"
90 << "Key=val\nAddress=::/0\n[]\n=\nKey";
Gunnar Mills57d9c502018-09-14 14:42:34 -050091 filestream.close();
Gunnar Mills57d9c502018-09-14 14:42:34 -050092 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -070093
94 void ValidateSectionMap()
95 {
96 EXPECT_THAT(
William A. Kennington III34bb3e22022-08-18 15:17:22 -070097 parser.map,
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -070098 testing::ContainerEq(SectionMap(SectionMapInt{
99 {"Match", {{{"Name", {"eth0"}}}}},
100 {"Network",
101 {
102 {{"DHCP", {"true"}}},
103 {{"DHCP", {"false #hi", "yes"}}},
104 {{"Key", {"val"}}, {"Address", {"::/0"}}},
105 }},
106 {"DHCP", {{{"ClientIdentifier", {"mac"}}}}},
107 {" SEC ", {{{"'DHCP#'", {"\"#hi\""}}, {"DHCP#", {"ho"}}}}},
108 {"", {{{"", {""}}}}},
109 })));
110 }
Ratan Guptaed123a32017-06-15 09:07:31 +0530111};
112
William A. Kennington IIIbc52d932022-08-18 16:34:02 -0700113TEST_F(TestConfigParser, EmptyObject)
114{
William A. Kennington III301e8ad2022-11-15 15:45:32 -0800115 EXPECT_FALSE(parser.getFileExists());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700116 EXPECT_TRUE(parser.getFilename().empty());
William A. Kennington IIIbc52d932022-08-18 16:34:02 -0700117 EXPECT_EQ(0, parser.getWarnings().size());
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700118 EXPECT_EQ(SectionMap(), parser.map);
William A. Kennington IIIbc52d932022-08-18 16:34:02 -0700119}
120
121TEST_F(TestConfigParser, ReadDirectory)
122{
123 parser.setFile("/");
William A. Kennington III301e8ad2022-11-15 15:45:32 -0800124 EXPECT_FALSE(parser.getFileExists());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700125 EXPECT_EQ("/", parser.getFilename());
William A. Kennington IIIbc52d932022-08-18 16:34:02 -0700126 EXPECT_EQ(1, parser.getWarnings().size());
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700127 EXPECT_EQ(SectionMap(), parser.map);
William A. Kennington IIIbc52d932022-08-18 16:34:02 -0700128}
129
130TEST_F(TestConfigParser, ReadConfigDataMissingFile)
131{
132 parser.setFile("/no-such-path");
William A. Kennington III301e8ad2022-11-15 15:45:32 -0800133 EXPECT_FALSE(parser.getFileExists());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700134 EXPECT_EQ("/no-such-path", parser.getFilename());
William A. Kennington IIIbc52d932022-08-18 16:34:02 -0700135 EXPECT_EQ(1, parser.getWarnings().size());
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700136 EXPECT_EQ(SectionMap(), parser.map);
William A. Kennington IIIbc52d932022-08-18 16:34:02 -0700137}
138
Ratan Guptaed123a32017-06-15 09:07:31 +0530139TEST_F(TestConfigParser, ReadConfigDataFromFile)
140{
William A. Kennington III25511a12022-08-04 16:32:28 -0700141 WriteSampleFile();
142 parser.setFile(filename);
William A. Kennington III301e8ad2022-11-15 15:45:32 -0800143 EXPECT_TRUE(parser.getFileExists());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700144 EXPECT_EQ(filename, parser.getFilename());
William A. Kennington IIIbc52d932022-08-18 16:34:02 -0700145 EXPECT_EQ(4, parser.getWarnings().size());
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700146 ValidateSectionMap();
Ratan Guptac27170a2017-11-22 15:44:42 +0530147
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700148 const auto& map = parser.map;
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700149
150 EXPECT_EQ("eth0", *map.getLastValueString("Match", "Name"));
151 EXPECT_EQ("yes", *map.getLastValueString("Network", "DHCP"));
152 EXPECT_EQ(nullptr, map.getLastValueString("Match", "BadKey"));
153 EXPECT_EQ(nullptr, map.getLastValueString("BadSec", "Name"));
154 EXPECT_EQ(nullptr, map.getLastValueString("BadSec", "Name"));
155
156 EXPECT_THAT(map.getValueStrings("Match", "Name"), ElementsAre("eth0"));
157 EXPECT_THAT(map.getValueStrings("DHCP", "ClientIdentifier"),
William A. Kennington III25511a12022-08-04 16:32:28 -0700158 ElementsAre("mac"));
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700159 EXPECT_THAT(map.getValueStrings("Network", "DHCP"),
William A. Kennington III61ef4f22022-08-18 16:29:09 -0700160 ElementsAre("true", "false #hi", "yes"));
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700161 EXPECT_THAT(map.getValueStrings(" SEC ", "'DHCP#'"),
162 ElementsAre("\"#hi\""));
163 EXPECT_THAT(map.getValueStrings("Blah", "nil"), ElementsAre());
164 EXPECT_THAT(map.getValueStrings("Network", "nil"), ElementsAre());
Ratan Guptaed123a32017-06-15 09:07:31 +0530165}
166
William A. Kennington III409f1a62022-08-11 15:44:37 -0700167TEST_F(TestConfigParser, WriteConfigFile)
168{
169 WriteSampleFile();
170 parser.setFile(filename);
171 EXPECT_EQ(4, parser.getWarnings().size());
172 ValidateSectionMap();
173
174 parser.writeFile();
175
176 parser.setFile(filename);
177 EXPECT_EQ(0, parser.getWarnings().size());
178 ValidateSectionMap();
179}
180
William A. Kennington IIId9e2d722022-08-18 15:21:08 -0700181TEST_F(TestConfigParser, Perf)
182{
183 GTEST_SKIP();
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700184 stdplus::fd::AtomicWriter file(std::format("{}/tmp.XXXXXX", CaseTmpDir()),
William A. Kennington IIId9e2d722022-08-18 15:21:08 -0700185 0600);
186 stdplus::fd::FormatBuffer out(file);
William A. Kennington III86642522023-07-24 17:55:55 -0700187 std::string obj(500, 'a');
188 std::string kv(500 * 70, 'b');
William A. Kennington IIId9e2d722022-08-18 15:21:08 -0700189 for (size_t i = 0; i < 500; ++i)
190 {
William A. Kennington III86642522023-07-24 17:55:55 -0700191 out.appends("["sv, std::string_view{obj}.substr(0, i + 1), "[\n"sv);
William A. Kennington IIId9e2d722022-08-18 15:21:08 -0700192 for (size_t j = 0; j < 70; j++)
193 {
William A. Kennington III86642522023-07-24 17:55:55 -0700194 auto sv = std::string_view(kv).substr(0, i * 70 + j + 1);
195 out.appends(sv, "="sv, sv, "\n"sv);
William A. Kennington IIId9e2d722022-08-18 15:21:08 -0700196 }
197 }
198 out.flush();
199 file.commit();
200
201 auto start = std::chrono::steady_clock::now();
202 parser.setFile(filename);
William A. Kennington IIIb7401962023-07-21 16:36:11 -0700203 stdplus::print("Duration: {}\n", std::chrono::steady_clock::now() - start);
William A. Kennington IIId9e2d722022-08-18 15:21:08 -0700204 // Make sure this test isn't enabled
205 EXPECT_FALSE(true);
206}
207
William A. Kennington III25511a12022-08-04 16:32:28 -0700208} // namespace config
Gunnar Mills57d9c502018-09-14 14:42:34 -0500209} // namespace network
210} // namespace phosphor