blob: 29e086fcf124792843f4fa872290ecf076d3afa4 [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 unsetenv.
///
//===----------------------------------------------------------------------===//
#include "src/__support/alloc-checker.h"
#include "src/stdlib/environ_internal.h"
#include "src/stdlib/getenv.h"
#include "src/stdlib/setenv.h"
#include "src/stdlib/unsetenv.h"
#include "src/string/memory_utils/inline_memcpy.h"
#include "src/unistd/environ.h"
#include "test/IntegrationTest/test.h"
#include <errno.h>
namespace LIBC_NAMESPACE {
TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
[[maybe_unused]] char **envp) {
// Test: Remove a variable set by setenv
{
ASSERT_EQ(setenv("UNSET_VAR", "value", 1), 0);
ASSERT_TRUE(getenv("UNSET_VAR") != nullptr);
ASSERT_EQ(unsetenv("UNSET_VAR"), 0);
ASSERT_TRUE(getenv("UNSET_VAR") == nullptr);
}
// Test: Unset non-existent variable succeeds
{
ASSERT_EQ(unsetenv("DOES_NOT_EXIST"), 0);
}
// Test: Empty name sets errno to EINVAL
{
errno = 0;
ASSERT_EQ(unsetenv(""), -1);
ASSERT_ERRNO_EQ(EINVAL);
}
// Test: Name with '=' sets errno to EINVAL
{
errno = 0;
ASSERT_EQ(unsetenv("BAD=NAME"), -1);
ASSERT_ERRNO_EQ(EINVAL);
}
// Test: Unset then re-set
{
ASSERT_EQ(setenv("REUSE_VAR", "first", 1), 0);
ASSERT_STREQ(getenv("REUSE_VAR"), "first");
ASSERT_EQ(unsetenv("REUSE_VAR"), 0);
ASSERT_TRUE(getenv("REUSE_VAR") == nullptr);
ASSERT_EQ(setenv("REUSE_VAR", "second", 1), 0);
ASSERT_STREQ(getenv("REUSE_VAR"), "second");
}
// Test: Unset multiple variables
{
ASSERT_EQ(setenv("MULTI_A", "a", 1), 0);
ASSERT_EQ(setenv("MULTI_B", "b", 1), 0);
ASSERT_EQ(setenv("MULTI_C", "c", 1), 0);
ASSERT_EQ(unsetenv("MULTI_B"), 0);
ASSERT_TRUE(getenv("MULTI_A") != nullptr);
ASSERT_TRUE(getenv("MULTI_B") == nullptr);
ASSERT_TRUE(getenv("MULTI_C") != nullptr);
ASSERT_STREQ(getenv("MULTI_A"), "a");
ASSERT_STREQ(getenv("MULTI_C"), "c");
}
// Test: Unset same variable twice is harmless
{
ASSERT_EQ(setenv("DOUBLE_UNSET", "val", 1), 0);
ASSERT_EQ(unsetenv("DOUBLE_UNSET"), 0);
ASSERT_EQ(unsetenv("DOUBLE_UNSET"), 0);
ASSERT_TRUE(getenv("DOUBLE_UNSET") == nullptr);
}
// Test: environ is updated and does NOT contain the variable
{
ASSERT_EQ(setenv("ENV_CHECK", "val", 1), 0);
// Verify it is in environ
bool found = false;
for (char **env = environ; *env != nullptr; ++env) {
if (cpp::string_view(*env) == "ENV_CHECK=val") {
found = true;
break;
}
}
ASSERT_TRUE(found);
// Now unset it
ASSERT_EQ(unsetenv("ENV_CHECK"), 0);
// Verify it is NOT in environ
found = false;
for (char **env = environ; *env != nullptr; ++env) {
bool match = true;
const char *prefix = "ENV_CHECK=";
for (size_t i = 0; i < 10; ++i) {
if ((*env)[i] == '\0' || (*env)[i] != prefix[i]) {
match = false;
break;
}
}
if (match) {
found = true;
break;
}
}
ASSERT_FALSE(found);
}
// Test: Unset removes all duplicate instances of a variable
{
ASSERT_EQ(setenv("DUP_VAL1", "1", 1), 0);
ASSERT_EQ(setenv("DUP_VAL2", "2", 1), 0);
AllocChecker ac;
char *d1 = new (ac) char[14];
ASSERT_TRUE(ac);
const char *s1 = "DUP_VAR=first";
inline_memcpy(d1, s1, 14);
char *d2 = new (ac) char[15];
ASSERT_TRUE(ac);
const char *s2 = "DUP_VAR=second";
inline_memcpy(d2, s2, 15);
internal::EnvironmentManager &mgr =
internal::EnvironmentManager::get_instance();
char **env_array = mgr.begin();
size_t count = mgr.size();
size_t idx1 = count;
size_t idx2 = count;
for (size_t i = 0; i < count; ++i) {
cpp::string_view curr(env_array[i]);
if (curr.starts_with("DUP_VAL1="))
idx1 = i;
if (curr.starts_with("DUP_VAL2="))
idx2 = i;
}
ASSERT_TRUE(idx1 < count);
ASSERT_TRUE(idx2 < count);
delete[] env_array[idx1];
delete[] env_array[idx2];
env_array[idx1] = d1;
env_array[idx2] = d2;
ASSERT_EQ(unsetenv("DUP_VAR"), 0);
ASSERT_TRUE(getenv("DUP_VAR") == nullptr);
}
return 0;
}
} // namespace LIBC_NAMESPACE