tests: posix: tests for environ, getenv, setenv, unsetenv
Add tests for environ, getenv(), setenv(), unsetenv(), and getenv_r(). Signed-off-by: Christopher Friedt <cfriedt@meta.com>
This commit is contained in:
parent
0f23818153
commit
8912ba9004
4 changed files with 228 additions and 0 deletions
13
tests/posix/env/CMakeLists.txt
vendored
Normal file
13
tests/posix/env/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
project(posix_common)
|
||||||
|
|
||||||
|
FILE(GLOB app_sources src/*.c)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE ${app_sources})
|
||||||
|
# For setenv() and unsetenv()
|
||||||
|
target_compile_options(app PRIVATE -U_POSIX_C_SOURCE -D_POSIX_C_SOURCE=200809L)
|
||||||
|
# For getenv_r() visibility and testing
|
||||||
|
target_compile_definitions(app PRIVATE _BSD_SOURCE)
|
3
tests/posix/env/prj.conf
vendored
Normal file
3
tests/posix/env/prj.conf
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
CONFIG_ZTEST=y
|
||||||
|
CONFIG_POSIX_ENV=y
|
||||||
|
CONFIG_COMMON_LIBC_MALLOC=y
|
180
tests/posix/env/src/env.c
vendored
Normal file
180
tests/posix/env/src/env.c
vendored
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023, Meta
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <zephyr/ztest.h>
|
||||||
|
|
||||||
|
#define M_HOME "/home/zephyr"
|
||||||
|
#define M_UID "1000"
|
||||||
|
#define M_PWD "/tmp"
|
||||||
|
|
||||||
|
#define _m_alt_home "/this/path/is/much/longer/than" M_HOME
|
||||||
|
|
||||||
|
#define DEFINE_ENVIRON(_handle, _key, _val) char _handle[] = _key "=" _val
|
||||||
|
#define RESET_ENVIRON(_handle, _key, _val) \
|
||||||
|
snprintf(_handle, ARRAY_SIZE(_handle), "%s=%s", _key, _val)
|
||||||
|
|
||||||
|
#if defined(CONFIG_NEWLIB_LIBC) || defined(CONFIG_PICOLIBC)
|
||||||
|
/* newlib headers seem to be missing this */
|
||||||
|
int getenv_r(const char *name, char *val, size_t len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern char **environ;
|
||||||
|
static char **old_environ;
|
||||||
|
|
||||||
|
static DEFINE_ENVIRON(home, "HOME", M_HOME);
|
||||||
|
static DEFINE_ENVIRON(uid, "UID", M_UID);
|
||||||
|
static DEFINE_ENVIRON(pwd, "PWD", M_PWD);
|
||||||
|
|
||||||
|
static char *environ_for_test[] = {home, uid, pwd, NULL};
|
||||||
|
|
||||||
|
ZTEST(env, test_getenv)
|
||||||
|
{
|
||||||
|
zassert_equal(getenv(NULL), NULL);
|
||||||
|
zassert_equal(getenv(""), NULL);
|
||||||
|
zassert_equal(getenv("invalid=key"), NULL);
|
||||||
|
zassert_equal(getenv("HOME=" M_HOME), NULL);
|
||||||
|
zassert_equal(getenv("PWDR"), NULL);
|
||||||
|
|
||||||
|
zassert_mem_equal(getenv("HOME"), M_HOME, strlen(M_HOME) + 1);
|
||||||
|
zassert_mem_equal(getenv("UID"), M_UID, strlen(M_UID) + 1);
|
||||||
|
zassert_mem_equal(getenv("PWD"), M_PWD, strlen(M_PWD) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(env, test_getenv_r)
|
||||||
|
{
|
||||||
|
static char buf[16];
|
||||||
|
static const int exp_errno[] = {
|
||||||
|
EINVAL, EINVAL, EINVAL, EINVAL, ENOENT, ENOENT, ENOENT, EINVAL, EINVAL, EINVAL,
|
||||||
|
};
|
||||||
|
static const struct args_s {
|
||||||
|
const char *name;
|
||||||
|
char *buf;
|
||||||
|
size_t size;
|
||||||
|
} args[] = {
|
||||||
|
/* invalid input */
|
||||||
|
{NULL, NULL, 0},
|
||||||
|
{NULL, NULL, 42},
|
||||||
|
{NULL, buf, 0},
|
||||||
|
{NULL, buf, sizeof(buf)},
|
||||||
|
{"hello", NULL, 0},
|
||||||
|
{"hello", NULL, 42},
|
||||||
|
{"hello", buf, 0},
|
||||||
|
|
||||||
|
/* invalid names */
|
||||||
|
{"", buf, sizeof(buf)},
|
||||||
|
{"invalid=key", buf, sizeof(buf)},
|
||||||
|
{"HOME=", buf, sizeof(buf)},
|
||||||
|
};
|
||||||
|
|
||||||
|
BUILD_ASSERT(ARRAY_SIZE(exp_errno) == ARRAY_SIZE(args));
|
||||||
|
|
||||||
|
ARRAY_FOR_EACH(args, i)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
zassert_equal(getenv_r(args[i].name, args[i].buf, args[i].size), -1,
|
||||||
|
"getenv_r(\"%s\", %p, %zu): expected to fail", args[i].name,
|
||||||
|
args[i].buf, args[i].size);
|
||||||
|
zassert_equal(errno, exp_errno[i],
|
||||||
|
"getenv_r(\"%s\", %p, %zu): act_errno: %d exp_errno: %d",
|
||||||
|
args[i].name, args[i].buf, args[i].size, errno, exp_errno[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
zassert_mem_equal(getenv("HOME"), M_HOME, strlen(M_HOME) + 1);
|
||||||
|
zassert_mem_equal(getenv("UID"), M_UID, strlen(M_UID) + 1);
|
||||||
|
zassert_mem_equal(getenv("PWD"), M_PWD, strlen(M_PWD) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(env, test_setenv)
|
||||||
|
{
|
||||||
|
zassert_equal(setenv(NULL, NULL, 0), -1);
|
||||||
|
zassert_equal(errno, EINVAL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bug in picolibc / newlib
|
||||||
|
* https://github.com/picolibc/picolibc/issues/648
|
||||||
|
*/
|
||||||
|
zassert_equal(setenv("", "42", 0), -1);
|
||||||
|
zassert_equal(errno, EINVAL);
|
||||||
|
|
||||||
|
zassert_equal(setenv("invalid=key", "42", 0), -1);
|
||||||
|
zassert_equal(errno, EINVAL);
|
||||||
|
|
||||||
|
/* do not overwrite if environ[key] exists */
|
||||||
|
zassert_ok(setenv("HOME", "/root", 0));
|
||||||
|
zassert_mem_equal(getenv("HOME"), M_HOME, strlen(M_HOME) + 1);
|
||||||
|
|
||||||
|
/* should overwrite (without malloc) */
|
||||||
|
zassert_ok(setenv("HOME", "/root", 1));
|
||||||
|
zassert_mem_equal(getenv("HOME"), "/root", strlen("/root") + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(env, test_unsetenv)
|
||||||
|
{
|
||||||
|
/* not hardened / application should fault */
|
||||||
|
zassert_equal(unsetenv(NULL), -1);
|
||||||
|
zassert_equal(errno, EINVAL);
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
/* bug in picolibc / newlib */
|
||||||
|
zassert_equal(unsetenv(""), -1);
|
||||||
|
zassert_equal(errno, EINVAL);
|
||||||
|
|
||||||
|
zassert_equal(unsetenv("invalid=key"), -1);
|
||||||
|
zassert_equal(errno, EINVAL);
|
||||||
|
|
||||||
|
/* restore original environ */
|
||||||
|
environ = old_environ;
|
||||||
|
/* should overwrite (requires realloc) */
|
||||||
|
zassert_ok(setenv("HOME", _m_alt_home, 1));
|
||||||
|
zassert_mem_equal(getenv("HOME"), _m_alt_home, strlen(_m_alt_home) + 1);
|
||||||
|
zassert_ok(unsetenv("HOME"));
|
||||||
|
zassert_is_null(getenv("HOME"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST(env, test_watertight)
|
||||||
|
{
|
||||||
|
extern size_t posix_env_get_allocated_space(void);
|
||||||
|
|
||||||
|
char buf[4];
|
||||||
|
|
||||||
|
/* restore original environ, which should support realloc, free, etc */
|
||||||
|
environ = old_environ;
|
||||||
|
|
||||||
|
for (int i = 0; i < 256; ++i) {
|
||||||
|
snprintf(buf, sizeof(buf), "%u", i);
|
||||||
|
zassert_ok(setenv("COUNTER", buf, 1));
|
||||||
|
zassert_mem_equal(getenv("COUNTER"), buf, strlen(buf));
|
||||||
|
zassert_ok(getenv_r("COUNTER", buf, sizeof(buf)));
|
||||||
|
zassert_equal(atoi(buf), i);
|
||||||
|
zassert_ok(unsetenv("COUNTER"));
|
||||||
|
}
|
||||||
|
|
||||||
|
zassert_equal(posix_env_get_allocated_space(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void before(void *arg)
|
||||||
|
{
|
||||||
|
old_environ = environ;
|
||||||
|
|
||||||
|
RESET_ENVIRON(home, "HOME", M_HOME);
|
||||||
|
RESET_ENVIRON(uid, "UID", M_UID);
|
||||||
|
RESET_ENVIRON(pwd, "PWD", M_PWD);
|
||||||
|
environ_for_test[0] = home;
|
||||||
|
environ_for_test[1] = uid;
|
||||||
|
environ_for_test[2] = pwd;
|
||||||
|
|
||||||
|
zassert_equal((environ = environ_for_test), environ_for_test);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void after(void *arg)
|
||||||
|
{
|
||||||
|
environ = old_environ;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZTEST_SUITE(env, NULL, NULL, before, after, NULL);
|
32
tests/posix/env/testcase.yaml
vendored
Normal file
32
tests/posix/env/testcase.yaml
vendored
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
common:
|
||||||
|
filter: not CONFIG_NATIVE_LIBC
|
||||||
|
arch_exclude:
|
||||||
|
- posix
|
||||||
|
integration_platforms:
|
||||||
|
- qemu_riscv64
|
||||||
|
tags: posix
|
||||||
|
tests:
|
||||||
|
portability.posix.env: {}
|
||||||
|
portability.posix.env.armclang_std_libc:
|
||||||
|
toolchain_allow: armclang
|
||||||
|
extra_configs:
|
||||||
|
- CONFIG_ARMCLANG_STD_LIBC=y
|
||||||
|
portability.posix.env.arcmwdtlib:
|
||||||
|
toolchain_allow: arcmwdt
|
||||||
|
extra_configs:
|
||||||
|
- CONFIG_ARCMWDT_LIBC=y
|
||||||
|
portability.posix.env.minimal:
|
||||||
|
extra_configs:
|
||||||
|
- CONFIG_MINIMAL_LIBC=y
|
||||||
|
- CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=256
|
||||||
|
portability.posix.env.newlib:
|
||||||
|
platform_exclude:
|
||||||
|
- hifive1
|
||||||
|
filter: TOOLCHAIN_HAS_NEWLIB == 1
|
||||||
|
extra_configs:
|
||||||
|
- CONFIG_NEWLIB_LIBC=y
|
||||||
|
portability.posix.env.picolibc:
|
||||||
|
tags: picolibc
|
||||||
|
filter: CONFIG_PICOLIBC_SUPPORTED
|
||||||
|
extra_configs:
|
||||||
|
- CONFIG_PICOLIBC=y
|
Loading…
Add table
Add a link
Reference in a new issue