1*4b9c6d91SCole Faust /* Copyright 2021 The ChromiumOS Authors
2*4b9c6d91SCole Faust * Use of this source code is governed by a BSD-style license that can be
3*4b9c6d91SCole Faust * found in the LICENSE file.
4*4b9c6d91SCole Faust *
5*4b9c6d91SCole Faust * Test config_parser.c using gtest.
6*4b9c6d91SCole Faust */
7*4b9c6d91SCole Faust
8*4b9c6d91SCole Faust #include <gtest/gtest.h>
9*4b9c6d91SCole Faust #include <string>
10*4b9c6d91SCole Faust
11*4b9c6d91SCole Faust #include "config_parser.h"
12*4b9c6d91SCole Faust #include "test_util.h"
13*4b9c6d91SCole Faust #include "util.h"
14*4b9c6d91SCole Faust
15*4b9c6d91SCole Faust namespace {
16*4b9c6d91SCole Faust
17*4b9c6d91SCole Faust class ConfigFileTest : public ::testing::Test {
18*4b9c6d91SCole Faust protected:
SetUp()19*4b9c6d91SCole Faust virtual void SetUp() {
20*4b9c6d91SCole Faust list_ = new_config_entry_list();
21*4b9c6d91SCole Faust ASSERT_NE(list_, nullptr);
22*4b9c6d91SCole Faust }
TearDown()23*4b9c6d91SCole Faust virtual void TearDown() { free_config_entry_list(list_); }
24*4b9c6d91SCole Faust struct config_entry_list *list_;
25*4b9c6d91SCole Faust };
26*4b9c6d91SCole Faust
27*4b9c6d91SCole Faust } // namespace
28*4b9c6d91SCole Faust
TEST(ParsingConfigTest,valid_config_line)29*4b9c6d91SCole Faust TEST(ParsingConfigTest, valid_config_line) {
30*4b9c6d91SCole Faust ScopedConfigEntry entry(
31*4b9c6d91SCole Faust (config_entry *)calloc(1, sizeof(struct config_entry)));
32*4b9c6d91SCole Faust const std::vector<std::string> valid_conf_lines = {
33*4b9c6d91SCole Faust "mount=none",
34*4b9c6d91SCole Faust "valueless_key"
35*4b9c6d91SCole Faust "binding = none",
36*4b9c6d91SCole Faust " xyz = abc ",
37*4b9c6d91SCole Faust };
38*4b9c6d91SCole Faust
39*4b9c6d91SCole Faust for (const auto& conf_line : valid_conf_lines) {
40*4b9c6d91SCole Faust ASSERT_TRUE(parse_config_line(conf_line.c_str(), entry.get()));
41*4b9c6d91SCole Faust clear_config_entry(entry.get());
42*4b9c6d91SCole Faust }
43*4b9c6d91SCole Faust }
44*4b9c6d91SCole Faust
TEST(ParsingConfigTest,invalid_config_line)45*4b9c6d91SCole Faust TEST(ParsingConfigTest, invalid_config_line) {
46*4b9c6d91SCole Faust ScopedConfigEntry entry(
47*4b9c6d91SCole Faust (config_entry *)calloc(1, sizeof(struct config_entry)));
48*4b9c6d91SCole Faust const std::vector<std::string> invalid_conf_lines = {
49*4b9c6d91SCole Faust "= none",
50*4b9c6d91SCole Faust "",
51*4b9c6d91SCole Faust "empty_arg=",
52*4b9c6d91SCole Faust "empty_arg= ",
53*4b9c6d91SCole Faust };
54*4b9c6d91SCole Faust
55*4b9c6d91SCole Faust for (const auto& conf_line : invalid_conf_lines) {
56*4b9c6d91SCole Faust ASSERT_FALSE(parse_config_line(conf_line.c_str(), entry.get()));
57*4b9c6d91SCole Faust }
58*4b9c6d91SCole Faust }
59*4b9c6d91SCole Faust
TEST_F(ConfigFileTest,malformed_config_line)60*4b9c6d91SCole Faust TEST_F(ConfigFileTest, malformed_config_line) {
61*4b9c6d91SCole Faust std::string config = "% minijail-config-file v0\n"
62*4b9c6d91SCole Faust "=malformed";
63*4b9c6d91SCole Faust ScopedFILE config_file(write_to_pipe(config));
64*4b9c6d91SCole Faust ASSERT_NE(config_file.get(), nullptr);
65*4b9c6d91SCole Faust
66*4b9c6d91SCole Faust bool res = parse_config_file(config_file.get(), list_);
67*4b9c6d91SCole Faust
68*4b9c6d91SCole Faust // Policy is malformed, but process should not crash.
69*4b9c6d91SCole Faust ASSERT_FALSE(res);
70*4b9c6d91SCole Faust ASSERT_EQ(list_->num_entries, 0);
71*4b9c6d91SCole Faust }
72*4b9c6d91SCole Faust
TEST_F(ConfigFileTest,bad_directive)73*4b9c6d91SCole Faust TEST_F(ConfigFileTest, bad_directive) {
74*4b9c6d91SCole Faust std::string config = "% bad-directive\n"
75*4b9c6d91SCole Faust "# comments";
76*4b9c6d91SCole Faust ScopedFILE config_file(write_to_pipe(config));
77*4b9c6d91SCole Faust ASSERT_NE(config_file.get(), nullptr);
78*4b9c6d91SCole Faust
79*4b9c6d91SCole Faust bool res = parse_config_file(config_file.get(), list_);
80*4b9c6d91SCole Faust
81*4b9c6d91SCole Faust // Policy is malformed, but process should not crash.
82*4b9c6d91SCole Faust ASSERT_FALSE(res);
83*4b9c6d91SCole Faust ASSERT_EQ(list_->num_entries, 0);
84*4b9c6d91SCole Faust }
85*4b9c6d91SCole Faust
TEST_F(ConfigFileTest,wellformed_single_line)86*4b9c6d91SCole Faust TEST_F(ConfigFileTest, wellformed_single_line) {
87*4b9c6d91SCole Faust std::string config = "% minijail-config-file v0\n"
88*4b9c6d91SCole Faust "# Comments \n"
89*4b9c6d91SCole Faust "\n"
90*4b9c6d91SCole Faust "uts\n"
91*4b9c6d91SCole Faust "mount= xyz\n"
92*4b9c6d91SCole Faust "binding = none,/tmp";
93*4b9c6d91SCole Faust ScopedFILE config_file(write_to_pipe(config));
94*4b9c6d91SCole Faust ASSERT_NE(config_file.get(), nullptr);
95*4b9c6d91SCole Faust
96*4b9c6d91SCole Faust bool res = parse_config_file(config_file.get(), list_);
97*4b9c6d91SCole Faust
98*4b9c6d91SCole Faust ASSERT_TRUE(res);
99*4b9c6d91SCole Faust ASSERT_EQ(list_->num_entries, 3);
100*4b9c6d91SCole Faust struct config_entry *first_entry = list_->entries;
101*4b9c6d91SCole Faust struct config_entry *second_entry = list_->entries + 1;
102*4b9c6d91SCole Faust struct config_entry *third_entry = list_->entries + 2;
103*4b9c6d91SCole Faust ASSERT_EQ(std::string(first_entry->key), "uts");
104*4b9c6d91SCole Faust ASSERT_EQ(first_entry->value, nullptr);
105*4b9c6d91SCole Faust ASSERT_EQ(std::string(second_entry->key), "mount");
106*4b9c6d91SCole Faust ASSERT_EQ(std::string(second_entry->value), "xyz");
107*4b9c6d91SCole Faust ASSERT_EQ(std::string(third_entry->key), "binding");
108*4b9c6d91SCole Faust ASSERT_EQ(std::string(third_entry->value), "none,/tmp");
109*4b9c6d91SCole Faust }
110*4b9c6d91SCole Faust
TEST_F(ConfigFileTest,wellformed_multi_line)111*4b9c6d91SCole Faust TEST_F(ConfigFileTest, wellformed_multi_line) {
112*4b9c6d91SCole Faust std::string config = "% minijail-config-file v0\n"
113*4b9c6d91SCole Faust "# Comments \n"
114*4b9c6d91SCole Faust "\n"
115*4b9c6d91SCole Faust "mount = \\\n"
116*4b9c6d91SCole Faust "none\n"
117*4b9c6d91SCole Faust "binding = none,\\\n"
118*4b9c6d91SCole Faust "/tmp";
119*4b9c6d91SCole Faust ScopedFILE config_file(write_to_pipe(config));
120*4b9c6d91SCole Faust ASSERT_NE(config_file.get(), nullptr);
121*4b9c6d91SCole Faust
122*4b9c6d91SCole Faust int res = parse_config_file(config_file.get(), list_);
123*4b9c6d91SCole Faust
124*4b9c6d91SCole Faust ASSERT_TRUE(res);
125*4b9c6d91SCole Faust ASSERT_EQ(list_->num_entries, 2);
126*4b9c6d91SCole Faust struct config_entry *first_entry = list_->entries;
127*4b9c6d91SCole Faust struct config_entry *second_entry = list_->entries + 1;
128*4b9c6d91SCole Faust ASSERT_EQ(std::string(first_entry->key), "mount");
129*4b9c6d91SCole Faust ASSERT_EQ(std::string(first_entry->value), "none");
130*4b9c6d91SCole Faust ASSERT_EQ(std::string(second_entry->key), "binding");
131*4b9c6d91SCole Faust ASSERT_EQ(std::string(second_entry->value), "none, /tmp");
132*4b9c6d91SCole Faust }
133