示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
// 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
}
示例#8
0
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
}
示例#9
0
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
}
示例#10
0
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__
}
示例#11
0
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__
}
示例#12
0
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__
}
示例#13
0
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__
}
示例#14
0
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__
}
示例#16
0
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
}
示例#18
0
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__
}
示例#19
0
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__
}
示例#20
0
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__
}
示例#21
0
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__
}
示例#22
0
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;
}
示例#23
0
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
}
示例#24
0
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__
}
示例#25
0
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__
}
示例#26
0
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);
}
示例#27
0
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__
}
示例#28
0
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;
}
示例#29
0
// 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__
}