diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f00889..0a6dd44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ set(SOURCES # signal src/signal/signal.c # stdio + src/stdio/files.c src/stdio/printf.c # stdlib src/stdlib/arith.c diff --git a/include/ft/all-tests.h b/include/ft/all-tests.h index b21aee3..6011acf 100644 --- a/include/ft/all-tests.h +++ b/include/ft/all-tests.h @@ -27,6 +27,7 @@ extern ft_test ft_signal_signal; extern ft_test ft_stdio_printf_basics; extern ft_test ft_stdio_printf_formats; extern ft_test ft_stdio_printf_fp; +extern ft_test ft_stdio_open; /* stdlib */ extern ft_test ft_stdlib_arith; diff --git a/src/main.c b/src/main.c index d44188f..d5dd1a8 100644 --- a/src/main.c +++ b/src/main.c @@ -43,6 +43,7 @@ ft_list headers_libc[] = { &ft_stdio_printf_basics, &ft_stdio_printf_formats, &ft_stdio_printf_fp, + &ft_stdio_open, NULL, }}, { _("stdlib.h", ""), (ft_test*[]){ diff --git a/src/stdio/files.c b/src/stdio/files.c new file mode 100644 index 0000000..2efe4b9 --- /dev/null +++ b/src/stdio/files.c @@ -0,0 +1,71 @@ +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "util.h" + +static void _stdio_open_switch(ft_test *t) +{ + int fd, rc; + FILE *fp; + + /* Create a basic file */ + DO_E(fd, creat("ft_stdio.txt", 0755), t, "%d"); + ft_assert(t, fd >= 0); + DO_E(rc, write(fd, "Hello, stdio!\n", 14), t, "%d"); + ft_assert(t, rc == 14); + DO_E(rc, close(fd), t, "%d"); + ft_assert(t, rc == 0); + + /* Try to open it with */ + DO_E(fp, fopen("ft_stdio.txt", "r"), t, "%p"); + ft_assert(t, fp != NULL); + ft_log_FILE(t, "", fp); + + /* Change buffer settings a couple times */ + DO_E(rc, setvbuf(fp, NULL, _IONBF, 0), t, "%d"); + ft_assert(t, rc == 0); + ft_log_FILE(t, "", fp); + DO_E(rc, setvbuf(fp, NULL, _IOLBF, 1024), t, "%d"); + ft_assert(t, rc == 0); + ft_log_FILE(t, "", fp); + DO_E(rc, setvbuf(fp, NULL, _IOFBF, BUFSIZ), t, "%d"); + ft_assert(t, rc == 0); + ft_log_FILE(t, "", fp); + + /* Reopen with different permissions */ + DO_E(fp, freopen("ft_stdio.txt", "w+", fp), t, "%p"); + ft_assert(t, fp != NULL); + ft_log_FILE(t, "", fp); + DO_E(fp, freopen("ft_stdio.txt", "rb+", fp), t, "%p"); + ft_assert(t, fp != NULL); + ft_log_FILE(t, "", fp); + DO_E(fp, freopen("ft_stdio.txt", "ab", fp), t, "%p"); + ft_assert(t, fp != NULL); + ft_log_FILE(t, "", fp); + DO_E(fp, freopen("ft_stdio.txt", "w", fp), t, "%p"); + ft_assert(t, fp != NULL); + ft_log_FILE(t, "", fp); + + DO_E(rc, fclose(fp), t, "%d"); + ft_assert(t, rc == 0); +} + +static void _stdio_open(ft_test *t) +{ + gint_world_switch(GINT_CALL(_stdio_open_switch, (void *)t)); +} + +ft_test ft_stdio_open = { + .name = "Opening files", + .function = _stdio_open, +}; diff --git a/src/stdio/util.h b/src/stdio/util.h new file mode 100644 index 0000000..48d9b35 --- /dev/null +++ b/src/stdio/util.h @@ -0,0 +1,42 @@ +#ifndef _STDIO_UTIL_H +#define _STDIO_UTIL_H + +#include +#include + +/* Print a FILE to an ft_test. */ +static inline void ft_log_FILE(ft_test *t, char const *prefix, FILE *fp) +{ + ft_log(t, "%s%s", prefix, (*prefix ? " " : "")); + if(!fp) { + ft_log(t, "(null)\n"); + return; + } + + ft_log(t, "{fd %d/%d, mode %s%s%s%s%s%s, %s", + fp->fd, fp->fdpos, + fp->readable ? "r" : "", + fp->writable ? "w" : "", + fp->append ? "A" : "", + fp->text ? "" : "b", + fp->error ? " ERROR" : "", + fp->eof ? " EOF" : "", + fp->bufmode == _IONBF ? "_IONBF" : + fp->bufmode == _IOLBF ? "_IOLBF" : + fp->bufmode == _IOFBF ? "_IOFBF" : "_???"); + + if(fp->bufmode != _IONBF) { + ft_log(t, " %p/%d", fp->buf, fp->bufsize); + + if(fp->bufpos == 0) + ft_log(t, " EMPTY"); + else if(fp->bufdir == __FILE_BUF_READ) + ft_log(t, " READ %d/%d", fp->bufpos, fp->bufread); + else if(fp->bufdir == __FILE_BUF_WRITE) + ft_log(t, " WRITE %d", fp->bufpos); + } + + ft_log(t, "}\n"); +} + +#endif /* _STDIO_UTIL_H */