"""Unit tests for converter module.

author:  jonathan lung
"""
import unittest
import os
from convert import *
from random import *

TEST_FILE_NAME_1 = "convertTestData.1"
TEST_FILE_NAME_2 = "convertTestData.2"

class TestBinConverter(unittest.TestCase):
    """Test convert.py.  Note that we do not test what happens
    when parameters of unexpected types are given to the converter.
    The converter is not robust!  We also don't give the writer an invalid
    input string for the same reason; all input is a length of a multiple
    of a multiple of BYTE_SIZE_IN_BITS bits and contains only "1"s and "0"s.


    We also don't test writing random stuff helter-skelter to prevent
    damaging data.  Normally, we'd use dummy file objects for testing file
    I/O, but the functions being tested now use file names, not file objects.
    Warning:  the files specified in TEST_FILE_NAME_n will be deleted if they
    exist."""
	

    def testReadMissingFile(self):
        """Make sure an exception is thrown when a file is not found."""
        try:
            # Try reading from a non-existent file.
            read_binary_file("noSuchFile.hopefully")
            assert False, "No exception thrown.  File may exist."
        except IOError, e:
            pass

    def testWritingEmptyFile(self):
        """Make sure we don't die writing an empty file."""

	# Write an empty file
        write_string_as_binary("", TEST_FILE_NAME_1)

	# And read it back
        assert "" == read_binary_file(TEST_FILE_NAME_1), "Empty not read."

    def testWritingOneByteOfOnes(self):
        """Make sure we can write a byte of all ones."""

	# Generate a string of ones.
	onesString = "".join(["1"] * BYTE_SIZE_IN_BITS)

	# Write the data
        write_string_as_binary(onesString, TEST_FILE_NAME_1)

	# And read it back
        assert onesString == read_binary_file(TEST_FILE_NAME_1), \
               "Ones not read."

    def testWritingOneByteOfZeroes(self):
        """Make sure we can write a byte of all zeroes."""

	# Generate a string of zeroes.
	zeroesString = "".join(["0"] * BYTE_SIZE_IN_BITS)

	# Write the data
        write_string_as_binary(zeroesString, TEST_FILE_NAME_1)

	# And read it back
        assert zeroesString == read_binary_file(TEST_FILE_NAME_1), \
               "Zeroes not read."

    def testWritingTenBytesOfRandomData(self):
        """Make sure we can write ten bytes of random data."""

	# Generate a random string
	randomString = self.getKBitRandomString(10 * BYTE_SIZE_IN_BITS)

	# Write the data
        write_string_as_binary(randomString, TEST_FILE_NAME_1)

	# And read it back
        assert randomString == read_binary_file(TEST_FILE_NAME_1), \
               "Random bytes not read."

    def testWritingOneKibibytesOfRandomData(self):
        """Make sure we can write 10KiB of random data."""

	# Generate a random string
	randomString = self.getKBitRandomString(1024 * 10 * BYTE_SIZE_IN_BITS)

	# Write the data
        write_string_as_binary(randomString, TEST_FILE_NAME_1)

	# And read it back
        assert randomString == read_binary_file(TEST_FILE_NAME_1), \
               "Random bytes not read."

    def testWritingOneKibibytesOfRandomDataToTwoFiles(self):
        """Make sure we can write 10KiB of random data to two files."""

	# Generate random strings
	randomString1 = self.getKBitRandomString(1024 * 10 * BYTE_SIZE_IN_BITS)
	randomString2 = self.getKBitRandomString(1024 * 10 * BYTE_SIZE_IN_BITS)

	# Write the data
        write_string_as_binary(randomString1, TEST_FILE_NAME_1)
        write_string_as_binary(randomString2, TEST_FILE_NAME_2)

	# And read it back
        assert randomString1 == read_binary_file(TEST_FILE_NAME_1), \
               "Random bytes not read."
        assert randomString2 == read_binary_file(TEST_FILE_NAME_2), \
               "Random bytes not read."

    def getKBitRandomString(self, k):
	"""Return a random string of "0"s and "1"s of length k."""
	builtString = []
        for bit in xrange(0, k):
		builtString.append(choice(["0", "1"]))
	return "".join(builtString)

    def tearDown(self):
        """Clean up after ourselves by removing test files."""
	try:
            os.remove(TEST_FILE_NAME_1)
            os.remove(TEST_FILE_NAME_2)
	except OSError:
		pass    # We expect this if the file does not exist

if __name__ == '__main__':
    seed(0)            # Seed our random data.
    unittest.main()    # Run our tests.

