Merge "ueventd: add a test for ueventd_parser.cpp"
This commit is contained in:
commit
bd130567f8
4 changed files with 244 additions and 12 deletions
|
@ -180,6 +180,7 @@ cc_test {
|
|||
"service_test.cpp",
|
||||
"subcontext_test.cpp",
|
||||
"tokenizer_test.cpp",
|
||||
"ueventd_parser_test.cpp",
|
||||
"ueventd_test.cpp",
|
||||
"util_test.cpp",
|
||||
],
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace init {
|
|||
|
||||
class Permissions {
|
||||
public:
|
||||
friend void TestPermissions(const Permissions& expected, const Permissions& test);
|
||||
|
||||
Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid);
|
||||
|
||||
bool Match(const std::string& path) const;
|
||||
|
@ -57,6 +59,8 @@ class Permissions {
|
|||
|
||||
class SysfsPermissions : public Permissions {
|
||||
public:
|
||||
friend void TestSysfsPermissions(const SysfsPermissions& expected, const SysfsPermissions& test);
|
||||
|
||||
SysfsPermissions(const std::string& name, const std::string& attribute, mode_t perm, uid_t uid,
|
||||
gid_t gid)
|
||||
: Permissions(name, perm, uid, gid), attribute_(attribute) {}
|
||||
|
@ -71,16 +75,24 @@ class SysfsPermissions : public Permissions {
|
|||
class Subsystem {
|
||||
public:
|
||||
friend class SubsystemParser;
|
||||
friend void TestSubsystems(const Subsystem& expected, const Subsystem& test);
|
||||
|
||||
enum DevnameSource {
|
||||
DEVNAME_UEVENT_DEVNAME,
|
||||
DEVNAME_UEVENT_DEVPATH,
|
||||
};
|
||||
|
||||
Subsystem() {}
|
||||
Subsystem(std::string name) : name_(std::move(name)) {}
|
||||
Subsystem(const std::string& name) : name_(name) {}
|
||||
Subsystem(const std::string& name, DevnameSource source, const std::string& dir_name)
|
||||
: name_(name), devname_source_(source), dir_name_(dir_name) {}
|
||||
|
||||
// Returns the full path for a uevent of a device that is a member of this subsystem,
|
||||
// according to the rules parsed from ueventd.rc
|
||||
std::string ParseDevPath(const Uevent& uevent) const {
|
||||
std::string devname = devname_source_ == DevnameSource::DEVNAME_UEVENT_DEVNAME
|
||||
? uevent.device_name
|
||||
: android::base::Basename(uevent.path);
|
||||
std::string devname = devname_source_ == DEVNAME_UEVENT_DEVNAME
|
||||
? uevent.device_name
|
||||
: android::base::Basename(uevent.path);
|
||||
|
||||
return dir_name_ + "/" + devname;
|
||||
}
|
||||
|
@ -88,14 +100,9 @@ class Subsystem {
|
|||
bool operator==(const std::string& string_name) const { return name_ == string_name; }
|
||||
|
||||
private:
|
||||
enum class DevnameSource {
|
||||
DEVNAME_UEVENT_DEVNAME,
|
||||
DEVNAME_UEVENT_DEVPATH,
|
||||
};
|
||||
|
||||
std::string name_;
|
||||
DevnameSource devname_source_ = DEVNAME_UEVENT_DEVNAME;
|
||||
std::string dir_name_ = "/dev";
|
||||
DevnameSource devname_source_;
|
||||
};
|
||||
|
||||
class DeviceHandler {
|
||||
|
|
|
@ -117,11 +117,11 @@ Result<Success> SubsystemParser::ParseSection(std::vector<std::string>&& args,
|
|||
|
||||
Result<Success> SubsystemParser::ParseDevName(std::vector<std::string>&& args) {
|
||||
if (args[1] == "uevent_devname") {
|
||||
subsystem_.devname_source_ = Subsystem::DevnameSource::DEVNAME_UEVENT_DEVNAME;
|
||||
subsystem_.devname_source_ = Subsystem::DEVNAME_UEVENT_DEVNAME;
|
||||
return Success();
|
||||
}
|
||||
if (args[1] == "uevent_devpath") {
|
||||
subsystem_.devname_source_ = Subsystem::DevnameSource::DEVNAME_UEVENT_DEVPATH;
|
||||
subsystem_.devname_source_ = Subsystem::DEVNAME_UEVENT_DEVPATH;
|
||||
return Success();
|
||||
}
|
||||
|
||||
|
|
224
init/ueventd_parser_test.cpp
Normal file
224
init/ueventd_parser_test.cpp
Normal file
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "ueventd_parser.h"
|
||||
|
||||
#include <android-base/test_utils.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
void TestSubsystems(const Subsystem& expected, const Subsystem& test) {
|
||||
EXPECT_EQ(expected.name_, test.name_);
|
||||
EXPECT_EQ(expected.devname_source_, test.devname_source_) << expected.name_;
|
||||
EXPECT_EQ(expected.dir_name_, test.dir_name_) << expected.name_;
|
||||
}
|
||||
|
||||
void TestPermissions(const Permissions& expected, const Permissions& test) {
|
||||
EXPECT_EQ(expected.name_, test.name_);
|
||||
EXPECT_EQ(expected.perm_, test.perm_) << expected.name_;
|
||||
EXPECT_EQ(expected.uid_, test.uid_) << expected.name_;
|
||||
EXPECT_EQ(expected.gid_, test.gid_) << expected.name_;
|
||||
EXPECT_EQ(expected.prefix_, test.prefix_) << expected.name_;
|
||||
EXPECT_EQ(expected.wildcard_, test.wildcard_) << expected.name_;
|
||||
}
|
||||
|
||||
void TestSysfsPermissions(const SysfsPermissions& expected, const SysfsPermissions& test) {
|
||||
TestPermissions(expected, test);
|
||||
EXPECT_EQ(expected.attribute_, test.attribute_);
|
||||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
void TestVector(const T& expected, const T& test, F function) {
|
||||
ASSERT_EQ(expected.size(), test.size());
|
||||
auto expected_it = expected.begin();
|
||||
auto test_it = test.begin();
|
||||
|
||||
for (; expected_it != expected.end(); ++expected_it, ++test_it) {
|
||||
function(*expected_it, *test_it);
|
||||
}
|
||||
}
|
||||
|
||||
void TestUeventdFile(const std::string& content, const UeventdConfiguration& expected) {
|
||||
TemporaryFile tf;
|
||||
ASSERT_TRUE(tf.fd != -1);
|
||||
ASSERT_TRUE(android::base::WriteStringToFd(content, tf.fd));
|
||||
|
||||
auto result = ParseConfig({tf.path});
|
||||
|
||||
TestVector(expected.subsystems, result.subsystems, TestSubsystems);
|
||||
TestVector(expected.sysfs_permissions, result.sysfs_permissions, TestSysfsPermissions);
|
||||
TestVector(expected.dev_permissions, result.dev_permissions, TestPermissions);
|
||||
EXPECT_EQ(expected.firmware_directories, result.firmware_directories);
|
||||
}
|
||||
|
||||
TEST(ueventd_parser, EmptyFile) {
|
||||
TestUeventdFile("", {});
|
||||
}
|
||||
|
||||
TEST(ueventd_parser, Subsystems) {
|
||||
auto ueventd_file = R"(
|
||||
subsystem test_devname
|
||||
devname uevent_devname
|
||||
|
||||
subsystem test_devpath_no_dirname
|
||||
devname uevent_devpath
|
||||
|
||||
subsystem test_devname2
|
||||
devname uevent_devname
|
||||
|
||||
subsystem test_devpath_dirname
|
||||
devname uevent_devpath
|
||||
dirname /dev/graphics
|
||||
)";
|
||||
|
||||
auto subsystems = std::vector<Subsystem>{
|
||||
{"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
|
||||
{"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
|
||||
{"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
|
||||
{"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
|
||||
|
||||
TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}});
|
||||
}
|
||||
|
||||
TEST(ueventd_parser, Permissions) {
|
||||
auto ueventd_file = R"(
|
||||
/dev/rtc0 0640 system system
|
||||
/dev/graphics/* 0660 root graphics
|
||||
/dev/*/test 0660 root system
|
||||
|
||||
/sys/devices/platform/trusty.* trusty_version 0440 root log
|
||||
/sys/devices/virtual/input/input enable 0660 root input
|
||||
/sys/devices/virtual/*/input poll_delay 0660 root input
|
||||
)";
|
||||
|
||||
auto permissions = std::vector<Permissions>{
|
||||
{"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM},
|
||||
{"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS},
|
||||
{"/dev/*/test", 0660, AID_ROOT, AID_SYSTEM},
|
||||
};
|
||||
|
||||
auto sysfs_permissions = std::vector<SysfsPermissions>{
|
||||
{"/sys/devices/platform/trusty.*", "trusty_version", 0440, AID_ROOT, AID_LOG},
|
||||
{"/sys/devices/virtual/input/input", "enable", 0660, AID_ROOT, AID_INPUT},
|
||||
{"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT},
|
||||
};
|
||||
|
||||
TestUeventdFile(ueventd_file, {{}, sysfs_permissions, permissions, {}});
|
||||
}
|
||||
|
||||
TEST(ueventd_parser, FirmwareDirectories) {
|
||||
auto ueventd_file = R"(
|
||||
firmware_directories /first/ /second /third
|
||||
firmware_directories /more
|
||||
)";
|
||||
|
||||
auto firmware_directories = std::vector<std::string>{
|
||||
"/first/",
|
||||
"/second",
|
||||
"/third",
|
||||
"/more",
|
||||
};
|
||||
|
||||
TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories});
|
||||
}
|
||||
|
||||
TEST(ueventd_parser, AllTogether) {
|
||||
auto ueventd_file = R"(
|
||||
|
||||
/dev/rtc0 0640 system system
|
||||
firmware_directories /first/ /second /third
|
||||
/sys/devices/platform/trusty.* trusty_version 0440 root log
|
||||
|
||||
subsystem test_devname
|
||||
devname uevent_devname
|
||||
|
||||
/dev/graphics/* 0660 root graphics
|
||||
|
||||
subsystem test_devpath_no_dirname
|
||||
devname uevent_devpath
|
||||
|
||||
/sys/devices/virtual/input/input enable 0660 root input
|
||||
|
||||
## this is a comment
|
||||
|
||||
subsystem test_devname2
|
||||
## another comment
|
||||
devname uevent_devname
|
||||
|
||||
subsystem test_devpath_dirname
|
||||
devname uevent_devpath
|
||||
dirname /dev/graphics
|
||||
|
||||
/dev/*/test 0660 root system
|
||||
/sys/devices/virtual/*/input poll_delay 0660 root input
|
||||
firmware_directories /more
|
||||
|
||||
#ending comment
|
||||
)";
|
||||
|
||||
auto subsystems = std::vector<Subsystem>{
|
||||
{"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
|
||||
{"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
|
||||
{"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
|
||||
{"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
|
||||
|
||||
auto permissions = std::vector<Permissions>{
|
||||
{"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM},
|
||||
{"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS},
|
||||
{"/dev/*/test", 0660, AID_ROOT, AID_SYSTEM},
|
||||
};
|
||||
|
||||
auto sysfs_permissions = std::vector<SysfsPermissions>{
|
||||
{"/sys/devices/platform/trusty.*", "trusty_version", 0440, AID_ROOT, AID_LOG},
|
||||
{"/sys/devices/virtual/input/input", "enable", 0660, AID_ROOT, AID_INPUT},
|
||||
{"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT},
|
||||
};
|
||||
|
||||
auto firmware_directories = std::vector<std::string>{
|
||||
"/first/",
|
||||
"/second",
|
||||
"/third",
|
||||
"/more",
|
||||
};
|
||||
|
||||
TestUeventdFile(ueventd_file,
|
||||
{subsystems, sysfs_permissions, permissions, firmware_directories});
|
||||
}
|
||||
|
||||
// All of these lines are ill-formed, so test that there is 0 output.
|
||||
TEST(ueventd_parser, ParseErrors) {
|
||||
auto ueventd_file = R"(
|
||||
|
||||
/dev/rtc0 badmode baduidbad system
|
||||
/dev/rtc0 0640 baduidbad system
|
||||
/dev/rtc0 0640 system baduidbad
|
||||
firmware_directories #no directory listed
|
||||
/sys/devices/platform/trusty.* trusty_version badmode root log
|
||||
/sys/devices/platform/trusty.* trusty_version 0440 baduidbad log
|
||||
/sys/devices/platform/trusty.* trusty_version 0440 root baduidbad
|
||||
|
||||
subsystem #no name
|
||||
|
||||
)";
|
||||
|
||||
TestUeventdFile(ueventd_file, {});
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
Loading…
Reference in a new issue