summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandroid-build-team Robot2017-07-09 02:28:08 -0500
committerandroid-build-team Robot2017-07-09 02:28:08 -0500
commit6851d65907cb9f6e5c0619e3517eaa257cc36331 (patch)
treeb3d37db090c842eee037ed4db35844621d3500d3
parent0a5a61c8969184ff53be33fd573388f010740479 (diff)
parent448c04e670472e42c0cf6473f55c431bd46b8f57 (diff)
downloadplatform-system-libvintf-6851d65907cb9f6e5c0619e3517eaa257cc36331.tar.gz
platform-system-libvintf-6851d65907cb9f6e5c0619e3517eaa257cc36331.tar.xz
platform-system-libvintf-6851d65907cb9f6e5c0619e3517eaa257cc36331.zip
release-request-fda658d8-eecf-4c78-a2e9-e5093ca10451-for-git_oc-mr1-release-4165363 snap-temp-L49300000080728237
Change-Id: I1f6e5af954e1f9a8cb9eb751a620989d86b74fb5
-rw-r--r--KernelConfigParser.cpp58
-rw-r--r--assemble_vintf.cpp4
-rw-r--r--include/vintf/KernelConfigParser.h2
-rw-r--r--test/main.cpp79
4 files changed, 108 insertions, 35 deletions
diff --git a/KernelConfigParser.cpp b/KernelConfigParser.cpp
index e657a33..44cbf07 100644
--- a/KernelConfigParser.cpp
+++ b/KernelConfigParser.cpp
@@ -18,6 +18,13 @@
18 18
19#include <regex> 19#include <regex>
20 20
21#define KEY "(CONFIG[\\w_]+)"
22#define COMMENT "(?:#.*)"
23
24static const std::regex sKeyValuePattern("^\\s*" KEY "\\s*=\\s*([^#]+)" COMMENT "?$");
25static const std::regex sNotSetPattern("^\\s*#\\s*" KEY " is not set\\s*$");
26static const std::regex sCommentPattern("^\\s*" COMMENT "$");
27
21namespace android { 28namespace android {
22namespace vintf { 29namespace vintf {
23 30
@@ -27,8 +34,8 @@ status_t KernelConfigParser::finish() {
27 return process("\n", 1 /* sizeof "\n" */); 34 return process("\n", 1 /* sizeof "\n" */);
28} 35}
29 36
30const std::stringstream& KernelConfigParser::error() const { 37std::stringbuf* KernelConfigParser::error() const {
31 return mError; 38 return mError.rdbuf();
32} 39}
33 40
34std::map<std::string, std::string>& KernelConfigParser::configs() { 41std::map<std::string, std::string>& KernelConfigParser::configs() {
@@ -39,43 +46,44 @@ const std::map<std::string, std::string>& KernelConfigParser::configs() const {
39 return mConfigs; 46 return mConfigs;
40} 47}
41 48
49// trim spaces between value and #, value and end of line
50std::string trimTrailingSpaces(const std::string& s) {
51 auto r = s.rbegin();
52 for (; r != s.rend() && std::isspace(*r); ++r)
53 ;
54 return std::string{s.begin(), r.base()};
55}
56
42status_t KernelConfigParser::processRemaining() { 57status_t KernelConfigParser::processRemaining() {
43 static std::regex sCommentPattern("^# (CONFIG[\\w_]+) is not set$");
44 58
45 if (mRemaining.empty()) { 59 if (mRemaining.empty()) {
46 return OK; 60 return OK;
47 } 61 }
48 62
49 if (mRemaining[0] == '#') { 63 std::smatch match;
50 if (!mProcessComments) { 64 if (std::regex_match(mRemaining, match, sKeyValuePattern)) {
65 if (mConfigs.emplace(match[1], trimTrailingSpaces(match[2])).second) {
51 return OK; 66 return OK;
52 } 67 }
53 std::smatch sm; 68 mError << "Duplicated key in configs: " << match[1] << "\n";
54 if (!std::regex_match(mRemaining, sm, sCommentPattern)) { 69 return UNKNOWN_ERROR;
55 return OK; // ignore this comment;
56 }
57 if (!mConfigs.emplace(sm[1], "n").second) {
58 mError << "Key " << sm[1] << " is set but commented as not set"
59 << "\n";
60 return UNKNOWN_ERROR;
61 }
62
63 return OK;
64 } 70 }
65 71
66 size_t equalPos = mRemaining.find('='); 72 if (mProcessComments && std::regex_match(mRemaining, match, sNotSetPattern)) {
67 if (equalPos == std::string::npos) { 73 if (mConfigs.emplace(match[1], "n").second) {
68 mError << "Unrecognized line in configs: " << mRemaining << "\n"; 74 return OK;
75 }
76 mError << "Key " << match[1] << " is set but commented as not set"
77 << "\n";
69 return UNKNOWN_ERROR; 78 return UNKNOWN_ERROR;
70 } 79 }
71 std::string key = mRemaining.substr(0, equalPos); 80
72 std::string value = mRemaining.substr(equalPos + 1); 81 if (std::regex_match(mRemaining, match, sCommentPattern)) {
73 if (!mConfigs.emplace(std::move(key), std::move(value)).second) { 82 return OK;
74 mError << "Duplicated key in configs: " << mRemaining.substr(0, equalPos) << "\n";
75 return UNKNOWN_ERROR;
76 } 83 }
77 84
78 return OK; 85 mError << "Unrecognized line in configs: " << mRemaining << "\n";
86 return UNKNOWN_ERROR;
79} 87}
80 88
81status_t KernelConfigParser::process(const char* buf, size_t len) { 89status_t KernelConfigParser::process(const char* buf, size_t len) {
diff --git a/assemble_vintf.cpp b/assemble_vintf.cpp
index 1354d19..52510b5 100644
--- a/assemble_vintf.cpp
+++ b/assemble_vintf.cpp
@@ -69,12 +69,12 @@ public:
69 std::string content = read(ifs); 69 std::string content = read(ifs);
70 status_t err = parser.process(content.c_str(), content.size()); 70 status_t err = parser.process(content.c_str(), content.size());
71 if (err != OK) { 71 if (err != OK) {
72 std::cerr << parser.error().rdbuf(); 72 std::cerr << parser.error();
73 return false; 73 return false;
74 } 74 }
75 err = parser.finish(); 75 err = parser.finish();
76 if (err != OK) { 76 if (err != OK) {
77 std::cerr << parser.error().rdbuf(); 77 std::cerr << parser.error();
78 return false; 78 return false;
79 } 79 }
80 80
diff --git a/include/vintf/KernelConfigParser.h b/include/vintf/KernelConfigParser.h
index 0ef7088..bad66a5 100644
--- a/include/vintf/KernelConfigParser.h
+++ b/include/vintf/KernelConfigParser.h
@@ -33,7 +33,7 @@ class KernelConfigParser {
33 33
34 status_t process(const char* buf, size_t len); 34 status_t process(const char* buf, size_t len);
35 status_t finish(); 35 status_t finish();
36 const std::stringstream& error() const; 36 std::stringbuf* error() const;
37 std::map<std::string, std::string>& configs(); 37 std::map<std::string, std::string>& configs();
38 const std::map<std::string, std::string>& configs() const; 38 const std::map<std::string, std::string>& configs() const;
39 39
diff --git a/test/main.cpp b/test/main.cpp
index cf537c4..b3b8a59 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -1310,16 +1310,19 @@ TEST_F(LibVintfTest, MatrixXmlFilePathMissing) {
1310 EXPECT_EQ(matrix.getXmlSchemaPath("media_profile", {2, 0}), ""); 1310 EXPECT_EQ(matrix.getXmlSchemaPath("media_profile", {2, 0}), "");
1311} 1311}
1312 1312
1313static KernelConfigParser processData(const std::string& data, bool processComments) { 1313std::pair<KernelConfigParser, status_t> processData(const std::string& data, bool processComments) {
1314 KernelConfigParser parser(processComments); 1314 KernelConfigParser parser(processComments);
1315 const char* p = data.c_str(); 1315 const char* p = data.c_str();
1316 size_t n = 0; 1316 size_t n = 0;
1317 size_t chunkSize; 1317 size_t chunkSize;
1318 status_t status = OK;
1318 for (; n < data.size(); p += chunkSize, n += chunkSize) { 1319 for (; n < data.size(); p += chunkSize, n += chunkSize) {
1319 chunkSize = std::min<size_t>(5, data.size() - n); 1320 chunkSize = std::min<size_t>(5, data.size() - n);
1320 parser.process(p, chunkSize); 1321 if ((status = parser.process(p, chunkSize)) != OK) {
1322 break;
1323 }
1321 } 1324 }
1322 return parser; 1325 return {std::move(parser), status};
1323} 1326}
1324 1327
1325TEST_F(LibVintfTest, KernelConfigParser) { 1328TEST_F(LibVintfTest, KernelConfigParser) {
@@ -1329,8 +1332,9 @@ TEST_F(LibVintfTest, KernelConfigParser) {
1329 "CONFIG_ONE=1\n" 1332 "CONFIG_ONE=1\n"
1330 "CONFIG_Y=y\n" 1333 "CONFIG_Y=y\n"
1331 "CONFIG_STR=\"string\"\n"; 1334 "CONFIG_STR=\"string\"\n";
1332 KernelConfigParser parser = processData(data, false /* processComments */); 1335 auto pair = processData(data, false /* processComments */);
1333 const auto& configs = parser.configs(); 1336 ASSERT_EQ(OK, pair.second) << pair.first.error();
1337 const auto& configs = pair.first.configs();
1334 1338
1335 EXPECT_EQ(configs.find("CONFIG_ONE")->second, "1"); 1339 EXPECT_EQ(configs.find("CONFIG_ONE")->second, "1");
1336 EXPECT_EQ(configs.find("CONFIG_Y")->second, "y"); 1340 EXPECT_EQ(configs.find("CONFIG_Y")->second, "y");
@@ -1347,8 +1351,9 @@ TEST_F(LibVintfTest, KernelConfigParser2) {
1347 "CONFIG_STR=string\n" 1351 "CONFIG_STR=string\n"
1348 "# ignore_thiscomment\n" 1352 "# ignore_thiscomment\n"
1349 "# CONFIG_NOT_SET2 is not set\n"; 1353 "# CONFIG_NOT_SET2 is not set\n";
1350 KernelConfigParser parser = processData(data, true /* processComments */); 1354 auto pair = processData(data, true /* processComments */);
1351 const auto& configs = parser.configs(); 1355 ASSERT_EQ(OK, pair.second) << pair.first.error();
1356 const auto& configs = pair.first.configs();
1352 1357
1353 EXPECT_EQ(configs.find("CONFIG_ONE")->second, "1"); 1358 EXPECT_EQ(configs.find("CONFIG_ONE")->second, "1");
1354 EXPECT_EQ(configs.find("CONFIG_Y")->second, "y"); 1359 EXPECT_EQ(configs.find("CONFIG_Y")->second, "y");
@@ -1357,6 +1362,66 @@ TEST_F(LibVintfTest, KernelConfigParser2) {
1357 EXPECT_EQ(configs.find("CONFIG_NOT_SET2")->second, "n"); 1362 EXPECT_EQ(configs.find("CONFIG_NOT_SET2")->second, "n");
1358} 1363}
1359 1364
1365TEST_F(LibVintfTest, KernelConfigParserSpace) {
1366 // usage in android-base.cfg
1367 const std::string data =
1368 " # CONFIG_NOT_SET is not set \n"
1369 " CONFIG_ONE=1 # 'tis a one!\n"
1370 " CONFIG_TWO=2 #'tis a two! \n"
1371 " CONFIG_THREE=3#'tis a three! \n"
1372 " CONFIG_233=233#'tis a three! \n"
1373 "#yey! random comments\n"
1374 "CONFIG_Y=y \n"
1375 " CONFIG_YES=y#YES! \n"
1376 "CONFIG_STR=string\n"
1377 "CONFIG_HELLO=hello world! #still works\n"
1378 "CONFIG_WORLD=hello world! \n"
1379 "CONFIG_GOOD = good morning! #comments here\n"
1380 " CONFIG_MORNING = good morning! \n";
1381 auto pair = processData(data, true /* processComments */);
1382 ASSERT_EQ(OK, pair.second) << pair.first.error();
1383 const auto& configs = pair.first.configs();
1384
1385 EXPECT_EQ(configs.find("CONFIG_ONE")->second, "1");
1386 EXPECT_EQ(configs.find("CONFIG_TWO")->second, "2");
1387 EXPECT_EQ(configs.find("CONFIG_THREE")->second, "3");
1388 EXPECT_EQ(configs.find("CONFIG_Y")->second, "y");
1389 EXPECT_EQ(configs.find("CONFIG_STR")->second, "string");
1390 EXPECT_EQ(configs.find("CONFIG_HELLO")->second, "hello world!")
1391 << "Value should be \"hello world!\" without trailing spaces";
1392 EXPECT_EQ(configs.find("CONFIG_WORLD")->second, "hello world!")
1393 << "Value should be \"hello world!\" without trailing spaces";
1394 EXPECT_EQ(configs.find("CONFIG_GOOD")->second, "good morning!")
1395 << "Value should be \"good morning!\" without leading or trailing spaces";
1396 EXPECT_EQ(configs.find("CONFIG_MORNING")->second, "good morning!")
1397 << "Value should be \"good morning!\" without leading or trailing spaces";
1398 EXPECT_EQ(configs.find("CONFIG_NOT_SET")->second, "n");
1399}
1400
1401// Run KernelConfigParserInvalidTest on processComments = {true, false}
1402class KernelConfigParserInvalidTest : public ::testing::TestWithParam<bool> {};
1403
1404TEST_P(KernelConfigParserInvalidTest, NonSet1) {
1405 const std::string data = "# CONFIG_NOT_EXIST is not sat\n";
1406 auto pair = processData(data, GetParam() /* processComments */);
1407 ASSERT_EQ(OK, pair.second) << pair.first.error();
1408 const auto& configs = pair.first.configs();
1409 EXPECT_EQ(configs.find("CONFIG_NOT_EXIST"), configs.end())
1410 << "CONFIG_NOT_EXIST should not exist because of typo";
1411}
1412
1413TEST_P(KernelConfigParserInvalidTest, InvalidLine1) {
1414 const std::string data = "FOO_CONFIG=foo\n";
1415 ASSERT_NE(OK, processData(data, GetParam() /* processComments */).second);
1416}
1417
1418TEST_P(KernelConfigParserInvalidTest, InvalidLine2) {
1419 const std::string data = "CONFIG_BAR-BAZ=foo\n";
1420 ASSERT_NE(OK, processData(data, GetParam() /* processComments */).second);
1421}
1422
1423INSTANTIATE_TEST_CASE_P(KernelConfigParser, KernelConfigParserInvalidTest, ::testing::Bool());
1424
1360} // namespace vintf 1425} // namespace vintf
1361} // namespace android 1426} // namespace android
1362 1427