unsigned int TestClient::GetPcRegisterId() { if (m_pc_register != UINT_MAX) return m_pc_register; for (unsigned int register_id = 0;; register_id++) { std::string message = formatv("qRegisterInfo{0:x-}", register_id).str(); std::string response; if (!SendMessage(message, response)) { GTEST_LOG_(ERROR) << "Unable to query register ID for PC register."; return UINT_MAX; } auto elements_or_error = SplitPairList("GetPcRegisterId", response); if (auto split_error = elements_or_error.takeError()) { GTEST_LOG_(ERROR) << "GetPcRegisterId: Error splitting response: " << response; return UINT_MAX; } auto elements = *elements_or_error; if (elements["alt-name"] == "pc" || elements["generic"] == "pc") { m_pc_register = register_id; break; } } return m_pc_register; }
static bool check_unique(const std::string& config, const std::string& prefix) { int retval = false; std::string data; if (!android::base::ReadFileToString(config, &data)) return retval; const fs_path_config_from_file* pc = reinterpret_cast<const fs_path_config_from_file*>(data.c_str()); size_t len = data.size(); std::vector<const char*> paths_tmp; size_t entry_number = 0; while (len > 0) { uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX; if (host_len > len) { GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " (" << host_len << " > " << len << ")"; const std::string unknown("?"); GTEST_LOG_(WARNING) << config << ": entry[" << entry_number << "]={ " << "len=" << ((len >= endof(pc, len)) ? android::base::StringPrintf("%" PRIu16, pc->len) : unknown) << ", mode=" << ((len >= endof(pc, mode)) ? android::base::StringPrintf("0%" PRIo16, pc->mode) : unknown) << ", uid=" << ((len >= endof(pc, uid)) ? android::base::StringPrintf("%" PRIu16, pc->uid) : unknown) << ", gid=" << ((len >= endof(pc, gid)) ? android::base::StringPrintf("%" PRIu16, pc->gid) : unknown) << ", capabilities=" << ((len >= endof(pc, capabilities)) ? android::base::StringPrintf("0x%" PRIx64, pc->capabilities) : unknown) << ", prefix=" << ((len >= offsetof(fs_path_config_from_file, prefix)) ? android::base::StringPrintf( "\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)), pc->prefix) : unknown) << " }"; retval = true; break; } paths_tmp.push_back(pc->prefix); pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) + host_len); len -= host_len; ++entry_number; } return check_unique(paths_tmp, config, prefix) || retval; }
bool TestClient::SendMessage(StringRef message, std::string &response_string, PacketResult expected_result) { StringExtractorGDBRemote response; GTEST_LOG_(INFO) << "Send Packet: " << message.str(); PacketResult result = SendPacketAndWaitForResponse(message, response, false); response.GetEscapedBinaryData(response_string); GTEST_LOG_(INFO) << "Read Packet: " << response_string; if (result != expected_result) { GTEST_LOG_(ERROR) << FormatFailedResult(message, result); return false; } return true; }
static bool check_unique(std::vector<const char*>& paths, const std::string& config_name, const std::string& prefix) { bool retval = false; std::string alternate = "system/" + prefix; for (size_t idx = 0; idx < paths.size(); ++idx) { size_t second; std::string path(paths[idx]); // check if there are multiple identical paths for (second = idx + 1; second < paths.size(); ++second) { if (path == paths[second]) { GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx]; retval = true; break; } } // check if path is <partition>/ if (android::base::StartsWith(path, prefix)) { // rebuild path to be system/<partition>/... to check for alias path = alternate + path.substr(prefix.size()); for (second = 0; second < paths.size(); ++second) { if (path == paths[second]) { GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": " << paths[idx] << " and " << paths[second] << " (remove latter)"; retval = true; break; } } continue; } // check if path is system/<partition>/ if (android::base::StartsWith(path, alternate)) { // rebuild path to be <partition>/... to check for alias path = prefix + path.substr(alternate.size()); for (second = 0; second < paths.size(); ++second) { if (path == paths[second]) break; } if (second >= paths.size()) { GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx] << " with " << path; retval = true; } } } return retval; }
TEST_F(DlExtRelroSharingTest, VerifyMemorySaving) { if (geteuid() != 0) { GTEST_LOG_(INFO) << "This test must be run as root.\n"; return; } TemporaryFile tf; // Use tf to get an unique filename. ASSERT_NOERROR(close(tf.fd)); ASSERT_NO_FATAL_FAILURE(CreateRelroFile(LIBNAME, tf.filename)); int pipefd[2]; ASSERT_NOERROR(pipe(pipefd)); size_t without_sharing, with_sharing; ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(LIBNAME, false, &without_sharing)); ASSERT_NO_FATAL_FAILURE(SpawnChildrenAndMeasurePss(LIBNAME, true, &with_sharing)); // We expect the sharing to save at least 10% of the total PSS. In practice // it saves 40%+ for this test. size_t expected_size = without_sharing - (without_sharing/10); EXPECT_LT(with_sharing, expected_size); // Use destructor of tf to close and unlink the file. tf.fd = extinfo_.relro_fd; }
// Starts capturing an output stream (stdout/stderr). void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) { if (*stream != NULL) { GTEST_LOG_(FATAL) << "Only one " << stream_name << " capturer can exist at a time."; } *stream = new CapturedStream(fd); }
TEST(getauxval, unexpected_values) { #if defined(GETAUXVAL_CAN_COMPILE) ASSERT_EQ((unsigned long int) 0, getauxval(0xdeadbeef)); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif }
TEST(STDIO_TEST, fseek_ftell_unseekable) { #if defined(__BIONIC__) // glibc has fopencookie instead. auto read_fn = [](void*, char*, int) { return -1; }; FILE* fp = funopen(nullptr, read_fn, nullptr, nullptr, nullptr); ASSERT_TRUE(fp != nullptr); // Check that ftell balks on an unseekable FILE*. errno = 0; ASSERT_EQ(-1, ftell(fp)); ASSERT_EQ(ESPIPE, errno); // SEEK_CUR is rewritten as SEEK_SET internally... errno = 0; ASSERT_EQ(-1, fseek(fp, 0, SEEK_CUR)); ASSERT_EQ(ESPIPE, errno); // ...so it's worth testing the direct seek path too. errno = 0; ASSERT_EQ(-1, fseek(fp, 0, SEEK_SET)); ASSERT_EQ(ESPIPE, errno); fclose(fp); #else GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n"; #endif }
TEST(STDIO_TEST, funopen_seek) { #if defined(__BIONIC__) auto read_fn = [](void*, char*, int) { return -1; }; auto seek_fn = [](void*, fpos_t, int) -> fpos_t { return 0xfedcba12; }; auto seek64_fn = [](void*, fpos64_t, int) -> fpos64_t { return 0xfedcba12345678; }; FILE* fp = funopen(nullptr, read_fn, nullptr, seek_fn, nullptr); ASSERT_TRUE(fp != nullptr); fpos_t pos; #if defined(__LP64__) EXPECT_EQ(0, fgetpos(fp, &pos)) << strerror(errno); EXPECT_EQ(0xfedcba12LL, pos); #else EXPECT_EQ(-1, fgetpos(fp, &pos)) << strerror(errno); EXPECT_EQ(EOVERFLOW, errno); #endif FILE* fp64 = funopen64(nullptr, read_fn, nullptr, seek64_fn, nullptr); ASSERT_TRUE(fp64 != nullptr); fpos64_t pos64; EXPECT_EQ(0, fgetpos64(fp64, &pos64)) << strerror(errno); EXPECT_EQ(0xfedcba12345678, pos64); #else GTEST_LOG_(INFO) << "glibc uses fopencookie instead.\n"; #endif }
TEST(pthread, pthread_setname_np__too_long) { #if defined(__BIONIC__) // Not all build servers have a new enough glibc? TODO: remove when they're on gprecise. ASSERT_EQ(ERANGE, pthread_setname_np(pthread_self(), "this name is far too long for linux")); #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
TEST(pthread, pthread_setname_np__self) { #if defined(__BIONIC__) // Not all build servers have a new enough glibc? TODO: remove when they're on gprecise. ASSERT_EQ(0, pthread_setname_np(pthread_self(), "short 1")); #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
TEST(pthread, pthread_cond_broadcast__preserves_condattr_flags) { #if defined(__BIONIC__) // This tests a bionic implementation detail. pthread_condattr_t attr; pthread_condattr_init(&attr); ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)); ASSERT_EQ(0, pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)); pthread_cond_t cond_var; ASSERT_EQ(0, pthread_cond_init(&cond_var, &attr)); ASSERT_EQ(0, pthread_cond_signal(&cond_var)); ASSERT_EQ(0, pthread_cond_broadcast(&cond_var)); attr = static_cast<pthread_condattr_t>(cond_var.value); clockid_t clock; ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock)); ASSERT_EQ(CLOCK_MONOTONIC, clock); int pshared; ASSERT_EQ(0, pthread_condattr_getpshared(&attr, &pshared)); ASSERT_EQ(PTHREAD_PROCESS_SHARED, pshared); #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
TEST(pthread, pthread_key_create_lots) { #if defined(__BIONIC__) // glibc uses keys internally that its sysconf value doesn't account for. // POSIX says PTHREAD_KEYS_MAX should be at least 128. ASSERT_GE(PTHREAD_KEYS_MAX, 128); int sysconf_max = sysconf(_SC_THREAD_KEYS_MAX); // sysconf shouldn't return a smaller value. ASSERT_GE(sysconf_max, PTHREAD_KEYS_MAX); // We can allocate _SC_THREAD_KEYS_MAX keys. sysconf_max -= 2; // (Except that gtest takes two for itself.) std::vector<pthread_key_t> keys; for (int i = 0; i < sysconf_max; ++i) { pthread_key_t key; // If this fails, it's likely that GLOBAL_INIT_THREAD_LOCAL_BUFFER_COUNT is wrong. ASSERT_EQ(0, pthread_key_create(&key, NULL)) << i << " of " << sysconf_max; keys.push_back(key); } // ...and that really is the maximum. pthread_key_t key; ASSERT_EQ(EAGAIN, pthread_key_create(&key, NULL)); // (Don't leak all those keys!) for (size_t i = 0; i < keys.size(); ++i) { ASSERT_EQ(0, pthread_key_delete(keys[i])); } #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
bool TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) { std::stringstream command; command << "A"; for (size_t i = 0; i < inferior_args.size(); i++) { if (i > 0) command << ','; std::string hex_encoded = toHex(inferior_args[i]); command << hex_encoded.size() << ',' << i << ',' << hex_encoded; } if (!SendMessage(command.str())) return false; if (!SendMessage("qLaunchSuccess")) return false; std::string response; if (!SendMessage("qProcessInfo", response)) return false; auto create_or_error = ProcessInfo::Create(response); if (auto create_error = create_or_error.takeError()) { GTEST_LOG_(ERROR) << toString(std::move(create_error)); return false; } m_process_info = *create_or_error; return true; }
TEST(properties, wait) { #if defined(__BIONIC__) LocalPropertyTestState pa; ASSERT_TRUE(pa.valid); unsigned int serial; prop_info *pi; pthread_t t; int flag = 0; ASSERT_EQ(0, __system_property_add("property", 8, "value1", 6)); serial = __system_property_wait_any(0); pi = (prop_info *)__system_property_find("property"); ASSERT_NE((prop_info *)NULL, pi); __system_property_update(pi, "value2", 6); serial = __system_property_wait_any(serial); ASSERT_EQ(0, pthread_create(&t, NULL, PropertyWaitHelperFn, &flag)); ASSERT_EQ(flag, 0); serial = __system_property_wait_any(serial); ASSERT_EQ(flag, 1); void* result; ASSERT_EQ(0, pthread_join(t, &result)); #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
TEST(pthread, pthread_types_allow_four_bytes_alignment) { #if defined(__BIONIC__) // For binary compatibility with old version, we need to allow 4-byte aligned data for pthread types. StrictAlignmentAllocator allocator; pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>( allocator.allocate(sizeof(pthread_mutex_t), 4)); ASSERT_EQ(0, pthread_mutex_init(mutex, NULL)); ASSERT_EQ(0, pthread_mutex_lock(mutex)); ASSERT_EQ(0, pthread_mutex_unlock(mutex)); ASSERT_EQ(0, pthread_mutex_destroy(mutex)); pthread_cond_t* cond = reinterpret_cast<pthread_cond_t*>( allocator.allocate(sizeof(pthread_cond_t), 4)); ASSERT_EQ(0, pthread_cond_init(cond, NULL)); ASSERT_EQ(0, pthread_cond_signal(cond)); ASSERT_EQ(0, pthread_cond_broadcast(cond)); ASSERT_EQ(0, pthread_cond_destroy(cond)); pthread_rwlock_t* rwlock = reinterpret_cast<pthread_rwlock_t*>( allocator.allocate(sizeof(pthread_rwlock_t), 4)); ASSERT_EQ(0, pthread_rwlock_init(rwlock, NULL)); ASSERT_EQ(0, pthread_rwlock_rdlock(rwlock)); ASSERT_EQ(0, pthread_rwlock_unlock(rwlock)); ASSERT_EQ(0, pthread_rwlock_wrlock(rwlock)); ASSERT_EQ(0, pthread_rwlock_unlock(rwlock)); ASSERT_EQ(0, pthread_rwlock_destroy(rwlock)); #else GTEST_LOG_(INFO) << "This test tests bionic implementation details."; #endif }
TEST(signal, sys_signame) { #if defined(__BIONIC__) ASSERT_TRUE(sys_signame[0] == NULL); ASSERT_STREQ("HUP", sys_signame[SIGHUP]); #else GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif }
TEST(math, __isnormall) { #if defined(__BIONIC__) ASSERT_TRUE(__isnormall(123.0L)); ASSERT_FALSE(__isnormall(ldouble_subnormal())); #else // __BIONIC__ GTEST_LOG_(INFO) << "glibc doesn't have __isnormall.\n"; #endif // __BIONIC__ }
TEST(math, __isnormalf) { #if defined(__BIONIC__) ASSERT_TRUE(__isnormalf(123.0f)); ASSERT_FALSE(__isnormalf(float_subnormal())); #else // __BIONIC__ GTEST_LOG_(INFO) << "glibc doesn't have __isnormalf.\n"; #endif // __BIONIC__ }
TEST(math, __isfinitel) { #if defined(__BIONIC__) ASSERT_TRUE(__isfinitel(123.0f)); ASSERT_FALSE(__isfinitel(HUGE_VALL)); #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
TEST(math, __isnormall) { #if defined(__BIONIC__) ASSERT_TRUE(__isnormall(123.0)); ASSERT_FALSE(__isnormall(double_subnormal())); #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
bool TestClient::StartDebugger() { const ArchSpec &arch_spec = HostInfo::GetArchitecture(); Args args; args.AppendArgument(LLDB_SERVER); args.AppendArgument("gdbserver"); args.AppendArgument("--log-channels=gdb-remote packets"); args.AppendArgument("--reverse-connect"); std::string log_file_name = GenerateLogFileName(arch_spec); if (log_file_name.size()) { args.AppendArgument("--log-file=" + log_file_name); } Status error; TCPSocket listen_socket(true, false); error = listen_socket.Listen("127.0.0.1:0", 5); if (error.Fail()) { GTEST_LOG_(ERROR) << "Unable to open listen socket."; return false; } char connect_remote_address[64]; snprintf(connect_remote_address, sizeof(connect_remote_address), "localhost:%u", listen_socket.GetLocalPortNumber()); args.AppendArgument(connect_remote_address); m_server_process_info.SetArchitecture(arch_spec); m_server_process_info.SetArguments(args, true); Status status = Host::LaunchProcess(m_server_process_info); if (status.Fail()) { GTEST_LOG_(ERROR) << formatv("Failure to launch lldb server: {0}.", status).str(); return false; } char connect_remote_uri[64]; snprintf(connect_remote_uri, sizeof(connect_remote_uri), "connect://%s", connect_remote_address); Socket *accept_socket; listen_socket.Accept(accept_socket); SetConnection(new ConnectionFileDescriptor(accept_socket)); SendAck(); // Send this as a handshake. return true; }
TEST(sys_random, getrandom_EFAULT) { #if defined(HAVE_SYS_RANDOM) errno = 0; ASSERT_EQ(-1, getrandom(nullptr, 256, 0)); ASSERT_EQ(EFAULT, errno); #else GTEST_LOG_(INFO) << "This test requires a C library with <sys/random.h>.\n"; #endif }
TEST(math, gammaf_r) { #if defined(__BIONIC__) int sign; ASSERT_FLOAT_EQ(logf(24.0f), gammaf_r(5.0f, &sign)); ASSERT_EQ(1, sign); #else // __BIONIC__ GTEST_LOG_(INFO) << "glibc doesn't have gammaf_r.\n"; #endif // __BIONIC__ }
TEST(libc_logging, lld_LLONG_MIN) { #if defined(__BIONIC__) char buf[BUFSIZ]; __libc_format_buffer(buf, sizeof(buf), "%lld", LLONG_MIN); EXPECT_STREQ("-9223372036854775808", buf); #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
TEST(pty, bug_28979140) { // This test is to test a kernel bug, which uses a lock free ring-buffer to // pass data through a raw pty, but missing necessary memory barriers. cpu_set_t cpus; ASSERT_EQ(0, sched_getaffinity(0, sizeof(cpu_set_t), &cpus)); if (CPU_COUNT(&cpus) < 2) { GTEST_LOG_(INFO) << "This test tests bug happens only on multiprocessors."; return; } constexpr uint32_t TEST_DATA_COUNT = 200000; // 1. Open raw pty. int master; int slave; ASSERT_EQ(0, openpty(&master, &slave, nullptr, nullptr, nullptr)); termios tattr; ASSERT_EQ(0, tcgetattr(slave, &tattr)); cfmakeraw(&tattr); ASSERT_EQ(0, tcsetattr(slave, TCSADRAIN, &tattr)); // 2. Make master thread and slave thread running on different cpus: // master thread uses first available cpu, and slave thread uses other cpus. PtyReader_28979140_Arg arg; arg.main_cpu_id = -1; for (int i = 0; i < CPU_SETSIZE; i++) { if (CPU_ISSET(i, &cpus)) { arg.main_cpu_id = i; break; } } ASSERT_GE(arg.main_cpu_id, 0); // 3. Create thread for slave reader. pthread_t thread; arg.slave_fd = slave; arg.data_count = TEST_DATA_COUNT; arg.matched = true; ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void*(*)(void*)>(PtyReader_28979140), &arg)); CPU_ZERO(&cpus); CPU_SET(arg.main_cpu_id, &cpus); ASSERT_EQ(0, sched_setaffinity(0, sizeof(cpu_set_t), &cpus)); // 4. Send data to slave. uint32_t counter = 0; while (counter <= TEST_DATA_COUNT) { ASSERT_TRUE(android::base::WriteFully(master, &counter, sizeof(counter))); ASSERT_TRUE(arg.matched) << "failed at count = " << counter; counter++; } ASSERT_EQ(0, pthread_join(thread, nullptr)); ASSERT_TRUE(arg.finished); ASSERT_TRUE(arg.matched); close(master); }
TEST(libc_logging, d_INT_MIN) { #if defined(__BIONIC__) char buf[BUFSIZ]; __libc_format_buffer(buf, sizeof(buf), "%d", INT_MIN); EXPECT_STREQ("-2147483648", buf); #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing.\n"; #endif // __BIONIC__ }
bool TestClient::Continue(StringRef message) { if (!m_process_info.hasValue()) { GTEST_LOG_(ERROR) << "Continue() called before m_process_info initialized."; return false; } std::string response; if (!SendMessage(message, response)) return false; auto creation = StopReply::Create(response, m_process_info->GetEndian()); if (auto create_error = creation.takeError()) { GTEST_LOG_(ERROR) << toString(std::move(create_error)); return false; } m_stop_reply = std::move(*creation); return true; }
// libtest_dlopen_from_ctor_main.so depends on // libtest_dlopen_from_ctor.so which has a constructor // that calls dlopen(libc...). This is to test the situation // described in b/7941716. TEST(dlfcn, dlopen_dlopen_from_ctor) { #if defined(__BIONIC__) void* handle = dlopen("libtest_dlopen_from_ctor_main.so", RTLD_NOW); ASSERT_TRUE(handle != nullptr) << dlerror(); dlclose(handle); #else GTEST_LOG_(INFO) << "This test is disabled for glibc (glibc segfaults if you try to call dlopen from a constructor).\n"; #endif }
TEST(math_logf, logf_intel) { #if defined(__BIONIC__) for (size_t i = 0; i < sizeof(g_logf_intel_data)/sizeof(logf_intel_data_t); i++) { EXPECT_FLOAT_EQ(g_logf_intel_data[i].expected, logf(g_logf_intel_data[i].call_data)) << "Failed on element " << i; } #else // __BIONIC__ GTEST_LOG_(INFO) << "This test does nothing."; #endif // __BIONIC__ }