stdio: tests for simple fwrite() patterns and line buffering

This commit is contained in:
Lephenixnoir 2022-01-10 21:33:25 +01:00
parent 4ffcf4c892
commit ab763cf712
Signed by untrusted user: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
3 changed files with 192 additions and 0 deletions

View File

@ -29,6 +29,8 @@ extern ft_test ft_stdio_printf_formats;
extern ft_test ft_stdio_printf_fp;
extern ft_test ft_stdio_open;
extern ft_test ft_stdio_simple_read;
extern ft_test ft_stdio_simple_write;
extern ft_test ft_stdio_line_buffering;
/* stdlib */
extern ft_test ft_stdlib_arith;

View File

@ -45,6 +45,8 @@ ft_list headers_libc[] = {
&ft_stdio_printf_fp,
&ft_stdio_open,
&ft_stdio_simple_read,
&ft_stdio_simple_write,
&ft_stdio_line_buffering,
NULL,
}},
{ _("stdlib.h", "<stdlib.h>"), (ft_test*[]){

View File

@ -87,6 +87,7 @@ static void _ft_stdio_simple_read_switch(ft_test *t)
int fd, rc;
FILE *fp;
char *str = malloc(384);
fpos_t pos1, pos2;
/* Create a basic large file (compared to its buffer size) */
DO_E(fd, creat("ft_stdio.txt", 0755), t, "%d");
@ -175,6 +176,24 @@ static void _ft_stdio_simple_read_switch(ft_test *t)
ft_assert(t, fp->eof == 0);
ft_assert(t, feof(fp) == 0);
/* Move around with fgetpos() and fsetpos() */
DO_E(rc, fgetpos(fp, &pos1), t, "%d");
ft_assert(t, rc == 0);
ft_assert(t, (size_t)pos1 == 571);
DO_E(rc, fseek(fp, 12, SEEK_SET), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, fgetpos(fp, &pos2), t, "%d");
ft_assert(t, rc == 0);
ft_assert(t, (size_t)pos2 == 12);
DO_E(rc, fsetpos(fp, &pos1), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, ftell(fp), t, "%d");
ft_assert(t, rc == 571);
DO_E(rc, fsetpos(fp, &pos2), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, ftell(fp), t, "%d");
ft_assert(t, rc == 12);
/* Seek at end of file, the EOF flag should be cleared */
DO_E(rc, fseek(fp, 0, SEEK_END), t, "%d");
ft_assert(t, rc == 0);
@ -236,3 +255,172 @@ ft_test ft_stdio_simple_read = {
.name = "Simple file reading",
.function = _ft_stdio_simple_read,
};
static void _ft_stdio_simple_write_switch(ft_test *t)
{
FILE *fp;
int rc;
/* Open a new file */
DO_E(fp, fopen("ft_stdio.txt", "w"), t, "%p");
ft_assert(t, fp != NULL);
ft_log_FILE(t, "", fp);
DO_E(rc, setvbuf(fp, NULL, _IOFBF, 128), t, "%d");
ft_assert(t, rc == 0);
ft_log_FILE(t, "", fp);
DO_E(rc, ftell(fp), t, "%d");
ft_assert(t, rc == 0);
/* Write small parts into the buffer until it flushes */
DO_E(rc, fwrite(filler, 1, 32, fp), t, "%d");
ft_assert(t, rc == 32);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->fdpos == 0);
ft_assert(t, fp->bufpos == 32);
DO_E(rc, ftell(fp), t, "%d");
ft_assert(t, rc == 32);
DO_E(rc, fwrite(filler, 1, 32, fp), t, "%d");
ft_assert(t, rc == 32);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->fdpos == 0);
ft_assert(t, fp->bufpos == 64);
DO_E(rc, ftell(fp), t, "%d");
ft_assert(t, rc == 64);
DO_E(rc, fwrite(filler, 1, 32, fp), t, "%d");
ft_assert(t, rc == 32);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->fdpos == 0);
ft_assert(t, fp->bufpos == 96);
DO_E(rc, ftell(fp), t, "%d");
ft_assert(t, rc == 96);
DO_E(rc, fwrite(filler, 1, 32, fp), t, "%d");
ft_assert(t, rc == 32);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->fdpos == 128);
ft_assert(t, fp->bufpos == 0);
/* Write small bits and flush them immediately */
DO_E(rc, fwrite(filler, 1, 9, fp), t, "%d");
ft_assert(t, rc == 9);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->fdpos == 128);
ft_assert(t, fp->bufpos == 9);
DO_E(rc, fflush(fp), t, "%d");
ft_assert(t, rc == 0);
ft_assert(t, fp->fdpos == 137);
ft_assert(t, fp->bufpos == 0);
/* Write a large section which will flush several times */
DO_E(rc, fwrite(filler, 1, 591, fp), t, "%d");
ft_assert(t, rc == 591);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->fdpos == 649);
ft_assert(t, fp->bufpos == 79);
/* Flush by seeking somewhere else */
DO_E(rc, fseek(fp, -16, SEEK_END), t, "%d");
ft_assert(t, rc == 0);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 712);
ft_assert(t, fp->bufpos == 0);
DO_E(rc, ftell(fp), t, "%d");
ft_assert(t, rc == 712);
/* Now overwrite the last 16 bytes and extend the file */
DO_E(rc, fwrite(filler, 1, 32, fp), t, "%d");
ft_assert(t, rc == 32);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->fdpos == 712);
ft_assert(t, fp->bufpos == 32);
/* Close the file, which should flush */
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
/* Check the new file size */
DO_E(fp, fopen("ft_stdio.txt", "r"), t, "%p");
ft_assert(t, fp != NULL);
DO_E(rc, fseek(fp, 0, SEEK_END), t, "%d");
ft_assert(t, rc == 0);
DO_E(rc, ftell(fp), t, "%d");
ft_assert(t, rc == 744);
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
}
static void _ft_stdio_simple_write(ft_test *t)
{
gint_world_switch(GINT_CALL(_ft_stdio_simple_write_switch, (void *)t));
}
ft_test ft_stdio_simple_write = {
.name = "Simple file writing",
.function = _ft_stdio_simple_write,
};
static void _ft_stdio_line_buffering_switch(ft_test *t)
{
FILE *fp;
int rc;
/* Open a new line-buffered file */
DO_E(fp, fopen("ft_stdio.txt", "w"), t, "%p");
ft_assert(t, fp != NULL);
ft_log_FILE(t, "", fp);
DO_E(rc, setvbuf(fp, NULL, _IOLBF, 128), t, "%d");
ft_assert(t, rc == 0);
ft_log_FILE(t, "", fp);
/* Write some short strings, which should flush due to newlines */
DO_E(rc, fwrite("Line #1\n", 1, 8, fp), t, "%d");
ft_assert(t, rc == 8);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 8);
ft_assert(t, fp->bufpos == 0);
DO_E(rc, fwrite("A longer line #2\n", 1, 17, fp), t, "%d");
ft_assert(t, rc == 17);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 25);
ft_assert(t, fp->bufpos == 0);
DO_E(rc, fwrite("Partial line #", 1, 14, fp), t, "%d");
ft_assert(t, rc == 14);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 25);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->bufpos == 14);
DO_E(rc, fwrite("3\nand something on the-- ", 1, 25, fp), t, "%d");
ft_assert(t, rc == 25);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 41);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->bufpos == 23);
/* The buffer should still flush when full */
DO_E(rc, fwrite(filler, 1, 250, fp), t, "%d");
ft_assert(t, rc == 250);
ft_log_FILE(t, "", fp);
ft_assert(t, fp->fdpos == 297);
ft_assert(t, fp->bufdir == __FILE_BUF_WRITE);
ft_assert(t, fp->bufpos == 17);
DO_E(rc, fclose(fp), t, "%d");
ft_assert(t, rc == 0);
}
static void _ft_stdio_line_buffering(ft_test *t)
{
gint_world_switch(GINT_CALL(_ft_stdio_line_buffering_switch,
(void *)t));
}
ft_test ft_stdio_line_buffering = {
.name = "Writing with line buffering",
.function = _ft_stdio_line_buffering,
};