blob: 7f2eb34bd322f2abc0a1cf6150e4a121645ea667 [file] [edit]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Integration tests for putenv.
///
//===----------------------------------------------------------------------===//
#include "src/stdlib/getenv.h"
#include "src/stdlib/putenv.h"
#include "src/unistd/environ.h"
#include "test/IntegrationTest/test.h"
#include <errno.h>
static char set_var[] = "PUTENV_TEST=hello";
static char replace_var[] = "PUTENV_TEST=world";
static char empty_value[] = "PUTENV_EMPTY=";
static char special_chars[] = "PUTENV_SPECIAL=!@#$%^&*()";
TEST_MAIN() {
// Test: Basic set
{
ASSERT_EQ(LIBC_NAMESPACE::putenv(set_var), 0);
char *value = LIBC_NAMESPACE::getenv("PUTENV_TEST");
ASSERT_TRUE(value != nullptr);
ASSERT_STREQ(value, "hello");
}
// Test: Overwrite existing variable
{
ASSERT_EQ(LIBC_NAMESPACE::putenv(replace_var), 0);
char *value = LIBC_NAMESPACE::getenv("PUTENV_TEST");
ASSERT_TRUE(value != nullptr);
ASSERT_STREQ(value, "world");
}
// Test: The pointer itself is used (not a copy)
{
// After putenv, getenv should return a pointer into the original string.
char *value = LIBC_NAMESPACE::getenv("PUTENV_TEST");
ASSERT_TRUE(value == replace_var + 12); // "PUTENV_TEST=" is 12 chars
}
// Test: Empty value
{
ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_value), 0);
char *value = LIBC_NAMESPACE::getenv("PUTENV_EMPTY");
ASSERT_TRUE(value != nullptr);
ASSERT_STREQ(value, "");
}
// Test: Special characters in value
{
ASSERT_EQ(LIBC_NAMESPACE::putenv(special_chars), 0);
char *value = LIBC_NAMESPACE::getenv("PUTENV_SPECIAL");
ASSERT_TRUE(value != nullptr);
ASSERT_STREQ(value, "!@#$%^&*()");
}
// Test: No '=' removes the variable (POSIX behavior)
{
// First set a variable via putenv
static char var_to_remove[] = "REMOVE_ME=present";
ASSERT_EQ(LIBC_NAMESPACE::putenv(var_to_remove), 0);
ASSERT_TRUE(LIBC_NAMESPACE::getenv("REMOVE_ME") != nullptr);
// Now call putenv without '=' to remove it
static char remove_cmd[] = "REMOVE_ME";
ASSERT_EQ(LIBC_NAMESPACE::putenv(remove_cmd), 0);
ASSERT_TRUE(LIBC_NAMESPACE::getenv("REMOVE_ME") == nullptr);
}
// Test: environ is updated and contains the exact pointer
{
bool found = false;
for (char **env = LIBC_NAMESPACE::environ; *env != nullptr; ++env) {
if (*env == replace_var) {
found = true;
break;
}
}
ASSERT_TRUE(found);
}
// Test: Pathological inputs (empty names, empty string) are allowed to match
// glibc.
{
// Empty name with value (=value) should succeed and be found in environ.
static char empty_name[] = "=value";
ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_name), 0);
bool found = false;
for (char **env = LIBC_NAMESPACE::environ; *env != nullptr; ++env) {
if (*env == empty_name) {
found = true;
break;
}
}
ASSERT_TRUE(found);
// Just "=" should succeed and be found in environ.
static char just_equals[] = "=";
ASSERT_EQ(LIBC_NAMESPACE::putenv(just_equals), 0);
found = false;
for (char **env = LIBC_NAMESPACE::environ; *env != nullptr; ++env) {
if (*env == just_equals) {
found = true;
break;
}
}
ASSERT_TRUE(found);
// Empty string unsets the empty name.
static char empty_string[] = "";
ASSERT_EQ(LIBC_NAMESPACE::putenv(empty_string), 0);
// Verify "=value" is no longer in environ (it should have been unset).
found = false;
for (char **env = LIBC_NAMESPACE::environ; *env != nullptr; ++env) {
if (*env == empty_name) {
found = true;
break;
}
}
ASSERT_FALSE(found);
}
return 0;
}