#!/usr/bin/env python

"""Test the compressed_string_mod module."""

from __future__ import with_statement

import os
import sys

import bufsock
import compressed_string_mod
import constants_mod
import helpers


def round_trip(filename, description):
    """Test compressing and decompressing a string.  If the result is equal, the test passes."""
    input_file = os.open(filename, os.O_RDONLY)
    input_bs = bufsock.bufsock(input_file)
    input_data = input_bs.read()
    input_bs.close()

    compressed_data = compressed_string_mod.compress_string(input_data)

    decompressed_data = compressed_string_mod.decompress_string(compressed_data)

    if input_data == decompressed_data:
        return True
    sys.stderr.write('%s: %s: input_data (%d) != decompressed_data (%d) - compressed_data (%d)\n' % (
        description,
        sys.argv[0],
        len(input_data),
        len(decompressed_data),
        len(compressed_data),
        ))
    return False


def hard_string_round_trip():
    """Test compressing and decompressing an already-hard string.  If the result is equal, the test passes."""
    return round_trip('hard-file', 'already-compressed data')


def soft_string_round_trip():
    """Test compressing and decompressing an easy-to-compress file.  If the result is equal, the test passes."""
    return round_trip('soft-file', 'easy-to-compress data')


def compression_type(filename, expected):
    """Compress a file.  Verify what kind of compression was used."""
    ints_expected = [helpers.string_to_binary(element)[0] for element in expected]

    file_ = bufsock.rawio(filename, 'r')
    data = file_.read()
    file_.close()

    compressed_data = compressed_string_mod.compress_string(data)

    actual = compressed_data[0]
    # FIXME: This assumes that constants_mod.Constants.b_newline is a single character - probably
    # pretty safe assumption, but still, it's an assumption
    if compressed_data[1] == constants_mod.Constants.b_newline[0]:
        pass
    else:
        print('compressed_data[1]: %s, constants_mod.Constants.b_newline[0]: %s\n' % (
            compressed_data[1],
            constants_mod.Constants.b_newline[0],
            ))
        sys.exit(1)

    if actual in ints_expected:
        if actual != ints_expected[0]:
            sys.stderr.write('%s: Warning: Allowed compression found, but not preferred compression\n' % sys.argv[0])
        return True
    else:
        sys.stderr.write('%s: filename %s, got wrong compression type %s, ints_expected %s\n' % (
            sys.argv[0],
            filename,
            actual,
            ints_expected,
            ))
        return False


def hard_string_compression_type():
    """Make sure a hard file is stored rather than recompressed."""
    return compression_type('hard-file', ['1'])


def soft_string_compression_type():
    """Make sure a soft file is compressed rather than stored."""
    # We expect either bzip2 or xz - preferring xz over bzip2.
    return compression_type('soft-file', ['8', '5'])


def main():
    """Start testing."""
    all_good = True

    all_good &= hard_string_round_trip()
    all_good &= soft_string_round_trip()
    all_good &= hard_string_compression_type()
    all_good &= soft_string_compression_type()

    if all_good:
        sys.stderr.write('%s: All tests passed\n' % sys.argv[0])
        sys.exit(0)
    else:
        sys.stderr.write('%s: One or more tests failed\n' % sys.argv[0])
        sys.exit(1)


main()