blob: 60b45b9f7fb0c180118b77ea88b7d1be8008ffd6 [file] [log] [blame]
Tom Cherrycb0f9bb2017-09-12 15:58:47 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "subcontext.h"
18
19#include <unistd.h>
20
21#include <chrono>
22
23#include <android-base/properties.h>
24#include <android-base/strings.h>
25#include <gtest/gtest.h>
26
27#include "builtin_arguments.h"
28#include "test_function_map.h"
29
30using namespace std::literals;
31
32using android::base::GetProperty;
33using android::base::Join;
34using android::base::SetProperty;
35using android::base::Split;
36using android::base::WaitForProperty;
37
38namespace android {
39namespace init {
40
41TEST(subcontext, CheckDifferentPid) {
42 auto subcontext = Subcontext("path", kVendorContext);
43 auto subcontext_killer = SubcontextKiller(subcontext);
44
45 auto result = subcontext.Execute(std::vector<std::string>{"return_pids_as_error"});
46 ASSERT_FALSE(result);
47
48 auto pids = Split(result.error_string(), " ");
49 ASSERT_EQ(2U, pids.size());
50 auto our_pid = std::to_string(getpid());
51 EXPECT_NE(our_pid, pids[0]);
52 EXPECT_EQ(our_pid, pids[1]);
53}
54
55TEST(subcontext, SetProp) {
56 auto subcontext = Subcontext("path", kVendorContext);
57 auto subcontext_killer = SubcontextKiller(subcontext);
58
59 SetProperty("init.test.subcontext", "fail");
60 WaitForProperty("init.test.subcontext", "fail");
61
62 auto args = std::vector<std::string>{
63 "setprop",
64 "init.test.subcontext",
65 "success",
66 };
67 auto result = subcontext.Execute(args);
68 ASSERT_TRUE(result) << result.error();
69
70 EXPECT_TRUE(WaitForProperty("init.test.subcontext", "success", 10s));
71}
72
73TEST(subcontext, MultipleCommands) {
74 auto subcontext = Subcontext("path", kVendorContext);
75 auto subcontext_killer = SubcontextKiller(subcontext);
76
77 auto first_pid = subcontext.pid();
78
79 auto expected_words = std::vector<std::string>{
80 "this",
81 "is",
82 "a",
83 "test",
84 };
85
86 for (const auto& word : expected_words) {
87 auto args = std::vector<std::string>{
88 "add_word",
89 word,
90 };
91 auto result = subcontext.Execute(args);
92 ASSERT_TRUE(result) << result.error();
93 }
94
95 auto result = subcontext.Execute(std::vector<std::string>{"return_words_as_error"});
96 ASSERT_FALSE(result);
97 EXPECT_EQ(Join(expected_words, " "), result.error_string());
98 EXPECT_EQ(first_pid, subcontext.pid());
99}
100
101TEST(subcontext, RecoverAfterAbort) {
102 auto subcontext = Subcontext("path", kVendorContext);
103 auto subcontext_killer = SubcontextKiller(subcontext);
104
105 auto first_pid = subcontext.pid();
106
107 auto result = subcontext.Execute(std::vector<std::string>{"cause_log_fatal"});
108 ASSERT_FALSE(result);
109
110 auto result2 = subcontext.Execute(std::vector<std::string>{"generate_sane_error"});
111 ASSERT_FALSE(result2);
112 EXPECT_EQ("Sane error!", result2.error_string());
113 EXPECT_NE(subcontext.pid(), first_pid);
114}
115
116TEST(subcontext, ContextString) {
117 auto subcontext = Subcontext("path", kVendorContext);
118 auto subcontext_killer = SubcontextKiller(subcontext);
119
120 auto result = subcontext.Execute(std::vector<std::string>{"return_context_as_error"});
121 ASSERT_FALSE(result);
122 ASSERT_EQ(kVendorContext, result.error_string());
123}
124
125TestFunctionMap BuildTestFunctionMap() {
126 TestFunctionMap test_function_map;
127 // For CheckDifferentPid
128 test_function_map.Add("return_pids_as_error", 0, 0, true,
129 [](const BuiltinArguments& args) -> Result<Success> {
130 return Error() << getpid() << " " << getppid();
131 });
132
133 // For SetProp
134 test_function_map.Add("setprop", 2, 2, true, [](const BuiltinArguments& args) {
135 android::base::SetProperty(args[1], args[2]);
136 return Success();
137 });
138
139 // For MultipleCommands
140 // Using a shared_ptr to extend lifetime of words to both lambdas
141 auto words = std::make_shared<std::vector<std::string>>();
142 test_function_map.Add("add_word", 1, 1, true, [words](const BuiltinArguments& args) {
143 words->emplace_back(args[1]);
144 return Success();
145 });
146 test_function_map.Add("return_words_as_error", 0, 0, true,
147 [words](const BuiltinArguments& args) -> Result<Success> {
148 return Error() << Join(*words, " ");
149 });
150
151 // For RecoverAfterAbort
152 test_function_map.Add("cause_log_fatal", 0, 0, true,
153 [](const BuiltinArguments& args) -> Result<Success> {
154 return Error() << std::string(4097, 'f');
155 });
156 test_function_map.Add(
157 "generate_sane_error", 0, 0, true,
158 [](const BuiltinArguments& args) -> Result<Success> { return Error() << "Sane error!"; });
159
160 // For ContextString
161 test_function_map.Add(
162 "return_context_as_error", 0, 0, true,
163 [](const BuiltinArguments& args) -> Result<Success> { return Error() << args.context; });
164
165 return test_function_map;
166}
167
168} // namespace init
169} // namespace android
170
171int main(int argc, char** argv) {
172 if (argc > 1 && !strcmp(basename(argv[1]), "subcontext")) {
173 auto test_function_map = android::init::BuildTestFunctionMap();
174 return android::init::SubcontextMain(argc, argv, &test_function_map);
175 }
176
177 testing::InitGoogleTest(&argc, argv);
178 return RUN_ALL_TESTS();
179}