#!/usr/bin/python

import os
import sys
import math
import time
import random

sys.path.insert(0, '../..')

import comma_mod
import min_max_chunker_mod

def my_range(up_to):
	value = 0
	while value < up_to:
		yield value
		value += 1

class Perf:
	def __init__(self, module, description):
		self.module = module
		self.description = description

	def start(self):
		self.t0 = time.time()

	def finish(self):
		self.t1 = time.time()
		self.difference = self.t1 - self.t0

	def __str__(self):
		return self.description

def avg(list_):
	total = sum(list_)
	return total / len(list_)
		
def stddev(list_, average):
	total = 0.0
	for element in list_:
		total += (element - average) ** 2
	return math.sqrt(total)

def main():
	top = 2**21

	while sys.argv[1:]:
		if sys.argv[1] == '--top':
			top = int(sys.argv[2])
			del sys.argv[1]
		else:
			sys.stderr.write('Illegal option: %s\n' % sys.argv[1])
			sys.exit(1)
		del sys.argv[1]

	min_max_chunker = Perf(min_max_chunker_mod, 'min_max_chunker_mod')

	# we do pyx_mod twice to avoid cache effects
	all_good = True
	for pm in [ min_max_chunker ]:
		random.seed(3)
		block_lens = []

		pm.start()
		file_handle = os.open('input-data', os.O_RDONLY)
		stat_buf = os.fstat(file_handle)
		expected_size = stat_buf.st_size
		for block in pm.module.min_max_chunker(file_handle):
			block_lens.append(len(block))
		os.close(file_handle)
		pm.finish()

		actual_size = sum(block_lens)

		if actual_size != expected_size:
			sys.stderr.write('%s: Expected file length %s, got %s\n' % (
				sys.argv[0], 
				comma_mod.gimme_commas(expected_size), 
				comma_mod.gimme_commas(actual_size)
				))
			all_good = False

		minimum = min(block_lens)
		maximum = max(block_lens)
		average = avg(block_lens)
		standard_deviation = stddev(block_lens, average)

		if standard_deviation < 2**18:
			sys.stderr.write('%s: %s stddev too small: %f < 2**18, average: %f\n' % (sys.argv[0], pm, standard_deviation, average))
			all_good = False

		if 2**20 - 2**18 < average < 2**20 + 2**18:
			pass
		else:
			sys.stderr.write('%s: %s average out of range: not (2**20 - 2**17 < %f < 2**20 + 2**17)\n' % (sys.argv[0], pm, average))
			all_good = False

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

	#print py_mod.difference, pyx_mod.difference

main()