#!/usr/bin/python

'''Unit tests for rolling checksum mod - there are others, these are just the most rudimentary'''

import os
import sys
import math
import pprint
import random

import comma_mod

import min_max_chunker_mod
import rolling_checksum_py_mod as rolling_checksum_mod

def my_range(up_to):
	'''A range() function (generator) with consistent semantics from 2.x to 3.x'''
	value = 0
	while value < up_to:
		yield value
		value += 1

def rcm_accuracy_test():
	'''Test for accuracy'''
	all_good = True

	sys.stderr.write('Running accuracy test\n')

	file_ = open('rcm-input-data', 'r')
	expected = file_.read()
	file_.close()

	blocks = []
	file_handle = os.open('rcm-input-data', os.O_RDONLY)

	total_len = 0
	for blockno, block in enumerate(rolling_checksum_mod.Tri_level_chunker(file_handle)):
		blocks.append(block)
		total_len += len(block)
		sys.stderr.write('Appended blockno %d of length (%s) %s\n' % (blockno, comma_mod.gimme_commas(total_len), comma_mod.gimme_commas(len(block))))

	os.close(file_handle)

	actual = ''.join(blocks)
	if actual == expected:
		os.write(3, 'Good, files match: %d, %d\n' % (len(expected), len(actual)))
	else:
		os.write(3, 'Incorrect content\n')
		all_good = False
	#string = pprint.pformat([ len(block) for block in blocks ])
	#os.write(3, '%s\n' % string)
	return all_good

def stddev(list_, average):
	'''Compute the standard deviation of a list, given the list and its precomputed average'''
	total = 0.0
	for element in list_:
		total += (element - average) ** 2
	return math.sqrt(total)

def rcm_size_test():
	'''Test that the sizes returned look reasonable'''
	all_good = True
	sys.stderr.write('Running size test\n')
	random.seed(3)
	file_handle = os.open('rcm-input-data', os.O_RDONLY)
	tri_level_chunker = rolling_checksum_mod.Tri_level_chunker(file_handle)
	size_list = []
	for chunk in tri_level_chunker:
		len_chunk = len(chunk)
		size_list.append(len_chunk)
		sys.stdout.write('Got chunk of length %d\n' % len_chunk)
	os.close(file_handle)
	average = float(sum(size_list)) / len(size_list)
	os.write(3, 'average size is %s\n' % average)
	if 500000 < average < 2000000:
		pass
	else:
		sys.stderr.write('average is not between 500000 and 2000000: %s\n' % average)
		all_good = False
	standard_deviation = stddev(size_list, average)
	os.write(3, 'stddev is %s\n' % standard_deviation)
	os.write(3, pprint.pformat(size_list[:10] + [ '...' ] + size_list[-10:]))
	os.write(3, '\n')
	return all_good

def main():
	'''Main function'''

	if sys.argv[1:]:
		sys.stderr.write('Illegal option: %s\n' % sys.argv[1])
		sys.exit(1)

	all_good = True
	all_good &= rcm_accuracy_test()
	all_good &= rcm_size_test()

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

main()