Merge "Add test for ambient caps"
diff --git a/README.md b/README.md
index 0dd7490..61314b6 100644
--- a/README.md
+++ b/README.md
@@ -200,9 +200,8 @@
### Device tests
- $ mma
- $ adb remount
- $ adb sync
+ $ mma # In $ANDROID_ROOT/bionic.
+ $ adb root && adb remount && adb sync
$ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
$ adb shell \
/data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
@@ -216,6 +215,30 @@
<https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#running-test-programs-advanced-options>,
in particular for test isolation and parallelism (both on by default).
+### Device tests via CTS
+
+Most of the unit tests are executed by CTS. By default, CTS runs as
+a non-root user, so the unit tests must also pass when not run as root.
+Some tests cannot do any useful work unless run as root. In this case,
+the test should check `getuid() == 0` and do nothing otherwise (typically
+we log in this case to prevent accidents!). Obviously, if the test can be
+rewritten to not require root, that's an even better solution.
+
+Currently, the list of bionic CTS tests is generated at build time by
+running a host version of the test executable and dumping the list of
+all tests. In order for this to continue to work, all architectures must
+have the same number of tests, and the host version of the executable
+must also have the same number of tests.
+
+Running the gtests directly is orders of magnitude faster than using CTS,
+but in cases where you really have to run CTS:
+
+ $ make cts # In $ANDROID_ROOT.
+ $ adb unroot # Because real CTS doesn't run as root.
+ # This will sync any *test* changes, but not *code* changes:
+ $ cts-tradefed \
+ run singleCommand cts --skip-preconditions -m CtsBionicTestCases
+
### Host tests
The host tests require that you have `lunch`ed either an x86 or x86_64 target.
diff --git a/libc/Android.bp b/libc/Android.bp
index 05df811..b1d077d 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1578,10 +1578,9 @@
// dynamic linker.
cc_library_static {
+ name: "libc_nomalloc",
+
defaults: ["libc_defaults"],
- srcs: [
- "bionic/dl_iterate_phdr_static.cpp",
- ],
arch: {
arm: {
@@ -1591,8 +1590,6 @@
cflags: ["-DLIBC_STATIC"],
- name: "libc_nomalloc",
-
whole_static_libs: [
"libc_common",
"libc_init_static",
diff --git a/libc/bionic/wcstod.cpp b/libc/bionic/wcstod.cpp
index eb66ba0..f7bd433 100644
--- a/libc/bionic/wcstod.cpp
+++ b/libc/bionic/wcstod.cpp
@@ -32,8 +32,14 @@
#include "local.h"
-template <typename float_type> float_type wcstod(const wchar_t* str, wchar_t** end,
- float_type strtod_fn(const char*, char**)) {
+/// Performs wide-character string to floating point conversion.
+template <typename float_type>
+float_type wcstod(const wchar_t* str, wchar_t** end, float_type strtod_fn(const char*, char**)) {
+ const wchar_t* original_str = str;
+ while (iswspace(*str)) {
+ str++;
+ }
+
// What's the longest span of the input that might be part of the float?
size_t max_len = wcsspn(str, L"-+0123456789.xXeEpP()nNaAiIfFtTyY");
@@ -70,7 +76,15 @@
float_type result = strtod_fn(ascii_str, &ascii_end);
if (ascii_end != ascii_str + actual_len) abort();
- if (end) *end = const_cast<wchar_t*>(str) + actual_len;
+ if (end) {
+ if (actual_len == 0) {
+ // There was an error. We need to set the end pointer back to the original string, not the
+ // one we advanced past the leading whitespace.
+ *end = const_cast<wchar_t*>(original_str);
+ } else {
+ *end = const_cast<wchar_t*>(str) + actual_len;
+ }
+ }
delete[] ascii_str;
return result;
diff --git a/libc/dns/net/getaddrinfo.c b/libc/dns/net/getaddrinfo.c
index c6f0d24..6c26cd3 100644
--- a/libc/dns/net/getaddrinfo.c
+++ b/libc/dns/net/getaddrinfo.c
@@ -108,10 +108,6 @@
#include <stdarg.h>
#include "nsswitch.h"
-#if defined(__BIONIC__)
-#include <sys/system_properties.h>
-#endif
-
typedef union sockaddr_union {
struct sockaddr generic;
struct sockaddr_in in;
diff --git a/libc/dns/net/getnameinfo.c b/libc/dns/net/getnameinfo.c
index 63a347e..236e7f2 100644
--- a/libc/dns/net/getnameinfo.c
+++ b/libc/dns/net/getnameinfo.c
@@ -62,7 +62,6 @@
#include <arpa/nameser.h>
#include "resolv_netid.h"
#include "resolv_private.h"
-#include <sys/system_properties.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
diff --git a/libc/dns/resolv/res_cache.c b/libc/dns/resolv/res_cache.c
index ad2c5c0..8b3c76b 100644
--- a/libc/dns/resolv/res_cache.c
+++ b/libc/dns/resolv/res_cache.c
@@ -38,7 +38,6 @@
#include <errno.h>
#include <arpa/nameser.h>
-#include <sys/system_properties.h>
#include <net/if.h>
#include <netdb.h>
#include <linux/if.h>
@@ -137,7 +136,6 @@
* *****************************************
*/
#define CONFIG_MAX_ENTRIES 64 * 2 * 5
-/* name of the system property that can be used to set the cache size */
/****************************************************************************/
/****************************************************************************/
@@ -2010,8 +2008,8 @@
}
cache_info->nscount = numservers;
- // Flush the cache and reset the stats.
- _flush_cache_for_net_locked(netid);
+ // Clear the NS statistics because the mapping to nameservers might have changed.
+ _res_cache_clear_stats_locked(cache_info);
// increment the revision id to ensure that sample state is not written back if the
// servers change; in theory it would suffice to do so only if the servers or
@@ -2286,4 +2284,3 @@
pthread_mutex_unlock(&_res_cache_list_lock);
}
-
diff --git a/libc/dns/resolv/res_init.c b/libc/dns/resolv/res_init.c
index a5413dd..b9fc131 100644
--- a/libc/dns/resolv/res_init.c
+++ b/libc/dns/resolv/res_init.c
@@ -101,7 +101,6 @@
#ifdef ANDROID_CHANGES
#include <errno.h>
#include <fcntl.h>
-#include <sys/system_properties.h>
#endif /* ANDROID_CHANGES */
/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
diff --git a/libc/dns/resolv/res_state.c b/libc/dns/resolv/res_state.c
index 0e02a8f..4ed168c 100644
--- a/libc/dns/resolv/res_state.c
+++ b/libc/dns/resolv/res_state.c
@@ -36,8 +36,6 @@
#include <stdlib.h>
#include <string.h>
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
/* Set to 1 to enable debug traces */
#define DEBUG 0
@@ -54,8 +52,6 @@
int _h_errno;
// TODO: Have one __res_state per network so we don't have to repopulate frequently.
struct __res_state _nres[1];
- unsigned _serial;
- struct prop_info* _pi;
struct res_static _rstatic[1];
} _res_thread;
@@ -66,12 +62,6 @@
if (rt) {
rt->_h_errno = 0;
- /* Special system property which tracks any changes to 'net.*'. */
- rt->_serial = 0;
- rt->_pi = (struct prop_info*) __system_property_find("net.change");
- if (rt->_pi) {
- rt->_serial = __system_property_serial(rt->_pi);
- }
memset(rt->_rstatic, 0, sizeof rt->_rstatic);
}
return rt;
@@ -116,32 +106,7 @@
rt = pthread_getspecific( _res_key );
if (rt != NULL) {
- /* We already have one thread-specific DNS state object.
- * Check the serial value for any changes to net.* properties */
- D("%s: Called for tid=%d rt=%p rt->pi=%p rt->serial=%d",
- __FUNCTION__, gettid(), rt, rt->_pi, rt->_serial);
- if (rt->_pi == NULL) {
- /* The property wasn't created when _res_thread_get() was
- * called the last time. This should only happen very
- * early during the boot sequence. First, let's try to see if it
- * is here now. */
- rt->_pi = (struct prop_info*) __system_property_find("net.change");
- if (rt->_pi == NULL) {
- /* Still nothing, return current state */
- D("%s: exiting for tid=%d rt=%p since system property not found",
- __FUNCTION__, gettid(), rt);
- return rt;
- }
- }
- if (rt->_serial == __system_property_serial(rt->_pi)) {
- /* Nothing changed, so return the current state */
- D("%s: tid=%d rt=%p nothing changed, returning",
- __FUNCTION__, gettid(), rt);
- return rt;
- }
- /* Update the recorded serial number, and go reset the state */
- rt->_serial = __system_property_serial(rt->_pi);
- goto RESET_STATE;
+ return rt;
}
/* It is the first time this function is called in this thread,
@@ -154,11 +119,10 @@
D("%s: tid=%d Created new DNS state rt=%p",
__FUNCTION__, gettid(), rt);
-RESET_STATE:
/* Reset the state, note that res_ninit() can now properly reset
* an existing state without leaking memory.
*/
- D("%s: tid=%d, rt=%p, resetting DNS state (options RES_INIT=%d)",
+ D("%s: tid=%d, rt=%p, setting DNS state (options RES_INIT=%d)",
__FUNCTION__, gettid(), rt, (rt->_nres->options & RES_INIT) != 0);
if ( res_ninit( rt->_nres ) < 0 ) {
/* This should not happen */
diff --git a/linker/Android.bp b/linker/Android.bp
index 5745d73..1b7b5a7 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -103,6 +103,12 @@
cppflags: ["-Wold-style-cast"],
+ // we are going to link libc++_static manually because
+ // when stl is not set to "none" build system adds libdl
+ // to the list of static libraries which needs to be
+ // avoided in the case of building loader.
+ stl: "none",
+
// we don't want crtbegin.o (because we have begin.o), so unset it
// just for this module
nocrt: true,
@@ -114,6 +120,7 @@
"libbase",
"libz",
"liblog",
+ "libc++_static",
// Important: The liblinker_malloc should be the last library in the list
// to overwrite any other malloc implementations by other static libraries.
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 62e6bb6..be4b584 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1785,18 +1785,21 @@
std::string asan_name_holder;
const char* translated_name = name;
- if (g_is_asan) {
- if (file_is_in_dir(name, kSystemLibDir)) {
- asan_name_holder = std::string(kAsanSystemLibDir) + "/" + basename(name);
- if (file_exists(asan_name_holder.c_str())) {
- translated_name = asan_name_holder.c_str();
- PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
- }
- } else if (file_is_in_dir(name, kVendorLibDir)) {
- asan_name_holder = std::string(kAsanVendorLibDir) + "/" + basename(name);
- if (file_exists(asan_name_holder.c_str())) {
- translated_name = asan_name_holder.c_str();
- PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+ if (g_is_asan && translated_name != nullptr && translated_name[0] == '/') {
+ char translated_path[PATH_MAX];
+ if (realpath(translated_name, translated_path) != nullptr) {
+ if (file_is_in_dir(translated_path, kSystemLibDir)) {
+ asan_name_holder = std::string(kAsanSystemLibDir) + "/" + basename(translated_path);
+ if (file_exists(asan_name_holder.c_str())) {
+ translated_name = asan_name_holder.c_str();
+ PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+ }
+ } else if (file_is_in_dir(translated_path, kVendorLibDir)) {
+ asan_name_holder = std::string(kAsanVendorLibDir) + "/" + basename(translated_path);
+ if (file_exists(asan_name_holder.c_str())) {
+ translated_name = asan_name_holder.c_str();
+ PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+ }
}
}
}
diff --git a/tests/pty_test.cpp b/tests/pty_test.cpp
index 9b5785a..74415d5 100644
--- a/tests/pty_test.cpp
+++ b/tests/pty_test.cpp
@@ -14,11 +14,17 @@
* limitations under the License.
*/
+#include <pty.h>
+
#include <gtest/gtest.h>
-#include <pty.h>
+#include <pthread.h>
#include <sys/ioctl.h>
+#include <atomic>
+
+#include <android-base/file.h>
+
#include "utils.h"
TEST(pty, openpty) {
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 5b9442f..fc17cde 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -298,6 +298,11 @@
EXPECT_PRED_FORMAT2(pred, 9.0, fn("0.9e1", nullptr));
EXPECT_PRED_FORMAT2(pred, 9.0, fn("0x1.2p3", nullptr));
+ const char* s = " \t\v\f\r\n9.0";
+ char* p;
+ EXPECT_PRED_FORMAT2(pred, 9.0, fn(s, &p));
+ EXPECT_EQ(s + strlen(s), p);
+
EXPECT_TRUE(isnan(fn("+nan", nullptr)));
EXPECT_TRUE(isnan(fn("nan", nullptr)));
EXPECT_TRUE(isnan(fn("-nan", nullptr)));
@@ -306,7 +311,6 @@
EXPECT_TRUE(isnan(fn("nan(0xff)", nullptr)));
EXPECT_TRUE(isnan(fn("-nan(0xff)", nullptr)));
- char* p;
EXPECT_TRUE(isnan(fn("+nanny", &p)));
EXPECT_STREQ("ny", p);
EXPECT_TRUE(isnan(fn("nanny", &p)));
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 34ed5a7..830eb70 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -686,6 +686,11 @@
EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0.9e1", nullptr));
EXPECT_PRED_FORMAT2(pred, 9.0, fn(L"0x1.2p3", nullptr));
+ const wchar_t* s = L" \t\v\f\r\n9.0";
+ wchar_t* p;
+ EXPECT_PRED_FORMAT2(pred, 9.0, fn(s, &p));
+ EXPECT_EQ(s + wcslen(s), p);
+
EXPECT_TRUE(isnan(fn(L"+nan", nullptr)));
EXPECT_TRUE(isnan(fn(L"nan", nullptr)));
EXPECT_TRUE(isnan(fn(L"-nan", nullptr)));
@@ -694,7 +699,6 @@
EXPECT_TRUE(isnan(fn(L"nan(0xff)", nullptr)));
EXPECT_TRUE(isnan(fn(L"-nan(0xff)", nullptr)));
- wchar_t* p;
EXPECT_TRUE(isnan(fn(L"+nanny", &p)));
EXPECT_STREQ(L"ny", p);
EXPECT_TRUE(isnan(fn(L"nanny", &p)));