blob: 8a43bd84a3d82e734217b208c7e1c40ad39e7d2a [file] [log] [blame]
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/ztest.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/fdtable.h>
#include <errno.h>
/* The thread will test that the refcounting of fd object will
* work as expected.
*/
static struct k_thread fd_thread;
static int shared_fd;
static struct fd_op_vtable fd_vtable = { 0 };
#define VTABLE_INIT (&fd_vtable)
K_THREAD_STACK_DEFINE(fd_thread_stack, CONFIG_ZTEST_STACK_SIZE +
CONFIG_TEST_EXTRA_STACK_SIZE);
ZTEST(fdtable, test_z_reserve_fd)
{
int fd = z_reserve_fd(); /* function being tested */
zassert_true(fd >= 0, "fd < 0");
z_free_fd(fd);
}
ZTEST(fdtable, test_z_get_fd_obj_and_vtable)
{
const struct fd_op_vtable *vtable;
int fd = z_reserve_fd();
zassert_true(fd >= 0, "fd < 0");
int *obj;
obj = z_get_fd_obj_and_vtable(fd, &vtable,
NULL); /* function being tested */
zassert_is_null(obj, "obj is not NULL");
z_free_fd(fd);
}
ZTEST(fdtable, test_z_get_fd_obj)
{
int fd = z_reserve_fd();
zassert_true(fd >= 0, "fd < 0");
int err = -1;
const struct fd_op_vtable *vtable = 0;
const struct fd_op_vtable *vtable2 = vtable+1;
int *obj = z_get_fd_obj(fd, vtable, err); /* function being tested */
/* take branch -- if (_check_fd(fd) < 0) */
zassert_is_null(obj, "obj not is NULL");
obj = (void *)1;
vtable = NULL;
/* This will set obj and vtable properly */
z_finalize_fd(fd, obj, vtable);
obj = z_get_fd_obj(-1, vtable, err); /* function being tested */
zassert_equal_ptr(obj, NULL, "obj is not NULL when fd < 0");
zassert_equal(errno, EBADF, "fd: out of bounds error");
/* take branch -- if (vtable != NULL && fd_entry->vtable != vtable) */
obj = z_get_fd_obj(fd, vtable2, err); /* function being tested */
zassert_equal_ptr(obj, NULL, "obj is not NULL - vtable doesn't match");
zassert_equal(errno, err, "vtable matches");
z_free_fd(fd);
}
ZTEST(fdtable, test_z_finalize_fd)
{
const struct fd_op_vtable *vtable;
int fd = z_reserve_fd();
zassert_true(fd >= 0);
int *obj = z_get_fd_obj_and_vtable(fd, &vtable, NULL);
const struct fd_op_vtable *original_vtable = vtable;
int *original_obj = obj;
z_finalize_fd(fd, obj, vtable); /* function being tested */
obj = z_get_fd_obj_and_vtable(fd, &vtable, NULL);
zassert_equal_ptr(obj, original_obj, "obj is different after finalizing");
zassert_equal_ptr(vtable, original_vtable, "vtable is different after finalizing");
z_free_fd(fd);
}
ZTEST(fdtable, test_z_alloc_fd)
{
const struct fd_op_vtable *vtable = NULL;
int *obj = NULL;
int fd = z_alloc_fd(obj, vtable); /* function being tested */
zassert_true(fd >= 0);
obj = z_get_fd_obj_and_vtable(fd, &vtable, NULL);
zassert_equal_ptr(obj, NULL, "obj is different after allocating");
zassert_equal_ptr(vtable, NULL, "vtable is different after allocating");
z_free_fd(fd);
}
ZTEST(fdtable, test_z_free_fd)
{
const struct fd_op_vtable *vtable = NULL;
int fd = z_reserve_fd();
zassert_true(fd >= 0);
z_free_fd(fd); /* function being tested */
int *obj = z_get_fd_obj_and_vtable(fd, &vtable, NULL);
zassert_equal_ptr(obj, NULL, "obj is not NULL after freeing");
}
static void test_cb(void *fd_ptr)
{
int fd = POINTER_TO_INT(fd_ptr);
const struct fd_op_vtable *vtable;
int *obj;
obj = z_get_fd_obj_and_vtable(fd, &vtable, NULL);
zassert_not_null(obj, "obj is null");
zassert_not_null(vtable, "vtable is null");
z_free_fd(fd);
obj = z_get_fd_obj_and_vtable(fd, &vtable, NULL);
zassert_is_null(obj, "obj is still there");
zassert_equal(errno, EBADF, "fd was found");
}
ZTEST(fdtable, test_z_fd_multiple_access)
{
const struct fd_op_vtable *vtable = VTABLE_INIT;
void *obj = (void *)vtable;
shared_fd = z_reserve_fd();
zassert_true(shared_fd >= 0, "fd < 0");
z_finalize_fd(shared_fd, obj, vtable);
k_thread_create(&fd_thread, fd_thread_stack,
K_THREAD_STACK_SIZEOF(fd_thread_stack),
(k_thread_entry_t)test_cb,
INT_TO_POINTER(shared_fd), NULL, NULL,
CONFIG_ZTEST_THREAD_PRIORITY, 0, K_NO_WAIT);
k_thread_join(&fd_thread, K_FOREVER);
/* should be null since freed in the other thread */
obj = z_get_fd_obj_and_vtable(shared_fd, &vtable, NULL);
zassert_is_null(obj, "obj is still there");
zassert_equal(errno, EBADF, "fd was found");
}
ZTEST_SUITE(fdtable, NULL, NULL, NULL, NULL, NULL);