init
This commit is contained in:
commit
38355d2442
9083 changed files with 1225834 additions and 0 deletions
392
.venv/lib/python3.8/site-packages/pygame/tests/time_test.py
Normal file
392
.venv/lib/python3.8/site-packages/pygame/tests/time_test.py
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
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 old timer for an event is deleted when a new timer is set
|
||||
pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay)
|
||||
pygame.time.delay(int(timer_delay * 3.5))
|
||||
self.assertEqual(pygame.event.get().count(timer_event), 3)
|
||||
pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay * 10) # long wait time
|
||||
pygame.time.delay(timer_delay * 5)
|
||||
self.assertNotIn(timer_event, pygame.event.get())
|
||||
pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay * 3)
|
||||
pygame.time.delay(timer_delay * 7)
|
||||
self.assertEqual(pygame.event.get().count(timer_event), 2)
|
||||
pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay)
|
||||
pygame.time.delay(int(timer_delay * 5.5))
|
||||
self.assertEqual(pygame.event.get().count(timer_event), 5)
|
||||
|
||||
# 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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue