Check that __system_property_set() doesn't leak FDs
Bug: 143936364
Test: fail when b/143936364 repros
Test: pass when b/143936364 is fixed
Change-Id: I01d061c4fb4f37b0300ef418a19c88003038092c
diff --git a/tests/system_properties_test2.cpp b/tests/system_properties_test2.cpp
index b9936dd..0953bde 100644
--- a/tests/system_properties_test2.cpp
+++ b/tests/system_properties_test2.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include <gtest/gtest.h>
-
#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -24,6 +22,10 @@
#include <sstream>
#include <string>
+#include <gtest/gtest.h>
+
+#include "utils.h"
+
#if defined(__BIONIC__)
#include <sys/system_properties.h>
int64_t NanoTime() {
@@ -128,6 +130,29 @@
#endif // __BIONIC__
}
+TEST(properties, no_fd_leaks) {
+#if defined(__BIONIC__)
+ FdLeakChecker leak_checker;
+ std::stringstream ss;
+ ss << "debug.test." << getpid() << "." << NanoTime() << ".";
+ const std::string property_prefix = ss.str();
+ const std::string property_name = property_prefix + "property1";
+
+ for (size_t i = 0; i < 100; ++i) {
+ char propvalue[PROP_VALUE_MAX];
+ ASSERT_EQ(0, __system_property_set(property_name.c_str(), "value1"));
+ ASSERT_EQ(6, __system_property_get(property_name.c_str(), propvalue));
+ ASSERT_STREQ("value1", propvalue);
+
+ ASSERT_EQ(0, __system_property_set(property_name.c_str(), "value2"));
+ ASSERT_EQ(6, __system_property_get(property_name.c_str(), propvalue));
+ ASSERT_STREQ("value2", propvalue);
+ }
+#else // __BIONIC__
+ GTEST_SKIP() << "bionic-only test";
+#endif // __BIONIC__
+}
+
TEST(properties, empty_value) {
#if defined(__BIONIC__)
char propvalue[PROP_VALUE_MAX];
@@ -136,13 +161,13 @@
ss << "debug.test." << getpid() << "." << NanoTime() << "." << "property_empty";
const std::string property_name = ss.str();
- for (size_t i=0; i<1000; ++i) {
+ for (size_t i = 0; i < 1000; ++i) {
ASSERT_EQ(0, __system_property_set(property_name.c_str(), ""));
ASSERT_EQ(0, __system_property_get(property_name.c_str(), propvalue));
ASSERT_STREQ("", propvalue);
}
-#else // __BIONIC__
- GTEST_SKIP() << "bionic-only test";
+#else // __BIONIC__
+ GTEST_SKIP() << "bionic-only test";
#endif // __BIONIC__
}
diff --git a/tests/utils.h b/tests/utils.h
index 1f4cece..cfc68c9 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -16,6 +16,7 @@
#pragma once
+#include <dirent.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -253,3 +254,29 @@
std::string output_;
};
#endif
+
+class FdLeakChecker {
+ public:
+ FdLeakChecker() {
+ }
+
+ ~FdLeakChecker() {
+ size_t end_count = CountOpenFds();
+ EXPECT_EQ(start_count_, end_count);
+ }
+
+ private:
+ static size_t CountOpenFds() {
+ auto fd_dir = std::unique_ptr<DIR, decltype(&closedir)>{ opendir("/proc/self/fd"), closedir };
+ size_t count = 0;
+ dirent* de = nullptr;
+ while ((de = readdir(fd_dir.get())) != nullptr) {
+ if (de->d_type == DT_LNK) {
+ ++count;
+ }
+ }
+ return count;
+ }
+
+ size_t start_count_ = CountOpenFds();
+};