#!/usr/bin/env python3

"""Automated tests for bufsock.py."""

import sys

import bufsock
import readline0

TOPLEVEL_CHUNK_SIZE = 12345


def finds():
    """Read filenames using 3 methods (bufsock, rawio bufsock, open), and compare the 3 results."""
    all_good = True
    for filename in readline0.readline0():
        python_bufsock_file = bufsock.bufsock(open(filename, 'rb'))
        raw_bufsock_file = bufsock.bufsock(bufsock.rawio(filename, 'rb'))
        regular_file = open(filename, 'rb')
        python_bufsock_offset = 0
        raw_bufsock_offset = 0
        regular_offset = 0
        while True:
            # Note: assumption here is that both file I/O methods are going to return all that they can - EG, if we ask for
            # 512K, we're going to get 512K until we hit EOF.  If the two methods return short blocks inconsistently, this
            # test may appear to have failed, when it wouldn't if we were being careful about potential blocking
            # differences
            python_bufsock_block = python_bufsock_file.read(TOPLEVEL_CHUNK_SIZE)
            raw_bufsock_block = raw_bufsock_file.read(TOPLEVEL_CHUNK_SIZE)
            regular_block = regular_file.read(TOPLEVEL_CHUNK_SIZE)
            if python_bufsock_block != regular_block or raw_bufsock_block != regular_block:
                sys.stderr.write(
                    'Error on file %s, python_bufsock len: %d, raw_bufsock_len: %d, regular I/O len: %d'
                    % (filename, len(python_bufsock_block), len(raw_bufsock_block), len(regular_block)))
                sys.stderr.write(
                    ', req\'d block size: %d, odir offset: %d, reg offset: %d\n'
                    % (TOPLEVEL_CHUNK_SIZE, python_bufsock_offset, regular_offset))
                all_good = False
            python_bufsock_offset += len(python_bufsock_block)
            raw_bufsock_offset += len(raw_bufsock_block)
            regular_offset += len(regular_block)
            if not python_bufsock_block:
                # if these were different, that should've been caught above with an if, so here we just assert
                assert not raw_bufsock_block and not regular_block
                break
        del python_bufsock_file
        del raw_bufsock_file
        regular_file.close()

    return all_good


def lengthless_read():
    """Test readline a file in 2 pieces using bufsock (and catenate the pieces), and compare to reading all at once with open."""
    file1 = open('readline0.py', 'rb')
    bs_file = bufsock.bufsock(file1, chunk_len=1024)
    bs_content1 = bs_file.read(10)
    bs_content2 = bs_file.read()
    file1.close()
    bs_content = bs_content1 + bs_content2

    file2 = open('readline0.py', 'rb')
    file_content = file2.read()
    file2.close()

    if bs_content == file_content:
        return True
    else:
        sys.stderr.write('lengthless_read: bs_content != file_content\n')
        return False


def rawio_lengthless_read():
    """
    Test reading a file in 2 pieces using bufsock rawio (and catenate the pieces).

    Compare to reading all at once with open.
    """
    file1 = bufsock.rawio('readline0.py')
    bs_file = bufsock.bufsock(file1, chunk_len=1024)
    bs_content1 = bs_file.read(10)
    bs_content2 = bs_file.read()
    file1.close()
    bs_content = bs_content1 + bs_content2

    file2 = open('readline0.py', 'rb')
    file_content = file2.read()
    file2.close()

    if bs_content == file_content:
        return True
    else:
        sys.stderr.write('rawio_lengthless_read: bs_content != file_content\n')
        return False


def two_char_readto():
    """Test readto with a 2-character delimiter."""
    all_good = True

    file1 = bufsock.rawio('double-file')
    bs_file = bufsock.bufsock(file1, chunk_len=1024)
    bs_content1 = bs_file.readto('oo')
    bs_content2 = bs_file.read()
    file1.close()
    bs_content = bs_content1 + bs_content2

    if not bs_content1.endswith(b'oo'):
        sys.stderr.write('two_char_readto: bs_content1 does not end with oo\n')
        all_good = False

    if len(bs_content) != 419:
        sys.stderr.write('two_char_readto: len(bs_content) == %d' % len(bs_content))
        all_good = False

    return all_good


def two_char_readtomax():
    """Test readtomax with a 2 character delimiter."""
    all_good = True

    file1 = bufsock.rawio('double-file')
    bs_file = bufsock.bufsock(file1, chunk_len=1024)
    bs_content1 = bs_file.readtomax('oo', 2**20)
    bs_content2 = bs_file.read()
    file1.close()
    bs_content = bs_content1 + bs_content2

    if not bs_content1.endswith(b'oo'):
        sys.stderr.write('two_char_readtomax: bs_content1 does not end with oo\n')
        all_good = False

    if len(bs_content) != 419:
        sys.stderr.write('two_char_readtomax: len(bs_content) == %d' % len(bs_content))
        all_good = False

    return all_good


def main():
    """Test bufsock."""
    all_good = True

    all_good &= finds()
    all_good &= lengthless_read()
    all_good &= rawio_lengthless_read()
    all_good &= two_char_readto()
    all_good &= two_char_readtomax()

    error_found = not all_good

    sys.exit(error_found)


main()