
/*
 *  Copyright (c) 2014 Gerard Green
 *  All rights reserved
 *
 *  Please see the file 'LICENSE' for further information
 */

#include "libc_test.h"

#include <stdio.h>
#include <unistd.h>

int getc_unlocked_test();
int fgetc_test();
int ungetc_test();
int ungetc_ftell_test();
int ungetc_fseek_test();
int sortie_test();
int fread_test();
int freadbig_test();

int stdio_test()
{
    getc_unlocked_test();
    fgetc_test();
    ungetc_test();
    ungetc_ftell_test();
    ungetc_fseek_test();
    sortie_test();
    fread_test();
    freadbig_test();

    printf("STDIO TEST: DONE !!!!!!!!!!!!!!!!!\n");

    return 0;
}

int getc_unlocked_test()
{
    FILE *f;
    int c;
    off_t cnt;

    f = fopen("/usr/etc/libc_test/testfile.bin", "r");
    test_assert(f != NULL);

    cnt = 0;
    for (int j=0; j<10; ++j)
    {
        for (int i=0x21; i<0x7e; ++i)
        {
            c = getc_unlocked(f);
            ++cnt;
            test_assert(c == i);
            test_assert(ftello(f) == cnt);
        }
    }

    c = getc_unlocked(f);
    test_assert(c == EOF);

    c = getc_unlocked(f);
    test_assert(c == EOF);

    fclose(f);

    return 0;
}

int fgetc_test()
{
    FILE *f;
    int c;
    off_t cnt;

    f = fopen("/usr/etc/libc_test/testfile.bin", "r");
    test_assert(f != NULL);

    cnt = 0;
    for (int j=0; j<10; ++j)
    {
        for (int i=0x21; i<0x7e; ++i)
        {
            c = fgetc(f);
            ++cnt;
            test_assert(c == i);
            test_assert(ftello(f) == cnt);
        }
    }

    c = fgetc(f);
    test_assert(c == EOF);

    c = fgetc(f);
    test_assert(c == EOF);

    fclose(f);

    return 0;
}

int ungetc_test()
{
    FILE *f;
    int c;
    off_t cnt;

    f = fopen("/usr/etc/libc_test/testfile.bin", "r");
    test_assert(f != NULL);

    /* ungetc on new stream should work */
    test_assert(ungetc('1', f) == '1');
    test_assert(ungetc('2', f) == '2');
    test_assert(fgetc(f) == '2');
    test_assert(fgetc(f) == '1');

    test_assert(fgetc(f) == 0x21);
    test_assert(fgetc(f) == 0x22);

    test_assert(ungetc('3', f) == '3');
    test_assert(ungetc('4', f) == '4');
    test_assert(ungetc('5', f) == EOF);
    test_assert(fgetc(f) == '4');
    test_assert(fgetc(f) == '3');
    test_assert(fgetc(f) == 0x23);
    test_assert(fgetc(f) == 0x24);

    fclose(f);

    return 0;
}

int ungetc_ftell_test()
{
    FILE *f;
    int c;
    off_t cnt;

    f = fopen("/usr/etc/libc_test/testfile.bin", "r");
    test_assert(f != NULL);

    /* ungetc on new stream should work */
    test_assert(ungetc('1', f) == '1');
    test_assert(ungetc('2', f) == '2');
    test_assert(ftell(f) == -2);

    test_assert(fgetc(f) == '2');
    test_assert(fgetc(f) == '1');
    test_assert(ftell(f) == 0);

    test_assert(fgetc(f) == 0x21);
    test_assert(fgetc(f) == 0x22);
    test_assert(ftell(f) == 2);

    test_assert(ungetc('3', f) == '3');
    test_assert(ungetc('4', f) == '4');
    test_assert(ungetc('5', f) == EOF);
    test_assert(ftell(f) == 0);

    test_assert(fgetc(f) == '4');
    test_assert(fgetc(f) == '3');
    test_assert(ftell(f) == 2);

    test_assert(fgetc(f) == 0x23);
    test_assert(fgetc(f) == 0x24);
    test_assert(ftell(f) == 4);

    fclose(f);

    return 0;
}

int ungetc_fseek_test()
{
    FILE *f;
    int c;
    off_t cnt;

    f = fopen("/usr/etc/libc_test/testfile.bin", "r");
    test_assert(f != NULL);

    /* ungetc on new stream should work */
    test_assert(ungetc('1', f) == '1');
    test_assert(ungetc('2', f) == '2');

    test_assert(fseek(f, 0, SEEK_CUR) == 0);
    test_assert(ftell(f) == 0);

//    test_assert(fgetc(f) == '2');
//    test_assert(fgetc(f) == '1');
//    test_assert(ftell(f) == 0);

    test_assert(fgetc(f) == 0x21);
    test_assert(fgetc(f) == 0x22);
    test_assert(ftell(f) == 2);

    test_assert(fseek(f, 0, SEEK_CUR) == 0);
    test_assert(ftell(f) == 2);

    test_assert(ungetc('3', f) == '3');
    test_assert(ungetc('4', f) == '4');
    test_assert(ungetc('5', f) == EOF);
    test_assert(fseek(f, 5, SEEK_CUR) == 0);
    test_assert(ftell(f) == 7);

//    test_assert(fgetc(f) == '4');
//    test_assert(fgetc(f) == '3');
//    test_assert(ftell(f) == 0);

    test_assert(fgetc(f) == 0x28);
    test_assert(fgetc(f) == 0x29);
    test_assert(ftell(f) == 9);

    rewind(f);
    test_assert(fgetc(f) == 0x21);
    test_assert(ftell(f) == 1);
    test_assert(fseek(f, 0, SEEK_CUR) == 0);
    test_assert(ftell(f) == 1);

    rewind(f);
    test_assert(fgetc(f) == 0x21);
    test_assert(ftell(f) == 1);
    test_assert(ungetc('x', f) == 'x');
    test_assert(ftell(f) == 0);
    test_assert(fseek(f, 0, SEEK_CUR) == 0);
    test_assert(ftell(f) == 0);

    fclose(f);

    return 0;
}

int sortie_test()
{
    FILE *f;
    int c;
    off_t cnt;

    f = fopen("/usr/etc/libc_test/testfile.bin", "r");
    test_assert(f != NULL);

    test_assert(ungetc('A', f) == 'A');
    test_assert(ftell(f) == -1);
    test_assert(fgetc(f) == 'A');
    test_assert(ftell(f) == 0);
    test_assert(fgetc(f) == 0x21);
    test_assert(ftell(f) == 1);
    test_assert(ungetc('B', f) == 'B');
    test_assert(ftell(f) == 0);
    test_assert(fgetc(f) == 'B');

    fclose(f);

    return 0;
}

int fread_test()
{
    FILE *f;
    int c;
    off_t cnt;

    f = fopen("/usr/etc/libc_test/testfile.bin", "r");
    test_assert(f != NULL);

    cnt = 0;
    for (int j=0; j<10; ++j)
    {
        char buf[0x7e - 0x21];
        cnt = fread(buf, 1, 0x7e - 0x21, f);
        test_assert(cnt == (0x7e - 0x21));
        for (int i=0x21; i<0x7e; ++i)
        {
            test_assert(buf[i-0x21] == i);
            //test_assert(ftello(f) == cnt);
        }
    }

    c = fgetc(f);
    test_assert(c == EOF);

    c = fgetc(f);
    test_assert(c == EOF);

    fclose(f);

    return 0;
}

int freadbig_test()
{
    FILE *f;
    int c;
    off_t cnt;

    f = fopen("/usr/etc/libc_test/testfile2.bin", "r");
    test_assert(f != NULL);

    c = fgetc(f);
    ungetc(c, f);

    unsigned char buf[32768];
    cnt = fread(buf, 1, 32768, f);

    test_assert(cnt == 1024);

    for (int i=0; i<256; ++i)
    {
        test_assert(buf[i] == i);
    }
    for (int i=0; i<256; ++i)
    {
        test_assert(buf[i+256] == 255-i);
    }
    for (int i=0; i<256; ++i)
    {
        test_assert(buf[i+512] == i);
    }
    for (int i=0; i<256; ++i)
    {
        test_assert(buf[i+768] == 255-i);
    }

    cnt = fread(buf, 1, 32768, f);
    test_assert(cnt == 0);

    cnt = fread(buf, 1, 32768, f);
    test_assert(cnt == 0);

    c = fgetc(f);
    test_assert(c == EOF);

    c = fgetc(f);
    test_assert(c == EOF);

    fclose(f);

    return 0;
}
