Projekt_AI-Automatyczny_saper/venv/Lib/site-packages/pygame/tests/time_test.py
2021-03-13 21:16:35 +01:00

344 lines
14 KiB
Python

import unittest
import pygame
import time
Clock = pygame.time.Clock
class ClockTypeTest(unittest.TestCase):
__tags__ = ['timing']
def test_construction(self):
"""Ensure a Clock object can be created"""
c = Clock()
self.assertTrue(c, "Clock cannot be constructed")
def test_get_fps(self):
""" test_get_fps tests pygame.time.get_fps() """
# Initialization check, first call should return 0 fps
c = Clock()
self.assertEqual(c.get_fps(), 0)
# Type check get_fps should return float
self.assertTrue(type(c.get_fps()) == float)
# Allowable margin of error in percentage
delta = 0.30
# Test fps correctness for 100, 60 and 30 fps
self._fps_test(c, 100, delta)
self._fps_test(c, 60, delta)
self._fps_test(c, 30, delta)
def _fps_test(self, clock, fps, delta):
"""ticks fps times each second, hence get_fps() should return fps"""
delay_per_frame = 1.0/fps
for f in range(fps): # For one second tick and sleep
clock.tick()
time.sleep(delay_per_frame)
# We should get around fps (+- fps*delta -- delta % of fps)
self.assertAlmostEqual(clock.get_fps(), fps, delta=fps*delta)
def test_get_rawtime(self):
iterations = 10
delay = 0.1
delay_miliseconds = delay*(10**3) #actual time difference between ticks
framerate_limit = 5
delta = 50 #allowable error in milliseconds
#Testing Clock Initialization
c = Clock()
self.assertEqual(c.get_rawtime(), 0)
#Testing Raw Time with Frame Delay
for f in range(iterations):
time.sleep(delay)
c.tick(framerate_limit)
c1 = c.get_rawtime()
self.assertAlmostEqual(delay_miliseconds, c1, delta=delta)
#Testing get_rawtime() = get_time()
for f in range(iterations):
time.sleep(delay)
c.tick()
c1 = c.get_rawtime()
c2 = c.get_time()
self.assertAlmostEqual(c1, c2, delta=delta)
def test_get_time(self):
#Testing parameters
delay = 0.1 #seconds
delay_miliseconds = delay*(10**3)
iterations = 10
delta = 50 #milliseconds
#Testing Clock Initialization
c = Clock()
self.assertEqual(c.get_time(), 0)
#Testing within delay parameter range
for i in range(iterations):
time.sleep(delay)
c.tick()
c1 = c.get_time()
self.assertAlmostEqual(delay_miliseconds, c1, delta=delta)
#Comparing get_time() results with the 'time' module
for i in range(iterations):
t0 = time.time()
time.sleep(delay)
c.tick()
t1 = time.time()
c1 = c.get_time() #elapsed time in milliseconds
d0 = (t1-t0)*(10**3) #'time' module elapsed time converted to milliseconds
self.assertAlmostEqual(d0, c1, delta=delta)
def test_tick(self):
"""Tests time.Clock.tick()"""
"""
Loops with a set delay a few times then checks what tick reports to
verify its accuracy. Then calls tick with a desired frame-rate and
verifies it is not faster than the desired frame-rate nor is it taking
a dramatically long time to complete
"""
# Adjust this value to increase the acceptable sleep jitter
epsilon = 1.5
# Adjust this value to increase the acceptable locked frame-rate jitter
epsilon2 = 0.3
# adjust this value to increase the acceptable frame-rate margin
epsilon3 = 20
testing_framerate = 60
milliseconds = 5.0
collection = []
c = Clock()
# verify time.Clock.tick() will measure the time correctly
c.tick()
for i in range(100):
time.sleep(milliseconds / 1000) # convert to seconds
collection.append(c.tick())
# removes the first highest and lowest value
for outlier in [min(collection), max(collection)]:
if outlier != milliseconds:
collection.remove(outlier)
average_time = float(sum(collection)) / len(collection)
# assert the deviation from the intended frame-rate is within the
# acceptable amount (the delay is not taking a dramatically long time)
self.assertAlmostEqual(average_time, milliseconds, delta=epsilon)
# verify tick will control the frame-rate
c = Clock()
collection = []
start = time.time()
for i in range(testing_framerate):
collection.append(c.tick(testing_framerate))
# remove the highest and lowest outliers
for outlier in [min(collection), max(collection)]:
if outlier != round(1000/testing_framerate):
collection.remove(outlier)
end = time.time()
# Since calling tick with a desired fps will prevent the program from
# running at greater than the given fps, 100 iterations at 100 fps
# should last no less than 1 second
self.assertAlmostEqual(end - start, 1, delta=epsilon2)
average_tick_time = float(sum(collection)) / len(collection)
self.assertAlmostEqual(1000/average_tick_time,
testing_framerate, delta=epsilon3)
def test_tick_busy_loop(self):
"""Test tick_busy_loop"""
c = Clock()
# Test whether the return value of tick_busy_loop is equal to
# (FPS is accurate) or greater than (slower than the set FPS)
# with a small margin for error based on differences in how this
# test runs in practise - it either sometimes runs slightly fast
# or seems to based on a rounding error.
second_length = 1000
shortfall_tolerance = 1 # (ms) The amount of time a tick is allowed to run short of, to account for underlying rounding errors
sample_fps = 40
self.assertGreaterEqual(c.tick_busy_loop(sample_fps), (second_length/sample_fps) - shortfall_tolerance)
pygame.time.wait(10) # incur delay between ticks that's faster than sample_fps
self.assertGreaterEqual(c.tick_busy_loop(sample_fps), (second_length/sample_fps) - shortfall_tolerance)
pygame.time.wait(200) # incur delay between ticks that's slower than sample_fps
self.assertGreaterEqual(c.tick_busy_loop(sample_fps), (second_length/sample_fps) - shortfall_tolerance)
high_fps = 500
self.assertGreaterEqual(c.tick_busy_loop(high_fps), (second_length/high_fps) - shortfall_tolerance)
low_fps = 1
self.assertGreaterEqual(c.tick_busy_loop(low_fps), (second_length/low_fps) - shortfall_tolerance)
low_non_factor_fps = 35 # 1000/35 makes 28.5714285714
frame_length_without_decimal_places = int(second_length/low_non_factor_fps) # Same result as math.floor
self.assertGreaterEqual(c.tick_busy_loop(low_non_factor_fps), frame_length_without_decimal_places - shortfall_tolerance)
high_non_factor_fps = 750 # 1000/750 makes 1.3333...
frame_length_without_decimal_places_2 = int(second_length/high_non_factor_fps) # Same result as math.floor
self.assertGreaterEqual(c.tick_busy_loop(high_non_factor_fps), frame_length_without_decimal_places_2 - shortfall_tolerance)
zero_fps = 0
self.assertEqual(c.tick_busy_loop(zero_fps), 0)
# Check behaviour of unexpected values
negative_fps = -1
self.assertEqual(c.tick_busy_loop(negative_fps), 0)
fractional_fps = 32.75
frame_length_without_decimal_places_3 = int(second_length/fractional_fps)
self.assertGreaterEqual(c.tick_busy_loop(fractional_fps), frame_length_without_decimal_places_3 - shortfall_tolerance)
bool_fps = True
self.assertGreaterEqual(c.tick_busy_loop(bool_fps), (second_length/bool_fps) - shortfall_tolerance)
class TimeModuleTest(unittest.TestCase):
__tags__ = ['timing']
def test_delay(self):
"""Tests time.delay() function."""
millis = 50 # millisecond to wait on each iteration
iterations = 20 # number of iterations
delta = 150 # Represents acceptable margin of error for wait in ms
# Call checking function
self._wait_delay_check(pygame.time.delay, millis, iterations, delta)
# After timing behaviour, check argument type exceptions
self._type_error_checks(pygame.time.delay)
def test_get_ticks(self):
"""Tests time.get_ticks()"""
"""
Iterates and delays for arbitrary amount of time for each iteration,
check get_ticks to equal correct gap time
"""
iterations = 20
millis = 50
delta = 15 # Acceptable margin of error in ms
# Assert return type to be int
self.assertTrue(type(pygame.time.get_ticks()) == int)
for i in range(iterations):
curr_ticks = pygame.time.get_ticks() # Save current tick count
curr_time = time.time() # Save current time
pygame.time.delay(millis) # Delay for millis
# Time and Ticks difference from start of the iteration
time_diff = round((time.time() - curr_time)*1000)
ticks_diff = pygame.time.get_ticks() - curr_ticks
# Assert almost equality of the ticking time and time difference
self.assertAlmostEqual(ticks_diff, time_diff, delta=delta)
def test_set_timer(self):
"""Tests time.set_timer()"""
"""
Tests if a timer will post the correct amount of eventid events in
the specified delay. Test is posting event objects work.
Also tests if setting milliseconds to 0 stops the timer and if
the once argument and repeat arguments work.
"""
pygame.init()
TIMER_EVENT_TYPE = pygame.event.custom_type()
timer_event = pygame.event.Event(TIMER_EVENT_TYPE)
delta = 50
timer_delay = 100
test_number = 8 # Number of events to read for the test
events = 0 # Events read
pygame.event.clear()
pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay)
# Test that 'test_number' events are posted in the right amount of time
t1 = pygame.time.get_ticks()
max_test_time = t1 + timer_delay * test_number + delta
while events < test_number:
for event in pygame.event.get():
if event == timer_event:
events += 1
# The test takes too much time
if pygame.time.get_ticks() > max_test_time:
break
pygame.time.set_timer(TIMER_EVENT_TYPE, 0)
t2 = pygame.time.get_ticks()
# Is the number ef events and the timing right?
self.assertEqual(events, test_number)
self.assertAlmostEqual(timer_delay * test_number, t2-t1, delta=delta)
# Test that the timer stopped when set with 0ms delay.
pygame.time.delay(200)
self.assertNotIn(timer_event, pygame.event.get())
# Test that the loops=True works
pygame.time.set_timer(TIMER_EVENT_TYPE, 10, True)
pygame.time.delay(40)
self.assertEqual(pygame.event.get().count(timer_event), 1)
# Test a variety of event objects, test loops argument
events_to_test = [
pygame.event.Event(TIMER_EVENT_TYPE),
pygame.event.Event(TIMER_EVENT_TYPE, foo="9gwz5", baz=12,
lol=[124, (34, "")]),
pygame.event.Event(pygame.KEYDOWN, key=pygame.K_a, unicode="a")
]
repeat = 3
millis = 50
for e in events_to_test:
pygame.time.set_timer(e, millis, loops=repeat)
pygame.time.delay(2 * millis * repeat)
self.assertEqual(pygame.event.get().count(e), repeat)
pygame.quit()
def test_wait(self):
"""Tests time.wait() function."""
millis = 100 # millisecond to wait on each iteration
iterations = 10 # number of iterations
delta = 50 # Represents acceptable margin of error for wait in ms
# Call checking function
self._wait_delay_check(pygame.time.wait, millis, iterations, delta)
# After timing behaviour, check argument type exceptions
self._type_error_checks(pygame.time.wait)
def _wait_delay_check(self, func_to_check, millis, iterations, delta):
""""
call func_to_check(millis) "iterations" times and check each time if
function "waited" for given millisecond (+- delta). At the end, take
average time for each call (whole_duration/iterations), which should
be equal to millis (+- delta - acceptable margin of error).
*Created to avoid code duplication during delay and wait tests
"""
# take starting time for duration calculation
start_time = time.time()
for i in range(iterations):
wait_time = func_to_check(millis)
# Check equality of wait_time and millis with margin of error delta
self.assertAlmostEqual(wait_time, millis, delta=delta)
stop_time = time.time()
# Cycle duration in millisecond
duration = round((stop_time-start_time)*1000)
# Duration/Iterations should be (almost) equal to predefined millis
self.assertAlmostEqual(duration/iterations, millis, delta=delta)
def _type_error_checks(self, func_to_check):
"""Checks 3 TypeError (float, tuple, string) for the func_to_check"""
"""Intended for time.delay and time.wait functions"""
# Those methods throw no exceptions on negative integers
self.assertRaises(TypeError, func_to_check, 0.1) # check float
self.assertRaises(TypeError, pygame.time.delay, (0, 1)) # check tuple
self.assertRaises(TypeError, pygame.time.delay, "10") # check string
###############################################################################
if __name__ == "__main__":
unittest.main()