Skip to content

Commit

Permalink
add ioctl test
Browse files Browse the repository at this point in the history
JIRA: CI-237
  • Loading branch information
adamdebek committed May 29, 2023
1 parent 9d58c96 commit 0c449cf
Show file tree
Hide file tree
Showing 3 changed files with 360 additions and 0 deletions.
5 changes: 5 additions & 0 deletions ioctl/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
NAME := test-ioctl
LOCAL_SRCS := test_ioctl.c
DEP_LIBS := unity

include $(binary.mk)
7 changes: 7 additions & 0 deletions ioctl/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
test:
type: unity
tests:
- name: unit
execute: test-ioctl
targets:
exclude: [armv7a9-zynq7000-qemu]
348 changes: 348 additions & 0 deletions ioctl/test_ioctl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
/*
* Phoenix-RTOS
*
* Phoenix-RTOS standard library functions tests
* HEADER:
* - ioctl.h
* TESTED:
* - ioctl()
*
* Copyright 2023 Phoenix Systems
* Author: Adam Debek
*
* This file is part of Phoenix-RTOS.
*
* %LICENSE%
*/

#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <phoenix/ioctl.h>
#include <sys/msg.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <posix/utils.h>
#include <unity_fixture.h>


static uint32_t port;
static pthread_t tid;
static int fd, dd;

#define BIG_SIZE 1024
#define MAX_FAIL 10
#define PATH "test_ioctl_tmpFile"
/* In above T stands for test, do not confuse with tty */
#define TIOCSIG _IOC(0, 'T', 0x01, 0)
#define TIOCVAL _IOC(0, 'T', 0x02, 4)
#define TIOCPTR _IOC(IOC_IN, 'T', 0x03, 4)
#define TIOCPTR2 _IOC(IOC_IN, 'T', 0x04, BIG_SIZE)
#define TIOCOUT _IOC(IOC_OUT, 'T', 0x05, 4)
#define TIOCOUT2 _IOC(IOC_OUT, 'T', 0x06, BIG_SIZE)

static void *thread(void *arg)
{
msg_t msg;
unsigned long int rid;
int32_t out = 15;
int8_t out2[BIG_SIZE];
memset(out2, 5, BIG_SIZE);
int32_t flag = 1;
void *retval;

while (1) {
if (msgRecv(port, &msg, &rid) < 0) {
continue;
}

if (msg.type == mtDevCtl) {
unsigned long request;
int err = 0;
const void *out_data = NULL;
const void *in_data = ioctl_unpack(&msg, &request, NULL);
switch (request) {
case TIOCVAL:
if (lseek(fd, 0, SEEK_SET) != 0) {
TEST_MESSAGE("lseek failed in TIOCVAL case");
}
if (write(fd, &in_data, 4) != 4) {
TEST_MESSAGE("write failed in TIOCVAL case");
}
break;
case TIOCSIG:
if (lseek(fd, 0, SEEK_SET) != 0) {
TEST_MESSAGE("lseek failed in TIOCSIG case");
}
if (write(fd, &flag, 4) != 4) {
TEST_MESSAGE("write failed in TIOCSIG case");
}
break;
case TIOCPTR:
if (lseek(fd, 0, SEEK_SET) != 0) {
TEST_MESSAGE("lseek failed in TIOCPTR case");
}
if (write(fd, in_data, 4) != 4) {
TEST_MESSAGE("write failed in TIOCPTR case");
}
break;
case TIOCPTR2:
if (lseek(fd, 0, SEEK_SET) != 0) {
TEST_MESSAGE("lseek failed in TIOCPTR2 case");
}
if (write(fd, in_data, BIG_SIZE) != 4) {
TEST_MESSAGE("write failed in TIOCPTR2 case");
}
break;
case TIOCOUT:
out_data = (const void *)(&out);
break;
case TIOCOUT2:
out_data = (const void *)(out2);
break;
}
ioctl_setResponse(&msg, request, err, out_data);
}
msgRespond(port, &msg, rid);
}
return retval;
}


TEST_GROUP(ioctl);


TEST_SETUP(ioctl)
{
}

TEST_TEAR_DOWN(ioctl)
{
}


TEST(ioctl, regular_file)
{
/* try regular file, not special device file */
int fd = open(PATH, O_RDWR | O_CREAT | O_TRUNC);
TEST_ASSERT_NOT_EQUAL_INT(-1, fd);
errno = 0;
int ret = ioctl(fd, TIOCSIG, NULL);
TEST_ASSERT_EQUAL_INT(-1, ret);
// TEST_ASSERT_EQUAL_INT(EBADF, errno);
}


TEST(ioctl, wrong_fd)
{
errno = 0;
int ret = ioctl(123, 0, NULL);
TEST_ASSERT_EQUAL_INT(-1, ret);
TEST_ASSERT_EQUAL_INT(EBADF, errno);
}


TEST(ioctl, no_data)
{
int32_t flag;
int ret;

/* Send data to driver by value */
ret = ioctl(dd, TIOCSIG, NULL);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT(0, lseek(fd, 0, SEEK_SET));
TEST_ASSERT_EQUAL_INT(4, read(fd, &flag, 4));
TEST_ASSERT_EQUAL_INT32(1, flag);
}


TEST(ioctl, in_val)
{
int32_t rdata, data = 14;
int ret;

/* Send data to driver by value */
ret = ioctl(dd, TIOCVAL, data);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT(0, lseek(fd, 0, SEEK_SET));
TEST_ASSERT_EQUAL_INT(4, read(fd, &rdata, 4));
TEST_ASSERT_EQUAL_INT32(14, rdata);
}


TEST(ioctl, data_in)
{
int32_t rdata, data_in = 20;
int ret;

/* Send data to driver by pointer */
ret = ioctl(dd, TIOCPTR, &data_in);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT(0, lseek(fd, 0, SEEK_SET));
TEST_ASSERT_EQUAL_INT(4, read(fd, &rdata, 4));
TEST_ASSERT_EQUAL_INT32(20, rdata);
}


TEST(ioctl, data_in_big)
{
/* Big data so that it is not copied inside message */
int8_t data_in[BIG_SIZE];
memset(data_in, 3, BIG_SIZE);
int8_t rdata[BIG_SIZE];
int ret;

/* Send data to driver by pointer , data big enough to not be copied by ioctl_pack directly into message */
ret = ioctl(dd, TIOCPTR2, data_in);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT(0, lseek(fd, 0, SEEK_SET));
TEST_ASSERT_EQUAL_INT(BIG_SIZE, read(fd, rdata, BIG_SIZE));
TEST_ASSERT_EQUAL_MEMORY(data_in, rdata, BIG_SIZE);
}


TEST(ioctl, data_out)
{
int32_t data_out;
int ret;

/* Get data from driver */
ret = ioctl(dd, TIOCOUT, &data_out);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_INT32(15, data_out);
}


TEST(ioctl, data_out_big)
{
/* Big data so that it is not copied inside message */
int8_t data_expected[BIG_SIZE];
memset(data_expected, 5, BIG_SIZE);
int8_t data_out[BIG_SIZE];
int ret;

/* Get data from driver */
ret = ioctl(dd, TIOCOUT2, data_out);
TEST_ASSERT_EQUAL_INT(0, ret);
TEST_ASSERT_EQUAL_MEMORY(data_expected, data_out, BIG_SIZE);
}


TEST_GROUP_RUNNER(ioctl)
{
char devName[5] = "test";
oid_t dev;
int res, n = 0;

fd = open(PATH, O_RDWR | O_CREAT | O_TRUNC);
if (fd < 0) {
fprintf(stderr, "Couldn't open file\n");
return 1;
}

res = portCreate(&port);
if (res != EOK) {
fprintf(stderr, "Couldn't create port\n");
return 1;
}

dev.port = port;
dev.id = 0;

res = create_dev(&dev, devName);
if (res != EOK) {
fprintf(stderr, "Coldn't create device\n");
return 1;
}

res = pthread_create(&tid, NULL, thread, NULL);
if (res != 0) {
fprintf(stderr, "Couldn't create thread\n");
return 1;
}

while ((dd = open("/dev/test", O_RDWR)) < 0 && n < MAX_FAIL) {
usleep(10000);
n++;
}

if (n == MAX_FAIL) {
close(fd);
remove(PATH);
fprintf(stderr, "Can't open device file\n");
return 1;
}
/* main thread - run test cases */
//RUN_TEST_CASE(ioctl, regular_file);
RUN_TEST_CASE(ioctl, wrong_fd);
RUN_TEST_CASE(ioctl, no_data);
RUN_TEST_CASE(ioctl, in_val);
RUN_TEST_CASE(ioctl, data_in);
RUN_TEST_CASE(ioctl, data_in_big);
RUN_TEST_CASE(ioctl, data_out);
RUN_TEST_CASE(ioctl, data_out_big);
/* device driver server (child process) no longer needed */
close(dd);
close(fd);
remove(PATH);
}


void runner(void)
{
RUN_TEST_GROUP(ioctl);
}


int main(int argc, char *argv[])
{
// char devName[5] = "test";
// oid_t dev;
// int res, n = 0;

// fd = open(PATH, O_RDWR | O_CREAT | O_TRUNC);
// if (fd < 0) {
// fprintf(stderr, "Couldn't open file\n");
// return 1;
// }

// res = portCreate(&port);
// if (res != EOK) {
// fprintf(stderr, "Couldn't create port\n");
// return 1;
// }

// dev.port = port;
// dev.id = 0;

// res = create_dev(&dev, devName);
// if (res != EOK) {
// fprintf(stderr, "Coldn't create device\n");
// return 1;
// }

// res = pthread_create(&tid, NULL, thread, NULL);
// if (res != 0) {
// fprintf(stderr, "Couldn't create thread\n");
// return 1;
// }

// while ((dd = open("/dev/test", O_RDWR)) < 0 && n < MAX_FAIL) {
// usleep(10000);
// n++;
// }

// if (n == MAX_FAIL) {
// close(fd);
// remove(PATH);
// fprintf(stderr, "Can't open device file\n");
// return 1;
// }

UnityMain(argc, (const char **)argv, runner);
return 0;
}

0 comments on commit 0c449cf

Please sign in to comment.