merge: iobackend on dev
This commit is contained in:
commit
9923ebc677
3 changed files with 218 additions and 17 deletions
|
|
@ -1,35 +1,102 @@
|
||||||
#include "io_backend.h"
|
#include "io_backend.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// === Static variables
|
||||||
|
|
||||||
static struct iob_context context;
|
static struct iob_context context;
|
||||||
static FILE *input;
|
static FILE *input = NULL;
|
||||||
|
static char *stream_buf = NULL;
|
||||||
|
static size_t stream_buf_size = 0;
|
||||||
|
static enum iob_state state = IOB_STATE_NOT_INITIALIZED;
|
||||||
|
|
||||||
|
// === Functions
|
||||||
|
|
||||||
int iob_init(struct iob_context *ctx)
|
int iob_init(struct iob_context *ctx)
|
||||||
{
|
{
|
||||||
|
if (state != IOB_STATE_NOT_INITIALIZED)
|
||||||
|
return IOB_ERROR_MODULE_ALREADY_INITIALIZED;
|
||||||
|
|
||||||
context = *ctx;
|
context = *ctx;
|
||||||
|
|
||||||
switch (context.mode)
|
switch (context.mode)
|
||||||
{
|
{
|
||||||
case IOB_MODE_STDIN:
|
case IOB_MODE_STDIN:
|
||||||
input = stdin;
|
input = stdin;
|
||||||
|
state = IOB_STATE_READY;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case IOB_MODE_SCRIPT:
|
case IOB_MODE_SCRIPT:
|
||||||
if (context.args == NULL)
|
if (context.args == NULL)
|
||||||
return -2;
|
return IOB_ERROR_BAD_ARG;
|
||||||
input = fopen(context.args, "r");
|
input = fopen(context.args, "r");
|
||||||
if (input == NULL)
|
if (input == NULL)
|
||||||
return -4;
|
return IOB_ERROR_CANNOT_OPEN_FILE;
|
||||||
|
state = IOB_STATE_READY;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case IOB_MODE_CMD:
|
case IOB_MODE_CMD:
|
||||||
if (context.args != NULL)
|
if (context.args != NULL)
|
||||||
return -2;
|
return IOB_ERROR_BAD_ARG;
|
||||||
else
|
state = IOB_STATE_READY;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -1;
|
return IOB_ERROR_BAD_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iob_close(void)
|
||||||
|
{
|
||||||
|
fclose(input);
|
||||||
|
if ((context.mode == IOB_MODE_STDIN || context.mode == IOB_MODE_SCRIPT)
|
||||||
|
&& stream_buf != NULL)
|
||||||
|
{
|
||||||
|
free(stream_buf);
|
||||||
|
stream_buf_size = 0;
|
||||||
|
}
|
||||||
|
state = IOB_STATE_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t stream_read(char **stream)
|
||||||
|
{
|
||||||
|
// Check args
|
||||||
|
if (stream == NULL)
|
||||||
|
return IOB_ERROR_BAD_ARG;
|
||||||
|
|
||||||
|
// Check env
|
||||||
|
if (state == IOB_STATE_NOT_INITIALIZED)
|
||||||
|
return IOB_ERROR_MODULE_NOT_INITIALIZED;
|
||||||
|
if (state == IOB_STATE_FINISHED)
|
||||||
|
return 0;
|
||||||
|
if (state == IOB_STATE_ERROR)
|
||||||
|
return IOB_ERROR_GENERIC;
|
||||||
|
|
||||||
|
// Use input
|
||||||
|
if (context.mode == IOB_MODE_STDIN || context.mode == IOB_MODE_SCRIPT)
|
||||||
|
{
|
||||||
|
ssize_t nread = getline(&stream_buf, &stream_buf_size, input);
|
||||||
|
if (nread == -1)
|
||||||
|
{
|
||||||
|
state = IOB_STATE_FINISHED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (nread < 0)
|
||||||
|
state = IOB_STATE_ERROR;
|
||||||
|
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
// Use args
|
||||||
|
else if (context.mode == IOB_MODE_CMD)
|
||||||
|
{
|
||||||
|
*stream = context.args;
|
||||||
|
return strlen(context.args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*stream = NULL;
|
||||||
|
return IOB_ERROR_GENERIC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,13 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
// Error codes
|
||||||
|
#define IOB_ERROR_GENERIC -1
|
||||||
|
#define IOB_ERROR_BAD_ARG -2
|
||||||
|
#define IOB_ERROR_MODULE_NOT_INITIALIZED -3
|
||||||
|
#define IOB_ERROR_MODULE_ALREADY_INITIALIZED -4
|
||||||
|
#define IOB_ERROR_CANNOT_OPEN_FILE -5
|
||||||
|
|
||||||
enum iob_mode
|
enum iob_mode
|
||||||
{
|
{
|
||||||
IOB_MODE_NULL = 0,
|
IOB_MODE_NULL = 0,
|
||||||
|
|
@ -11,11 +18,19 @@ enum iob_mode
|
||||||
IOB_MODE_CMD
|
IOB_MODE_CMD
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum iob_state
|
||||||
|
{
|
||||||
|
IOB_STATE_NOT_INITIALIZED,
|
||||||
|
IOB_STATE_READY,
|
||||||
|
IOB_STATE_FINISHED,
|
||||||
|
IOB_STATE_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
/* @struct iob_context
|
/* @struct iob_context
|
||||||
* @var mode
|
* @var mode
|
||||||
* @var args contains
|
* @var args contains
|
||||||
* the script name when mode is set to IOB_SCRIPT,
|
* the script name when mode is set to IOB_MODE_SCRIPT,
|
||||||
* the command to execute when mode is set to IOB_CMD,
|
* the command to execute when mode is set to IOB_MODE_CMD
|
||||||
*/
|
*/
|
||||||
struct iob_context
|
struct iob_context
|
||||||
{
|
{
|
||||||
|
|
@ -31,17 +46,16 @@ struct iob_context
|
||||||
*/
|
*/
|
||||||
int iob_init(struct iob_context *context);
|
int iob_init(struct iob_context *context);
|
||||||
|
|
||||||
/* TODO
|
/* @brief Closes the opened buffers and the module gracefully
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
void iob_close();
|
void iob_close(void);
|
||||||
|
|
||||||
/*i TODO
|
/* @brief reads at most one line of the input and stores it into *stream
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
|
* @param stream is a pointer that will be set to a string to parse
|
||||||
|
* @return the number of read characters if positive,
|
||||||
|
* zero if finished (reached EOF),
|
||||||
|
* the error code otherwise
|
||||||
*/
|
*/
|
||||||
ssize_t stream_read(char **stream);
|
ssize_t stream_read(char **stream);
|
||||||
|
|
||||||
|
|
|
||||||
120
tests/unit/io_backend/io_backend.c
Normal file
120
tests/unit/io_backend/io_backend.c
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
#include <criterion/criterion.h>
|
||||||
|
#include <criterion/new/assert.h>
|
||||||
|
#include <io_backend/io_backend.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
TestSuite(IO_Backend);
|
||||||
|
|
||||||
|
// IOB Init
|
||||||
|
|
||||||
|
Test(IO_Backend, init_null)
|
||||||
|
{
|
||||||
|
struct iob_context ctx =
|
||||||
|
{
|
||||||
|
.iob_mode = IOB_MODE_NULL;
|
||||||
|
.args = NULL;
|
||||||
|
};
|
||||||
|
int actual = iob_init(ctx);
|
||||||
|
int expected = IOB_ERROR_BAD_ARG;
|
||||||
|
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(IO_Backend, init_stdin)
|
||||||
|
{
|
||||||
|
struct iob_context ctx =
|
||||||
|
{
|
||||||
|
.iob_mode = IOB_MODE_STDIN;
|
||||||
|
.args = NULL;
|
||||||
|
};
|
||||||
|
int actual = iob_init(ctx);
|
||||||
|
int expected = 0;
|
||||||
|
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
|
||||||
|
iob_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// WARNING: this one could fail because of iob_close in the previous test
|
||||||
|
// Same applies for other tests
|
||||||
|
Test(IO_Backend, init_script)
|
||||||
|
{
|
||||||
|
char *script_name = "script.tmp" struct iob_context ctx = {
|
||||||
|
.iob_mode = IOB_MODE_SCRIPT;
|
||||||
|
.args = script_name;
|
||||||
|
};
|
||||||
|
// Create file
|
||||||
|
FILE *f = fopen(script_name, "w");
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
int actual = iob_init(ctx);
|
||||||
|
int expected = 0;
|
||||||
|
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
|
||||||
|
iob_close();
|
||||||
|
remove(script_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(IO_Backend, init_script_not_a_file)
|
||||||
|
{
|
||||||
|
char *script_name = "not_a_file.tmp" struct iob_context ctx = {
|
||||||
|
.iob_mode = IOB_MODE_SCRIPT;
|
||||||
|
.args = script_name;
|
||||||
|
};
|
||||||
|
int actual = iob_init(ctx);
|
||||||
|
int expected = IOB_ERROR_CANNOT_OPEN_FILE;
|
||||||
|
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(IO_Backend, init_script_null)
|
||||||
|
{
|
||||||
|
struct iob_context ctx =
|
||||||
|
{
|
||||||
|
.iob_mode = IOB_MODE_SCRIPT;
|
||||||
|
.args = NULL;
|
||||||
|
};
|
||||||
|
int actual = iob_init(ctx);
|
||||||
|
int expected = IOB_ERROR_CANNOT_OPEN_FILE;
|
||||||
|
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(IO_Backend, init_cmd)
|
||||||
|
{
|
||||||
|
char *cmd = "iamacommand --yesido" struct iob_context ctx = {
|
||||||
|
.iob_mode = IOB_MODE_CMD;
|
||||||
|
.args = cmd;
|
||||||
|
};
|
||||||
|
int actual = iob_init(ctx);
|
||||||
|
int expected = 0;
|
||||||
|
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
|
||||||
|
iob_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(IO_Backend, init_cmd_null)
|
||||||
|
{
|
||||||
|
struct iob_context ctx =
|
||||||
|
{
|
||||||
|
.iob_mode = IOB_MODE_CMD;
|
||||||
|
.args = NULL;
|
||||||
|
};
|
||||||
|
int actual = iob_init(ctx);
|
||||||
|
int expected = IOB_ERROR_BAD_ARG;
|
||||||
|
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(IO_Backend, init_already_init)
|
||||||
|
{
|
||||||
|
char *cmd = "iamacommand --yesido" struct iob_context ctx = {
|
||||||
|
.iob_mode = IOB_MODE_CMD;
|
||||||
|
.args = cmd;
|
||||||
|
};
|
||||||
|
iob_init(ctx);
|
||||||
|
int actual = iob_init(ctx);
|
||||||
|
int expected = IOB_ERROR_ALREADY_INITIALIZED;
|
||||||
|
cr_expect(actual == expected, "Expected: %d. Got: %d", expected, actual);
|
||||||
|
iob_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Test(IO_Backend, close_not_init)
|
||||||
|
{
|
||||||
|
iob_close(); // Shouldn't do anything
|
||||||
|
}
|
||||||
|
|
||||||
|
// IOB Stream
|
||||||
|
// TODO
|
||||||
Loading…
Add table
Add a link
Reference in a new issue