usingnamespace std::string_literals; using stdlib_DeathTest = SilentDeathTest;
template <typename T = int (*)(char*)> class GenericTemporaryFile { public: explicit GenericTemporaryFile(T mk_fn = mkstemp) : mk_fn_(mk_fn) { // Since we might be running on the host or the target, and if we're // running on the host we might be running under bionic or glibc, // let's just try both possible temporary directories and take the // first one that works.
init("/data/local/tmp"); if (fd == -1) {
init("/tmp");
}
}
// The random number generator tests all set the seed, get four values, reset the seed and check // that they get the first two values repeated, and then reset the seed and check two more values // to rule out the possibility that we're just going round a cycle of four values. // TODO: factor this out.
for (int iter = 0; iter < iterations; ++iter) { long rand_val = jrand48(xsubi); for (int bit = 0; bit < 32; ++bit) {
bits[bit] += (static_cast<unsignedlong>(rand_val) >> bit) & 0x01;
}
}
// Check that bit probability is uniform for (int bit = 0; bit < 32; ++bit) {
EXPECT_TRUE((pivot_low <= bits[bit]) && (bits[bit] <= pivot_high));
}
}
for (int iter = 0; iter < iterations; ++iter) { long rand_val = mrand48(); for (int bit = 0; bit < 32; ++bit) {
bits[bit] += (static_cast<unsignedlong>(rand_val) >> bit) & 0x01;
}
}
// Check that bit probability is uniform for (int bit = 0; bit < 32; ++bit) {
EXPECT_TRUE((pivot_low <= bits[bit]) && (bits[bit] <= pivot_high));
}
}
TEST(stdlib, free_sized) { #ifdefined(__BIONIC__) void* ptr = malloc(4);
free_sized(ptr, 4); #else
GTEST_SKIP() << "Our glibc is too old."; #endif
}
// These should all fail. for (size_t align = 0; align < sizeof(long); align++) {
ASSERT_EQ(EINVAL, posix_memalign(&ptr, align, 256))
<< "Unexpected value at align " << align;
}
// Verify powers of 2 up to 2048 allocate, and verify that all other // alignment values between the powers of 2 fail.
size_t last_align = sizeof(long); for (size_t align = sizeof(long); align <= 2048; align <<= 1) { // Try all of the non power of 2 values from the last until this value. for (size_t fail_align = last_align + 1; fail_align < align; fail_align++) {
ASSERT_EQ(EINVAL, posix_memalign(&ptr, fail_align, 256))
<< "Unexpected success at align " << fail_align;
}
ASSERT_EQ(0, posix_memalign(&ptr, align, 256))
<< "Unexpected failure at align " << align;
ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
<< "Did not return a valid aligned ptr " << ptr << " expected alignment " << align;
free(ptr);
last_align = align;
}
}
TEST(stdlib, realpath) { // Get the name of this executable. char executable_path[PATH_MAX]; int rc = readlink("/proc/self/exe", executable_path, sizeof(executable_path));
ASSERT_NE(rc, -1);
executable_path[rc] = '\0';
// Create a file "A".
std::string A_path = td.path + "/A"s;
ASSERT_TRUE(android::base::WriteStringToFile("test\n", A_path));
// Get an O_PATH fd for it.
android::base::unique_fd fd(open(A_path.c_str(), O_PATH));
ASSERT_NE(fd, -1);
// Create a file "A (deleted)".
android::base::unique_fd fd2(open((td.path + "/A (deleted)"s).c_str(),
O_CREAT | O_TRUNC | O_WRONLY, 0644));
ASSERT_NE(fd2, -1);
// Delete "A".
ASSERT_EQ(0, unlink(A_path.c_str()));
// Now realpath() on the O_PATH fd, and check we *don't* get "A (deleted)".
std::string path = android::base::StringPrintf("/proc/%d/fd/%d", static_cast<int>(getpid()),
fd.get());
errno = 0; char* result = realpath(path.c_str(), nullptr);
ASSERT_EQ(nullptr, result) << result;
ASSERT_ERRNO(ENOENT);
free(result);
}
// Even though this isn't really a death test, we have to say "DeathTest" here so gtest knows to // run this test (which exits normally) in its own process.
status = system("exit 0");
ASSERT_TRUE(WIFEXITED(status));
ASSERT_EQ(0, WEXITSTATUS(status));
status = system("exit 1");
ASSERT_TRUE(WIFEXITED(status));
ASSERT_EQ(1, WEXITSTATUS(status));
}
TEST(stdlib, system_NULL) { // "The system() function shall always return non-zero when command is NULL." // https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/system.html #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnonnull"
ASSERT_NE(0, system(nullptr)); #pragma clang diagnostic pop
}
// https://austingroupbugs.net/view.php?id=1440
TEST(stdlib, system_minus) { // Create a script with a name that starts with a '-'.
TemporaryDir td;
std::string script = std::string(td.path) + "/-minus";
ASSERT_TRUE(android::base::WriteStringToFile("#!" BIN_DIR "sh\nexit 66\n", script));
// Set $PATH so we can find it.
setenv("PATH", td.path, 1); // Make it executable so we can run it.
ASSERT_EQ(0, chmod(script.c_str(), 0555));
int status = system("-minus");
EXPECT_TRUE(WIFEXITED(status));
EXPECT_EQ(66, WEXITSTATUS(status));
// While we're here and have all the setup, let's test popen(3) too...
FILE* fp = popen("-minus", "r");
ASSERT_TRUE(fp != nullptr);
status = pclose(fp);
EXPECT_TRUE(WIFEXITED(status));
EXPECT_EQ(66, WEXITSTATUS(status));
}
TEST(stdlib, strtod_largest_subnormal) { // This value has been known to cause javac and java to infinite loop. // http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/
ASSERT_EQ(2.2250738585072014e-308, strtod("2.2250738585072012e-308", nullptr));
ASSERT_EQ(2.2250738585072014e-308, strtod("0.00022250738585072012e-304", nullptr));
ASSERT_EQ(2.2250738585072014e-308, strtod("00000002.2250738585072012e-308", nullptr));
ASSERT_EQ(2.2250738585072014e-308, strtod("2.225073858507201200000e-308", nullptr));
ASSERT_EQ(2.2250738585072014e-308, strtod("2.2250738585072012e-00308", nullptr));
ASSERT_EQ(2.2250738585072014e-308, strtod("2.22507385850720129978001e-308", nullptr));
ASSERT_EQ(-2.2250738585072014e-308, strtod("-2.2250738585072012e-308", nullptr));
}
staticvoid exit_from_atexit_func3() {
std::thread([] { exit(3); }).detach();
fprintf(stderr, "3");
usleep(1000); // This should cause us to exit with status 99, // but not before printing "4", // and without re-running the previous atexit handlers. exit(99);
}
staticvoid exit_from_atexit_func2() {
std::thread([] { exit(2); }).detach();
fprintf(stderr, "2");
usleep(1000); // Register another atexit handler from within an atexit handler.
atexit(exit_from_atexit_func3);
}
staticvoid exit_from_atexit_func1() { // These atexit handlers all spawn another thread that tries to exit, // and sleep to try to lose the race. // The lock in exit() should ensure that only the first thread to call // exit() can ever win (but see exit_from_atexit_func3() for a subtelty).
std::thread([] { exit(1); }).detach();
usleep(1000);
fprintf(stderr, "1");
}
staticvoid exit_torturer() {
atexit(exit_from_atexit_func4); // We deliberately don't register exit_from_atexit_func3() here; // see exit_from_atexit_func2().
atexit(exit_from_atexit_func2);
atexit(exit_from_atexit_func1); exit(0);
}
TEST(stdlib, exit_torture) { // Test that the atexit() handlers are run in the defined order (reverse // order of registration), even though one of them is registered by another // when it runs, and that we get the exit code from the last call to exit() // on the first thread to call exit() (rather than one of the other threads // or a deadlock from the second call on the same thread).
ASSERT_EXIT(exit_torturer(), testing::ExitedWithCode(99), "1234");
}
TEST(stdlib, mblen) { // "If s is a null pointer, mblen() shall return a non-zero or 0 value, if character encodings, // respectively, do or do not have state-dependent encodings." We're always UTF-8.
EXPECT_EQ(0, mblen(nullptr, 1));
// Both leading + or - are always allowed (even for the strtou* family).
ASSERT_EQ(T(-123), fn("-123", &end_p, 10));
ASSERT_EQ(T(123), fn("+123", &end_p, 10));
// If we see "0b" *not* followed by a binary digit, we shouldn't swallow the 'b'.
ASSERT_EQ(T(0), fn("0b", &end_p, 2));
ASSERT_EQ('b', *end_p);
// Binary (the "0b" prefix) is case-insensitive.
ASSERT_EQ(T(0b101), fn("0b101", &end_p, 0));
ASSERT_EQ(T(0b101), fn("0B101", &end_p, 0));
// If we see "0x" *not* followed by a hex digit, we shouldn't swallow the 'x'.
ASSERT_EQ(T(0), fn("0xy", &end_p, 16));
ASSERT_EQ('x', *end_p);
// Hexadecimal (both the "0x" prefix and the digits) is case-insensitive.
ASSERT_EQ(T(0xab), fn("0xab", &end_p, 0));
ASSERT_EQ(T(0xab), fn("0Xab", &end_p, 0));
ASSERT_EQ(T(0xab), fn("0xAB", &end_p, 0));
ASSERT_EQ(T(0xab), fn("0XAB", &end_p, 0));
ASSERT_EQ(T(0xab), fn("0xAb", &end_p, 0));
ASSERT_EQ(T(0xab), fn("0XAb", &end_p, 0));
// Maximum (such as 127).
std::string max{std::to_string(std::numeric_limits<T>::max())};
end_p = nullptr;
ASSERT_ERRNO_SUCCESS(0, std::numeric_limits<T>::max(), fn(max.c_str(), &end_p, 0));
ASSERT_EQ('\0', *end_p); // Too positive (such as 128).
max.back() = (max.back() + 1);
end_p = nullptr;
ASSERT_ERRNO_FAILURE(ERANGE, std::numeric_limits<T>::max(), fn(max.c_str(), &end_p, 0));
ASSERT_EQ('\0', *end_p);
// Junk at the end of a valid conversion.
ASSERT_ERRNO_SUCCESS(0, static_cast<T>(123), fn("123abc", &end_p, 0));
ASSERT_STREQ("abc", end_p);
// In case of overflow, strto* leaves us pointing past the end of the number, // not at the digit that overflowed.
end_p = nullptr;
errno = 0;
ASSERT_ERRNO_FAILURE(ERANGE,
std::numeric_limits<T>::max(),
fn("99999999999999999999999999999999999999999999999999999abc", &end_p, 0));
ASSERT_STREQ("abc", end_p); if (std::numeric_limits<T>::is_signed) {
end_p = nullptr;
ASSERT_ERRNO_FAILURE(ERANGE,
std::numeric_limits<T>::min(),
fn("-99999999999999999999999999999999999999999999999999999abc", &end_p, 0));
ASSERT_STREQ("abc", end_p);
}
}
// The second argument should have been size_t.
ASSERT_EQ(-1, getloadavg(load, -1));
ASSERT_EQ(-1, getloadavg(load, INT_MIN));
// Zero is a no-op.
ASSERT_EQ(0, getloadavg(load, 0));
// The Linux kernel doesn't support more than 3 (but you can ask for fewer).
ASSERT_EQ(1, getloadavg(load, 1));
ASSERT_EQ(2, getloadavg(load, 2));
ASSERT_EQ(3, getloadavg(load, 3));
ASSERT_EQ(3, getloadavg(load, 4));
ASSERT_EQ(3, getloadavg(load, INT_MAX));
// Check that getloadavg(3) at least overwrote the NaNs.
ASSERT_FALSE(isnan(load[0]));
ASSERT_FALSE(isnan(load[1]));
ASSERT_FALSE(isnan(load[2])); // And that the difference between /proc/loadavg and getloadavg(3) is "small".
ASSERT_TRUE(fabs(expected[0] - load[0]) < 0.5) << expected[0] << ' ' << load[0];
ASSERT_TRUE(fabs(expected[1] - load[1]) < 0.5) << expected[1] << ' ' << load[1];
ASSERT_TRUE(fabs(expected[2] - load[2]) < 0.5) << expected[2] << ' ' << load[2];
}
TEST(stdlib, getprogname) { #ifdefined(__GLIBC__) || defined(ANDROID_HOST_MUSL)
GTEST_SKIP() << "glibc and musl don't have getprogname()"; #else // You should always have a name.
ASSERT_TRUE(getprogname() != nullptr); // The name should never have a slash in it.
ASSERT_TRUE(strchr(getprogname(), '/') == nullptr); #endif
}
TEST(stdlib, setprogname) { #ifdefined(__GLIBC__) || defined(ANDROID_HOST_MUSL)
GTEST_SKIP() << "glibc and musl don't have setprogname()"; #else // setprogname() only takes the basename of what you give it.
setprogname("/usr/bin/muppet");
ASSERT_STREQ("muppet", getprogname()); #endif
}
TEST(stdlib, div) {
div_t r;
r = div(5, 3);
EXPECT_EQ(1, r.quot);
EXPECT_EQ(2, r.rem);
r = div(5, -3);
EXPECT_EQ(-1, r.quot);
EXPECT_EQ(2, r.rem);
r = div(-5, 3);
EXPECT_EQ(-1, r.quot);
EXPECT_EQ(-2, r.rem);
r = div(-5, -3);
EXPECT_EQ(1, r.quot);
EXPECT_EQ(-2, r.rem);
}
TEST(stdlib, ldiv) {
ldiv_t r;
r = ldiv(5, 3);
EXPECT_EQ(1, r.quot);
EXPECT_EQ(2, r.rem);
r = ldiv(5, -3);
EXPECT_EQ(-1, r.quot);
EXPECT_EQ(2, r.rem);
r = ldiv(-5, 3);
EXPECT_EQ(-1, r.quot);
EXPECT_EQ(-2, r.rem);
r = ldiv(-5, -3);
EXPECT_EQ(1, r.quot);
EXPECT_EQ(-2, r.rem);
}
TEST(stdlib, lldiv) {
lldiv_t r;
r = lldiv(5, 3);
EXPECT_EQ(1, r.quot);
EXPECT_EQ(2, r.rem);
r = lldiv(5, -3);
EXPECT_EQ(-1, r.quot);
EXPECT_EQ(2, r.rem);
r = lldiv(-5, 3);
EXPECT_EQ(-1, r.quot);
EXPECT_EQ(-2, r.rem);
r = lldiv(-5, -3);
EXPECT_EQ(1, r.quot);
EXPECT_EQ(-2, r.rem);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.4 Sekunden
(vorverarbeitet am 2026-06-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.