Merge changes I975ba933,Ica9d211b am: a9ef4dc7a2
am: 9ece9401a4
Change-Id: I4aceabe7b0d39d0a2cf214577d6764d30fc95858
diff --git a/base/file.cpp b/base/file.cpp
index 32c2439..81b04d7 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -238,8 +238,11 @@
#endif
}
-std::string Basename(const std::string& path) {
+std::string GetExecutableDirectory() {
+ return Dirname(GetExecutablePath());
+}
+std::string Basename(const std::string& path) {
// Copy path because basename may modify the string passed in.
std::string result(path);
diff --git a/base/file_test.cpp b/base/file_test.cpp
index bbd5037..1021326 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -159,6 +159,14 @@
#endif
}
+TEST(file, GetExecutableDirectory) {
+ std::string path = android::base::GetExecutableDirectory();
+ ASSERT_NE("", path);
+ ASSERT_NE(android::base::GetExecutablePath(), path);
+ ASSERT_EQ('/', path[0]);
+ ASSERT_NE('/', path[path.size() - 1]);
+}
+
TEST(file, GetExecutablePath) {
ASSERT_NE("", android::base::GetExecutablePath());
}
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index c7e094e..33d1ab3 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -51,6 +51,7 @@
#endif
std::string GetExecutablePath();
+std::string GetExecutableDirectory();
// Like the regular basename and dirname, but thread-safe on all
// platforms and capable of correctly handling exotic Windows paths.
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
index 70ada72..ea606a1 100644
--- a/libutils/tests/Android.bp
+++ b/libutils/tests/Android.bp
@@ -23,6 +23,7 @@
srcs: [
"BitSet_test.cpp",
"LruCache_test.cpp",
+ "Singleton_test.cpp",
"String8_test.cpp",
"StrongPointer_test.cpp",
"Unicode_test.cpp",
@@ -42,6 +43,8 @@
"liblog",
"libcutils",
"libutils",
+ "libbase",
+ "libdl",
],
},
linux: {
@@ -54,13 +57,35 @@
static_libs: [
"libutils",
"liblog",
+ "libbase",
],
+ host_ldlibs: ["-ldl"],
},
},
+ required: [
+ "libutils_tests_singleton1",
+ "libutils_tests_singleton2",
+ ],
+
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
}
+
+cc_test_library {
+ name: "libutils_tests_singleton1",
+ host_supported: true,
+ relative_install_path: "libutils_tests",
+ srcs: ["Singleton_test1.cpp"],
+}
+
+cc_test_library {
+ name: "libutils_tests_singleton2",
+ host_supported: true,
+ relative_install_path: "libutils_tests",
+ srcs: ["Singleton_test2.cpp"],
+ shared_libs: ["libutils_tests_singleton1"],
+}
diff --git a/libutils/tests/Singleton_test.cpp b/libutils/tests/Singleton_test.cpp
new file mode 100644
index 0000000..9acd3c3
--- /dev/null
+++ b/libutils/tests/Singleton_test.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#define LOG_TAG "Singleton_test"
+
+#include <dlfcn.h>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <utils/Singleton.h>
+
+#include <gtest/gtest.h>
+
+#include "Singleton_test.h"
+
+namespace android {
+
+TEST(SingletonTest, bug35674422) {
+ std::string path = android::base::GetExecutableDirectory();
+ // libutils_tests_singleton1.so contains the ANDROID_SINGLETON_STATIC_INSTANCE
+ // definition of SingletonTestData, load it first.
+ std::string lib = android::base::StringPrintf("%s/libutils_tests_singleton1.so", path.c_str());
+ void* handle1 = dlopen(lib.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle1 != nullptr) << dlerror();
+
+ // libutils_tests_singleton2.so references SingletonTestData but should not
+ // have a definition
+ lib = android::base::StringPrintf("%s/libutils_tests_singleton2.so", path.c_str());
+ void* handle2 = dlopen(lib.c_str(), RTLD_NOW);
+ ASSERT_TRUE(handle2 != nullptr) << dlerror();
+
+ using has_fn_t = decltype(&singletonHasInstance);
+ using get_fn_t = decltype(&singletonGetInstanceContents);
+ using set_fn_t = decltype(&singletonSetInstanceContents);
+
+ has_fn_t has1 = reinterpret_cast<has_fn_t>(dlsym(handle1, "singletonHasInstance"));
+ ASSERT_TRUE(has1 != nullptr) << dlerror();
+ has_fn_t has2 = reinterpret_cast<has_fn_t>(dlsym(handle2, "singletonHasInstance"));
+ ASSERT_TRUE(has2 != nullptr) << dlerror();
+ get_fn_t get1 = reinterpret_cast<get_fn_t>(dlsym(handle1, "singletonGetInstanceContents"));
+ ASSERT_TRUE(get1 != nullptr) << dlerror();
+ get_fn_t get2 = reinterpret_cast<get_fn_t>(dlsym(handle2, "singletonGetInstanceContents"));
+ ASSERT_TRUE(get2 != nullptr) << dlerror();
+ set_fn_t set1 = reinterpret_cast<set_fn_t>(dlsym(handle2, "singletonSetInstanceContents"));
+ ASSERT_TRUE(set1 != nullptr) << dlerror();
+
+ EXPECT_FALSE(has1());
+ EXPECT_FALSE(has2());
+ set1(12345678U);
+ EXPECT_TRUE(has1());
+ EXPECT_TRUE(has2());
+ EXPECT_EQ(12345678U, get1());
+ EXPECT_EQ(12345678U, get2());
+}
+
+}
diff --git a/libutils/tests/Singleton_test.h b/libutils/tests/Singleton_test.h
new file mode 100644
index 0000000..c77d9ff
--- /dev/null
+++ b/libutils/tests/Singleton_test.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_UTILS_SINGLETON_TEST_H
+#define ANDROID_UTILS_SINGLETON_TEST_H
+
+#include <sys/cdefs.h>
+
+#include "Singleton_test.h"
+
+namespace android {
+
+struct SingletonTestData : Singleton<SingletonTestData> {
+ unsigned int contents;
+};
+
+__BEGIN_DECLS
+
+unsigned int singletonGetInstanceContents();
+void singletonSetInstanceContents(unsigned int);
+bool singletonHasInstance();
+
+__END_DECLS
+
+}
+
+#endif // ANDROID_UTILS_SINGLETON_TEST_H
+
diff --git a/libutils/tests/Singleton_test1.cpp b/libutils/tests/Singleton_test1.cpp
new file mode 100644
index 0000000..4a91ec0
--- /dev/null
+++ b/libutils/tests/Singleton_test1.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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 <utils/Singleton.h>
+
+#include "Singleton_test.h"
+
+namespace android {
+
+// Singleton<SingletonTestStruct> is referenced in Singleton_test1.cpp and
+// Singleton_test2.cpp, but only defined in Singleton_test1.cpp.
+ANDROID_SINGLETON_STATIC_INSTANCE(SingletonTestData);
+
+void singletonSetInstanceContents(unsigned int contents) {
+ SingletonTestData::getInstance().contents = contents;
+}
+
+unsigned int singletonGetInstanceContents() {
+ return SingletonTestData::getInstance().contents;
+}
+
+bool singletonHasInstance() {
+ return SingletonTestData::hasInstance();
+}
+
+}
diff --git a/libutils/tests/Singleton_test2.cpp b/libutils/tests/Singleton_test2.cpp
new file mode 100644
index 0000000..eb2a9df
--- /dev/null
+++ b/libutils/tests/Singleton_test2.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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 <utils/Singleton.h>
+
+#include "Singleton_test.h"
+
+namespace android {
+
+// Singleton<SingletonTestStruct> is referenced in Singleton_test1.cpp and
+// Singleton_test2.cpp, but only defined in Singleton_test1.cpp.
+
+void singletonSetInstanceContents(unsigned int contents) {
+ SingletonTestData::getInstance().contents = contents;
+}
+
+unsigned int singletonGetInstanceContents() {
+ return SingletonTestData::getInstance().contents;
+}
+
+bool singletonHasInstance() {
+ return SingletonTestData::hasInstance();
+}
+
+}