blob: f11f50987f2e9b72a3739be92f7614f15608aff7 [file] [log] [blame]
Colin Crossb27e2002013-01-28 17:19:43 -08001/*
2 * Copyright (C) 2013 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 <gtest/gtest.h>
Yabin Cui9df70402014-11-05 18:01:01 -080018
Elliott Hughese4375192013-10-21 17:09:52 -070019#include <errno.h>
Yabin Cui9df70402014-11-05 18:01:01 -080020#include <sys/wait.h>
Greg Hackmanncb215a72013-02-13 14:41:48 -080021#include <unistd.h>
Elliott Hughesa0d374d2017-02-10 18:13:46 -080022
Greg Hackmanncb215a72013-02-13 14:41:48 -080023#include <string>
Elliott Hughesa0d374d2017-02-10 18:13:46 -080024#include <thread>
Colin Crossb27e2002013-01-28 17:19:43 -080025
Mark Salyzynba1a7232018-11-14 15:19:53 -080026#include <android-base/file.h>
Elliott Hughes141b9172021-04-09 17:13:09 -070027#include <android-base/silent_death_test.h>
Nate Myrenb8c87b12023-08-28 16:46:39 -070028#include <android-base/stringprintf.h>
29
30#include "utils.h"
Tom Cherrye275d6d2017-12-11 23:31:33 -080031
Tom Cherry8a311632017-10-09 13:49:17 -070032using namespace std::literals;
33
Christopher Ferrisf04935c2013-12-20 18:43:21 -080034#if defined(__BIONIC__)
Colin Crossb27e2002013-01-28 17:19:43 -080035
36#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
Nate Myren0ab06152023-10-19 16:50:59 -070037#include <stdlib.h>
Colin Crossb27e2002013-01-28 17:19:43 -080038#include <sys/_system_properties.h>
Nate Myrenb8c87b12023-08-28 16:46:39 -070039#include <sys/mount.h>
Colin Crossb27e2002013-01-28 17:19:43 -080040
Tom Cherrye275d6d2017-12-11 23:31:33 -080041#include <system_properties/system_properties.h>
Greg Hackmanncb215a72013-02-13 14:41:48 -080042
Tom Cherrye275d6d2017-12-11 23:31:33 -080043class SystemPropertiesTest : public SystemProperties {
44 public:
45 SystemPropertiesTest() : SystemProperties(false) {
Nate Myrenb8c87b12023-08-28 16:46:39 -070046 appcompat_path = android::base::StringPrintf("%s/appcompat_override", dir_.path);
Nate Myren0ab06152023-10-19 16:50:59 -070047 mount_path = android::base::StringPrintf("%s/__properties__", dir_.path);
Nate Myrenb8c87b12023-08-28 16:46:39 -070048 mkdir(appcompat_path.c_str(), S_IRWXU | S_IXGRP | S_IXOTH);
49 valid_ = AreaInit(dir_.path, nullptr, true);
Tom Cherrye275d6d2017-12-11 23:31:33 -080050 }
51 ~SystemPropertiesTest() {
52 if (valid_) {
Tom Cherryee8e3dd2018-02-21 15:01:22 -080053 contexts_->FreeAndUnmap();
Colin Crossb27e2002013-01-28 17:19:43 -080054 }
Nate Myren0ab06152023-10-19 16:50:59 -070055 umount2(dir_.path, MNT_DETACH);
56 umount2(real_sysprop_dir.c_str(), MNT_DETACH);
Tom Cherrye275d6d2017-12-11 23:31:33 -080057 }
Colin Crossb27e2002013-01-28 17:19:43 -080058
Tom Cherrye275d6d2017-12-11 23:31:33 -080059 bool valid() const {
60 return valid_;
61 }
Greg Hackmanncb215a72013-02-13 14:41:48 -080062
Nate Myrenb8c87b12023-08-28 16:46:39 -070063 const char* get_path() const { return dir_.path; }
64
65 const char* get_appcompat_path() const { return appcompat_path.c_str(); }
66
Nate Myren0ab06152023-10-19 16:50:59 -070067 const char* get_mount_path() const { return mount_path.c_str(); }
68
69 const char* get_real_sysprop_dir() const { return real_sysprop_dir.c_str(); }
70
Nate Myrenb8c87b12023-08-28 16:46:39 -070071 std::string appcompat_path;
Nate Myren0ab06152023-10-19 16:50:59 -070072 std::string mount_path;
73 std::string real_sysprop_dir = "/dev/__properties__";
Nate Myrenb8c87b12023-08-28 16:46:39 -070074
Tom Cherrye275d6d2017-12-11 23:31:33 -080075 private:
76 TemporaryDir dir_;
77 bool valid_;
Colin Crossb27e2002013-01-28 17:19:43 -080078};
79
Christopher Ferrisf04935c2013-12-20 18:43:21 -080080static void foreach_test_callback(const prop_info *pi, void* cookie) {
81 size_t *count = static_cast<size_t *>(cookie);
82
Dimitry Ivanov16b2a4d2017-01-24 20:43:29 +000083 ASSERT_TRUE(pi != nullptr);
Christopher Ferrisf04935c2013-12-20 18:43:21 -080084 (*count)++;
85}
86
87static void hierarchical_test_callback(const prop_info *pi, void *cookie) {
88 bool (*ok)[8][8] = static_cast<bool (*)[8][8]>(cookie);
89
90 char name[PROP_NAME_MAX];
91 char value[PROP_VALUE_MAX];
92
93 __system_property_read(pi, name, value);
94
95 int name_i, name_j, name_k;
96 int value_i, value_j, value_k;
97 ASSERT_EQ(3, sscanf(name, "property_%d.%d.%d", &name_i, &name_j, &name_k));
98 ASSERT_EQ(3, sscanf(value, "value_%d.%d.%d", &value_i, &value_j, &value_k));
99 ASSERT_EQ(name_i, value_i);
100 ASSERT_GE(name_i, 0);
101 ASSERT_LT(name_i, 8);
102 ASSERT_EQ(name_j, value_j);
103 ASSERT_GE(name_j, 0);
104 ASSERT_LT(name_j, 8);
105 ASSERT_EQ(name_k, value_k);
106 ASSERT_GE(name_k, 0);
107 ASSERT_LT(name_k, 8);
108
109 ok[name_i][name_j][name_k] = true;
110}
111
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800112#endif // __BIONIC__
113
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800114TEST(properties, __system_property_add) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800115#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800116 SystemPropertiesTest system_properties;
117 ASSERT_TRUE(system_properties.valid());
Colin Crossb27e2002013-01-28 17:19:43 -0800118
Tom Cherrye275d6d2017-12-11 23:31:33 -0800119 ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
120 ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
121 ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
Colin Crossb27e2002013-01-28 17:19:43 -0800122
Dimitry Ivanov16b2a4d2017-01-24 20:43:29 +0000123 // check that there is no limit on property name length
124 char name[PROP_NAME_MAX + 11];
125 name[0] = 'p';
126 for (size_t i = 1; i < sizeof(name); i++) {
127 name[i] = 'x';
128 }
129
130 name[sizeof(name)-1] = '\0';
Tom Cherrye275d6d2017-12-11 23:31:33 -0800131 ASSERT_EQ(0, system_properties.Add(name, strlen(name), "value", 5));
Dimitry Ivanov16b2a4d2017-01-24 20:43:29 +0000132
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800133 char propvalue[PROP_VALUE_MAX];
Tom Cherrye275d6d2017-12-11 23:31:33 -0800134 ASSERT_EQ(6, system_properties.Get("property", propvalue));
Colin Crossb27e2002013-01-28 17:19:43 -0800135 ASSERT_STREQ(propvalue, "value1");
136
Tom Cherrye275d6d2017-12-11 23:31:33 -0800137 ASSERT_EQ(6, system_properties.Get("other_property", propvalue));
Colin Crossb27e2002013-01-28 17:19:43 -0800138 ASSERT_STREQ(propvalue, "value2");
139
Tom Cherrye275d6d2017-12-11 23:31:33 -0800140 ASSERT_EQ(6, system_properties.Get("property_other", propvalue));
Colin Crossb27e2002013-01-28 17:19:43 -0800141 ASSERT_STREQ(propvalue, "value3");
Dimitry Ivanov16b2a4d2017-01-24 20:43:29 +0000142
Tom Cherrye275d6d2017-12-11 23:31:33 -0800143 ASSERT_EQ(5, system_properties.Get(name, propvalue));
Dimitry Ivanov16b2a4d2017-01-24 20:43:29 +0000144 ASSERT_STREQ(propvalue, "value");
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800145#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800146 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800147#endif // __BIONIC__
Colin Crossb27e2002013-01-28 17:19:43 -0800148}
149
Nate Myrenb8c87b12023-08-28 16:46:39 -0700150TEST(properties, __system_property_add_appcompat) {
151#if defined(__BIONIC__)
152 if (getuid() != 0) GTEST_SKIP() << "test requires root";
153 SystemPropertiesTest system_properties;
154 ASSERT_TRUE(system_properties.valid());
155
156 char name[] = "ro.property";
157 char override_name[] = "ro.appcompat_override.ro.property";
158 char name_not_written[] = "ro.property_other";
159 char override_with_no_real[] = "ro.appcompat_override.ro.property_other";
160 ASSERT_EQ(0, system_properties.Add(name, strlen(name), "value1", 6));
161 ASSERT_EQ(0, system_properties.Add(override_name, strlen(override_name), "value2", 6));
162 ASSERT_EQ(0, system_properties.Add(override_with_no_real, strlen(override_with_no_real),
163 "value3", 6));
164
165 char propvalue[PROP_VALUE_MAX];
166 ASSERT_EQ(6, system_properties.Get(name, propvalue));
167 ASSERT_STREQ(propvalue, "value1");
168
169 ASSERT_EQ(6, system_properties.Get(override_name, propvalue));
170 ASSERT_STREQ(propvalue, "value2");
171
172 ASSERT_EQ(0, system_properties.Get(name_not_written, propvalue));
173 ASSERT_STREQ(propvalue, "");
174
175 ASSERT_EQ(6, system_properties.Get(override_with_no_real, propvalue));
176 ASSERT_STREQ(propvalue, "value3");
177
178 int ret = mount(system_properties.get_appcompat_path(), system_properties.get_path(), nullptr,
179 MS_BIND | MS_REC, nullptr);
180 if (ret != 0) {
181 ASSERT_ERRNO(0);
182 }
183 system_properties.Reload(true);
184
185 ASSERT_EQ(6, system_properties.Get(name, propvalue));
186 ASSERT_STREQ(propvalue, "value2");
187
188 ASSERT_EQ(0, system_properties.Get(override_name, propvalue));
189 ASSERT_STREQ(propvalue, "");
190
191 ASSERT_EQ(6, system_properties.Get(name_not_written, propvalue));
192 ASSERT_STREQ(propvalue, "value3");
193
194 ASSERT_EQ(0, system_properties.Get(override_with_no_real, propvalue));
195 ASSERT_STREQ(propvalue, "");
196
197#else // __BIONIC__
198 GTEST_SKIP() << "bionic-only test";
199#endif // __BIONIC__
200}
201
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800202TEST(properties, __system_property_update) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800203#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800204 SystemPropertiesTest system_properties;
205 ASSERT_TRUE(system_properties.valid());
Colin Crossb27e2002013-01-28 17:19:43 -0800206
Tom Cherrye275d6d2017-12-11 23:31:33 -0800207 ASSERT_EQ(0, system_properties.Add("property", 8, "oldvalue1", 9));
208 ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
209 ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
Colin Crossb27e2002013-01-28 17:19:43 -0800210
Tom Cherrye275d6d2017-12-11 23:31:33 -0800211 const prop_info* pi = system_properties.Find("property");
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800212 ASSERT_TRUE(pi != nullptr);
Tom Cherrye275d6d2017-12-11 23:31:33 -0800213 system_properties.Update(const_cast<prop_info*>(pi), "value4", 6);
Colin Crossb27e2002013-01-28 17:19:43 -0800214
Tom Cherrye275d6d2017-12-11 23:31:33 -0800215 pi = system_properties.Find("other_property");
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800216 ASSERT_TRUE(pi != nullptr);
Tom Cherrye275d6d2017-12-11 23:31:33 -0800217 system_properties.Update(const_cast<prop_info*>(pi), "newvalue5", 9);
Colin Crossb27e2002013-01-28 17:19:43 -0800218
Tom Cherrye275d6d2017-12-11 23:31:33 -0800219 pi = system_properties.Find("property_other");
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800220 ASSERT_TRUE(pi != nullptr);
Tom Cherrye275d6d2017-12-11 23:31:33 -0800221 system_properties.Update(const_cast<prop_info*>(pi), "value6", 6);
Colin Crossb27e2002013-01-28 17:19:43 -0800222
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800223 char propvalue[PROP_VALUE_MAX];
Tom Cherrye275d6d2017-12-11 23:31:33 -0800224 ASSERT_EQ(6, system_properties.Get("property", propvalue));
Colin Crossb27e2002013-01-28 17:19:43 -0800225 ASSERT_STREQ(propvalue, "value4");
226
Tom Cherrye275d6d2017-12-11 23:31:33 -0800227 ASSERT_EQ(9, system_properties.Get("other_property", propvalue));
Colin Crossb27e2002013-01-28 17:19:43 -0800228 ASSERT_STREQ(propvalue, "newvalue5");
229
Tom Cherrye275d6d2017-12-11 23:31:33 -0800230 ASSERT_EQ(6, system_properties.Get("property_other", propvalue));
Colin Crossb27e2002013-01-28 17:19:43 -0800231 ASSERT_STREQ(propvalue, "value6");
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800232#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800233 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800234#endif // __BIONIC__
Colin Crossb27e2002013-01-28 17:19:43 -0800235}
236
Greg Hackmanncb215a72013-02-13 14:41:48 -0800237TEST(properties, fill) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800238#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800239 SystemPropertiesTest system_properties;
240 ASSERT_TRUE(system_properties.valid());
241
Colin Crossb27e2002013-01-28 17:19:43 -0800242 char prop_name[PROP_NAME_MAX];
243 char prop_value[PROP_VALUE_MAX];
244 char prop_value_ret[PROP_VALUE_MAX];
Greg Hackmanncb215a72013-02-13 14:41:48 -0800245 int count = 0;
Colin Crossb27e2002013-01-28 17:19:43 -0800246 int ret;
247
Greg Hackmanncb215a72013-02-13 14:41:48 -0800248 while (true) {
249 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", count);
Colin Crossb27e2002013-01-28 17:19:43 -0800250 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
Greg Hackmanncb215a72013-02-13 14:41:48 -0800251 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", count);
Colin Crossb27e2002013-01-28 17:19:43 -0800252 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
253 prop_name[PROP_NAME_MAX - 1] = 0;
254 prop_value[PROP_VALUE_MAX - 1] = 0;
255
Tom Cherrye275d6d2017-12-11 23:31:33 -0800256 ret = system_properties.Add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1);
Greg Hackmanncb215a72013-02-13 14:41:48 -0800257 if (ret < 0)
258 break;
259
260 count++;
Colin Crossb27e2002013-01-28 17:19:43 -0800261 }
262
Greg Hackmanncb215a72013-02-13 14:41:48 -0800263 // For historical reasons at least 247 properties must be supported
264 ASSERT_GE(count, 247);
265
266 for (int i = 0; i < count; i++) {
Colin Crossb27e2002013-01-28 17:19:43 -0800267 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d", i);
268 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
269 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d", i);
270 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
271 prop_name[PROP_NAME_MAX - 1] = 0;
272 prop_value[PROP_VALUE_MAX - 1] = 0;
273 memset(prop_value_ret, '\0', PROP_VALUE_MAX);
274
Tom Cherrye275d6d2017-12-11 23:31:33 -0800275 ASSERT_EQ(PROP_VALUE_MAX - 1, system_properties.Get(prop_name, prop_value_ret));
Colin Crossb27e2002013-01-28 17:19:43 -0800276 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
277 }
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800278#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800279 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800280#endif // __BIONIC__
Greg Hackmannc6ff8442013-02-12 16:39:31 -0800281}
282
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800283TEST(properties, __system_property_foreach) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800284#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800285 SystemPropertiesTest system_properties;
286 ASSERT_TRUE(system_properties.valid());
Greg Hackmannc6ff8442013-02-12 16:39:31 -0800287
Tom Cherrye275d6d2017-12-11 23:31:33 -0800288 ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
289 ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
290 ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
Greg Hackmannc6ff8442013-02-12 16:39:31 -0800291
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800292 size_t count = 0;
Tom Cherrye275d6d2017-12-11 23:31:33 -0800293 ASSERT_EQ(0, system_properties.Foreach(foreach_test_callback, &count));
Greg Hackmannc6ff8442013-02-12 16:39:31 -0800294 ASSERT_EQ(3U, count);
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800295#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800296 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800297#endif // __BIONIC__
Greg Hackmannc6ff8442013-02-12 16:39:31 -0800298}
299
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800300TEST(properties, __system_property_find_nth) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800301#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800302 SystemPropertiesTest system_properties;
303 ASSERT_TRUE(system_properties.valid());
Colin Crossb27e2002013-01-28 17:19:43 -0800304
Tom Cherrye275d6d2017-12-11 23:31:33 -0800305 ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
306 ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
307 ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
Colin Crossb27e2002013-01-28 17:19:43 -0800308
Elliott Hughes438e0192017-04-17 14:53:07 -0700309 char name[PROP_NAME_MAX];
310 char value[PROP_VALUE_MAX];
Tom Cherrye275d6d2017-12-11 23:31:33 -0800311 EXPECT_EQ(6, system_properties.Read(system_properties.FindNth(0), name, value));
Elliott Hughes438e0192017-04-17 14:53:07 -0700312 EXPECT_STREQ("property", name);
313 EXPECT_STREQ("value1", value);
Tom Cherrye275d6d2017-12-11 23:31:33 -0800314 EXPECT_EQ(6, system_properties.Read(system_properties.FindNth(1), name, value));
Elliott Hughes438e0192017-04-17 14:53:07 -0700315 EXPECT_STREQ("other_property", name);
316 EXPECT_STREQ("value2", value);
Tom Cherrye275d6d2017-12-11 23:31:33 -0800317 EXPECT_EQ(6, system_properties.Read(system_properties.FindNth(2), name, value));
Elliott Hughes438e0192017-04-17 14:53:07 -0700318 EXPECT_STREQ("property_other", name);
319 EXPECT_STREQ("value3", value);
320
321 for (unsigned i = 3; i < 1024; ++i) {
Tom Cherrye275d6d2017-12-11 23:31:33 -0800322 ASSERT_TRUE(system_properties.FindNth(i) == nullptr);
Elliott Hughes438e0192017-04-17 14:53:07 -0700323 }
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800324#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800325 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800326#endif // __BIONIC__
Greg Hackmannd5276422013-06-17 12:37:09 -0700327}
328
329TEST(properties, fill_hierarchical) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800330#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800331 SystemPropertiesTest system_properties;
332 ASSERT_TRUE(system_properties.valid());
333
Greg Hackmannd5276422013-06-17 12:37:09 -0700334 char prop_name[PROP_NAME_MAX];
335 char prop_value[PROP_VALUE_MAX];
336 char prop_value_ret[PROP_VALUE_MAX];
337 int ret;
338
339 for (int i = 0; i < 8; i++) {
340 for (int j = 0; j < 8; j++) {
341 for (int k = 0; k < 8; k++) {
342 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
343 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
344 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
345 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
346 prop_name[PROP_NAME_MAX - 1] = 0;
347 prop_value[PROP_VALUE_MAX - 1] = 0;
348
Tom Cherrye275d6d2017-12-11 23:31:33 -0800349 ASSERT_EQ(0, system_properties.Add(
350 prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1));
Greg Hackmannd5276422013-06-17 12:37:09 -0700351 }
352 }
353 }
354
355 for (int i = 0; i < 8; i++) {
356 for (int j = 0; j < 8; j++) {
357 for (int k = 0; k < 8; k++) {
358 ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
359 memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
360 ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
361 memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
362 prop_name[PROP_NAME_MAX - 1] = 0;
363 prop_value[PROP_VALUE_MAX - 1] = 0;
364 memset(prop_value_ret, '\0', PROP_VALUE_MAX);
365
Tom Cherrye275d6d2017-12-11 23:31:33 -0800366 ASSERT_EQ(PROP_VALUE_MAX - 1, system_properties.Get(prop_name, prop_value_ret));
Greg Hackmannd5276422013-06-17 12:37:09 -0700367 ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
368 }
369 }
370 }
371
372 bool ok[8][8][8];
373 memset(ok, 0, sizeof(ok));
Tom Cherrye275d6d2017-12-11 23:31:33 -0800374 system_properties.Foreach(hierarchical_test_callback, ok);
Greg Hackmannd5276422013-06-17 12:37:09 -0700375
376 for (int i = 0; i < 8; i++) {
377 for (int j = 0; j < 8; j++) {
378 for (int k = 0; k < 8; k++) {
379 ASSERT_TRUE(ok[i][j][k]);
380 }
381 }
382 }
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800383#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800384 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800385#endif // __BIONIC__
Greg Hackmannd5276422013-06-17 12:37:09 -0700386}
387
Colin Crossb27e2002013-01-28 17:19:43 -0800388TEST(properties, errors) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800389#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800390 SystemPropertiesTest system_properties;
391 ASSERT_TRUE(system_properties.valid());
392
Colin Crossb27e2002013-01-28 17:19:43 -0800393 char prop_value[PROP_NAME_MAX];
394
Tom Cherrye275d6d2017-12-11 23:31:33 -0800395 ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
396 ASSERT_EQ(0, system_properties.Add("other_property", 14, "value2", 6));
397 ASSERT_EQ(0, system_properties.Add("property_other", 14, "value3", 6));
Colin Crossb27e2002013-01-28 17:19:43 -0800398
Tom Cherrye275d6d2017-12-11 23:31:33 -0800399 ASSERT_EQ(0, system_properties.Find("property1"));
400 ASSERT_EQ(0, system_properties.Get("property1", prop_value));
Colin Crossb27e2002013-01-28 17:19:43 -0800401
Tom Cherrye275d6d2017-12-11 23:31:33 -0800402 ASSERT_EQ(-1, system_properties.Add("name", 4, "value", PROP_VALUE_MAX));
403 ASSERT_EQ(-1, system_properties.Update(NULL, "value", PROP_VALUE_MAX));
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800404#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800405 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800406#endif // __BIONIC__
Colin Crossb27e2002013-01-28 17:19:43 -0800407}
408
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800409TEST(properties, __system_property_serial) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800410#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800411 SystemPropertiesTest system_properties;
412 ASSERT_TRUE(system_properties.valid());
Colin Crossb27e2002013-01-28 17:19:43 -0800413
Tom Cherrye275d6d2017-12-11 23:31:33 -0800414 ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
415 const prop_info* pi = system_properties.Find("property");
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800416 ASSERT_TRUE(pi != nullptr);
Raman Tennetib481a2e2019-11-12 20:41:55 +0000417 unsigned serial = __system_property_serial(pi);
Tom Cherrye275d6d2017-12-11 23:31:33 -0800418 ASSERT_EQ(0, system_properties.Update(const_cast<prop_info*>(pi), "value2", 6));
Raman Tennetib481a2e2019-11-12 20:41:55 +0000419 ASSERT_NE(serial, __system_property_serial(pi));
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800420#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800421 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800422#endif // __BIONIC__
Colin Crossb27e2002013-01-28 17:19:43 -0800423}
424
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800425TEST(properties, __system_property_wait_any) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800426#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800427 SystemPropertiesTest system_properties;
428 ASSERT_TRUE(system_properties.valid());
Colin Crossb27e2002013-01-28 17:19:43 -0800429
Tom Cherrye275d6d2017-12-11 23:31:33 -0800430 ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
431 unsigned serial = system_properties.WaitAny(0);
Dimitry Ivanov16b2a4d2017-01-24 20:43:29 +0000432
Tom Cherrye275d6d2017-12-11 23:31:33 -0800433 prop_info* pi = const_cast<prop_info*>(system_properties.Find("property"));
Dimitry Ivanov16b2a4d2017-01-24 20:43:29 +0000434 ASSERT_TRUE(pi != nullptr);
Tom Cherrye275d6d2017-12-11 23:31:33 -0800435 system_properties.Update(pi, "value2", 6);
436 serial = system_properties.WaitAny(serial);
Colin Crossb27e2002013-01-28 17:19:43 -0800437
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800438 int flag = 0;
Tom Cherrye275d6d2017-12-11 23:31:33 -0800439 std::thread thread([&system_properties, &flag]() {
440 prop_info* pi = const_cast<prop_info*>(system_properties.Find("property"));
441 usleep(100000);
442
443 flag = 1;
444 system_properties.Update(pi, "value3", 6);
445 });
Colin Crossb27e2002013-01-28 17:19:43 -0800446 ASSERT_EQ(flag, 0);
Tom Cherrye275d6d2017-12-11 23:31:33 -0800447 serial = system_properties.WaitAny(serial);
Colin Crossb27e2002013-01-28 17:19:43 -0800448 ASSERT_EQ(flag, 1);
449
Tom Cherrye275d6d2017-12-11 23:31:33 -0800450 thread.join();
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800451#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800452 GTEST_SKIP() << "bionic-only test";
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800453#endif // __BIONIC__
454}
455
456TEST(properties, __system_property_wait) {
457#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800458 SystemPropertiesTest system_properties;
459 ASSERT_TRUE(system_properties.valid());
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800460
Tom Cherrye275d6d2017-12-11 23:31:33 -0800461 ASSERT_EQ(0, system_properties.Add("property", 8, "value1", 6));
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800462
Tom Cherrye275d6d2017-12-11 23:31:33 -0800463 prop_info* pi = const_cast<prop_info*>(system_properties.Find("property"));
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800464 ASSERT_TRUE(pi != nullptr);
465
Raman Tennetib481a2e2019-11-12 20:41:55 +0000466 unsigned serial = __system_property_serial(pi);
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800467
Tom Cherrye275d6d2017-12-11 23:31:33 -0800468 std::thread thread([&system_properties]() {
469 prop_info* pi = const_cast<prop_info*>(system_properties.Find("property"));
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800470 ASSERT_TRUE(pi != nullptr);
471
Tom Cherrye275d6d2017-12-11 23:31:33 -0800472 system_properties.Update(pi, "value2", 6);
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800473 });
474
Elliott Hughes40c885a2017-02-16 17:13:04 -0800475 uint32_t new_serial;
Tom Cherrye275d6d2017-12-11 23:31:33 -0800476 system_properties.Wait(pi, serial, &new_serial, nullptr);
Elliott Hughes40c885a2017-02-16 17:13:04 -0800477 ASSERT_GT(new_serial, serial);
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800478
479 char value[PROP_VALUE_MAX];
Tom Cherrye275d6d2017-12-11 23:31:33 -0800480 ASSERT_EQ(6, system_properties.Get("property", value));
Elliott Hughesa0d374d2017-02-10 18:13:46 -0800481 ASSERT_STREQ("value2", value);
482
483 thread.join();
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800484#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800485 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800486#endif // __BIONIC__
Colin Crossb27e2002013-01-28 17:19:43 -0800487}
488
489class KilledByFault {
490 public:
491 explicit KilledByFault() {};
492 bool operator()(int exit_status) const;
493};
494
495bool KilledByFault::operator()(int exit_status) const {
496 return WIFSIGNALED(exit_status) &&
497 (WTERMSIG(exit_status) == SIGSEGV ||
498 WTERMSIG(exit_status) == SIGBUS ||
499 WTERMSIG(exit_status) == SIGABRT);
500}
501
Elliott Hughes141b9172021-04-09 17:13:09 -0700502using properties_DeathTest = SilentDeathTest;
Yabin Cui9df70402014-11-05 18:01:01 -0800503
504TEST_F(properties_DeathTest, read_only) {
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800505#if defined(__BIONIC__)
Elliott Hughese4375192013-10-21 17:09:52 -0700506
507 // This test only makes sense if we're talking to the real system property service.
508 struct stat sb;
Nate Myrenb8c87b12023-08-28 16:46:39 -0700509 ASSERT_FALSE(stat(PROP_DIRNAME, &sb) == -1 && errno == ENOENT);
Elliott Hughese4375192013-10-21 17:09:52 -0700510
511 ASSERT_EXIT(__system_property_add("property", 8, "value", 5), KilledByFault(), "");
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800512#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800513 GTEST_SKIP() << "bionic-only test";
Christopher Ferrisf04935c2013-12-20 18:43:21 -0800514#endif // __BIONIC__
Colin Crossb27e2002013-01-28 17:19:43 -0800515}
Tom Cherry8a311632017-10-09 13:49:17 -0700516
517TEST(properties, __system_property_extra_long_read_only) {
518#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800519 SystemPropertiesTest system_properties;
520 ASSERT_TRUE(system_properties.valid());
Tom Cherry8a311632017-10-09 13:49:17 -0700521
522 std::vector<std::pair<std::string, std::string>> short_properties = {
523 { "ro.0char", std::string() },
524 { "ro.50char", std::string(50, 'x') },
525 { "ro.91char", std::string(91, 'x') },
526 };
527
528 std::vector<std::pair<std::string, std::string>> long_properties = {
529 { "ro.92char", std::string(92, 'x') },
530 { "ro.93char", std::string(93, 'x') },
531 { "ro.1000char", std::string(1000, 'x') },
532 };
533
534 for (const auto& property : short_properties) {
535 const std::string& name = property.first;
536 const std::string& value = property.second;
Tom Cherrye275d6d2017-12-11 23:31:33 -0800537 ASSERT_EQ(0, system_properties.Add(name.c_str(), name.size(), value.c_str(), value.size()));
Tom Cherry8a311632017-10-09 13:49:17 -0700538 }
539
540 for (const auto& property : long_properties) {
541 const std::string& name = property.first;
542 const std::string& value = property.second;
Tom Cherrye275d6d2017-12-11 23:31:33 -0800543 ASSERT_EQ(0, system_properties.Add(name.c_str(), name.size(), value.c_str(), value.size()));
Tom Cherry8a311632017-10-09 13:49:17 -0700544 }
545
Tom Cherrye275d6d2017-12-11 23:31:33 -0800546 auto check_with_legacy_read = [&system_properties](const std::string& name,
547 const std::string& expected_value) {
Tom Cherry8a311632017-10-09 13:49:17 -0700548 char value[PROP_VALUE_MAX];
Tom Cherrye275d6d2017-12-11 23:31:33 -0800549 EXPECT_EQ(static_cast<int>(expected_value.size()), system_properties.Get(name.c_str(), value))
Tom Cherry8a311632017-10-09 13:49:17 -0700550 << name;
551 EXPECT_EQ(expected_value, value) << name;
552 };
553
Tom Cherrye275d6d2017-12-11 23:31:33 -0800554 auto check_with_read_callback = [&system_properties](const std::string& name,
555 const std::string& expected_value) {
556 const prop_info* pi = system_properties.Find(name.c_str());
Tom Cherry8a311632017-10-09 13:49:17 -0700557 ASSERT_NE(nullptr, pi);
558 std::string value;
Tom Cherrye275d6d2017-12-11 23:31:33 -0800559 system_properties.ReadCallback(pi,
560 [](void* cookie, const char*, const char* value, uint32_t) {
561 auto* out_value = reinterpret_cast<std::string*>(cookie);
562 *out_value = value;
563 },
564 &value);
Tom Cherry8a311632017-10-09 13:49:17 -0700565 EXPECT_EQ(expected_value, value) << name;
566 };
567
568 for (const auto& property : short_properties) {
569 const std::string& name = property.first;
570 const std::string& value = property.second;
571 check_with_legacy_read(name, value);
572 check_with_read_callback(name, value);
573 }
574
Elliott Hughes30088842023-09-14 18:35:11 +0000575 static constexpr const char* kExtraLongLegacyError =
Tom Cherry8a311632017-10-09 13:49:17 -0700576 "Must use __system_property_read_callback() to read";
577 for (const auto& property : long_properties) {
578 const std::string& name = property.first;
579 const std::string& value = property.second;
580 check_with_legacy_read(name, kExtraLongLegacyError);
581 check_with_read_callback(name, value);
582 }
583
584#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800585 GTEST_SKIP() << "bionic-only test";
Tom Cherry8a311632017-10-09 13:49:17 -0700586#endif // __BIONIC__
587}
588
589// pa_size is 128 * 1024 currently, if a property is longer then we expect it to fail gracefully.
590TEST(properties, __system_property_extra_long_read_only_too_long) {
591#if defined(__BIONIC__)
Tom Cherrye275d6d2017-12-11 23:31:33 -0800592 SystemPropertiesTest system_properties;
593 ASSERT_TRUE(system_properties.valid());
Tom Cherry8a311632017-10-09 13:49:17 -0700594
595 auto name = "ro.super_long_property"s;
Dennis Shen5951b412023-12-21 19:57:13 +0000596
597#ifdef LARGE_SYSTEM_PROPERTY_NODE
598 auto value = std::string(1024 * 1024 + 1, 'x');
599#else
Dennis Shen3d1ce8c2024-01-04 14:18:38 +0000600 auto value = std::string(128 * 1024 + 1, 'x');
Dennis Shen5951b412023-12-21 19:57:13 +0000601#endif
602
Tom Cherrye275d6d2017-12-11 23:31:33 -0800603 ASSERT_NE(0, system_properties.Add(name.c_str(), name.size(), value.c_str(), value.size()));
Tom Cherry8a311632017-10-09 13:49:17 -0700604
605#else // __BIONIC__
Elliott Hughesbcaa4542019-03-08 15:20:23 -0800606 GTEST_SKIP() << "bionic-only test";
Tom Cherry8a311632017-10-09 13:49:17 -0700607#endif // __BIONIC__
608}
Nate Myren0ab06152023-10-19 16:50:59 -0700609
610// Note that this test affects global state of the system
611// this tests tries to mitigate this by using utime+pid
612// prefix for the property name. It is still results in
613// pollution of property service since properties cannot
614// be removed.
615//
616// Note that there is also possibility to run into "out-of-memory"
617// if this test if it is executed often enough without reboot.
618TEST(properties, __system_property_reload_no_op) {
619#if defined(__BIONIC__)
620 std::string property_name =
621 android::base::StringPrintf("debug.test.%d.%" PRId64 ".property", getpid(), NanoTime());
622 ASSERT_EQ(0, __system_property_find(property_name.c_str()));
623 ASSERT_EQ(0, __system_property_set(property_name.c_str(), "test value"));
624 ASSERT_EQ(0, __system_properties_zygote_reload());
625 const prop_info* readptr = __system_property_find(property_name.c_str());
626 std::string expected_name = property_name;
627 __system_property_read_callback(
628 readptr,
629 [](void*, const char*, const char* value, unsigned) { ASSERT_STREQ("test value", value); },
630 &expected_name);
631#else // __BIONIC__
632 GTEST_SKIP() << "bionic-only test";
633#endif // __BIONIC__
634}
635
636TEST(properties, __system_property_reload_invalid) {
637#if defined(__BIONIC__)
638 if (getuid() != 0) GTEST_SKIP() << "test requires root";
639 SystemPropertiesTest system_properties;
640
641 // Create an invalid property_info file, so the system will attempt to initialize a
642 // ContextSerialized
643 std::string property_info_file =
644 android::base::StringPrintf("%s/property_info", system_properties.get_path());
645 fclose(fopen(property_info_file.c_str(), "w"));
646 int ret = mount(system_properties.get_path(), system_properties.get_real_sysprop_dir(), nullptr,
647 MS_BIND | MS_REC, nullptr);
648 if (ret != 0) {
649 ASSERT_ERRNO(0);
650 }
651
652 ASSERT_EQ(-1, __system_properties_zygote_reload());
653#else // __BIONIC__
654 GTEST_SKIP() << "bionic-only test";
655#endif // __BIONIC__
656}
657
658// Note that this test affects global state of the system
659// this tests tries to mitigate this by using utime+pid
660// prefix for the property name. It is still results in
661// pollution of property service since properties cannot
662// be removed.
663//
664// Note that there is also possibility to run into "out-of-memory"
665// if this test if it is executed often enough without reboot.
666TEST(properties, __system_property_reload_valid) {
667#if defined(__BIONIC__)
668 if (getuid() != 0) GTEST_SKIP() << "test requires root";
669 SystemPropertiesTest system_properties;
670
671 // Copy the system properties files into the temp directory
672 std::string shell_cmd = android::base::StringPrintf(
673 "cp -r %s %s", system_properties.get_real_sysprop_dir(), system_properties.get_path());
674 system(shell_cmd.c_str());
675
676 // Write a system property to the current set of system properties
677 std::string property_name =
678 android::base::StringPrintf("debug.test.%d.%" PRId64 ".property", getpid(), NanoTime());
679 ASSERT_EQ(0, __system_property_find(property_name.c_str()));
680 ASSERT_EQ(0, __system_property_set(property_name.c_str(), "test value"));
681
682 // Mount the temp directory (which doesn't have the property we just wrote) in place of the
683 // real one
684 int ret = mount(system_properties.get_mount_path(), system_properties.get_real_sysprop_dir(),
685 nullptr, MS_BIND | MS_REC, nullptr);
686 if (ret != 0) {
687 ASSERT_ERRNO(0);
688 }
689
690 // reload system properties in the new dir, and verify the property we wrote after we copied the
691 // files isn't there
692 ASSERT_EQ(0, __system_properties_zygote_reload());
693 ASSERT_EQ(0, __system_property_find(property_name.c_str()));
694
695#else // __BIONIC__
696 GTEST_SKIP() << "bionic-only test";
697#endif // __BIONIC__
698}