File size: 5,876 Bytes
78d2150 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | #include "../../unity/unity.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
/* Note:
- This test file is included at the end of env.c, so it shares the same
translation unit and can access the static symbols:
- usvars, usvars_used, usvars_alloc
- unset_envvars()
- We only manipulate usvars/usvars_used/usvars_alloc; we do not redefine any
symbol from the program.
*/
static char const **allocated_usvars = NULL; /* Track array we allocate for cleanup */
/* Helper: set the list of variables to unset. Copies the pointer list, not the strings. */
static void prepare_usvars_list(char const *const *list, size_t count)
{
/* Free any prior allocation from a previous test run */
if (allocated_usvars)
{
free((void *)allocated_usvars);
allocated_usvars = NULL;
}
if (count == 0 || list == NULL)
{
usvars = NULL;
usvars_used = 0;
usvars_alloc = 0;
return;
}
char const **arr = (char const **)malloc(sizeof(char const *) * count);
TEST_ASSERT_NOT_NULL(arr);
for (size_t i = 0; i < count; i++)
arr[i] = list[i];
usvars = arr;
usvars_used = (typeof(usvars_used))count;
usvars_alloc = (typeof(usvars_alloc))count;
allocated_usvars = arr;
}
/* Helper: make a unique environment variable name. Caller frees the returned string. */
static char *make_unique_name(const char *prefix)
{
char buf[128];
static unsigned counter = 0;
snprintf(buf, sizeof buf, "%s_%ld_%u", prefix, (long)getpid(), ++counter);
return strdup(buf);
}
void setUp(void)
{
/* Reset our managed allocation; program globals will be set per-test */
if (allocated_usvars)
{
free((void *)allocated_usvars);
allocated_usvars = NULL;
}
usvars = NULL;
usvars_used = 0;
usvars_alloc = 0;
}
void tearDown(void)
{
if (allocated_usvars)
{
free((void *)allocated_usvars);
allocated_usvars = NULL;
}
/* Leave environment as modified by the test; each test sets/clears variables it needs */
}
/* Test: unsetting a single existing variable removes it from the environment. */
static void test_unset_envvars_single_existing(void)
{
char *name = make_unique_name("ENV_TEST_ONE");
TEST_ASSERT_NOT_NULL(name);
/* Ensure the variable exists */
TEST_ASSERT_EQUAL_INT(0, setenv(name, "value", 1));
TEST_ASSERT_NOT_NULL(getenv(name));
char const *list[] = { name };
prepare_usvars_list(list, 1);
unset_envvars();
TEST_ASSERT_NULL(getenv(name));
free(name);
}
/* Test: unsetting multiple variables including one that does not exist. */
static void test_unset_envvars_multiple_existing_and_nonexistent(void)
{
char *n1 = make_unique_name("ENV_TEST_MULTI1");
char *n2 = make_unique_name("ENV_TEST_MULTI2");
char *n3 = make_unique_name("ENV_TEST_MULTI3_NOEXIST");
TEST_ASSERT_NOT_NULL(n1);
TEST_ASSERT_NOT_NULL(n2);
TEST_ASSERT_NOT_NULL(n3);
/* Create two variables, leave third non-existent */
TEST_ASSERT_EQUAL_INT(0, setenv(n1, "v1", 1));
TEST_ASSERT_EQUAL_INT(0, setenv(n2, "v2", 1));
TEST_ASSERT_NOT_NULL(getenv(n1));
TEST_ASSERT_NOT_NULL(getenv(n2));
TEST_ASSERT_NULL(getenv(n3));
char const *list[] = { n1, n2, n3 };
prepare_usvars_list(list, 3);
unset_envvars();
TEST_ASSERT_NULL(getenv(n1));
TEST_ASSERT_NULL(getenv(n2));
TEST_ASSERT_NULL(getenv(n3));
free(n1);
free(n2);
free(n3);
}
/* Test: unsetting a non-existent variable should not error and should remain non-existent. */
static void test_unset_envvars_nonexistent_only(void)
{
char *name = make_unique_name("ENV_TEST_NOEXIST");
TEST_ASSERT_NOT_NULL(name);
/* Ensure it does not exist */
unsetenv(name);
TEST_ASSERT_NULL(getenv(name));
char const *list[] = { name };
prepare_usvars_list(list, 1);
unset_envvars();
TEST_ASSERT_NULL(getenv(name));
free(name);
}
/* Test: empty unset list should be a no-op (does not unset other variables). */
static void test_unset_envvars_empty_list_noop(void)
{
char *persist = make_unique_name("ENV_TEST_PERSIST");
TEST_ASSERT_NOT_NULL(persist);
TEST_ASSERT_EQUAL_INT(0, setenv(persist, "keep", 1));
TEST_ASSERT_NOT_NULL(getenv(persist));
prepare_usvars_list(NULL, 0); /* No variables to unset */
unset_envvars();
TEST_ASSERT_NOT_NULL(getenv(persist));
/* Cleanup: remove the variable we created */
TEST_ASSERT_EQUAL_INT(0, unsetenv(persist));
TEST_ASSERT_NULL(getenv(persist));
free(persist);
}
/* Test: invalid variable name (contains '=') should cause error() to exit with EXIT_CANCELED.
Run in a child process to avoid terminating the whole test runner. */
static void test_unset_envvars_invalid_name_triggers_error(void)
{
fflush(stdout);
fflush(stderr);
pid_t pid = fork();
TEST_ASSERT_MESSAGE(pid >= 0, "fork() failed");
if (pid == 0)
{
/* Child: set invalid name and call function; should exit via error(). */
char const *list[] = { "BAD=NAME" };
prepare_usvars_list(list, 1);
/* Calling unset_envvars should invoke error(EXIT_CANCELED, ...) and exit. */
unset_envvars();
/* If we get here, it did not exit as expected. Use a distinct exit code. */
_exit(0xEE);
}
int status = 0;
pid_t w = waitpid(pid, &status, 0);
TEST_ASSERT_EQUAL_INT(pid, w);
TEST_ASSERT_TRUE(WIFEXITED(status));
int es = WEXITSTATUS(status);
/* EXIT_CANCELED is available from the program's headers included earlier. */
TEST_ASSERT_EQUAL_INT(EXIT_CANCELED, es);
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_unset_envvars_single_existing);
RUN_TEST(test_unset_envvars_multiple_existing_and_nonexistent);
RUN_TEST(test_unset_envvars_nonexistent_only);
RUN_TEST(test_unset_envvars_empty_list_noop);
RUN_TEST(test_unset_envvars_invalid_name_triggers_error);
return UNITY_END();
} |