stdio: tests for fdopen(), fputc(), fputs(), fgetc(), fgets()

This commit is contained in:
Lephenixnoir 2022-01-14 17:17:00 +01:00
parent 419fef4f1e
commit 58bab5137f
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 290 additions and 0 deletions

View File

@ -33,6 +33,9 @@ extern ft_test ft_stdio_simple_write;
extern ft_test ft_stdio_line_buffering;
extern ft_test ft_stdio_update_ungetc;
extern ft_test ft_stdio_append;
extern ft_test ft_stdio_fdopen;
extern ft_test ft_stdio_write_chars;
extern ft_test ft_stdio_read_chars;
/* stdlib */
extern ft_test ft_stdlib_arith;

View File

@ -49,6 +49,9 @@ ft_list headers_libc[] = {
&ft_stdio_line_buffering,
&ft_stdio_update_ungetc,
&ft_stdio_append,
&ft_stdio_fdopen,
&ft_stdio_write_chars,
&ft_stdio_read_chars,
NULL,
}},
{ _("stdlib.h", "<stdlib.h>"), (ft_test*[]){

View File

@ -670,3 +670,287 @@ ft_test ft_stdio_append = {
.name = "Append modes",
.function = _ft_stdio_append,
};
static void _ft_stdio_fdopen_switch(ft_test *t)
{
int fd, rc;
FILE *fp;
char str[128];
/* Write some stuff through fdopen() */
DO_E(fd, creat("ft_fdopen.txt", 0755), t, "%d");
ft_assert(t, fd >= 0);
if(fd < 0) return;
DO_E(fp, fdopen(fd, "w"), t, "%p");
ft_assert(t, fp != NULL);
if(fp == NULL) {
close(fd);
return;
}
DO_E(rc, fwrite(filler, 1, 128, fp), t, "%d");
ft_assert(t, rc == 128);
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
/* Check that the contents are correct */
DO_E(fp, fopen("ft_fdopen.txt", "r"), t, "%p");
ft_assert(t, fp != NULL);
if(fp == NULL) return;
DO_E(rc, fread(str, 1, 128, fp), t, "%d");
ft_assert(t, rc == 128);
ft_assert(t, !memcmp(str, filler, 128));
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
}
static void _ft_stdio_fdopen(ft_test *t)
{
gint_world_switch(GINT_CALL(_ft_stdio_fdopen_switch, (void *)t));
}
ft_test ft_stdio_fdopen = {
.name = "FILE wrapper with fdopen()",
.function = _ft_stdio_fdopen,
};
static void _ft_stdio_write_chars_switch(ft_test *t)
{
FILE *fp;
int rc;
/* Create a buffered file with basic data */
DO_E(fp, fopen("ft_fput.txt", "w"), t, "%p");
ft_assert(t, fp != NULL);
if(fp == NULL) return;
ft_log_FILE(t, "", fp);
DO_E(rc, setvbuf(fp, NULL, _IOFBF, 32), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, fputs("Test!", fp), t, "%d");
ft_assert(t, rc >= 0);
ft_log_FILE(t, "",fp);
ft_assert(t, fp->fdpos == 0);
ft_assert(t, fp->bufpos == 5);
DO_E(rc, fputs("Testing fputs() on _IOFBF streams\n", fp), t, "%d");
ft_assert(t, rc >= 0);
ft_log_FILE(t, "",fp);
ft_assert(t, fp->fdpos == 32);
ft_assert(t, fp->bufpos == 7);
for(int i = 0; i < 26; i++) {
DO_E(rc, fputc('A'+i, fp), t, "'%c'");
ft_assert(t, rc == 'A'+i);
DO_E(rc, fputc('a'+i, fp), t, "'%c'");
ft_assert(t, rc == 'a'+i);
}
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 64);
ft_assert(t, fp->bufpos == 27);
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
/* Same, but make it line-buffered */
DO_E(fp, fopen("ft_fput.txt", "w"), t, "%p");
ft_assert(t, fp != NULL);
if(fp == NULL) return;
ft_log_FILE(t, "", fp);
DO_E(rc, setvbuf(fp, NULL, _IOLBF, 32), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, fputs("Testing fputs() on _IOLBF streams\n", fp), t, "%d");
ft_assert(t, rc >= 0);
ft_log_FILE(t, "",fp);
ft_assert(t, fp->fdpos == 34);
ft_assert(t, fp->bufpos == 0);
for(int i = 0; i < 26; i++) {
DO_E(rc, fputc('a'+i, fp), t, "'%c'");
ft_assert(t, rc == 'a'+i);
}
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 34);
ft_assert(t, fp->bufpos == 26);
DO_E(rc, putc('\n', fp), t, "%d");
ft_assert(t, rc == '\n');
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 61);
ft_assert(t, fp->bufpos == 0);
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
/* Same with unbuffered */
DO_E(fp, fopen("ft_fput.txt", "w"), t, "%p");
ft_assert(t, fp != NULL);
if(fp == NULL) return;
ft_log_FILE(t, "", fp);
DO_E(rc, setvbuf(fp, NULL, _IONBF, 0), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, fputs("Testing fputs() on _IONBF streams\n", fp), t, "%d");
ft_assert(t, rc >= 0);
ft_log_FILE(t, "",fp);
/* Urgh this is going to be so slow. Don't do that kids */
for(int i = 0; i < 26; i++) {
DO_E(rc, putc('a'+i, fp), t, "'%c'");
ft_assert(t, rc == 'a'+i);
}
ft_log_FILE(t, "", fp);
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
}
static void _ft_stdio_write_chars(ft_test *t)
{
gint_world_switch(GINT_CALL(_ft_stdio_write_chars_switch, (void *)t));
}
ft_test ft_stdio_write_chars = {
.name = "Character output functions",
.function = _ft_stdio_write_chars,
};
static void _ft_stdio_read_chars_switch(ft_test *t)
{
FILE *fp;
int rc;
char str[20], *retstr;
/* Create an initial file with some filler */
DO_E(fp, fopen("ft_fget.txt", "w"), t, "%p");
ft_assert(t, fp != NULL);
if(fp == NULL) return;
DO_E(rc, fputs("Line #1\nLine #2\nLine #3", fp), t, "%d");
ft_assert(t, rc >= 0);
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
/* Read it with fgets() and fgetc() */
DO_E(fp, fopen("ft_fget.txt", "r"), t, "%p");
ft_assert(t, fp != NULL);
if(fp == NULL) return;
DO_E(rc, setvbuf(fp, NULL, _IOFBF, 14), t, "%d");
ft_assert(t, rc == 0);
ft_log_FILE(t, "", fp);
memset(str, 0xff, sizeof str);
DO_E(retstr, fgets(str, 20, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log_FILE(t, "", fp);
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "Line #1\n"));
memset(str, 0xff, sizeof str);
DO_E(retstr, fgets(str, 6, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log_FILE(t, "", fp);
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "Line "));
memset(str, 0xff, sizeof str);
DO_E(retstr, fgets(str, 20, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log_FILE(t, "", fp);
ft_assert(t, !strcmp(str, "#2\n"));
ft_log(t, "Reading to EOF with fgetc()...\n");
for(int i = 0; !feof(fp); i++) {
int c = fgetc(fp);
if(c == EOF) break;
str[i] = c;
str[i+1] = 0;
}
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "Line #3"));
/* Test fgets() at end of file */
DO_E(rc, fseek(fp, 16, SEEK_SET), t, "%d");
ft_assert(t, rc == 0);
DO_E(retstr, fgets(str, 20, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "Line #3"));
/* Test interactions of fgets() and fgetc() with ungetc() */
DO_E(rc, fseek(fp, 8, SEEK_SET), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, ungetc('#', fp), t, "'%c'");
ft_assert(t, rc == '#');
DO_E(rc, ungetc('!', fp), t, "'%c'");
ft_assert(t, rc == '!');
DO_E(rc, ungetc('$', fp), t, "'%c'");
ft_assert(t, rc == '$');
ft_log_FILE(t, "", fp);
DO_E(retstr, fgets(str, 20, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log_FILE(t, "", fp);
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "$!#Line #2\n"));
DO_E(rc, ungetc('#', fp), t, "'%c'");
ft_assert(t, rc == '#');
DO_E(rc, ungetc('!', fp), t, "'%c'");
ft_assert(t, rc == '!');
DO_E(rc, ungetc('$', fp), t, "'%c'");
ft_assert(t, rc == '$');
ft_log_FILE(t, "", fp);
ft_log(t, "Reading to EOF with fgetc()...\n");
for(int i = 0; !feof(fp); i++) {
int c = getc(fp);
if(c == EOF) break;
str[i] = c;
str[i+1] = 0;
}
ft_log_FILE(t, "", fp);
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "$!#Line #3"));
/* Try again without buffering */
rewind(fp);
ft_log(t, "rewind(fp)\n");
DO_E(rc, setvbuf(fp, NULL, _IONBF, 0), t, "%d");
ft_assert(t, rc == 0);
memset(str, 0xff, sizeof str);
DO_E(retstr, fgets(str, 20, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log_FILE(t, "", fp);
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "Line #1\n"));
memset(str, 0xff, sizeof str);
DO_E(retstr, fgets(str, 6, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log_FILE(t, "", fp);
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "Line "));
memset(str, 0xff, sizeof str);
DO_E(retstr, fgets(str, 20, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log_FILE(t, "", fp);
ft_assert(t, !strcmp(str, "#2\n"));
ft_log(t, "Reading to EOF with fgetc()...\n");
for(int i = 0; !feof(fp); i++) {
int c = fgetc(fp);
if(c == EOF) break;
str[i] = c;
str[i+1] = 0;
}
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "Line #3"));
/* Re-test interactions with ungetc() */
DO_E(rc, fseek(fp, 8, SEEK_SET), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, ungetc('#', fp), t, "'%c'");
ft_assert(t, rc == '#');
DO_E(rc, ungetc('!', fp), t, "'%c'");
ft_assert(t, rc == '!');
DO_E(rc, ungetc('$', fp), t, "'%c'");
ft_assert(t, rc == '$');
ft_log_FILE(t, "", fp);
DO_E(retstr, fgets(str, 20, fp), t, "%p");
ft_assert(t, retstr != NULL);
ft_log_FILE(t, "", fp);
ft_log(t, "str = '%s'\n", str);
ft_assert(t, !strcmp(str, "$!#Line #2\n"));
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
}
static void _ft_stdio_read_chars(ft_test *t)
{
gint_world_switch(GINT_CALL(_ft_stdio_read_chars_switch, (void *)t));
}
ft_test ft_stdio_read_chars = {
.name = "Character input functions",
.function = _ft_stdio_read_chars,
};