diff --git a/sdl2/audio.py b/sdl2/audio.py index 38fb661b..aa5fa0b2 100644 --- a/sdl2/audio.py +++ b/sdl2/audio.py @@ -53,6 +53,9 @@ "AUDIO_FORMATS" ] + +# Constants, enums, and macros + SDL_AudioFormat = Uint16 SDL_AUDIO_MASK_BITSIZE = 0xFF @@ -82,7 +85,6 @@ AUDIO_F32MSB = 0x9120 AUDIO_F32 = AUDIO_F32LSB - # All of the audio formats should be in this set which is provided as a # convenience to the end user for purposes of iteration and validation. # (is the provided audio format in the supported set?) @@ -98,10 +100,13 @@ AUDIO_F32LSB: "AUDIO_F32LSB", AUDIO_F32MSB: "AUDIO_F32MSB", } -AUDIO_FORMATS = set([AUDIO_U8, AUDIO_S8, AUDIO_U16LSB, AUDIO_S16LSB, - AUDIO_U16MSB, AUDIO_S16MSB, AUDIO_U16, AUDIO_S16, - AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S32, AUDIO_F32LSB, - AUDIO_F32MSB, AUDIO_F32]) +AUDIO_FORMATS = set([ + AUDIO_U8, AUDIO_S8, + AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U16, + AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S16, + AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S32, + AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_F32 +]) if SDL_BYTEORDER == SDL_LIL_ENDIAN: AUDIO_U16SYS = AUDIO_U16LSB @@ -123,21 +128,37 @@ SDL_AUDIO_ALLOW_CHANNELS_CHANGE | SDL_AUDIO_ALLOW_SAMPLES_CHANGE ) +SDL_AudioDeviceID = Uint32 + +SDL_AudioStatus = c_int +SDL_AUDIO_STOPPED = 0 +SDL_AUDIO_PLAYING = 1 +SDL_AUDIO_PAUSED = 2 + +SDL_MIX_MAXVOLUME = 128 +SDL_AUDIOCVT_MAX_FILTERS = 9 + + +# Structure, opaque type, and callback definitions + SDL_AudioCallback = CFUNCTYPE(None, c_void_p, POINTER(Uint8), c_int) class SDL_AudioSpec(Structure): - _fields_ = [("freq", c_int), - ("format", SDL_AudioFormat), - ("channels", Uint8), - ("silence", Uint8), - ("samples", Uint16), - ("padding", Uint16), - ("size", Uint32), - ("callback", SDL_AudioCallback), - ("userdata", c_void_p) - ] - def __init__(self, freq, aformat, channels, samples, - callback=SDL_AudioCallback(), userdata=c_void_p(0)): + _fields_ = [ + ("freq", c_int), + ("format", SDL_AudioFormat), + ("channels", Uint8), + ("silence", Uint8), + ("samples", Uint16), + ("padding", Uint16), + ("size", Uint32), + ("callback", SDL_AudioCallback), + ("userdata", c_void_p), + ] + def __init__( + self, freq, aformat, channels, samples, callback=SDL_AudioCallback(), + userdata=c_void_p(0) + ): super(SDL_AudioSpec, self).__init__() self.freq = freq self.format = aformat @@ -146,43 +167,41 @@ def __init__(self, freq, aformat, channels, samples, self.callback = callback self.userdata = userdata -SDL_AUDIOCVT_MAX_FILTERS = 9 - class SDL_AudioCVT(Structure): pass SDL_AudioFilter = CFUNCTYPE(POINTER(SDL_AudioCVT), SDL_AudioFormat) -SDL_AudioCVT._fields_ = [("needed", c_int), - ("src_format", SDL_AudioFormat), - ("dst_format", SDL_AudioFormat), - ("rate_incr", c_double), - ("buf", POINTER(Uint8)), - ("len", c_int), - ("len_cvt", c_int), - ("len_mult", c_int), - ("len_ratio", c_double), - ("filters", (SDL_AudioFilter * (SDL_AUDIOCVT_MAX_FILTERS+1))), - ("filter_index", c_int) - ] + +SDL_AudioCVT._fields_ = [ + ("needed", c_int), + ("src_format", SDL_AudioFormat), + ("dst_format", SDL_AudioFormat), + ("rate_incr", c_double), + ("buf", POINTER(Uint8)), + ("len", c_int), + ("len_cvt", c_int), + ("len_mult", c_int), + ("len_ratio", c_double), + ("filters", (SDL_AudioFilter * (SDL_AUDIOCVT_MAX_FILTERS+1))), + ("filter_index", c_int), +] class SDL_AudioStream(c_void_p): pass + +# Raw ctypes function definitions + SDL_GetNumAudioDrivers = _bind("SDL_GetNumAudioDrivers", None, c_int) SDL_GetAudioDriver = _bind("SDL_GetAudioDriver", [c_int], c_char_p) SDL_AudioInit = _bind("SDL_AudioInit", [c_char_p], c_int) SDL_AudioQuit = _bind("SDL_AudioQuit") SDL_GetCurrentAudioDriver = _bind("SDL_GetCurrentAudioDriver", None, c_char_p) SDL_OpenAudio = _bind("SDL_OpenAudio", [POINTER(SDL_AudioSpec), POINTER(SDL_AudioSpec)], c_int) -SDL_AudioDeviceID = Uint32 SDL_GetNumAudioDevices = _bind("SDL_GetNumAudioDevices", [c_int], c_int) SDL_GetAudioDeviceName = _bind("SDL_GetAudioDeviceName", [c_int, c_int], c_char_p) SDL_GetAudioDeviceSpec = _bind("SDL_GetAudioDeviceSpec", [c_int, c_int, POINTER(SDL_AudioSpec)], c_int, added='2.0.16') SDL_OpenAudioDevice = _bind("SDL_OpenAudioDevice", [c_char_p, c_int, POINTER(SDL_AudioSpec), POINTER(SDL_AudioSpec), c_int], SDL_AudioDeviceID) -SDL_AUDIO_STOPPED = 0 -SDL_AUDIO_PLAYING = 1 -SDL_AUDIO_PAUSED = 2 -SDL_AudioStatus = c_int SDL_GetAudioStatus = _bind("SDL_GetAudioStatus", None, SDL_AudioStatus) SDL_GetAudioDeviceStatus = _bind("SDL_GetAudioDeviceStatus", [SDL_AudioDeviceID], SDL_AudioStatus) SDL_PauseAudio = _bind("SDL_PauseAudio", [c_int]) @@ -192,7 +211,6 @@ class SDL_AudioStream(c_void_p): SDL_FreeWAV = _bind("SDL_FreeWAV", [POINTER(Uint8)]) SDL_BuildAudioCVT = _bind("SDL_BuildAudioCVT", [POINTER(SDL_AudioCVT), SDL_AudioFormat, Uint8, c_int, SDL_AudioFormat, Uint8, c_int], c_int) SDL_ConvertAudio = _bind("SDL_ConvertAudio", [POINTER(SDL_AudioCVT)], c_int) -SDL_MIX_MAXVOLUME = 128 SDL_MixAudio = _bind("SDL_MixAudio", [POINTER(Uint8), POINTER(Uint8), Uint32, c_int]) SDL_MixAudioFormat = _bind("SDL_MixAudioFormat", [POINTER(Uint8), POINTER(Uint8), SDL_AudioFormat, Uint32, c_int]) SDL_LockAudio = _bind("SDL_LockAudio") diff --git a/sdl2/dll.py b/sdl2/dll.py index bbd5b2ba..c3195da6 100644 --- a/sdl2/dll.py +++ b/sdl2/dll.py @@ -141,12 +141,6 @@ def _findlib(libnames, path=None): else: patterns = ["lib{0}.so"] - # On Apple Silicon Macs, search the non-standard Homebrew library path if no other - # path explicitly set - arm_brewpath = "/opt/Homebrew/lib" - if not path and platform == "darwin" and os.path.exists(arm_brewpath): - path = arm_brewpath - # Adding the potential 'd' suffix that is present on the library # when built in debug configuration searchfor = libnames + [libname + 'd' for libname in libnames] diff --git a/sdl2/ext/color.py b/sdl2/ext/color.py index e1e6755d..c3f2ea72 100644 --- a/sdl2/ext/color.py +++ b/sdl2/ext/color.py @@ -454,17 +454,12 @@ def is_rgb_color(v): False. """ - try: - if hasattr(v, "r") and hasattr(v, "g") and hasattr(v, "b"): - if 0 <= int(v.r) <= 255 and 0 <= int(v.g) <= 255 and \ - 0 <= v.b <= 255: - return True - - if len(v) >= 3: - if 0 <= int(v[0]) <= 255 and 0 <= int(v[1]) <= 255 and \ - 0 < int(v[2]) < 255: - return True + if hasattr(v, "r") and hasattr(v, "g") and hasattr(v, "b"): + v = [v.r, v.g, v.b] + if not isiterable(v) or len(v) < 3: return False + try: + return all([0 <= int(x) <= 255 for x in v[:3]]) except (TypeError, ValueError): return False diff --git a/sdl2/ext/image.py b/sdl2/ext/image.py index bb3a807b..cfaf58bf 100644 --- a/sdl2/ext/image.py +++ b/sdl2/ext/image.py @@ -171,6 +171,7 @@ def load_img(path, as_argb=True): img_surf = surfcopy if not img_surf: raise_sdl_err("converting '{0}' to ARGB format".format(fname)) + error.SDL_ClearError() # Clear any non-critical errors during loading return img_surf.contents diff --git a/sdl2/ext/renderer.py b/sdl2/ext/renderer.py index da518423..f9d5e2de 100644 --- a/sdl2/ext/renderer.py +++ b/sdl2/ext/renderer.py @@ -363,6 +363,7 @@ def __init__(self, target, backend=-1, logical_size=None, raise TypeError("unsupported target type") if not _renderer: raise_sdl_err("creating the SDL renderer") + error.SDL_ClearError() # Clear any errors from renderer selection self._renderer_ref = [_renderer] self.rendertarget = target diff --git a/sdl2/render.py b/sdl2/render.py index 5bdbc13c..c7cc3569 100644 --- a/sdl2/render.py +++ b/sdl2/render.py @@ -187,6 +187,8 @@ class SDL_Texture(c_void_p): SDL_SetTextureUserData = _bind("SDL_SetTextureUserData", [POINTER(SDL_Texture), c_void_p], c_int, added='2.0.18') SDL_GetTextureUserData = _bind("SDL_GetTextureUserData", [POINTER(SDL_Texture)], c_void_p, added='2.0.18') SDL_UpdateTexture = _bind("SDL_UpdateTexture", [POINTER(SDL_Texture), POINTER(SDL_Rect), c_void_p, c_int], c_int) +SDL_UpdateYUVTexture = _bind("SDL_UpdateYUVTexture", [POINTER(SDL_Texture), POINTER(SDL_Rect), POINTER(Uint8), c_int, POINTER(Uint8), c_int, POINTER(Uint8), c_int], c_int) +SDL_UpdateNVTexture = _bind("SDL_UpdateNVTexture", [POINTER(SDL_Texture), POINTER(SDL_Rect), POINTER(Uint8), c_int, POINTER(Uint8), c_int], c_int, added='2.0.16') SDL_LockTexture = _bind("SDL_LockTexture", [POINTER(SDL_Texture), POINTER(SDL_Rect), POINTER(c_void_p), POINTER(c_int)], c_int) SDL_LockTextureToSurface = _bind("SDL_LockTextureToSurface", [POINTER(SDL_Texture), POINTER(SDL_Rect), POINTER(POINTER(SDL_Surface))], c_int, added='2.0.12') SDL_UnlockTexture = _bind("SDL_UnlockTexture", [POINTER(SDL_Texture)]) @@ -195,6 +197,8 @@ class SDL_Texture(c_void_p): SDL_GetRenderTarget = _bind("SDL_GetRenderTarget", [POINTER(SDL_Renderer)], POINTER(SDL_Texture)) SDL_RenderSetLogicalSize = _bind("SDL_RenderSetLogicalSize", [POINTER(SDL_Renderer), c_int, c_int], c_int) SDL_RenderGetLogicalSize = _bind("SDL_RenderGetLogicalSize", [POINTER(SDL_Renderer), POINTER(c_int), POINTER(c_int)]) +SDL_RenderSetIntegerScale = _bind("SDL_RenderSetIntegerScale", [POINTER(SDL_Renderer), SDL_bool], c_int, added='2.0.5') +SDL_RenderGetIntegerScale = _bind("SDL_RenderGetIntegerScale", [POINTER(SDL_Renderer)], SDL_bool, added='2.0.5') SDL_RenderSetViewport = _bind("SDL_RenderSetViewport", [POINTER(SDL_Renderer), POINTER(SDL_Rect)], c_int) SDL_RenderGetViewport = _bind("SDL_RenderGetViewport", [POINTER(SDL_Renderer), POINTER(SDL_Rect)]) SDL_RenderGetClipRect = _bind("SDL_RenderGetClipRect", [POINTER(SDL_Renderer), POINTER(SDL_Rect)]) @@ -204,8 +208,6 @@ class SDL_Texture(c_void_p): SDL_RenderGetScale = _bind("SDL_RenderGetScale", [POINTER(SDL_Renderer), POINTER(c_float), POINTER(c_float)]) SDL_RenderWindowToLogical = _bind("SDL_RenderWindowToLogical", [POINTER(SDL_Renderer), c_int, c_int, POINTER(c_float), POINTER(c_float)], added='2.0.18') SDL_RenderLogicalToWindow = _bind("SDL_RenderLogicalToWindow", [POINTER(SDL_Renderer), c_float, c_float, POINTER(c_int), POINTER(c_int)], added='2.0.18') -SDL_RenderGetIntegerScale = _bind("SDL_RenderGetIntegerScale", [POINTER(SDL_Renderer)], SDL_bool, added='2.0.5') -SDL_RenderSetIntegerScale = _bind("SDL_RenderSetIntegerScale", [POINTER(SDL_Renderer), SDL_bool], c_int, added='2.0.5') SDL_SetRenderDrawColor = _bind("SDL_SetRenderDrawColor", [POINTER(SDL_Renderer), Uint8, Uint8, Uint8, Uint8], c_int) SDL_GetRenderDrawColor = _bind("SDL_GetRenderDrawColor", [POINTER(SDL_Renderer), POINTER(Uint8), POINTER(Uint8), POINTER(Uint8), POINTER(Uint8)], c_int) SDL_SetRenderDrawBlendMode = _bind("SDL_SetRenderDrawBlendMode", [POINTER(SDL_Renderer), SDL_BlendMode], c_int) @@ -240,8 +242,6 @@ class SDL_Texture(c_void_p): SDL_RenderFlush = _bind("SDL_RenderFlush", [POINTER(SDL_Renderer)], c_int, added='2.0.10') SDL_GL_BindTexture = _bind("SDL_GL_BindTexture", [POINTER(SDL_Texture), POINTER(c_float), POINTER(c_float)], c_int) SDL_GL_UnbindTexture = _bind("SDL_GL_UnbindTexture", [POINTER(SDL_Texture)], c_int) -SDL_UpdateYUVTexture = _bind("SDL_UpdateYUVTexture", [POINTER(SDL_Texture), POINTER(SDL_Rect), POINTER(Uint8), c_int, POINTER(Uint8), c_int, POINTER(Uint8), c_int], c_int) -SDL_UpdateNVTexture = _bind("SDL_UpdateNVTexture", [POINTER(SDL_Texture), POINTER(SDL_Rect), POINTER(Uint8), c_int, POINTER(Uint8), c_int], c_int, added='2.0.16') SDL_RenderGetMetalLayer = _bind("SDL_RenderGetMetalLayer", [POINTER(SDL_Renderer)], c_void_p, added='2.0.8') SDL_RenderGetMetalCommandEncoder = _bind("SDL_RenderGetMetalCommandEncoder", [POINTER(SDL_Renderer)], c_void_p, added='2.0.8') SDL_RenderSetVSync = _bind("SDL_RenderSetVSync", [POINTER(SDL_Renderer), c_int], c_int, added='2.0.18') diff --git a/sdl2/test/audio_test.py b/sdl2/test/audio_test.py index 164da366..17ad9c3e 100644 --- a/sdl2/test/audio_test.py +++ b/sdl2/test/audio_test.py @@ -8,6 +8,31 @@ from sdl2 import audio import pytest +# NOTE: This module is missing a lot of tests, but is also going to be tricky +# to write more tests for. + +# Get original audio driver, if one was set in the environment +original_driver = os.getenv("SDL_AUDIODRIVER", None) + +@pytest.fixture +def with_sdl_audio(): + # Reset original audio driver in the environment (if there was one) + if original_driver: + os.environ["SDL_AUDIODRIVER"] = original_driver + # Initialize SDL2 with video and audio subsystems + sdl2.SDL_ClearError() + ret = sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO | sdl2.SDL_INIT_AUDIO) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + yield + sdl2.SDL_Quit() + # Reset original audio driver in environment + os.environ.pop("SDL_AUDIODRIVER", None) + if original_driver: + os.environ["SDL_AUDIODRIVER"] = original_driver + + +# Test macro functions def test_SDL_AUDIO_BITSIZE(): assert audio.SDL_AUDIO_BITSIZE(audio.AUDIO_U8) == 8 @@ -121,263 +146,267 @@ def test_SDL_AUDIO_ISUNSIGNED(): assert not audio.SDL_AUDIO_ISUNSIGNED(audio.AUDIO_F32MSB) assert not audio.SDL_AUDIO_ISUNSIGNED(audio.AUDIO_F32) -def test_SDL_InitQuitAudio(): - SDL_Init(0) - ret = SDL_InitSubSystem(SDL_INIT_AUDIO) - SDL_Quit() - assert ret == 0 +# Test structs and objects -skipmsg = "audio subsystem not supported" -@pytest.mark.skipif(SDL_Init(SDL_INIT_AUDIO) != 0, reason=skipmsg) -class TestSDLAudio(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - def audio_cb(userdata, audiobytes, length): - pass - cls.audiocallback = audio.SDL_AudioCallback(audio_cb) - cls.original_driver = os.getenv("SDL_AUDIODRIVER") - - @classmethod - def teardown_class(cls): - if os.getenv("SDL_AUDIODRIVER"): - if cls.original_driver != None: - os.environ["SDL_AUDIODRIVER"] = cls.original_driver - else: - os.environ.pop("SDL_AUDIODRIVER") - - def setup_method(self): - SDL_ClearError() - SDL_Init(SDL_INIT_AUDIO) - if os.getenv("SDL_AUDIODRIVER"): - if self.original_driver != None: - os.environ["SDL_AUDIODRIVER"] = self.original_driver - else: - os.environ.pop("SDL_AUDIODRIVER") - - def teardown_method(self): - SDL_Quit() - - @pytest.mark.skip("not implemented") - def test_SDL_AudioSpec(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_AudioCVT(self): - pass - - def test_SDL_GetNumAudioDrivers(self): - count = audio.SDL_GetNumAudioDrivers() - assert count >= 1 - - def test_SDL_GetAudioDriver(self): - founddummy = False - drivercount = audio.SDL_GetNumAudioDrivers() - for index in range(drivercount): - drivername = audio.SDL_GetAudioDriver(index) - assert isinstance(drivername, (str, bytes)) - if drivername == b"dummy": - founddummy = True - assert founddummy, "could not find dummy driver" - with pytest.raises((ctypes.ArgumentError, TypeError)): - audio.SDL_GetAudioDriver("Test") - with pytest.raises((ctypes.ArgumentError, TypeError)): - audio.SDL_GetAudioDriver(None) - - def test_SDL_GetCurrentAudioDriver(self): - success = 0 - # Reset audio subsystem - SDL_Quit() - SDL_Init(0) - for index in range(audio.SDL_GetNumAudioDrivers()): - drivername = audio.SDL_GetAudioDriver(index) - os.environ["SDL_AUDIODRIVER"] = drivername.decode("utf-8") - # Certain drivers fail without bringing up the correct - # return value, such as the esd, if it is not running. - SDL_InitSubSystem(SDL_INIT_AUDIO) - driver = audio.SDL_GetCurrentAudioDriver() - SDL_QuitSubSystem(SDL_INIT_AUDIO) - # Do not handle wrong return values. - if driver is not None: - assert drivername == driver - success += 1 - assert success >= 1 - - def test_SDL_OpenCloseAudio(self): - fmt = audio.AUDIO_F32 if sys.platform == "darwin" else audio.AUDIO_U16SYS - reqspec = audio.SDL_AudioSpec(44100, fmt, 2, 1024) - spec = audio.SDL_AudioSpec(0, 0, 0, 0) - ret = audio.SDL_OpenAudio(reqspec, ctypes.byref(spec)) - assert ret == 0 - assert spec.format == reqspec.format - assert spec.freq == reqspec.freq - assert spec.channels == reqspec.channels - audio.SDL_CloseAudio() - - def test_SDL_GetNumAudioDevices(self): - outnum = audio.SDL_GetNumAudioDevices(False) - assert outnum >= 1 - innum = audio.SDL_GetNumAudioDevices(True) - assert innum >= 0 - - def test_SDL_GetAudioDeviceName(self): - backends = [] - devices = {} - # Reset audio subsystem - SDL_Quit() - SDL_Init(0) - for index in range(audio.SDL_GetNumAudioDrivers()): - # Get input/output device names for each audio driver - drivername = audio.SDL_GetAudioDriver(index) - backends.append(drivername.decode("utf-8")) - os.environ["SDL_AUDIODRIVER"] = drivername.decode("utf-8") - # Need to reinitialize subsystem for each driver - SDL_InitSubSystem(SDL_INIT_AUDIO) - driver = audio.SDL_GetCurrentAudioDriver() - if driver is not None: - driver = driver.decode("utf-8") - devices[driver] = {'input': [], 'output': []} - outnum = audio.SDL_GetNumAudioDevices(False) - innum = audio.SDL_GetNumAudioDevices(True) - for x in range(outnum): - name = audio.SDL_GetAudioDeviceName(x, False) - assert name is not None - devices[driver]['output'].append(name.decode('utf-8')) - for x in range(innum): - name = audio.SDL_GetAudioDeviceName(x, True) - assert name is not None - devices[driver]['input'].append(name.decode('utf-8')) - SDL_QuitSubSystem(SDL_INIT_AUDIO) - print("Audio backends supported by current SDL2 binary:") - print(backends) - print("\nAvailable audio drivers and devices:") - for driver in devices.keys(): - print(driver) - print(" - input: {0}".format(str(devices[driver]['input']))) - print(" - output: {0}".format(str(devices[driver]['output']))) - - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_GetAudioDeviceSpec(self): - # Reset audio subsystem - SDL_Quit() - SDL_Init(0) - # Find an audio driver with at least one output +@pytest.mark.skip("not implemented") +def test_SDL_AudioSpec(): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_AudioCVT(): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_AudioStream(): + pass + + +# Test actual function bindings + +@pytest.mark.skip("not implemented") +def test_SDL_AudioInitQuit(): + pass + +def test_SDL_GetNumAudioDrivers(with_sdl_audio): + count = audio.SDL_GetNumAudioDrivers() + assert count >= 1 + +def test_SDL_GetAudioDriver(with_sdl_audio): + founddummy = False + drivercount = audio.SDL_GetNumAudioDrivers() + for index in range(drivercount): + drivername = audio.SDL_GetAudioDriver(index) + assert isinstance(drivername, (str, bytes)) + if drivername == b"dummy": + founddummy = True + assert founddummy + +def test_SDL_GetCurrentAudioDriver(with_sdl_audio): + success = 0 + # Reset audio subsystem + SDL_Quit() + SDL_Init(0) + for index in range(audio.SDL_GetNumAudioDrivers()): + drivername = audio.SDL_GetAudioDriver(index) + os.environ["SDL_AUDIODRIVER"] = drivername.decode("utf-8") + # Certain drivers fail without bringing up the correct + # return value, such as the esd, if it is not running. + SDL_InitSubSystem(SDL_INIT_AUDIO) + driver = audio.SDL_GetCurrentAudioDriver() + SDL_QuitSubSystem(SDL_INIT_AUDIO) + # Do not handle wrong return values. + if driver is not None: + assert drivername == driver + success += 1 + assert success >= 1 + +def test_SDL_OpenCloseAudio(with_sdl_audio): + # TODO: Add test that checks which audio formats are supported for each + # audio device? + fmt = audio.AUDIO_F32 if sys.platform == "darwin" else audio.AUDIO_U16 + reqspec = audio.SDL_AudioSpec(44100, fmt, 2, 1024) + spec = audio.SDL_AudioSpec(0, 0, 0, 0) + ret = audio.SDL_OpenAudio(reqspec, ctypes.byref(spec)) + assert ret == 0 + assert spec.format > 0 # Can't guarantee we'll get requested format + assert spec.freq == reqspec.freq + assert spec.channels == reqspec.channels + audio.SDL_CloseAudio() + +def test_SDL_GetNumAudioDevices(with_sdl_audio): + outnum = audio.SDL_GetNumAudioDevices(False) + assert outnum >= 1 + innum = audio.SDL_GetNumAudioDevices(True) + assert innum >= 0 + +def test_SDL_GetAudioDeviceName(with_sdl_audio): + # NOTE: Check & print errors for drivers that failed to load? + backends = [] + devices = {} + # Reset audio subsystem + SDL_Quit() + SDL_Init(0) + for index in range(audio.SDL_GetNumAudioDrivers()): + # Get input/output device names for each audio driver + drivername = audio.SDL_GetAudioDriver(index) + backends.append(drivername.decode("utf-8")) + os.environ["SDL_AUDIODRIVER"] = drivername.decode("utf-8") + # Need to reinitialize subsystem for each driver SDL_InitSubSystem(SDL_INIT_AUDIO) driver = audio.SDL_GetCurrentAudioDriver() - if driver == None or audio.SDL_GetNumAudioDevices(False) == 0: - SDL_QuitSubSystem(SDL_INIT_AUDIO) - os.environ["SDL_AUDIODRIVER"] = b'dummy' - SDL_InitSubSystem(SDL_INIT_AUDIO) - driver = audio.SDL_GetCurrentAudioDriver() - drivername = driver.decode('utf-8') - # Get name and spec of first output device - outspec = audio.SDL_AudioSpec(0, 0, 0, 0) - outname = audio.SDL_GetAudioDeviceName(0, False).decode('utf-8') - ret = audio.SDL_GetAudioDeviceSpec(0, False, ctypes.byref(outspec)) + if driver is not None: + driver = driver.decode("utf-8") + devices[driver] = {'input': [], 'output': []} + outnum = audio.SDL_GetNumAudioDevices(False) + innum = audio.SDL_GetNumAudioDevices(True) + for x in range(outnum): + name = audio.SDL_GetAudioDeviceName(x, False) + assert name is not None + devices[driver]['output'].append(name.decode('utf-8')) + for x in range(innum): + name = audio.SDL_GetAudioDeviceName(x, True) + assert name is not None + devices[driver]['input'].append(name.decode('utf-8')) SDL_QuitSubSystem(SDL_INIT_AUDIO) - assert ret == 0 - # Validate frequency and channel count were set - hz = outspec.freq - fmt = audio.FORMAT_NAME_MAP[outspec.format] if outspec.format > 0 else 'unknown' - chans = outspec.channels - bufsize = outspec.samples if outspec.samples > 0 else 'unknown' - if driver != b"dummy": - assert hz > 0 - assert chans > 0 - # Print out device spec info - msg = "Audio device spec for {0} with '{1}' driver:" - msg2 = "{0} Hz, {1} channels, {2} format, {3} sample buffer size" - print(msg.format(outname, drivername)) - print(msg2.format(hz, chans, fmt, bufsize)) - - def test_SDL_OpenCloseAudioDevice(self): - #TODO: Add tests for callback - fmt = audio.AUDIO_F32 if sys.platform == "darwin" else audio.AUDIO_U16SYS - reqspec = audio.SDL_AudioSpec(44100, fmt, 2, 1024) - outnum = audio.SDL_GetNumAudioDevices(0) - for x in range(outnum): - spec = audio.SDL_AudioSpec(0, 0, 0, 0) - name = audio.SDL_GetAudioDeviceName(x, 0) - assert name is not None - deviceid = audio.SDL_OpenAudioDevice( - name, 0, reqspec, ctypes.byref(spec), - audio.SDL_AUDIO_ALLOW_ANY_CHANGE - ) - err = SDL_GetError() - assert deviceid >= 2 - assert isinstance(spec, audio.SDL_AudioSpec) - assert spec.format in audio.AUDIO_FORMATS - assert spec.freq > 0 - assert spec.channels > 0 - assert spec.samples > 0 - audio.SDL_CloseAudioDevice(deviceid) - - @pytest.mark.skip("not implemented") - def test_SDL_GetAudioStatus(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GetAudioDeviceStatus(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_PauseAudio(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_PauseAudioDevice(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_LoadWAV_RW(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_LoadWAV(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_FreeWAV(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_BuildAudioCVT(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_ConvertAudio(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_MixAudio(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_MixAudioFormat(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_LockUnlockAudio(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_LockUnlockAudioDevice(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_QueueAudio(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GetQueuedAudioSize(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_ClearQueuedAudio(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_DequeueAudio(self): - pass + print("Audio backends supported by current SDL2 binary:") + print(backends) + print("\nAvailable audio drivers and devices:") + for driver in devices.keys(): + print(driver) + print(" - input: {0}".format(str(devices[driver]['input']))) + print(" - output: {0}".format(str(devices[driver]['output']))) + +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_GetAudioDeviceSpec(with_sdl_audio): + # Reset audio subsystem + SDL_Quit() + SDL_Init(0) + # Find an audio driver with at least one output + SDL_InitSubSystem(SDL_INIT_AUDIO) + driver = audio.SDL_GetCurrentAudioDriver() + if driver == None or audio.SDL_GetNumAudioDevices(False) == 0: + SDL_QuitSubSystem(SDL_INIT_AUDIO) + os.environ["SDL_AUDIODRIVER"] = b'dummy' + SDL_InitSubSystem(SDL_INIT_AUDIO) + driver = audio.SDL_GetCurrentAudioDriver() + drivername = driver.decode('utf-8') + # Get name and spec of first output device + outspec = audio.SDL_AudioSpec(0, 0, 0, 0) + outname = audio.SDL_GetAudioDeviceName(0, False).decode('utf-8') + ret = audio.SDL_GetAudioDeviceSpec(0, False, ctypes.byref(outspec)) + SDL_QuitSubSystem(SDL_INIT_AUDIO) + assert ret == 0 + # Validate frequency and channel count were set + hz = outspec.freq + fmt = audio.FORMAT_NAME_MAP[outspec.format] if outspec.format > 0 else 'unknown' + chans = outspec.channels + bufsize = outspec.samples if outspec.samples > 0 else 'unknown' + if driver != b"dummy": + assert hz > 0 + assert chans > 0 + # Print out device spec info + msg = "Audio device spec for {0} with '{1}' driver:" + msg2 = "{0} Hz, {1} channels, {2} format, {3} sample buffer size" + print(msg.format(outname, drivername)) + print(msg2.format(hz, chans, fmt, bufsize)) + +def test_SDL_OpenCloseAudioDevice(with_sdl_audio): + #TODO: Add tests for callback + fmt = audio.AUDIO_F32 if sys.platform == "darwin" else audio.AUDIO_U16 + reqspec = audio.SDL_AudioSpec(44100, fmt, 2, 1024) + outnum = audio.SDL_GetNumAudioDevices(0) + for x in range(outnum): + spec = audio.SDL_AudioSpec(0, 0, 0, 0) + name = audio.SDL_GetAudioDeviceName(x, 0) + assert name is not None + deviceid = audio.SDL_OpenAudioDevice( + name, 0, reqspec, ctypes.byref(spec), + audio.SDL_AUDIO_ALLOW_ANY_CHANGE + ) + err = SDL_GetError() + assert deviceid >= 2 + assert isinstance(spec, audio.SDL_AudioSpec) + assert spec.format in audio.AUDIO_FORMATS + assert spec.freq > 0 + assert spec.channels > 0 + assert spec.samples > 0 + audio.SDL_CloseAudioDevice(deviceid) + +@pytest.mark.skip("not implemented") +def test_SDL_GetAudioStatus(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_GetAudioDeviceStatus(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_PauseAudio(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_PauseAudioDevice(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_LoadWAV_RW(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_LoadWAV(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_FreeWAV(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_BuildAudioCVT(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_ConvertAudio(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_MixAudio(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_MixAudioFormat(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_LockUnlockAudio(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_LockUnlockAudioDevice(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_QueueAudio(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_GetQueuedAudioSize(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_ClearQueuedAudio(self): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_DequeueAudio(self): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2007, reason="not available") +def test_SDL_NewAudioStream(): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2007, reason="not available") +def test_SDL_AudioStreamPut(): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2007, reason="not available") +def test_SDL_AudioStreamGet(): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2007, reason="not available") +def test_SDL_AudioStreamAvailable(): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2007, reason="not available") +def test_SDL_AudioStreamClear(): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2007, reason="not available") +def test_SDL_FreeAudioStream(): + pass diff --git a/sdl2/test/blendmode_test.py b/sdl2/test/blendmode_test.py index e59004c6..289f7fe1 100644 --- a/sdl2/test/blendmode_test.py +++ b/sdl2/test/blendmode_test.py @@ -4,18 +4,6 @@ from sdl2 import blendmode -class TestSDLBlendmode(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - if SDL_Init(SDL_INIT_VIDEO) != 0: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - SDL_Quit() - - @pytest.mark.skip("not implemented") - def test_SDL_ComposeCustomBlendMode(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_ComposeCustomBlendMode(self, with_sdl): + pass diff --git a/sdl2/test/clipboard_test.py b/sdl2/test/clipboard_test.py index 77eadef8..228eedd1 100644 --- a/sdl2/test/clipboard_test.py +++ b/sdl2/test/clipboard_test.py @@ -1,55 +1,36 @@ import sys import pytest -from sdl2 import SDL_Init, SDL_Quit, SDL_INIT_EVERYTHING +import sdl2 +from sdl2 import SDL_GetError from sdl2 import clipboard -from sdl2.stdinc import SDL_TRUE - - -def is_win_or_mac(): - return sys.platform in ("win32", "cygwin", "darwin") - - -class TestSDLClipboard(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - SDL_Init(SDL_INIT_EVERYTHING) - - @classmethod - def teardown_class(cls): - SDL_Quit() - - # @pytest.mark.skipif(not is_win_or_mac(), - # reason="we would need a SDL window") - # @interactive() - # def test_SDL_HasClipboardText(self): - # doprint("Please put some text on the clipboard") - # self.assertEqual(clipboard.SDL_HasClipboardText(), SDL_TRUE) - - # @pytest.mark.skipif(not is_win_or_mac(), - # reason="we would need a SDL window") - # @interactive("Does the shown value match the clipboard content?") - # def test_SDL_GetClipboardText(self): - # doprint("Please put some text on the clipboard") - # retval = clipboard.SDL_GetClipboardText() - # doprint("Clipboard content: '%s'" % retval) - - # @pytest.mark.skipif(not is_win_or_mac(), - # reason="we would need a SDL window") - # def test_SDL_SetClipboardText(self): - # self.assertEquals(clipboard.SDL_SetClipboardText(b"Test content"), 0) - # retval = clipboard.SDL_GetClipboardText() - # self.assertEqual(retval, b"Test content") - - # self.assertEquals(clipboard.SDL_SetClipboardText(b""), 0) - # retval = clipboard.SDL_GetClipboardText() - # self.assertEqual(retval, b"") - - # self.assertEquals(clipboard.SDL_SetClipboardText(b"Test content"), 0) - # retval = clipboard.SDL_GetClipboardText() - # self.assertEqual(retval, b"Test content") - - # self.assertEquals(clipboard.SDL_SetClipboardText(None), 0) - # retval = clipboard.SDL_GetClipboardText() - # self.assertEqual(retval, b"") +from sdl2.stdinc import SDL_TRUE, SDL_FALSE +from .conftest import SKIP_ANNOYING + +@pytest.fixture +def window(with_sdl): + flag = sdl2.SDL_WINDOW_BORDERLESS + w = sdl2.SDL_CreateWindow(b"Test", 10, 40, 12, 13, flag) + assert sdl2.SDL_GetError() == b"" + assert isinstance(w.contents, sdl2.SDL_Window) + yield w + sdl2.SDL_DestroyWindow(w) + + +@pytest.mark.skipif(SKIP_ANNOYING, reason="Skip unless requested") +def test_SDL_ClipboardText(window): + # Test retrieving text from the clipboard + ret = clipboard.SDL_GetClipboardText() + original_contents = ret + assert type(ret) in (str, bytes) + # Test whether HasClipboardText is accurate + expected = SDL_FALSE if len(ret) == 0 else SDL_TRUE + assert clipboard.SDL_HasClipboardText() == expected + # Set some new clipboard test and test for it + sdl2.SDL_ClearError() + ret = clipboard.SDL_SetClipboardText(b"test") + assert SDL_GetError() == b"" + assert ret == 0 + assert clipboard.SDL_HasClipboardText() == SDL_TRUE + assert clipboard.SDL_GetClipboardText() == b"test" + # Reset original contents + clipboard.SDL_SetClipboardText(original_contents) diff --git a/sdl2/test/conftest.py b/sdl2/test/conftest.py new file mode 100644 index 00000000..9533a45b --- /dev/null +++ b/sdl2/test/conftest.py @@ -0,0 +1,26 @@ +# pytest configuration file +import os +import gc +import pytest +import sdl2 +from sdl2 import ext as sdl2ext + +# A flag to skip annoying audiovisual tests (e.g. window minimize). +# Defaults to True unless an environment variable is explicitly set. +SKIP_ANNOYING = os.getenv("PYSDL2_ALL_TESTS", "0") == "0" + +@pytest.fixture(scope="module") +def with_sdl(): + sdl2.SDL_ClearError() + ret = sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO | sdl2.SDL_INIT_TIMER) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + yield + sdl2.SDL_Quit() + +@pytest.fixture(autouse=True) +def sdl_cleanup(): + sdl2.SDL_ClearError() + yield + sdl2.SDL_ClearError() + gc.collect() diff --git a/sdl2/test/cpuinfo_test.py b/sdl2/test/cpuinfo_test.py index 5b0614a9..e160092c 100644 --- a/sdl2/test/cpuinfo_test.py +++ b/sdl2/test/cpuinfo_test.py @@ -10,94 +10,91 @@ _HASMP = False -class TestSDLCPUInfo(object): - __tags__ = ["sdl"] - - def test_SDL_GetCPUCacheLineSize(self): - ret = cpuinfo.SDL_GetCPUCacheLineSize() - assert isinstance(ret, int) - - def test_SDL_GetCPUCount(self): - if _HASMP: - assert multiprocessing.cpu_count() == cpuinfo.SDL_GetCPUCount() - else: - assert cpuinfo.SDL_GetCPUCount() >= 1 - - def test_SDL_Has3DNow(self): - ret = cpuinfo.SDL_Has3DNow() - assert ret in (0, 1) - - def test_SDL_HasAltiVec(self): - ret = cpuinfo.SDL_HasAltiVec() - assert ret in (0, 1) - - def test_SDL_HasMMX(self): - ret = cpuinfo.SDL_HasMMX() - assert ret in (0, 1) - - def test_SDL_HasRDTSC(self): - ret = cpuinfo.SDL_HasRDTSC() - assert ret in (0, 1) - - def test_SDL_HasSSE(self): - ret = cpuinfo.SDL_HasSSE() - assert ret in (0, 1) - - def test_SDL_HasSSE2(self): - ret = cpuinfo.SDL_HasSSE2() - assert ret in (0, 1) - - def test_SDL_HasSSE3(self): - ret = cpuinfo.SDL_HasSSE3() - assert ret in (0, 1) - - def test_SDL_HasSSE41(self): - ret = cpuinfo.SDL_HasSSE41() - assert ret in (0, 1) - - def test_SDL_HasSSE42(self): - ret = cpuinfo.SDL_HasSSE42() - assert ret in (0, 1) - - def test_SDL_HasAVX(self): - ret = cpuinfo.SDL_HasAVX() - assert ret in (0, 1) - - def test_SDL_HasAVX2(self): - ret = cpuinfo.SDL_HasAVX2() - assert ret in (0, 1) - - def test_SDL_GetSystemRAM(self): - ret = cpuinfo.SDL_GetSystemRAM() - assert ret > 0 - - @pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") - def test_SDL_HasAVX512F(self): - ret = cpuinfo.SDL_HasAVX512F() - assert ret in (0, 1) - - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_HasARMSIMD(self): - ret = cpuinfo.SDL_HasARMSIMD() - assert ret in (0, 1) - - @pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") - def test_SDL_HasNEON(self): - ret = cpuinfo.SDL_HasNEON() - assert ret in (0, 1) - - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_SIMDGetAlignment(self): - ret = cpuinfo.SDL_SIMDGetAlignment() - assert ret % 8 == 0 # Should be multiple of 8 - - @pytest.mark.skip("not implemented (no clue how)") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_SIMDAllocFree(self): - # Should test both SDL_SIMDAlloc and SDL_SIMDFree - pass - - @pytest.mark.skip("not implemented (no clue how)") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_SIMDRealloc(self): - pass +def test_SDL_GetCPUCacheLineSize(): + ret = cpuinfo.SDL_GetCPUCacheLineSize() + assert isinstance(ret, int) + +def test_SDL_GetCPUCount(): + if _HASMP: + assert multiprocessing.cpu_count() == cpuinfo.SDL_GetCPUCount() + else: + assert cpuinfo.SDL_GetCPUCount() >= 1 + +def test_SDL_Has3DNow(): + ret = cpuinfo.SDL_Has3DNow() + assert ret in (0, 1) + +def test_SDL_HasAltiVec(): + ret = cpuinfo.SDL_HasAltiVec() + assert ret in (0, 1) + +def test_SDL_HasMMX(): + ret = cpuinfo.SDL_HasMMX() + assert ret in (0, 1) + +def test_SDL_HasRDTSC(): + ret = cpuinfo.SDL_HasRDTSC() + assert ret in (0, 1) + +def test_SDL_HasSSE(): + ret = cpuinfo.SDL_HasSSE() + assert ret in (0, 1) + +def test_SDL_HasSSE2(): + ret = cpuinfo.SDL_HasSSE2() + assert ret in (0, 1) + +def test_SDL_HasSSE3(): + ret = cpuinfo.SDL_HasSSE3() + assert ret in (0, 1) + +def test_SDL_HasSSE41(): + ret = cpuinfo.SDL_HasSSE41() + assert ret in (0, 1) + +def test_SDL_HasSSE42(): + ret = cpuinfo.SDL_HasSSE42() + assert ret in (0, 1) + +def test_SDL_HasAVX(): + ret = cpuinfo.SDL_HasAVX() + assert ret in (0, 1) + +def test_SDL_HasAVX2(): + ret = cpuinfo.SDL_HasAVX2() + assert ret in (0, 1) + +def test_SDL_GetSystemRAM(): + ret = cpuinfo.SDL_GetSystemRAM() + assert ret > 0 + +@pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") +def test_SDL_HasAVX512F(): + ret = cpuinfo.SDL_HasAVX512F() + assert ret in (0, 1) + +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_HasARMSIMD(): + ret = cpuinfo.SDL_HasARMSIMD() + assert ret in (0, 1) + +@pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") +def test_SDL_HasNEON(): + ret = cpuinfo.SDL_HasNEON() + assert ret in (0, 1) + +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_SIMDGetAlignment(): + ret = cpuinfo.SDL_SIMDGetAlignment() + assert ret % 8 == 0 # Should be multiple of 8 + +@pytest.mark.skip("not implemented (no clue how)") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_SIMDAllocFree(): + # Should test both SDL_SIMDAlloc and SDL_SIMDFree + pass + +@pytest.mark.skip("not implemented (no clue how)") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_SIMDRealloc(): + pass diff --git a/sdl2/test/endian_test.py b/sdl2/test/endian_test.py index 4236b40a..b512047c 100644 --- a/sdl2/test/endian_test.py +++ b/sdl2/test/endian_test.py @@ -4,82 +4,79 @@ from sdl2 import endian -class TestSDLEndian(object): - __tags__ = ["sdl"] +def test_SDL_BYTEORDER(): + if sys.byteorder == "little": + assert endian.SDL_BYTEORDER == endian.SDL_LIL_ENDIAN + else: + assert endian.SDL_BYTEORDER == endian.SDL_BIG_ENDIAN - def test_SDL_BYTEORDER(self): - if sys.byteorder == "little": - assert endian.SDL_BYTEORDER == endian.SDL_LIL_ENDIAN - else: - assert endian.SDL_BYTEORDER == endian.SDL_BIG_ENDIAN +def test_SDL_Swap16(): + assert endian.SDL_Swap16(0xFF00) == 0x00FF + assert endian.SDL_Swap16(0x0001) == 0x0100 + assert endian.SDL_Swap16(0x0032) == 0x3200 + assert endian.SDL_Swap16(0x0FF0) == 0xF00F + assert endian.SDL_Swap16(0x00FF) == 0xFF00 + assert endian.SDL_Swap16(0x1234) == 0x3412 + if sys.byteorder == "little": + assert endian.SDL_Swap16 == endian.SDL_SwapBE16 + assert endian.SDL_Swap16 != endian.SDL_SwapLE16 + else: + assert endian.SDL_Swap16 != endian.SDL_SwapBE16 + assert endian.SDL_Swap16 == endian.SDL_SwapLE16 - def test_SDL_Swap16(self): - assert endian.SDL_Swap16(0xFF00) == 0x00FF - assert endian.SDL_Swap16(0x0001) == 0x0100 - assert endian.SDL_Swap16(0x0032) == 0x3200 - assert endian.SDL_Swap16(0x0FF0) == 0xF00F - assert endian.SDL_Swap16(0x00FF) == 0xFF00 - assert endian.SDL_Swap16(0x1234) == 0x3412 - if sys.byteorder == "little": - assert endian.SDL_Swap16 == endian.SDL_SwapBE16 - assert endian.SDL_Swap16 != endian.SDL_SwapLE16 - else: - assert endian.SDL_Swap16 != endian.SDL_SwapBE16 - assert endian.SDL_Swap16 == endian.SDL_SwapLE16 +def test_SDL_Swap32(): + assert endian.SDL_Swap32(0xFF000000) == 0x000000FF + assert endian.SDL_Swap32(0x00FF0000) == 0x0000FF00 + assert endian.SDL_Swap32(0x0000FF00) == 0x00FF0000 + assert endian.SDL_Swap32(0x000000FF) == 0xFF000000 + assert endian.SDL_Swap32(0x12345678) == 0x78563412 + assert endian.SDL_Swap32(0xFF00FF00) == 0x00FF00FF + if sys.byteorder == "little": + assert endian.SDL_Swap32 == endian.SDL_SwapBE32 + assert endian.SDL_Swap32 != endian.SDL_SwapLE32 + else: + assert endian.SDL_Swap32 != endian.SDL_SwapBE32 + assert endian.SDL_Swap32 == endian.SDL_SwapLE32 - def test_SDL_Swap32(self): - assert endian.SDL_Swap32(0xFF000000) == 0x000000FF - assert endian.SDL_Swap32(0x00FF0000) == 0x0000FF00 - assert endian.SDL_Swap32(0x0000FF00) == 0x00FF0000 - assert endian.SDL_Swap32(0x000000FF) == 0xFF000000 - assert endian.SDL_Swap32(0x12345678) == 0x78563412 - assert endian.SDL_Swap32(0xFF00FF00) == 0x00FF00FF - if sys.byteorder == "little": - assert endian.SDL_Swap32 == endian.SDL_SwapBE32 - assert endian.SDL_Swap32 != endian.SDL_SwapLE32 - else: - assert endian.SDL_Swap32 != endian.SDL_SwapBE32 - assert endian.SDL_Swap32 == endian.SDL_SwapLE32 +def test_SDL_Swap64(): + assert endian.SDL_Swap64(0xFF00000000000000) == 0x00000000000000FF + assert endian.SDL_Swap64(0x00FF000000000000) == 0x000000000000FF00 + assert endian.SDL_Swap64(0x0000FF0000000000) == 0x0000000000FF0000 + assert endian.SDL_Swap64(0x000000FF00000000) == 0x00000000FF000000 + assert endian.SDL_Swap64(0x00000000FF000000) == 0x000000FF00000000 + assert endian.SDL_Swap64(0x0000000000FF0000) == 0x0000FF0000000000 + assert endian.SDL_Swap64(0x000000000000FF00) == 0x00FF000000000000 + assert endian.SDL_Swap64(0x00000000000000FF) == 0xFF00000000000000 + assert endian.SDL_Swap64(0x0123456789ABCDEF) == 0xEFCDAB8967452301 + if sys.byteorder == "little": + assert endian.SDL_Swap64 == endian.SDL_SwapBE64 + assert endian.SDL_Swap64 != endian.SDL_SwapLE64 + else: + assert endian.SDL_Swap64 != endian.SDL_SwapBE64 + assert endian.SDL_Swap64 == endian.SDL_SwapLE64 - def test_SDL_Swap64(self): - assert endian.SDL_Swap64(0xFF00000000000000) == 0x00000000000000FF - assert endian.SDL_Swap64(0x00FF000000000000) == 0x000000000000FF00 - assert endian.SDL_Swap64(0x0000FF0000000000) == 0x0000000000FF0000 - assert endian.SDL_Swap64(0x000000FF00000000) == 0x00000000FF000000 - assert endian.SDL_Swap64(0x00000000FF000000) == 0x000000FF00000000 - assert endian.SDL_Swap64(0x0000000000FF0000) == 0x0000FF0000000000 - assert endian.SDL_Swap64(0x000000000000FF00) == 0x00FF000000000000 - assert endian.SDL_Swap64(0x00000000000000FF) == 0xFF00000000000000 - assert endian.SDL_Swap64(0x0123456789ABCDEF) == 0xEFCDAB8967452301 - if sys.byteorder == "little": - assert endian.SDL_Swap64 == endian.SDL_SwapBE64 - assert endian.SDL_Swap64 != endian.SDL_SwapLE64 - else: - assert endian.SDL_Swap64 != endian.SDL_SwapBE64 - assert endian.SDL_Swap64 == endian.SDL_SwapLE64 - - def test_SDL_SwapFloat(self): - v = -100.0 - while v < 101: - p = endian.SDL_SwapFloat(v) - assert p != v - assert endian.SDL_SwapFloat(p) == v - v += 0.1 - values = (sys.float_info.epsilon, - sys.float_info.min, - sys.float_info.max, - - sys.float_info.min, - math.pi, - - math.pi - ) - for v in values: - p = endian.SDL_SwapFloat(v) - assert p != v - assert endian.SDL_SwapFloat(p) == v - - if sys.byteorder == "little": - assert endian.SDL_SwapFloat == endian.SDL_SwapFloatBE - assert endian.SDL_SwapFloat != endian.SDL_SwapFloatLE - else: - assert endian.SDL_SwapFloat != endian.SDL_SwapFloatBE - assert endian.SDL_SwapFloat == endian.SDL_SwapFloatLE +def test_SDL_SwapFloat(): + v = -100.0 + while v < 101: + p = endian.SDL_SwapFloat(v) + assert p != v + assert endian.SDL_SwapFloat(p) == v + v += 0.8 + values = ( + sys.float_info.epsilon, + sys.float_info.min, + sys.float_info.max, + -sys.float_info.min, + math.pi, + -math.pi + ) + for v in values: + p = endian.SDL_SwapFloat(v) + assert p != v + assert endian.SDL_SwapFloat(p) == v + if sys.byteorder == "little": + assert endian.SDL_SwapFloat == endian.SDL_SwapFloatBE + assert endian.SDL_SwapFloat != endian.SDL_SwapFloatLE + else: + assert endian.SDL_SwapFloat != endian.SDL_SwapFloatBE + assert endian.SDL_SwapFloat == endian.SDL_SwapFloatLE diff --git a/sdl2/test/error_test.py b/sdl2/test/error_test.py index fa9b6754..73c63c8c 100644 --- a/sdl2/test/error_test.py +++ b/sdl2/test/error_test.py @@ -2,41 +2,30 @@ import pytest import sdl2 from ctypes import create_string_buffer, byref -from sdl2 import SDL_Init, SDL_Quit, error +from sdl2 import error +# Override global cleanup fixture since it calls SDL_ClearError +@pytest.fixture(autouse=True) +def sdl_cleanup(): + yield -class TestSDLError(object): - __tags__ = ["sdl"] - @classmethod - def setup_class(cls): - SDL_Init(0) +def test_SDL_GetSetClearError(): + error.SDL_SetError(b"Hi there!") + assert error.SDL_GetError() == b"Hi there!" + error.SDL_SetError(b"Error 2"); + assert error.SDL_GetError() == b"Error 2" + error.SDL_ClearError(); + assert error.SDL_GetError() == b"" - @classmethod - def teardown_class(cls): - SDL_Quit() - - def test_SDL_GetSetClearError(self): - assert error.SDL_GetError() == b"" - error.SDL_SetError(b"A Unit Test Error Message") - assert error.SDL_GetError() == b"A Unit Test Error Message" - error.SDL_ClearError() - assert error.SDL_GetError() == b"" - error.SDL_SetError(b"A Unit Test Error Message") - assert error.SDL_GetError() == b"A Unit Test Error Message" - assert error.SDL_GetError() == b"A Unit Test Error Message" - error.SDL_ClearError() - error.SDL_SetError(b"123456789") - assert error.SDL_GetError() == b"123456789" - - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GetErrorMsg(self): - error.SDL_SetError(b"123456789") - assert error.SDL_GetError() == b"123456789" - buf = create_string_buffer(10) - assert error.SDL_GetErrorMsg(buf, 10) == b"123456789" - assert buf.value == b"123456789" - buf2 = create_string_buffer(5) - assert error.SDL_GetErrorMsg(buf2, 5) == b"1234" - assert buf2.value == b"1234" - error.SDL_ClearError() +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GetErrorMsg(): + error.SDL_SetError(b"123456789") + assert error.SDL_GetError() == b"123456789" + buf = create_string_buffer(10) + assert error.SDL_GetErrorMsg(buf, 10) == b"123456789" + assert buf.value == b"123456789" + buf2 = create_string_buffer(5) + assert error.SDL_GetErrorMsg(buf2, 5) == b"1234" + assert buf2.value == b"1234" + error.SDL_ClearError() diff --git a/sdl2/test/events_test.py b/sdl2/test/events_test.py index c9a506ed..280e908e 100644 --- a/sdl2/test/events_test.py +++ b/sdl2/test/events_test.py @@ -5,130 +5,135 @@ from sdl2 import SDL_Init, SDL_Quit, SDL_QuitSubSystem, SDL_INIT_EVERYTHING from sdl2 import events +# NOTE: These tests are very incomplete and in need of a rewrite -class TestSDLEvents(object): - __tags__ = ["sdl"] - @classmethod - def setup_class(cls): - SDL_Init(SDL_INIT_EVERYTHING) +# Test initializing event structs (is this actually useful?) - @classmethod - def teardown_class(cls): - SDL_QuitSubSystem(SDL_INIT_EVERYTHING) - SDL_Quit() +def test_SDL_AudioDeviceEvent(): + event = events.SDL_AudioDeviceEvent() + assert isinstance(event, events.SDL_AudioDeviceEvent) - def test_SDL_AudioDeviceEvent(self): - event = events.SDL_AudioDeviceEvent() - assert isinstance(event, events.SDL_AudioDeviceEvent) +def test_SDL_DisplayEvent(): + event = events.SDL_DisplayEvent() + assert isinstance(event, events.SDL_DisplayEvent) - def test_SDL_DisplayEvent(self): - event = events.SDL_DisplayEvent() - assert isinstance(event, events.SDL_DisplayEvent) +def test_SDL_WindowEvent(): + event = events.SDL_WindowEvent() + assert isinstance(event, events.SDL_WindowEvent) - def test_SDL_WindowEvent(self): - event = events.SDL_WindowEvent() - assert isinstance(event, events.SDL_WindowEvent) +def test_SDL_KeyboardEvent(): + event = events.SDL_KeyboardEvent() + assert isinstance(event, events.SDL_KeyboardEvent) - def test_SDL_KeyboardEvent(self): - event = events.SDL_KeyboardEvent() - assert isinstance(event, events.SDL_KeyboardEvent) +def test_SDL_TextEditingEvent(): + event = events.SDL_TextEditingEvent() + assert isinstance(event, events.SDL_TextEditingEvent) - def test_SDL_TextEditingEvent(self): - event = events.SDL_TextEditingEvent() - assert isinstance(event, events.SDL_TextEditingEvent) +def test_SDL_TextInputEvent(): + event = events.SDL_TextInputEvent() + assert isinstance(event, events.SDL_TextInputEvent) - def test_SDL_TextInputEvent(self): - event = events.SDL_TextInputEvent() - assert isinstance(event, events.SDL_TextInputEvent) +def test_SDL_MouseMotionEvent(): + event = events.SDL_MouseMotionEvent() + assert isinstance(event, events.SDL_MouseMotionEvent) - def test_SDL_MouseMotionEvent(self): - event = events.SDL_MouseMotionEvent() - assert isinstance(event, events.SDL_MouseMotionEvent) +def test_SDL_MouseButtonEvent(): + event = events.SDL_MouseButtonEvent() + assert isinstance(event, events.SDL_MouseButtonEvent) - def test_SDL_MouseButtonEvent(self): - event = events.SDL_MouseButtonEvent() - assert isinstance(event, events.SDL_MouseButtonEvent) +def test_SDL_MouseWheelEvent(): + event = events.SDL_MouseWheelEvent() + assert isinstance(event, events.SDL_MouseWheelEvent) - def test_SDL_MouseWheelEvent(self): - event = events.SDL_MouseWheelEvent() - assert isinstance(event, events.SDL_MouseWheelEvent) +def test_SDL_JoyAxisEvent(): + event = events.SDL_JoyAxisEvent() + assert isinstance(event, events.SDL_JoyAxisEvent) - def test_SDL_JoyAxisEvent(self): - event = events.SDL_JoyAxisEvent() - assert isinstance(event, events.SDL_JoyAxisEvent) +def test_SDL_JoyBallEvent(): + event = events.SDL_JoyBallEvent() + assert isinstance(event, events.SDL_JoyBallEvent) - def test_SDL_JoyBallEvent(self): - event = events.SDL_JoyBallEvent() - assert isinstance(event, events.SDL_JoyBallEvent) +def test_SDL_JoyHatEvent(): + event = events.SDL_JoyHatEvent() + assert isinstance(event, events.SDL_JoyHatEvent) - def test_SDL_JoyHatEvent(self): - event = events.SDL_JoyHatEvent() - assert isinstance(event, events.SDL_JoyHatEvent) +def test_SDL_JoyButtonEvent(): + event = events.SDL_JoyButtonEvent() + assert isinstance(event, events.SDL_JoyButtonEvent) - def test_SDL_JoyButtonEvent(self): - event = events.SDL_JoyButtonEvent() - assert isinstance(event, events.SDL_JoyButtonEvent) +def test_SDL_JoyDeviceEvent(): + event = events.SDL_JoyDeviceEvent() + assert isinstance(event, events.SDL_JoyDeviceEvent) - def test_SDL_JoyDeviceEvent(self): - event = events.SDL_JoyDeviceEvent() - assert isinstance(event, events.SDL_JoyDeviceEvent) +def test_SDL_ControllerAxisEvent(): + event = events.SDL_ControllerAxisEvent() + assert isinstance(event, events.SDL_ControllerAxisEvent) - def test_SDL_ControllerAxisEvent(self): - event = events.SDL_ControllerAxisEvent() - assert isinstance(event, events.SDL_ControllerAxisEvent) +def test_SDL_ControllerButtonEvent(): + event = events.SDL_ControllerButtonEvent() + assert isinstance(event, events.SDL_ControllerButtonEvent) - def test_SDL_ControllerButtonEvent(self): - event = events.SDL_ControllerButtonEvent() - assert isinstance(event, events.SDL_ControllerButtonEvent) +def test_SDL_ControllerDeviceEvent(): + event = events.SDL_ControllerDeviceEvent() + assert isinstance(event, events.SDL_ControllerDeviceEvent) - def test_SDL_ControllerDeviceEvent(self): - event = events.SDL_ControllerDeviceEvent() - assert isinstance(event, events.SDL_ControllerDeviceEvent) +def test_SDL_ControllerTouchpadEvent(): + event = events.SDL_ControllerTouchpadEvent() + assert isinstance(event, events.SDL_ControllerTouchpadEvent) - def test_SDL_ControllerTouchpadEvent(self): - event = events.SDL_ControllerTouchpadEvent() - assert isinstance(event, events.SDL_ControllerTouchpadEvent) +def test_SDL_ControllerSensorEvent(): + event = events.SDL_ControllerSensorEvent() + assert isinstance(event, events.SDL_ControllerSensorEvent) - def test_SDL_ControllerSensorEvent(self): - event = events.SDL_ControllerSensorEvent() - assert isinstance(event, events.SDL_ControllerSensorEvent) +def test_SDL_TouchFingerEvent(): + event = events.SDL_TouchFingerEvent() + assert isinstance(event, events.SDL_TouchFingerEvent) - def test_SDL_TouchFingerEvent(self): - event = events.SDL_TouchFingerEvent() - assert isinstance(event, events.SDL_TouchFingerEvent) +def test_SDL_MultiGestureEvent(): + event = events.SDL_MultiGestureEvent() + assert isinstance(event, events.SDL_MultiGestureEvent) - def test_SDL_MultiGestureEvent(self): - event = events.SDL_MultiGestureEvent() - assert isinstance(event, events.SDL_MultiGestureEvent) +def test_SDL_DollarGestureEvent(): + event = events.SDL_DollarGestureEvent() + assert isinstance(event, events.SDL_DollarGestureEvent) - def test_SDL_DollarGestureEvent(self): - event = events.SDL_DollarGestureEvent() - assert isinstance(event, events.SDL_DollarGestureEvent) +def test_SDL_DropEvent(): + event = events.SDL_DropEvent() + assert isinstance(event, events.SDL_DropEvent) - def test_SDL_DropEvent(self): - event = events.SDL_DropEvent() - assert isinstance(event, events.SDL_DropEvent) +def test_SDL_SensorEvent(): + event = events.SDL_SensorEvent() + assert isinstance(event, events.SDL_SensorEvent) - def test_SDL_SensorEvent(self): - event = events.SDL_SensorEvent() - assert isinstance(event, events.SDL_SensorEvent) +def test_SDL_QuitEvent(): + event = events.SDL_QuitEvent() + assert isinstance(event, events.SDL_QuitEvent) - def test_SDL_QuitEvent(self): - event = events.SDL_QuitEvent() - assert isinstance(event, events.SDL_QuitEvent) +def test_SDL_UserEvent(): + event = events.SDL_UserEvent() + assert isinstance(event, events.SDL_UserEvent) - def test_SDL_UserEvent(self): - event = events.SDL_UserEvent() - assert isinstance(event, events.SDL_UserEvent) +def test_SDL_SysWMEvent(): + event = events.SDL_SysWMEvent() + assert isinstance(event, events.SDL_SysWMEvent) - def test_SDL_SysWMEvent(self): - event = events.SDL_SysWMEvent() - assert isinstance(event, events.SDL_SysWMEvent) +def test_SDL_Event(): + event = events.SDL_Event() + assert isinstance(event, events.SDL_Event) - def test_SDL_Event(self): - event = events.SDL_Event() - assert isinstance(event, events.SDL_Event) + +class TestSDLEvents(object): + __tags__ = ["sdl"] + + @classmethod + def setup_class(cls): + SDL_Init(SDL_INIT_EVERYTHING) + + @classmethod + def teardown_class(cls): + SDL_QuitSubSystem(SDL_INIT_EVERYTHING) + SDL_Quit() def test_SDL_AddDelEventWatch(self): eventwatch = [] diff --git a/sdl2/test/filesystem_test.py b/sdl2/test/filesystem_test.py index 94a42cb4..b0a8c69f 100644 --- a/sdl2/test/filesystem_test.py +++ b/sdl2/test/filesystem_test.py @@ -5,25 +5,22 @@ from sdl2 import filesystem, SDL_free -class TestSDLFileSystem(object): - __tags__ = ["sdl"] +def test_SDL_GetBasePath(): + path = filesystem.SDL_GetBasePath() + path = path.decode("utf-8") + if sys.version_info[0] < 3: + is_python_path = False + for s in [u"python", u"pypy", u"pyenv", u"virtualenv"]: + if s in path.lower(): + is_python_path = True + break + assert is_python_path + else: + execprefix = sys.base_exec_prefix + assert execprefix.lower() in path.lower() - def test_SDL_GetBasePath(self): - path = filesystem.SDL_GetBasePath() - path = path.decode("utf-8") - if sys.version_info[0] < 3: - is_python_path = False - for s in [u"python", u"pypy", u"pyenv", u"virtualenv"]: - if s in path.lower(): - is_python_path = True - break - assert is_python_path - else: - execprefix = sys.base_exec_prefix - assert execprefix.lower() in path.lower() - - def test_SDL_GetPrefPath(self): - path = filesystem.SDL_GetPrefPath(b"OrgName", b"AppName") - path = path.decode("utf-8") - assert "OrgName" in path - assert "AppName" in path +def test_SDL_GetPrefPath(): + path = filesystem.SDL_GetPrefPath(b"OrgName", b"AppName") + path = path.decode("utf-8") + assert "OrgName" in path + assert "AppName" in path diff --git a/sdl2/test/gamecontroller_test.py b/sdl2/test/gamecontroller_test.py index 7a513ed3..7605e5ee 100644 --- a/sdl2/test/gamecontroller_test.py +++ b/sdl2/test/gamecontroller_test.py @@ -1,19 +1,68 @@ import sys import pytest import sdl2 -from sdl2 import SDL_Init, SDL_Quit, SDL_INIT_GAMECONTROLLER, SDL_TRUE +from sdl2 import ( + SDL_Init, SDL_Quit, SDL_ClearError, SDL_GetError, + SDL_FALSE, SDL_TRUE, SDL_IGNORE, SDL_ENABLE, SDL_QUERY +) from sdl2 import joystick from sdl2 import gamecontroller as gamepad +# Get status of gamepad support/availability before running tests +SDL_ClearError() +ret = SDL_Init(sdl2.SDL_INIT_GAMECONTROLLER) +gamepad_works = ret == 0 and SDL_GetError() == b"" +SDL_Quit() -# TODO: Move tests that don't need GameController instance out of class -# TODO: Add support for actual device tests from joystick +pytestmark = pytest.mark.skipif(not gamepad_works, reason="system unsupported") + +gamepad_types = [ + gamepad.SDL_CONTROLLER_TYPE_UNKNOWN, + gamepad.SDL_CONTROLLER_TYPE_XBOX360, + gamepad.SDL_CONTROLLER_TYPE_XBOXONE, + gamepad.SDL_CONTROLLER_TYPE_PS3, + gamepad.SDL_CONTROLLER_TYPE_PS4, + gamepad.SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO, + gamepad.SDL_CONTROLLER_TYPE_VIRTUAL, + gamepad.SDL_CONTROLLER_TYPE_PS5, + gamepad.SDL_CONTROLLER_TYPE_AMAZON_LUNA, + gamepad.SDL_CONTROLLER_TYPE_GOOGLE_STADIA, +] + + +# Overrides global fixture with one that initializes the joystick system +@pytest.fixture(scope="module") +def with_sdl(): + sdl2.SDL_ClearError() + sdl2.SDL_SetHint(b"SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", b"1") + ret = sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO | sdl2.SDL_INIT_GAMECONTROLLER) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + # Also initialize a virtual joystick (if supported) + if sdl2.dll.version >= 2014: + virt_type = joystick.SDL_JOYSTICK_TYPE_GAMECONTROLLER + virt_index = joystick.SDL_JoystickAttachVirtual(virt_type, 2, 4, 1) + yield + sdl2.SDL_Quit() + +@pytest.fixture() +def gamepads(with_sdl): + devices = [] + count = joystick.SDL_NumJoysticks() + for i in range(count): + if gamepad.SDL_IsGameController(i) == SDL_TRUE: + pad = gamepad.SDL_GameControllerOpen(i) + assert sdl2.SDL_GetError() == b"" + assert isinstance(pad.contents, gamepad.SDL_GameController) + devices.append(pad) + yield devices + for pad in devices: + gamepad.SDL_GameControllerClose(pad) + +def is_virtual(pad): + stick = gamepad.SDL_GameControllerGetJoystick(pad) + return joystick.SDL_JoystickName(stick) == b"Virtual Joystick" -# Make sure gamecontroller subsystem works before running tests -ret = SDL_Init(SDL_INIT_GAMECONTROLLER) -SDL_Quit() -skipmsg = 'Game controller subsystem not supported' -pytestmark = pytest.mark.skipif(ret != 0, reason=skipmsg) # Test if SDL_GameControllerMappingForGUID is able to be tested if sys.version_info >= (3, 8, 0) or sdl2.dll.version >= 2006: @@ -22,331 +71,369 @@ has_mapping_for_guid = False -class TestSDLGamecontroller(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - SDL_Init(SDL_INIT_GAMECONTROLLER) - num = joystick.SDL_NumJoysticks() - if num < 1: - pytest.skip("no available joystick devices") - gamepad_ids = [] - for i in range(num): - if gamepad.SDL_IsGameController(i) == SDL_TRUE: - gamepad_ids.append(i) - cls.gamepad_ids = gamepad_ids - - @classmethod - def teardown_class(cls): - SDL_Quit() - - def setup_method(self): - SDL_ClearError() - - def test_SDL_GameControllerAddMapping(self): - newmap = ( - b"030000005e0400002700000006010000,Microsoft SideWinder," - b"platform:Mac OS X,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1," - b"dpleft:-a0,dpright:+a0,lefttrigger:b4,righttrigger:b5" - ) - if sdl2.dll.version >= 2006: - n1 = gamepad.SDL_GameControllerNumMappings() - ret = gamepad.SDL_GameControllerAddMapping(newmap) - assert ret != -1 - n2 = gamepad.SDL_GameControllerNumMappings() - assert n2 == n1 + 1 - else: - # NumMappings not available before 2.0.6 - ret = gamepad.SDL_GameControllerAddMapping(newmap) - assert ret != -1 - - @pytest.mark.skipif(not has_mapping_for_guid, reason="not available") - def test_SDL_GameControllerMappingForGUID(self): - newmap = ( - b"030000005e0400002700000006010000,Microsoft SideWinder," - b"platform:Mac OS X,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1," - b"dpleft:-a0,dpright:+a0,lefttrigger:b4,righttrigger:b5" - ) +def test_SDL_GameControllerAddMapping(with_sdl): + newmap = ( + b"030000005e0400002700000006010000,Microsoft SideWinder," + b"platform:Mac OS X,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1," + b"dpleft:-a0,dpright:+a0,lefttrigger:b4,righttrigger:b5" + ) + if sdl2.dll.version >= 2006: + n1 = gamepad.SDL_GameControllerNumMappings() ret = gamepad.SDL_GameControllerAddMapping(newmap) - assert ret != 0 - # Get GUID for new mapping - guid_str = newmap.split(b",")[0] - guid = joystick.SDL_JoystickGetGUIDFromString(guid_str) - # Get mapping for GUID - retmap = gamepad.SDL_GameControllerMappingForGUID(guid) - assert retmap == newmap - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerMapping(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_IsGameController(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerNameForIndex(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_GameControllerTypeForIndex(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerOpen(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerName(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_GameControllerGetType(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerGetAttached(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerGetJoystick(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerEventState(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerUpdate(self): - pass - - def test_SDL_GameControllerGetAxisFromString(self): - expected = { - b'lefty': gamepad.SDL_CONTROLLER_AXIS_LEFTY, - b'lefttrigger': gamepad.SDL_CONTROLLER_AXIS_TRIGGERLEFT, - b'notanaxis': gamepad.SDL_CONTROLLER_AXIS_INVALID - } - for string in expected.keys(): - a = gamepad.SDL_GameControllerGetAxisFromString(string) - assert a == expected[string] - - def test_SDL_GameControllerGetStringForAxis(self): - expected = { - gamepad.SDL_CONTROLLER_AXIS_LEFTY: b'lefty', - gamepad.SDL_CONTROLLER_AXIS_TRIGGERLEFT: b'lefttrigger', - gamepad.SDL_CONTROLLER_AXIS_INVALID: None - } - for axis in expected.keys(): - s = gamepad.SDL_GameControllerGetStringForAxis(axis) - assert s == expected[axis] - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerGetBindForAxis(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerHasAxis(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerGetAxis(self): - pass - - def test_SDL_GameControllerGetButtonFromString(self): - expected = { - b'x': gamepad.SDL_CONTROLLER_BUTTON_X, - b'dpup': gamepad.SDL_CONTROLLER_BUTTON_DPAD_UP, - b'notabutton': gamepad.SDL_CONTROLLER_BUTTON_INVALID - } - for string in expected.keys(): - b = gamepad.SDL_GameControllerGetButtonFromString(string) - assert b == expected[string] - - def test_SDL_GameControllerGetStringForButton(self): - expected = { - gamepad.SDL_CONTROLLER_BUTTON_X: b'x', - gamepad.SDL_CONTROLLER_BUTTON_DPAD_UP: b'dpup', - gamepad.SDL_CONTROLLER_BUTTON_INVALID: None - } - for button in expected.keys(): - s = gamepad.SDL_GameControllerGetStringForButton(button) - assert s == expected[button] - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerGetBindForButton(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerHasButton(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerGetButton(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerGetNumTouchpads(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerGetNumTouchpadFingers(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerGetTouchpadFinger(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerHasSensor(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerSetSensorEnabled(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerIsSensorEnabled(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_GameControllerGetSensorDataRate(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerGetSensorData(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerClose(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerAddMappingsFromRW(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerAddMappingsFromFile(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GameControllerFromInstanceID(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_GameControllerFromPlayerIndex(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") - def test_SDL_GameControllerGetPlayerIndex(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_GameControllerSetPlayerIndex(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") - def test_SDL_GameControllerGetVendor(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") - def test_SDL_GameControllerGetProduct(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") - def test_SDL_GameControllerGetProductVersion(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerGetSerial(self): - pass - - @pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") - def test_SDL_GameControllerNumMappings(self): - num = gamepad.SDL_GameControllerNumMappings() - assert num > 0 - - @pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") - def test_SDL_GameControllerMappingForIndex(self): - newmap = ( - b"030000005e0400002700000006010000,Microsoft SideWinder," - b"platform:Mac OS X,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1," - b"dpleft:-a0,dpright:+a0,lefttrigger:b4,righttrigger:b5" - ) + assert ret >= 0 + n2 = gamepad.SDL_GameControllerNumMappings() + assert n2 == n1 + 1 + else: + # NumMappings not available before 2.0.6 ret = gamepad.SDL_GameControllerAddMapping(newmap) - assert ret != 0 - num = gamepad.SDL_GameControllerNumMappings() - retmap = gamepad.SDL_GameControllerMappingForIndex(num - 1) - assert newmap == retmap - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") - def test_SDL_GameControllerMappingForDeviceIndex(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") - def test_SDL_GameControllerRumble(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerRumbleTriggers(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_GameControllerHasSetLED(self): - pass - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_GameControllerHasRumble(self): - # If we ever add an interactive test suite, this should be moved there - for index in self.gamepad_ids: - pad = gamepad.SDL_GameControllerOpen(index) - has_rumble = gamepad.SDL_GameControllerHasRumble(pad) - assert has_rumble in [SDL_FALSE, SDL_TRUE] - joystick.SDL_JoystickClose(pad) - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_GameControllerHasRumbleTriggers(self): - # If we ever add an interactive test suite, this should be moved there - for index in self.gamepad_ids: + assert ret != -1 + +@pytest.mark.skipif(not has_mapping_for_guid, reason="not available") +def test_SDL_GameControllerMappingForGUID(with_sdl): + newmap = ( + b"030000005e0400002700000006010000,Microsoft SideWinder," + b"platform:Mac OS X,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1," + b"dpleft:-a0,dpright:+a0,lefttrigger:b4,righttrigger:b5" + ) + ret = gamepad.SDL_GameControllerAddMapping(newmap) + assert ret >= 0 + # Get GUID for new mapping + guid_str = newmap.split(b",")[0] + guid = joystick.SDL_JoystickGetGUIDFromString(guid_str) + # Get mapping for GUID + retmap = gamepad.SDL_GameControllerMappingForGUID(guid) + assert retmap == newmap + +def test_SDL_IsGameController(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + ret = gamepad.SDL_IsGameController(index) + assert sdl2.SDL_GetError() == b"" + assert ret in [SDL_TRUE, SDL_FALSE] + +def test_SDL_GameControllerNameForIndex(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + name = gamepad.SDL_GameControllerNameForIndex(index) + assert sdl2.SDL_GetError() == b"" + assert name == None or type(name) in (str, bytes) + +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_GameControllerTypeForIndex(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + padtype = gamepad.SDL_GameControllerTypeForIndex(index) + assert padtype in gamepad_types + +def test_SDL_GameControllerOpenClose(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + if gamepad.SDL_IsGameController(index) == SDL_TRUE: pad = gamepad.SDL_GameControllerOpen(index) - has_rumble_triggers = gamepad.SDL_GameControllerHasRumbleTriggers(pad) - assert has_rumble_triggers in [SDL_FALSE, SDL_TRUE] + assert sdl2.SDL_GetError() == b"" + assert isinstance(pad.contents, gamepad.SDL_GameController) gamepad.SDL_GameControllerClose(pad) - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_GameControllerSendEffect(self): - # Probably impossible to test since effect data would be specific - # to each controller type? - pass - - @pytest.mark.skip("Only relevant on iOS, not testable by PySDL2") - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_GameControllerGetAppleSFSymbolsNameForButtonAxis(self): - # The following two functions are deliberatly ignored: - # - SDL_GameControllerGetAppleSFSymbolsNameForButton - # - SDL_GameControllerGetAppleSFSymbolsNameForAxis - pass +def test_SDL_GameControllerMapping(gamepads): + for pad in gamepads: + mapping = gamepad.SDL_GameControllerMapping(pad) + assert SDL_GetError() == b"" + assert mapping == None or type(mapping) in (str, bytes) + +def test_SDL_GameControllerName(gamepads): + names = [] + for pad in gamepads: + name = gamepad.SDL_GameControllerName(pad) + assert type(name) in (str, bytes) + names.append(name.decode('utf-8')) + print(names) + +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_GameControllerGetType(gamepads): + for pad in gamepads: + padtype = gamepad.SDL_GameControllerGetType(pad) + assert SDL_GetError() == b"" + assert padtype in gamepad_types + if is_virtual(pad): + assert padtype == gamepad.SDL_CONTROLLER_TYPE_VIRTUAL + +def test_SDL_GameControllerGetAttached(gamepads): + for pad in gamepads: + ret = gamepad.SDL_GameControllerGetAttached(pad) + assert ret in [SDL_FALSE, SDL_TRUE] + +def test_SDL_GameControllerGetJoystick(gamepads): + for pad in gamepads: + stick = gamepad.SDL_GameControllerGetJoystick(pad) + assert SDL_GetError() == b"" + assert isinstance(stick.contents, joystick.SDL_Joystick) + +def test_SDL_GameControllerEventState(with_sdl): + for state in (SDL_IGNORE, SDL_ENABLE): + news = gamepad.SDL_GameControllerEventState(state) + assert news == state + query = gamepad.SDL_GameControllerEventState(SDL_QUERY) + assert query == state + +def test_SDL_GameControllerUpdate(with_sdl): + # NOTE: Returns void, can't really test anything else + gamepad.SDL_GameControllerUpdate() + assert SDL_GetError() == b"" + +def test_SDL_GameControllerGetAxisFromString(with_sdl): + expected = { + b'lefty': gamepad.SDL_CONTROLLER_AXIS_LEFTY, + b'lefttrigger': gamepad.SDL_CONTROLLER_AXIS_TRIGGERLEFT, + b'notanaxis': gamepad.SDL_CONTROLLER_AXIS_INVALID + } + for string in expected.keys(): + a = gamepad.SDL_GameControllerGetAxisFromString(string) + assert a == expected[string] + +def test_SDL_GameControllerGetStringForAxis(with_sdl): + expected = { + gamepad.SDL_CONTROLLER_AXIS_LEFTY: b'lefty', + gamepad.SDL_CONTROLLER_AXIS_TRIGGERLEFT: b'lefttrigger', + gamepad.SDL_CONTROLLER_AXIS_INVALID: None + } + for axis in expected.keys(): + s = gamepad.SDL_GameControllerGetStringForAxis(axis) + assert s == expected[axis] + +@pytest.mark.skip("not implemented") +def test_SDL_GameControllerGetBindForAxis(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerHasAxis(gamepads): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_GameControllerGetAxis(gamepads): + pass + +def test_SDL_GameControllerGetButtonFromString(with_sdl): + expected = { + b'x': gamepad.SDL_CONTROLLER_BUTTON_X, + b'dpup': gamepad.SDL_CONTROLLER_BUTTON_DPAD_UP, + b'notabutton': gamepad.SDL_CONTROLLER_BUTTON_INVALID + } + for string in expected.keys(): + b = gamepad.SDL_GameControllerGetButtonFromString(string) + assert b == expected[string] + +def test_SDL_GameControllerGetStringForButton(with_sdl): + expected = { + gamepad.SDL_CONTROLLER_BUTTON_X: b'x', + gamepad.SDL_CONTROLLER_BUTTON_DPAD_UP: b'dpup', + gamepad.SDL_CONTROLLER_BUTTON_INVALID: None + } + for button in expected.keys(): + s = gamepad.SDL_GameControllerGetStringForButton(button) + assert s == expected[button] + +@pytest.mark.skip("not implemented") +def test_SDL_GameControllerGetBindForButton(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerHasButton(gamepads): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_GameControllerGetButton(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerGetNumTouchpads(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerGetNumTouchpadFingers(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerGetTouchpadFinger(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerHasSensor(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerSetSensorEnabled(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerIsSensorEnabled(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_GameControllerGetSensorDataRate(gamepads): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerGetSensorData(gamepads): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_GameControllerAddMappingsFromRW(gamepads): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_GameControllerAddMappingsFromFile(gamepads): + pass + +def test_SDL_GameControllerFromInstanceID(gamepads): + for pad in gamepads: + stick = gamepad.SDL_GameControllerGetJoystick(pad) + iid = joystick.SDL_JoystickInstanceID(stick) + assert iid >= 0 + pad2 = gamepad.SDL_GameControllerFromInstanceID(iid) + name = gamepad.SDL_GameControllerName(pad) + assert gamepad.SDL_GameControllerName(pad2) == name + +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_GameControllerFromPlayerIndex(gamepads): + i = 0 + for pad in gamepads: + gamepad.SDL_GameControllerSetPlayerIndex(pad, i) + pad2 = gamepad.SDL_GameControllerFromPlayerIndex(i) + name = gamepad.SDL_GameControllerName(pad) + assert gamepad.SDL_GameControllerName(pad2) == name + i += 1 + +@pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") +def test_SDL_GameControllerGetPlayerIndex(gamepads): + for pad in gamepads: + player = gamepad.SDL_GameControllerGetPlayerIndex(pad) + assert player in [-1, 0, 1, 2, 3] + +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_GameControllerSetPlayerIndex(gamepads): + i = 0 + for pad in gamepads: + gamepad.SDL_GameControllerSetPlayerIndex(pad, i) + player = gamepad.SDL_GameControllerGetPlayerIndex(pad) + assert player == i + i += 1 + +@pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") +def test_SDL_GameControllerGetVendor(gamepads): + for pad in gamepads: + vid = gamepad.SDL_GameControllerGetVendor(pad) + assert SDL_GetError() == b"" + if not is_virtual(pad): + assert vid > 0 + +@pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") +def test_SDL_GameControllerGetProduct(gamepads): + for pad in gamepads: + pid = gamepad.SDL_GameControllerGetProduct(pad) + assert SDL_GetError() == b"" + if not is_virtual(pad): + assert pid > 0 + +@pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") +def test_SDL_GameControllerGetProductVersion(gamepads): + for pad in gamepads: + pver = gamepad.SDL_GameControllerGetProductVersion(pad) + assert SDL_GetError() == b"" + assert pver >= 0 + +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerGetSerial(gamepads): + for pad in gamepads: + serial = gamepad.SDL_GameControllerGetSerial(pad) + assert SDL_GetError() == b"" + assert serial == None or type(serial) in (str, bytes) + +@pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") +def test_SDL_GameControllerNumMappings(with_sdl): + num = gamepad.SDL_GameControllerNumMappings() + assert num > 0 + +@pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") +def test_SDL_GameControllerMappingForIndex(with_sdl): + newmap = ( + b"030000005e0400002700000006010000,Microsoft SideWinder," + b"platform:Mac OS X,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1," + b"dpleft:-a0,dpright:+a0,lefttrigger:b4,righttrigger:b5" + ) + ret = gamepad.SDL_GameControllerAddMapping(newmap) + assert ret >= 0 + num = gamepad.SDL_GameControllerNumMappings() + retmap = gamepad.SDL_GameControllerMappingForIndex(num - 1) + assert newmap == retmap + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") +def test_SDL_GameControllerMappingForDeviceIndex(with_sdl): + pass + +@pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") +def test_SDL_GameControllerRumble(gamepads): + # If we ever add an interactive test suite, this should be moved there + for pad in gamepads: + # 50% strength low-frequency, 25% high-frequency rumble for 500ms + ret = gamepad.SDL_GameControllerRumble(pad, 32767, 16384, 500) + assert ret in [-1, 0] + +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerRumbleTriggers(gamepads): + # If we ever add an interactive test suite, this should be moved there + for pad in gamepads: + # 50% strength left trigger, 25% right trigger rumble for 500ms + ret = gamepad.SDL_GameControllerRumbleTriggers(pad, 32767, 16384, 500) + assert ret in [-1, 0] + +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_GameControllerHasSetLED(gamepads): + # If we ever add an interactive test suite, this should be moved there + for pad in gamepads: + has_led = gamepad.SDL_GameControllerHasLED(pad) + assert has_led in [SDL_FALSE, SDL_TRUE] + expected = -1 if has_led == SDL_FALSE else 0 + cols = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] + for r, g, b in cols: + ret = gamepad.SDL_GameControllerSetLED(pad, r, g, b) + assert ret == expected + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_GameControllerHasRumble(gamepads): + # If we ever add an interactive test suite, this should be moved there + for pad in gamepads: + has_rumble = gamepad.SDL_GameControllerHasRumble(pad) + assert has_rumble in [SDL_FALSE, SDL_TRUE] + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_GameControllerHasRumbleTriggers(gamepads): + # If we ever add an interactive test suite, this should be moved there + for pad in gamepads: + has_rumble_triggers = gamepad.SDL_GameControllerHasRumbleTriggers(pad) + assert has_rumble_triggers in [SDL_FALSE, SDL_TRUE] + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_GameControllerSendEffect(gamepads): + # Probably impossible to test since effect data would be specific + # to each controller type? + pass + +@pytest.mark.skip("Only relevant on iOS, not testable by PySDL2") +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_GameControllerGetAppleSFSymbolsNameForButtonAxis(gamepads): + # The following two functions are deliberatly ignored: + # - SDL_GameControllerGetAppleSFSymbolsNameForButton + # - SDL_GameControllerGetAppleSFSymbolsNameForAxis + pass diff --git a/sdl2/test/hidapi_test.py b/sdl2/test/hidapi_test.py index a43b2a07..a82ea13a 100644 --- a/sdl2/test/hidapi_test.py +++ b/sdl2/test/hidapi_test.py @@ -20,6 +20,8 @@ def hidapi_setup(): assert ret == 0 +# NOTE: Remove this xfail once libudev is officially removed from pysdl2-dll +@pytest.mark.xfail("linux" in sys.platform, reason="udev problems") def test_SDL_hid_init_exit(): SDL_ClearError() # Initialize the library diff --git a/sdl2/test/hints_test.py b/sdl2/test/hints_test.py index 6a25c375..59308301 100644 --- a/sdl2/test/hints_test.py +++ b/sdl2/test/hints_test.py @@ -1,77 +1,74 @@ import sys import pytest from ctypes import cast, c_char_p -from sdl2 import SDL_Init, SDL_Quit, SDL_QuitSubSystem, SDL_INIT_EVERYTHING +import sdl2 from sdl2 import hints from sdl2.stdinc import SDL_TRUE, SDL_FALSE -class TestSDLHints(object): - __tags__ = ["sdl"] +# Need to override global fixture to init/quit on every test +@pytest.fixture +def with_sdl(): + sdl2.SDL_ClearError() + ret = sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + yield + sdl2.SDL_Quit() - def setup_method(self): - SDL_Init(SDL_INIT_EVERYTHING) - def teardown_method(self): - SDL_QuitSubSystem(SDL_INIT_EVERYTHING) - SDL_Quit() +def test_SDL_ClearHints(with_sdl): + assert hints.SDL_SetHint(b"TEST", b"32") == 1 + assert hints.SDL_GetHint(b"TEST") == b"32" + hints.SDL_ClearHints() + assert hints.SDL_GetHint(b"TEST") == None - def test_SDL_ClearHints(self): - assert hints.SDL_SetHint(b"TEST", b"32") == 1 - assert hints.SDL_GetHint(b"TEST") == b"32" - hints.SDL_ClearHints() - assert hints.SDL_GetHint(b"TEST") == None +def test_SDL_GetHint(with_sdl): + assert hints.SDL_SetHint(b"TEST", b"32") == 1 + assert hints.SDL_GetHint(b"TEST") == b"32" + assert hints.SDL_SetHint(hints.SDL_HINT_ALLOW_TOPMOST, b"true") == 1 + assert hints.SDL_GetHint(hints.SDL_HINT_ALLOW_TOPMOST) == b"true" - def test_SDL_GetHint(self): - assert hints.SDL_SetHint(b"TEST", b"32") == 1 - assert hints.SDL_GetHint(b"TEST") == b"32" - assert hints.SDL_SetHint(hints.SDL_HINT_ALLOW_TOPMOST, b"true") == 1 - assert hints.SDL_GetHint(hints.SDL_HINT_ALLOW_TOPMOST) == b"true" +def test_SDL_SetHint(with_sdl): + assert hints.SDL_SetHint(b"TEST", b"32") == 1 + assert hints.SDL_GetHint(b"TEST") == b"32" + assert hints.SDL_SetHint(b"TEST", b"abcdef") == 1 + assert hints.SDL_GetHint(b"TEST") == b"abcdef" + assert hints.SDL_SetHint(b"", b"hi") == 1 + assert hints.SDL_GetHint(b"") == b"hi" - def test_SDL_SetHint(self): - assert hints.SDL_SetHint(b"TEST", b"32") == 1 - assert hints.SDL_GetHint(b"TEST") == b"32" - assert hints.SDL_SetHint(b"TEST", b"abcdef") == 1 - assert hints.SDL_GetHint(b"TEST") == b"abcdef" - assert hints.SDL_SetHint(b"", b"hi") == 1 - assert hints.SDL_GetHint(b"") == b"hi" +def test_SDL_SetHintWithPriority(with_sdl): + tst_hints = [ + [hints.SDL_HINT_DEFAULT, b"abc", b"abc"], + [hints.SDL_HINT_NORMAL, b"ABC", b"ABC"], + [hints.SDL_HINT_OVERRIDE, b"123", b"123"], + [hints.SDL_HINT_NORMAL, b"xyz", b"123"], + ] + for priority, value, expected in tst_hints: + ret = hints.SDL_SetHintWithPriority(b"TEST", value, priority) + assert ret == (1 if value == expected else 0) + assert hints.SDL_GetHint(b"TEST") == expected - def test_SDL_SetHintWithPriority(self): - assert hints.SDL_SetHintWithPriority( - b"TEST", b"32", hints.SDL_HINT_DEFAULT) == 1 - assert hints.SDL_GetHint(b"TEST") == b"32" - assert hints.SDL_SetHintWithPriority( - b"TEST", b"abcdef", hints.SDL_HINT_NORMAL) == 1 - assert hints.SDL_GetHint(b"TEST") == b"abcdef" - assert hints.SDL_SetHintWithPriority( - b"", b"hi", hints.SDL_HINT_OVERRIDE) == 1 - assert hints.SDL_GetHint(b"") == b"hi" - assert hints.SDL_SetHintWithPriority( - b"", b"bye", hints.SDL_HINT_NORMAL) == 0 +def test_SDL_GetHintBoolean(with_sdl): + assert hints.SDL_SetHint(b"TEST", b"32") == 1 + assert hints.SDL_GetHintBoolean(b"TEST", SDL_TRUE) == SDL_TRUE + assert hints.SDL_GetHintBoolean(b"TEST", SDL_FALSE) == SDL_TRUE + assert hints.SDL_GetHintBoolean(b"TEST2", SDL_FALSE) != SDL_TRUE - def test_SDL_GetHintBoolean(self): - assert hints.SDL_SetHint(b"TEST", b"32") == 1 - assert hints.SDL_GetHintBoolean(b"TEST", SDL_TRUE) == SDL_TRUE - assert hints.SDL_GetHintBoolean(b"TEST", SDL_FALSE) == SDL_TRUE - assert hints.SDL_GetHintBoolean(b"TEST2", SDL_FALSE) != SDL_TRUE - - def test_SDL_AddDelHintCallback(self): - calls = [] - def callback(userdata, name, oldval, newval): - data = cast(userdata, c_char_p) - calls.append((data.value, name, oldval, newval)) - hintcb = hints.SDL_HintCallback(callback) - udata = c_char_p(b"banana") - hints.SDL_AddHintCallback(hints.SDL_HINT_ALLOW_TOPMOST, hintcb, - udata) - # SDL_AddHintCallback invokes the callback once. - assert len(calls) == 1 - assert calls[0] == (b"banana", hints.SDL_HINT_ALLOW_TOPMOST, - None, None) - hints.SDL_SetHint(hints.SDL_HINT_ALLOW_TOPMOST, b"true") - assert len(calls) == 2 - assert calls[1] == (b"banana", hints.SDL_HINT_ALLOW_TOPMOST, - None, b"true") - hints.SDL_DelHintCallback(hints.SDL_HINT_ALLOW_TOPMOST, hintcb, - udata) - hints.SDL_SetHint(hints.SDL_HINT_ALLOW_TOPMOST, b"false") - assert len(calls) == 2 +def test_SDL_AddDelHintCallback(with_sdl): + topmost_hint = hints.SDL_HINT_ALLOW_TOPMOST + calls = [] + def callback(userdata, name, oldval, newval): + data = cast(userdata, c_char_p) + calls.append((data.value, name, oldval, newval)) + hintcb = hints.SDL_HintCallback(callback) + udata = c_char_p(b"banana") + hints.SDL_AddHintCallback(topmost_hint, hintcb, udata) + # SDL_AddHintCallback invokes the callback once. + assert len(calls) == 1 + assert calls[0] == (b"banana", topmost_hint, None, None) + hints.SDL_SetHint(topmost_hint, b"true") + assert len(calls) == 2 + assert calls[1] == (b"banana", topmost_hint, None, b"true") + hints.SDL_DelHintCallback(topmost_hint, hintcb, udata) + hints.SDL_SetHint(topmost_hint, b"false") + assert len(calls) == 2 diff --git a/sdl2/test/joystick_test.py b/sdl2/test/joystick_test.py index 746b17be..bcb3e3c9 100644 --- a/sdl2/test/joystick_test.py +++ b/sdl2/test/joystick_test.py @@ -1,6 +1,6 @@ import sys import pytest -from ctypes import create_string_buffer, byref, c_int +from ctypes import create_string_buffer, byref, c_int, c_int16 import sdl2 from sdl2 import SDL_Init, SDL_Quit, SDL_INIT_JOYSTICK from sdl2.events import SDL_QUERY, SDL_ENABLE, SDL_IGNORE @@ -8,8 +8,75 @@ from sdl2.error import SDL_GetError, SDL_ClearError from sdl2 import joystick +# Get status of joystick support/availability before running tests +any_joysticks = False +SDL_ClearError() +ret = SDL_Init(SDL_INIT_JOYSTICK) +joystick_works = ret == 0 and SDL_GetError() == b"" +if joystick_works: + devices = joystick.SDL_NumJoysticks() + if sdl2.dll.version >= 2014: + # On 2.0.14 and above, we can test with a virtual joystick + devices += 1 + any_joysticks = devices > 0 +SDL_Quit() + +pytestmark = pytest.mark.skipif(not joystick_works, reason="system unsupported") + +joystick_types = [ + joystick.SDL_JOYSTICK_TYPE_UNKNOWN, + joystick.SDL_JOYSTICK_TYPE_GAMECONTROLLER, + joystick.SDL_JOYSTICK_TYPE_WHEEL, + joystick.SDL_JOYSTICK_TYPE_ARCADE_STICK, + joystick.SDL_JOYSTICK_TYPE_FLIGHT_STICK, + joystick.SDL_JOYSTICK_TYPE_DANCE_PAD, + joystick.SDL_JOYSTICK_TYPE_GUITAR, + joystick.SDL_JOYSTICK_TYPE_DRUM_KIT, + joystick.SDL_JOYSTICK_TYPE_ARCADE_PAD, + joystick.SDL_JOYSTICK_TYPE_THROTTLE, +] + + +# Overrides global fixture with one that initializes the joystick system +@pytest.fixture(scope="module") +def with_sdl(): + sdl2.SDL_ClearError() + sdl2.SDL_SetHint(b"SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", b"1") + ret = sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO | sdl2.SDL_INIT_JOYSTICK) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + # Also initialize a virtual joystick (if supported) + if sdl2.dll.version >= 2014: + virt_type = joystick.SDL_JOYSTICK_TYPE_GAMECONTROLLER + virt_index = joystick.SDL_JoystickAttachVirtual(virt_type, 2, 4, 1) + yield + sdl2.SDL_Quit() + +@pytest.fixture() +def joysticks(with_sdl): + devices = [] + count = joystick.SDL_NumJoysticks() + for i in range(count): + stick = joystick.SDL_JoystickOpen(i) + assert sdl2.SDL_GetError() == b"" + assert isinstance(stick.contents, joystick.SDL_Joystick) + devices.append(stick) + yield devices + for stick in devices: + joystick.SDL_JoystickClose(stick) + +def is_virtual(stick): + virtual = False + if isinstance(stick, int): + if sdl2.dll.version >= 2014: + virtual = joystick.SDL_JoystickIsVirtual(stick) == SDL_TRUE + elif isinstance(stick.contents, joystick.SDL_Joystick): + name = joystick.SDL_JoystickName(stick) + virtual = name == b"Virtual Joystick" + return virtual + -# TODO: merge all info functions into one, print results +# TODO: Make one of the tests gather/print out current joystick info def test_SDL_JoystickGetGUIDFromString(): guid_str = b'030000007e050000060300001c3a0000' # Wiimote on macOS @@ -24,11 +91,6 @@ def test_SDL_JoystickGetGUIDString(): joystick.SDL_JoystickGetGUIDString(guid, buff, 33) # Get GUID string assert guid_str == buff.value -def test_SDL_InitJoystick(): - ret = SDL_Init(SDL_INIT_JOYSTICK) - SDL_Quit() - assert ret == 0 - def test_SDL_NumJoysticks(): if SDL_Init(SDL_INIT_JOYSTICK) != 0: pytest.skip("joystick subsystem not supported") @@ -36,352 +98,354 @@ def test_SDL_NumJoysticks(): SDL_Quit() assert retval >= 0 +def test_SDL_JoystickNameForIndex(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + name = joystick.SDL_JoystickNameForIndex(index) + assert type(name) in (str, bytes) -skipmsg = "joystick subsystem not supported" -@pytest.mark.skipif(SDL_Init(SDL_INIT_JOYSTICK) != 0, reason=skipmsg) -class TestSDLJoystick(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - SDL_Init(SDL_INIT_JOYSTICK) - num = joystick.SDL_NumJoysticks() - if num < 1: - pytest.skip("no available joystick devices") - cls.jcount = num - - @classmethod - def teardown_class(cls): - SDL_Quit() - - def setup_method(self): - SDL_ClearError() - - def test_SDL_JoystickNameForIndex(self): - for index in range(self.jcount): - name = joystick.SDL_JoystickNameForIndex(index) - assert type(name) in (str, bytes) - - def test_SDL_JoystickOpenClose(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - assert isinstance(stick.contents, joystick.SDL_Joystick) - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickName(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - name = joystick.SDL_JoystickName(stick) - assert type(name) in (str, bytes) - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickGetDeviceGUID(self): - for index in range(self.jcount): - guid = joystick.SDL_JoystickGetDeviceGUID(index) - assert isinstance(guid, joystick.SDL_JoystickGUID) - guidlist = list(guid.data) - assert isinstance(guidlist[0], int) - - def test_SDL_JoystickGetGUID(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - guid = joystick.SDL_JoystickGetGUID(stick) - assert isinstance(guid, joystick.SDL_JoystickGUID) - guidlist = list(guid.data) - assert isinstance(guidlist[0], int) - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickGetAttached(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - ret = joystick.SDL_JoystickGetAttached(stick) - assert ret in [SDL_FALSE, SDL_TRUE] - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickInstanceID(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - ret = joystick.SDL_JoystickInstanceID(stick) - assert ret > 0 - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickNumAxes(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - assert isinstance(stick.contents, joystick.SDL_Joystick) - axes = joystick.SDL_JoystickNumAxes(stick) - assert axes >= 0 - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickNumBalls(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - assert isinstance(stick.contents, joystick.SDL_Joystick) - balls = joystick.SDL_JoystickNumBalls(stick) - assert balls >= 0 - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickNumHats(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - assert isinstance(stick.contents, joystick.SDL_Joystick) - hats = joystick.SDL_JoystickNumHats(stick) - assert hats >= 0 - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickNumButtons(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - assert isinstance(stick.contents, joystick.SDL_Joystick) - buttons = joystick.SDL_JoystickNumButtons(stick) - assert buttons >= 0 - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickUpdate(self): - # returns void, not sure what else to test here - joystick.SDL_JoystickUpdate() - - def test_SDL_JoystickEventState(self): - for state in (SDL_IGNORE, SDL_ENABLE): - news = joystick.SDL_JoystickEventState(state) - assert news == state - query = joystick.SDL_JoystickEventState(SDL_QUERY) - assert query == state - - def test_SDL_JoystickGetAxis(self): - sticks = [joystick.SDL_JoystickOpen(i) for i in range(self.jcount)] - numaxes = [joystick.SDL_JoystickNumAxes(s) for s in sticks] - if not any(numaxes): - pytest.skip("no axis on any connected controller") - for stick in sticks: - for axis in range(joystick.SDL_JoystickNumAxes(stick)): - val = joystick.SDL_JoystickGetAxis(stick, axis) - assert -32768 <= val <= 32767 - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickGetBall(self): - sticks = [joystick.SDL_JoystickOpen(i) for i in range(self.jcount)] - numball = [joystick.SDL_JoystickNumBalls(s) for s in sticks] - if not any(numball): - pytest.skip("no trackball on any connected controller") - dx, dy = c_int(0), c_int(0) - get_ball = joystick.SDL_JoystickGetBall - for stick in sticks: - for ball in range(joystick.SDL_JoystickNumBalls(stick)): - ret = get_ball(stick, ball, byref(dx), byref(dy)) - err = SDL_GetError() - assert ret == 0 - assert len(err) == 0 - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickGetHat(self): - hatvals = [ - joystick.SDL_HAT_UP, joystick.SDL_HAT_DOWN, joystick.SDL_HAT_LEFT, - joystick.SDL_HAT_RIGHT, joystick.SDL_HAT_CENTERED, - joystick.SDL_HAT_LEFTUP, joystick.SDL_HAT_LEFTDOWN, - joystick.SDL_HAT_RIGHTUP, joystick.SDL_HAT_RIGHTDOWN - ] - sticks = [joystick.SDL_JoystickOpen(i) for i in range(self.jcount)] - numhats = [joystick.SDL_JoystickNumHats(s) for s in sticks] - if not any(numhats): - pytest.skip("no POV hat on any connected controller") - for stick in sticks: - for hat in range(joystick.SDL_JoystickNumHats(stick)): - val = joystick.SDL_JoystickGetHat(stick, hat) - assert val in hatvals - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickGetButton(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - for button in range(joystick.SDL_JoystickNumButtons(stick)): - val = joystick.SDL_JoystickGetButton(stick, button) - assert val in [0, 1] - joystick.SDL_JoystickClose(stick) - - def test_SDL_JoystickCurrentPowerLevel(self): - levels = [ - joystick.SDL_JOYSTICK_POWER_UNKNOWN, - joystick.SDL_JOYSTICK_POWER_EMPTY, - joystick.SDL_JOYSTICK_POWER_LOW, - joystick.SDL_JOYSTICK_POWER_MEDIUM, - joystick.SDL_JOYSTICK_POWER_FULL, - joystick.SDL_JOYSTICK_POWER_WIRED, - joystick.SDL_JOYSTICK_POWER_MAX, - ] - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - pwr = joystick.SDL_JoystickCurrentPowerLevel(stick) - err = SDL_GetError() - assert pwr in levels - assert len(err) == 0 - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickFromInstanceID(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_JoystickFromPlayerIndex(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetVendor(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetProduct(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetProductVersion(self): - pass - - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_JoystickGetSerial(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - serial = joystick.SDL_JoystickGetSerial(stick) - assert type(serial) in (str, bytes) - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetAxisInitialState(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetType(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetDeviceVendor(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetDeviceProduct(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetDeviceProductVersion(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_JoystickGetDeviceType(self): - pass - - @pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") - def test_SDL_JoystickGetDeviceInstanceID(self): - for index in range(self.jcount): - ret = joystick.SDL_JoystickGetDeviceInstanceID(index) - assert ret > 0 - - @pytest.mark.skipif(sdl2.dll.version < 2007, reason="not available") - def test_SDL_LockUnlockJoysticks(self): - # NOTE: not sure how better to test these, since I don't know if - # they'd even be useful at all in Python given the GIL - joystick.SDL_LockJoysticks() - joystick.SDL_UnlockJoysticks() - - @pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") - def test_SDL_JoystickGetPlayerIndex(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - player = joystick.SDL_JoystickGetPlayerIndex(stick) - assert player in [-1, 0, 1, 2, 3] - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_JoystickSetPlayerIndex(self): - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - joystick.SDL_JoystickSetPlayerIndex(stick, index) - player = joystick.SDL_JoystickGetPlayerIndex(stick) - assert player == index - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") - def test_SDL_JoystickGetDevicePlayerIndex(self): - for index in range(self.jcount): - player = joystick.SDL_JoystickGetDevicePlayerIndex(index) - assert player in [-1, 0, 1, 2, 3] - - @pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") - def test_SDL_JoystickRumble(self): - # If we ever add an interactive test suite, this should be moved there - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - # 50% strength low-frequency, 25% high-frequency rumble for 500ms - ret = joystick.SDL_JoystickRumble(stick, 32767, 16384, 500) - assert ret in [-1, 0] - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_JoystickRumbleTriggers(self): - # If we ever add an interactive test suite, this should be moved there - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - # 50% strength left trigger, 25% right trigger rumble for 500ms - ret = joystick.SDL_JoystickRumbleTriggers(stick, 32767, 16384, 500) - assert ret in [-1, 0] - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_JoystickHasSetLED(self): - # If we ever add an interactive test suite, this should be moved there - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - has_led = joystick.SDL_JoystickHasLED(stick) - assert has_led in [SDL_FALSE, SDL_TRUE] - expected = -1 if has_led == SDL_FALSE else 0 - cols = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] - for r, g, b in cols: - ret = joystick.SDL_JoystickSetLED(stick, r, g, b) - assert ret == expected - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_JoystickHasRumble(self): - # If we ever add an interactive test suite, this should be moved there - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - has_rumble = joystick.SDL_JoystickHasRumble(stick) - assert has_rumble in [SDL_FALSE, SDL_TRUE] - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_JoystickHasRumbleTriggers(self): - # If we ever add an interactive test suite, this should be moved there - for index in range(self.jcount): - stick = joystick.SDL_JoystickOpen(index) - has_rumble_triggers = joystick.SDL_JoystickHasRumbleTriggers(stick) - assert has_rumble_triggers in [SDL_FALSE, SDL_TRUE] - joystick.SDL_JoystickClose(stick) - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_JoystickSendEffect(self): - # Probably impossible to test since effect data would be specific - # to each controller type? - pass - - @pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") - def test_SDL_JoystickVirtual(self): - jtype = joystick.SDL_JOYSTICK_TYPE_GAMECONTROLLER - index = joystick.SDL_JoystickAttachVirtual(jtype, 1, 2, 1) - assert index > 0 - assert joystick.SDL_JoystickIsVirtual(index) == SDL_TRUE +def test_SDL_JoystickOpenClose(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): stick = joystick.SDL_JoystickOpen(index) - assert joystick.SDL_JoystickSetVirtualAxis(stick, 0, -30) == 0 - assert joystick.SDL_JoystickSetVirtualButton(stick, 0, 255) == 0 - assert joystick.SDL_JoystickSetVirtualButton(stick, 1, 128) == 0 - assert joystick.SDL_JoystickSetVirtualHat(stick, 0, 36) == 0 - joystick.SDL_JoystickUpdate() - assert joystick.SDL_JoystickGetAxis(stick, 0) == -30 - assert joystick.SDL_JoystickGetButton(stick, 0) == 255 - assert joystick.SDL_JoystickGetButton(stick, 1) == 128 - assert joystick.SDL_JoystickGetHat(stick, 0) == 36 + assert isinstance(stick.contents, joystick.SDL_Joystick) joystick.SDL_JoystickClose(stick) - jcount = joystick.SDL_NumJoysticks() - assert joystick.SDL_JoystickDetachVirtual(index) == 0 - assert joystick.SDL_NumJoysticks() == (jcount - 1) + +def test_SDL_JoystickName(joysticks): + names = [] + for stick in joysticks: + name = joystick.SDL_JoystickName(stick) + assert type(name) in (str, bytes) + names.append(name.decode('utf-8')) + print(names) + +def test_SDL_JoystickGetDeviceGUID(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + guid = joystick.SDL_JoystickGetDeviceGUID(index) + assert isinstance(guid, joystick.SDL_JoystickGUID) + guidlist = list(guid.data) + assert isinstance(guidlist[0], int) + +def test_SDL_JoystickGetGUID(joysticks): + for stick in joysticks: + guid = joystick.SDL_JoystickGetGUID(stick) + assert isinstance(guid, joystick.SDL_JoystickGUID) + guidlist = list(guid.data) + assert isinstance(guidlist[0], int) + +def test_SDL_JoystickGetAttached(joysticks): + for stick in joysticks: + ret = joystick.SDL_JoystickGetAttached(stick) + assert ret in [SDL_FALSE, SDL_TRUE] + +def test_SDL_JoystickInstanceID(joysticks): + for stick in joysticks: + ret = joystick.SDL_JoystickInstanceID(stick) + assert ret >= 0 + +def test_SDL_JoystickNumAxes(joysticks): + for stick in joysticks: + assert isinstance(stick.contents, joystick.SDL_Joystick) + axes = joystick.SDL_JoystickNumAxes(stick) + assert axes >= 0 + if is_virtual(stick): + assert axes == 2 + +def test_SDL_JoystickNumBalls(joysticks): + for stick in joysticks: + assert isinstance(stick.contents, joystick.SDL_Joystick) + balls = joystick.SDL_JoystickNumBalls(stick) + assert balls >= 0 + +def test_SDL_JoystickNumHats(joysticks): + for stick in joysticks: + assert isinstance(stick.contents, joystick.SDL_Joystick) + hats = joystick.SDL_JoystickNumHats(stick) + assert hats >= 0 + if is_virtual(stick): + assert hats == 1 + +def test_SDL_JoystickNumButtons(joysticks): + for stick in joysticks: + assert isinstance(stick.contents, joystick.SDL_Joystick) + buttons = joystick.SDL_JoystickNumButtons(stick) + assert buttons >= 0 + if is_virtual(stick): + assert buttons == 4 + +def test_SDL_JoystickUpdate(with_sdl): + # NOTE: Returns void, can't really test anything else + joystick.SDL_JoystickUpdate() + assert SDL_GetError() == b"" + +def test_SDL_JoystickEventState(with_sdl): + for state in (SDL_IGNORE, SDL_ENABLE): + news = joystick.SDL_JoystickEventState(state) + assert news == state + query = joystick.SDL_JoystickEventState(SDL_QUERY) + assert query == state + +def test_SDL_JoystickGetAxis(joysticks): + for stick in joysticks: + for axis in range(joystick.SDL_JoystickNumAxes(stick)): + val = joystick.SDL_JoystickGetAxis(stick, axis) + assert -32768 <= val <= 32767 + +def test_SDL_JoystickGetBall(joysticks): + numball = [joystick.SDL_JoystickNumBalls(s) for s in joysticks] + if not any(numball): + pytest.skip("no trackball on any connected controller") + dx, dy = c_int(0), c_int(0) + get_ball = joystick.SDL_JoystickGetBall + for stick in sticks: + for ball in range(joystick.SDL_JoystickNumBalls(stick)): + ret = get_ball(stick, ball, byref(dx), byref(dy)) + assert SDL_GetError() == b"" + assert ret == 0 + +def test_SDL_JoystickGetHat(joysticks): + hatvals = [ + joystick.SDL_HAT_UP, joystick.SDL_HAT_DOWN, joystick.SDL_HAT_LEFT, + joystick.SDL_HAT_RIGHT, joystick.SDL_HAT_CENTERED, + joystick.SDL_HAT_LEFTUP, joystick.SDL_HAT_LEFTDOWN, + joystick.SDL_HAT_RIGHTUP, joystick.SDL_HAT_RIGHTDOWN + ] + for stick in joysticks: + for hat in range(joystick.SDL_JoystickNumHats(stick)): + val = joystick.SDL_JoystickGetHat(stick, hat) + assert val in hatvals + +def test_SDL_JoystickGetButton(joysticks): + for stick in joysticks: + for button in range(joystick.SDL_JoystickNumButtons(stick)): + val = joystick.SDL_JoystickGetButton(stick, button) + assert val in [0, 1] + +def test_SDL_JoystickCurrentPowerLevel(joysticks): + levels = [ + joystick.SDL_JOYSTICK_POWER_UNKNOWN, + joystick.SDL_JOYSTICK_POWER_EMPTY, + joystick.SDL_JOYSTICK_POWER_LOW, + joystick.SDL_JOYSTICK_POWER_MEDIUM, + joystick.SDL_JOYSTICK_POWER_FULL, + joystick.SDL_JOYSTICK_POWER_WIRED, + joystick.SDL_JOYSTICK_POWER_MAX, + ] + for stick in joysticks: + pwr = joystick.SDL_JoystickCurrentPowerLevel(stick) + assert SDL_GetError() == b"" + assert pwr in levels + +def test_SDL_JoystickFromInstanceID(joysticks): + for stick in joysticks: + iid = joystick.SDL_JoystickInstanceID(stick) + assert iid >= 0 + stick2 = joystick.SDL_JoystickFromInstanceID(iid) + name = joystick.SDL_JoystickName(stick) + assert joystick.SDL_JoystickName(stick2) == name + +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_JoystickFromPlayerIndex(joysticks): + i = 0 + for stick in joysticks: + joystick.SDL_JoystickSetPlayerIndex(stick, i) + stick2 = joystick.SDL_JoystickFromPlayerIndex(i) + name = joystick.SDL_JoystickName(stick) + assert joystick.SDL_JoystickName(stick2) == name + i += 1 + +def test_SDL_JoystickGetVendor(joysticks): + for stick in joysticks: + vid = joystick.SDL_JoystickGetVendor(stick) + assert SDL_GetError() == b"" + if not is_virtual(stick): + assert vid > 0 + +def test_SDL_JoystickGetProduct(joysticks): + for stick in joysticks: + pid = joystick.SDL_JoystickGetProduct(stick) + assert SDL_GetError() == b"" + if not is_virtual(stick): + assert pid > 0 + +def test_SDL_JoystickGetProductVersion(joysticks): + for stick in joysticks: + pver = joystick.SDL_JoystickGetProductVersion(stick) + assert SDL_GetError() == b"" + assert pver >= 0 + +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_JoystickGetSerial(joysticks): + for stick in joysticks: + serial = joystick.SDL_JoystickGetSerial(stick) + assert SDL_GetError() == b"" + assert serial == None or type(serial) in (str, bytes) + +def test_SDL_JoystickGetAxisInitialState(joysticks): + init_state = c_int16(0) + for stick in joysticks: + for axis in range(joystick.SDL_JoystickNumAxes(stick)): + ret = joystick.SDL_JoystickGetAxisInitialState( + stick, axis, byref(init_state) + ) + assert SDL_GetError() == b"" + assert -32768 <= init_state.value <= 32767 + assert ret in [SDL_TRUE, SDL_FALSE] + +def test_SDL_JoystickGetType(joysticks): + for stick in joysticks: + jtype = joystick.SDL_JoystickGetType(stick) + assert SDL_GetError() == b"" + assert jtype in joystick_types + if is_virtual(stick): + assert jtype == joystick.SDL_JOYSTICK_TYPE_GAMECONTROLLER + +def test_SDL_JoystickGetDeviceVendor(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + vid = joystick.SDL_JoystickGetDeviceVendor(index) + assert SDL_GetError() == b"" + if not is_virtual(index): + assert vid > 0 + +def test_SDL_JoystickGetDeviceProduct(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + pid = joystick.SDL_JoystickGetDeviceProduct(index) + assert SDL_GetError() == b"" + if not is_virtual(index): + assert pid > 0 + +def test_SDL_JoystickGetDeviceProductVersion(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + pver = joystick.SDL_JoystickGetDeviceProductVersion(index) + assert SDL_GetError() == b"" + assert pver >= 0 + +def test_SDL_JoystickGetDeviceType(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + jtype = joystick.SDL_JoystickGetDeviceType(index) + assert SDL_GetError() == b"" + assert jtype in joystick_types + if is_virtual(index): + assert jtype == joystick.SDL_JOYSTICK_TYPE_GAMECONTROLLER + +@pytest.mark.skipif(sdl2.dll.version < 2006, reason="not available") +def test_SDL_JoystickGetDeviceInstanceID(joysticks): + for index in range(len(joysticks)): + iid = joystick.SDL_JoystickGetDeviceInstanceID(index) + assert SDL_GetError() == b"" + stick = joysticks[index] + assert iid == joystick.SDL_JoystickInstanceID(stick) + +@pytest.mark.skipif(sdl2.dll.version < 2007, reason="not available") +def test_SDL_LockUnlockJoysticks(with_sdl): + # NOTE: Not sure how to test these more comprehensively + joystick.SDL_LockJoysticks() + joystick.SDL_UnlockJoysticks() + +@pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") +def test_SDL_JoystickGetPlayerIndex(joysticks): + for stick in joysticks: + player = joystick.SDL_JoystickGetPlayerIndex(stick) + assert player in [-1, 0, 1, 2, 3] + +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_JoystickSetPlayerIndex(joysticks): + i = 0 + for stick in joysticks: + joystick.SDL_JoystickSetPlayerIndex(stick, i) + player = joystick.SDL_JoystickGetPlayerIndex(stick) + assert player == i + i += 1 + +@pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") +def test_SDL_JoystickGetDevicePlayerIndex(with_sdl): + count = joystick.SDL_NumJoysticks() + for index in range(count): + player = joystick.SDL_JoystickGetDevicePlayerIndex(index) + assert player in [-1, 0, 1, 2, 3] + +@pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") +def test_SDL_JoystickRumble(joysticks): + # If we ever add an interactive test suite, this should be moved there + for stick in joysticks: + # 50% strength low-frequency, 25% high-frequency rumble for 500ms + ret = joystick.SDL_JoystickRumble(stick, 32767, 16384, 500) + assert ret in [-1, 0] + +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_JoystickRumbleTriggers(joysticks): + # If we ever add an interactive test suite, this should be moved there + for stick in joysticks: + # 50% strength left trigger, 25% right trigger rumble for 500ms + ret = joystick.SDL_JoystickRumbleTriggers(stick, 32767, 16384, 500) + assert ret in [-1, 0] + +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_JoystickHasSetLED(joysticks): + # If we ever add an interactive test suite, this should be moved there + for stick in joysticks: + has_led = joystick.SDL_JoystickHasLED(stick) + assert has_led in [SDL_FALSE, SDL_TRUE] + expected = -1 if has_led == SDL_FALSE else 0 + cols = [(255, 0, 0), (0, 255, 0), (0, 0, 255)] + for r, g, b in cols: + ret = joystick.SDL_JoystickSetLED(stick, r, g, b) + assert ret == expected + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_JoystickHasRumble(joysticks): + # If we ever add an interactive test suite, this should be moved there + for stick in joysticks: + has_rumble = joystick.SDL_JoystickHasRumble(stick) + assert has_rumble in [SDL_FALSE, SDL_TRUE] + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_JoystickHasRumbleTriggers(joysticks): + # If we ever add an interactive test suite, this should be moved there + for stick in joysticks: + has_rumble_triggers = joystick.SDL_JoystickHasRumbleTriggers(stick) + assert has_rumble_triggers in [SDL_FALSE, SDL_TRUE] + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_JoystickSendEffect(joysticks): + # NOTE: Not supported on macOS or Linux, and effect data would be specific + # to each controller type, so can't easily test this. + pass + +@pytest.mark.skipif(sdl2.dll.version < 2014, reason="not available") +def test_SDL_JoystickVirtual(with_sdl): + jcount = joystick.SDL_NumJoysticks() + jtype = joystick.SDL_JOYSTICK_TYPE_GAMECONTROLLER + index = joystick.SDL_JoystickAttachVirtual(jtype, 1, 2, 1) + assert index >= 0 + assert joystick.SDL_JoystickIsVirtual(index) == SDL_TRUE + assert joystick.SDL_NumJoysticks() == (jcount + 1) + stick = joystick.SDL_JoystickOpen(index) + # Test joystick configuration + assert joystick.SDL_JoystickNumAxes(stick) == 1 + assert joystick.SDL_JoystickNumButtons(stick) == 2 + assert joystick.SDL_JoystickNumHats(stick) == 1 + # Try setting and checking for some virtual values + assert joystick.SDL_JoystickSetVirtualAxis(stick, 0, -30) == 0 + assert joystick.SDL_JoystickSetVirtualButton(stick, 0, 255) == 0 + assert joystick.SDL_JoystickSetVirtualButton(stick, 1, 128) == 0 + assert joystick.SDL_JoystickSetVirtualHat(stick, 0, 36) == 0 + joystick.SDL_JoystickUpdate() + # NOTE: SDL2 doesn't update joystick values unless it has a window that + # has input focus. There's a hint to disable that but it doesn't seem to + # work, so for now these tests are disabled. + #assert joystick.SDL_JoystickGetAxis(stick, 0) == -30 + #assert joystick.SDL_JoystickGetButton(stick, 0) == 255 + #assert joystick.SDL_JoystickGetButton(stick, 1) == 128 + #assert joystick.SDL_JoystickGetHat(stick, 0) == 36 + # Check that removing the virtual joystick works properly + joystick.SDL_JoystickClose(stick) + jcount = joystick.SDL_NumJoysticks() + assert joystick.SDL_JoystickDetachVirtual(index) == 0 + assert joystick.SDL_NumJoysticks() == (jcount - 1) diff --git a/sdl2/test/keyboard_test.py b/sdl2/test/keyboard_test.py index 772e9d06..11bd8222 100644 --- a/sdl2/test/keyboard_test.py +++ b/sdl2/test/keyboard_test.py @@ -1,176 +1,165 @@ import sys import pytest -from ctypes import c_int, cast, POINTER -from sdl2 import SDL_Init, SDL_Quit, SDL_QuitSubSystem, SDL_INIT_VIDEO +from ctypes import c_int, cast, byref, POINTER +from sdl2 import SDL_TRUE, SDL_FALSE, SDL_GetError from sdl2 import rect, keyboard, scancode, keycode, video byteify = lambda x: x.encode("utf-8") - -class TestSDLKeyboard(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - if SDL_Init(SDL_INIT_VIDEO) != 0: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - SDL_QuitSubSystem(SDL_INIT_VIDEO) - SDL_Quit() - - def test_SDL_Keysym(self): - keysym = keyboard.SDL_Keysym() - assert keysym.scancode == 0 - assert keysym.sym == 0 - assert keysym.mod == 0 - - keysym = keyboard.SDL_Keysym(1, 2, 3, ord("b")) - assert keysym.scancode == 1 - assert keysym.sym == 2 - assert keysym.mod == 3 - - uval = "\u0220" - if sys.version_info[0] < 3: - uval = unichr(8224) - keysym = keyboard.SDL_Keysym(17, 32, 88, ord(uval)) - assert keysym.scancode == 17 - assert keysym.sym == 32 - assert keysym.mod == 88 - - @pytest.mark.skipif(sys.platform == "darwin", reason="crashes on OS X") - def test_SDL_GetKeyboardFocus(self): - # window = keyboard.SDL_GetKeyboardFocus() - # TODO: x - # self.assertEqual(window, None) - rwin = video.SDL_CreateWindow(b"test", 10, 10, 10, 10, 0) - window = keyboard.SDL_GetKeyboardFocus() - if window: - assert video.SDL_GetWindowID(window) == video.SDL_GetWindowID(rwin) - video.SDL_DestroyWindow(rwin) - - window = keyboard.SDL_GetKeyboardFocus() - # TODO: x - # self.assertEqual(window, None) - - def test_SDL_GetKeyboardState(self): - states = (c_int * scancode.SDL_NUM_SCANCODES)() - keyboard.SDL_GetKeyboardState(cast(states, POINTER(c_int))) - assert len(states) == scancode.SDL_NUM_SCANCODES - # TODO: x - # for state in states: - # self.assertEqual(state, 0) - - def test_SDL_GetKeyFromName(self): - for x in range(26): # a-z - key = keyboard.SDL_GetKeyFromName(byteify(chr(x + 97))) - assert key == x + 97 - - for x in range(10): - key = keyboard.SDL_GetKeyFromName(("%d" % x).encode("utf-8")) - assert key == 48 + x - - val = keyboard.SDL_GetKeyFromName(byteify(repr(self))) - assert val == keycode.SDLK_UNKNOWN - - def test_SDL_GetKeyFromScancode(self): - p = 0 - for x in (scancode.SDL_SCANCODE_A, - scancode.SDL_SCANCODE_B, - scancode.SDL_SCANCODE_C): - key = keyboard.SDL_GetKeyFromScancode(x) - assert key == p + 97 - p += 1 - - p = 0 - for x in range(scancode.SDL_SCANCODE_1, scancode.SDL_SCANCODE_0): - key = keyboard.SDL_GetKeyFromScancode(x) - assert key == 49 + p - p += 1 - - def test_SDL_GetKeyName(self): - x = 65 # SDL maps everything against upper-case letters - for key in range(ord('a'), ord('z')): - ch = chr(x) - name = keyboard.SDL_GetKeyName(key) - assert name == byteify(ch) - x += 1 - - def test_SDL_GetSetModState(self): - initial = keyboard.SDL_GetModState() - for state in(keycode.KMOD_NUM | keycode.KMOD_CAPS | keycode.KMOD_MODE, - keycode.KMOD_NUM | keycode.KMOD_CAPS, - keycode.KMOD_CAPS): - keyboard.SDL_SetModState(state) - assert keyboard.SDL_GetModState() == state - - state = keycode.KMOD_NUM +@pytest.fixture +def window(with_sdl): + flag = video.SDL_WINDOW_INPUT_FOCUS + w = video.SDL_CreateWindow(b"Test", 10, 40, 32, 24, flag) + assert SDL_GetError() == b"" + assert isinstance(w.contents, video.SDL_Window) + yield w + video.SDL_DestroyWindow(w) + + +def test_SDL_Keysym(): + keysym = keyboard.SDL_Keysym() + assert keysym.scancode == 0 + assert keysym.sym == 0 + assert keysym.mod == 0 + + keysym = keyboard.SDL_Keysym(1, 2, 3, ord("b")) + assert keysym.scancode == 1 + assert keysym.sym == 2 + assert keysym.mod == 3 + + uval = "\u0220" + if sys.version_info[0] < 3: + uval = unichr(8224) + keysym = keyboard.SDL_Keysym(17, 32, 88, ord(uval)) + assert keysym.scancode == 17 + assert keysym.sym == 32 + assert keysym.mod == 88 + + +def test_SDL_GetKeyboardFocus(window): + # NOTE: Would need to actually set keyboard focus for window to test, + # which I can't seem to get working in pytest + video.SDL_ShowWindow(window) + focused_win = keyboard.SDL_GetKeyboardFocus() + if focused_win: + focused_id = video.SDL_GetWindowID(focused_win) + assert video.SDL_GetWindowID(window) == focused_id + +def test_SDL_GetKeyboardState(with_sdl): + # NOTE: This function returns a pointer to an array, which we can use + # directly as an array in Python since we know how long it is from numkeys + states = (c_int * scancode.SDL_NUM_SCANCODES)() + numkeys = c_int(0) + keystates = keyboard.SDL_GetKeyboardState(byref(numkeys)) + assert numkeys.value > 0 + for key in keystates[:numkeys.value]: + assert key in [0, 1] + +def test_SDL_GetSetModState(with_sdl): + test_states = [ + keycode.KMOD_NUM | keycode.KMOD_CAPS | keycode.KMOD_MODE, + keycode.KMOD_LCTRL | keycode.KMOD_LSHIFT, + keycode.KMOD_CAPS, + ] + initial = keyboard.SDL_GetModState() + for state in test_states: keyboard.SDL_SetModState(state) assert keyboard.SDL_GetModState() == state - - keyboard.SDL_SetModState(initial) - assert keyboard.SDL_GetModState() == initial - - def test_SDL_GetScancodeFromKey(self): - codes = range(scancode.SDL_SCANCODE_1, scancode.SDL_SCANCODE_0) - xoff = 0 - for key in range(ord('1'), ord('0')): - code = keyboard.SDL_GetScancodeFromKey(key) - assert code == codes[xoff] - xoff += 1 - - key = keyboard.SDL_GetScancodeFromKey(477) - assert key == scancode.SDL_SCANCODE_UNKNOWN - - def test_SDL_GetScancodeFromName(self): - codes = range(scancode.SDL_SCANCODE_A, scancode.SDL_SCANCODE_Z) - xoff = 0 - for key in range(ord('a'), ord('z')): - ch = chr(key) - code = keyboard.SDL_GetScancodeFromName(byteify(ch)) - assert code == codes[xoff] - xoff += 1 - - key = keyboard.SDL_GetScancodeFromName(b"") - assert key == scancode.SDL_SCANCODE_UNKNOWN - - key = keyboard.SDL_GetScancodeFromName(None) - assert key == scancode.SDL_SCANCODE_UNKNOWN - - key = keyboard.SDL_GetScancodeFromName(b"Test") - assert key == scancode.SDL_SCANCODE_UNKNOWN - - key = keyboard.SDL_GetScancodeFromName(byteify(repr(self))) - assert key == scancode.SDL_SCANCODE_UNKNOWN - - def test_SDL_GetScancodeName(self): - names = range(ord('A'), ord('Z')) - xoff = 0 - for code in range(scancode.SDL_SCANCODE_A, scancode.SDL_SCANCODE_Z): - name = keyboard.SDL_GetScancodeName(code) - assert name == byteify(chr(names[xoff])) - xoff += 1 - - name = keyboard.SDL_GetScancodeName(0) - assert name == b"" - - # self.assertRaises(ValueError, keyboard.SDL_GetScancodeName, -22) - # self.assertRaises(ValueError, keyboard.SDL_GetScancodeName, - # scancode.SDL_NUM_SCANCODES) - - def test_SDL_SetTextInputRect(self): - # TODO: this test is a bit pointless - coords = [(0, 0, 0, 0), (-10, -70, 3, 6), (10, 10, 10, 10)] - for x, y, w, h in coords: - r = rect.SDL_Rect(x, y, w, h) - keyboard.SDL_SetTextInputRect(r) - keyboard.SDL_SetTextInputRect(rect.SDL_Rect()) - - @pytest.mark.skip("not implemented") - def test_SDL_StartTextInput(self): - keyboard.SDL_StartTextInput() - - @pytest.mark.skip("not implemented") - def test_SDL_StopTextInput(self): - keyboard.SDL_StopTextInput() + # Try resetting the modifier state to the initial value + keyboard.SDL_SetModState(initial) + assert keyboard.SDL_GetModState() == initial + +def test_SDL_GetKeyFromScancode(with_sdl): + # Test with letter keys + scan_key_offset = 93 + for scan in range(scancode.SDL_SCANCODE_A, scancode.SDL_SCANCODE_Z + 1): + key = keyboard.SDL_GetKeyFromScancode(scan) + assert key == scan + scan_key_offset + # Test with number keys + scan_key_offset = 19 + for scan in range(scancode.SDL_SCANCODE_1, scancode.SDL_SCANCODE_9 + 1): + key = keyboard.SDL_GetKeyFromScancode(scan) + assert key == scan + scan_key_offset + +def test_SDL_GetScancodeFromKey(with_sdl): + # Test with letter keys + scan_key_offset = 93 + for scan in range(scancode.SDL_SCANCODE_A, scancode.SDL_SCANCODE_Z + 1): + key = scan + scan_key_offset + assert keyboard.SDL_GetScancodeFromKey(key) == scan + # Test with number keys + scan_key_offset = 19 + for scan in range(scancode.SDL_SCANCODE_1, scancode.SDL_SCANCODE_9 + 1): + key = scan + scan_key_offset + assert keyboard.SDL_GetScancodeFromKey(key) == scan + # Test with unknown key + key = keyboard.SDL_GetScancodeFromKey(477) + assert key == scancode.SDL_SCANCODE_UNKNOWN + +def test_SDL_GetScancodeName(with_sdl): + names = range(ord('A'), ord('Z')) + xoff = 0 + for code in range(scancode.SDL_SCANCODE_A, scancode.SDL_SCANCODE_Z): + name = keyboard.SDL_GetScancodeName(code) + assert name == byteify(chr(names[xoff])) + xoff += 1 + # Test with unknown scancode + name = keyboard.SDL_GetScancodeName(0) + assert name == b"" + +def test_SDL_GetScancodeFromName(with_sdl): + codes = range(scancode.SDL_SCANCODE_A, scancode.SDL_SCANCODE_Z) + xoff = 0 + for key in range(ord('a'), ord('z')): + ch = chr(key) + code = keyboard.SDL_GetScancodeFromName(byteify(ch)) + assert code == codes[xoff] + xoff += 1 + # Test with invalid key name + key = keyboard.SDL_GetScancodeFromName(b"") + assert key == scancode.SDL_SCANCODE_UNKNOWN + +def test_SDL_GetKeyName(with_sdl): + x = 65 # SDL maps everything against upper-case letters + for key in range(ord('a'), ord('z')): + ch = chr(x) + name = keyboard.SDL_GetKeyName(key) + assert name == byteify(ch) + x += 1 + +def test_SDL_GetKeyFromName(with_sdl): + # Test with lower-case ASCII characters + for x in range(26): + key = keyboard.SDL_GetKeyFromName(byteify(chr(x + 97))) + assert key == x + 97 + # Test with ASCII numbers + for x in range(10): + key = keyboard.SDL_GetKeyFromName(("%d" % x).encode("utf-8")) + assert key == 48 + x + # Test handling of unknown values + val = keyboard.SDL_GetKeyFromName(b"not a key") + assert val == keycode.SDLK_UNKNOWN + +def test_SDL_StartStopTextInput(with_sdl): + keyboard.SDL_StopTextInput() + assert SDL_GetError() == b"" + assert keyboard.SDL_IsTextInputActive() == SDL_FALSE + keyboard.SDL_StartTextInput() + assert SDL_GetError() == b"" + assert keyboard.SDL_IsTextInputActive() == SDL_TRUE + +def test_SDL_SetTextInputRect(with_sdl): + keyboard.SDL_StartTextInput() + coords = [(0, 0, 0, 0), (-10, -70, 3, 6), (10, 10, 10, 10)] + for x, y, w, h in coords: + r = rect.SDL_Rect(x, y, w, h) + keyboard.SDL_SetTextInputRect(r) + assert SDL_GetError() == b"" + +def test_SDL_HasScreenKeyboardSupport(with_sdl): + ret = keyboard.SDL_HasScreenKeyboardSupport() + assert ret in [SDL_TRUE, SDL_FALSE] + +def test_SDL_IsScreenKeyboardShown(window): + ret = keyboard.SDL_IsScreenKeyboardShown(window) + assert ret in [SDL_TRUE, SDL_FALSE] diff --git a/sdl2/test/metal_test.py b/sdl2/test/metal_test.py index 74714450..ba35389f 100644 --- a/sdl2/test/metal_test.py +++ b/sdl2/test/metal_test.py @@ -7,59 +7,46 @@ macos = sys.platform == "darwin" -# TODO: Add more complete tests with pyobjc - - -class TestSDLMetal(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - if SDL_Init(SDL_INIT_VIDEO) != 0: - raise pytest.skip('Video subsystem not supported') - @classmethod - def teardown_class(cls): - SDL_Quit() - - @pytest.mark.xfail(reason="Metal not supported on all macs") - @pytest.mark.skipif(sdl2.dll.version < 2012 or not macos, reason="not available") - def test_SDL_Metal_CreateDestroyView(self): - error.SDL_ClearError() - flags = video.SDL_WINDOW_HIDDEN | video.SDL_WINDOW_METAL - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flags) - assert isinstance(window.contents, video.SDL_Window) - view = metal.SDL_Metal_CreateView(window) - err = error.SDL_GetError() - if len(err): - print("Metal Error: '{0}'".format(err.decode('utf-8'))) - assert view # Verify pointer is not null - metal.SDL_Metal_DestroyView(view) - video.SDL_DestroyWindow(window) - - @pytest.mark.xfail(reason="Metal not supported on all macs") - @pytest.mark.skipif(sdl2.dll.version < 2014 or not macos, reason="not available") - def test_SDL_Metal_GetLayer(self): - flags = video.SDL_WINDOW_HIDDEN | video.SDL_WINDOW_METAL - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flags) - assert isinstance(window.contents, video.SDL_Window) - view = metal.SDL_Metal_CreateView(window) - assert view # Verify pointer is not null - layer = metal.SDL_Metal_GetLayer(view) - assert layer # Verify pointer is not null - metal.SDL_Metal_DestroyView(view) - video.SDL_DestroyWindow(window) +# TODO: Add more complete tests with pyobjc - @pytest.mark.xfail(reason="Metal not supported on all macs") - @pytest.mark.skipif(sdl2.dll.version < 2014 or not macos, reason="not available") - def test_SDL_Metal_GetDrawableSize(self): - flags = video.SDL_WINDOW_HIDDEN | video.SDL_WINDOW_METAL - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flags) - assert isinstance(window.contents, video.SDL_Window) - view = metal.SDL_Metal_CreateView(window) - assert view # Verify pointer is not null - w, h = c_int(0), c_int(0) - metal.SDL_Metal_GetDrawableSize(window, byref(w), byref(h)) - assert w.value == 10 and h.value == 10 - metal.SDL_Metal_DestroyView(view) - video.SDL_DestroyWindow(window) +@pytest.mark.xfail(reason="Metal not supported on all macs") +@pytest.mark.skipif(sdl2.dll.version < 2012 or not macos, reason="not available") +def test_SDL_Metal_CreateDestroyView(with_sdl): + flags = video.SDL_WINDOW_HIDDEN | video.SDL_WINDOW_METAL + window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flags) + assert isinstance(window.contents, video.SDL_Window) + view = metal.SDL_Metal_CreateView(window) + err = error.SDL_GetError() + if len(err): + print("Metal Error: '{0}'".format(err.decode('utf-8'))) + assert view # Verify pointer is not null + metal.SDL_Metal_DestroyView(view) + video.SDL_DestroyWindow(window) + +@pytest.mark.xfail(reason="Metal not supported on all macs") +@pytest.mark.skipif(sdl2.dll.version < 2014 or not macos, reason="not available") +def test_SDL_Metal_GetLayer(with_sdl): + flags = video.SDL_WINDOW_HIDDEN | video.SDL_WINDOW_METAL + window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flags) + assert isinstance(window.contents, video.SDL_Window) + view = metal.SDL_Metal_CreateView(window) + assert view # Verify pointer is not null + layer = metal.SDL_Metal_GetLayer(view) + assert layer # Verify pointer is not null + metal.SDL_Metal_DestroyView(view) + video.SDL_DestroyWindow(window) + +@pytest.mark.xfail(reason="Metal not supported on all macs") +@pytest.mark.skipif(sdl2.dll.version < 2014 or not macos, reason="not available") +def test_SDL_Metal_GetDrawableSize(with_sdl): + flags = video.SDL_WINDOW_HIDDEN | video.SDL_WINDOW_METAL + window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flags) + assert isinstance(window.contents, video.SDL_Window) + view = metal.SDL_Metal_CreateView(window) + assert view # Verify pointer is not null + w, h = c_int(0), c_int(0) + metal.SDL_Metal_GetDrawableSize(window, byref(w), byref(h)) + assert w.value == 10 and h.value == 10 + metal.SDL_Metal_DestroyView(view) + video.SDL_DestroyWindow(window) diff --git a/sdl2/test/mouse_test.py b/sdl2/test/mouse_test.py index 758c505f..101069b6 100644 --- a/sdl2/test/mouse_test.py +++ b/sdl2/test/mouse_test.py @@ -2,57 +2,74 @@ import pytest from sdl2 import mouse +# NOTE: Will need to use a window fixture to test most of these. Will also want +# to mark most as "SKIP_ANNOYING". + @pytest.mark.skip("not implemented") -class TestSDLMouse(object): - __tags__ = ["sdl"] +def test_SDL_GetMouseFocus(): + pass - @classmethod - def setup_class(cls): - pass +@pytest.mark.skip("not implemented") +def test_SDL_GetMouseState(): + pass - @classmethod - def teardown_class(cls): - pass +@pytest.mark.skip("not implemented") +def test_SDL_GetRelativeMouseState(): + pass - def test_SDL_GetMouseFocus(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_WarpMouseInWindow(): + pass - def test_SDL_GetMouseState(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_SetRelativeMouseMode(): + pass - def test_SDL_GetRelativeMouseState(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_GetRelativeMouseMode(): + pass - def test_SDL_WarpMouseInWindow(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_CreateCursor(): + pass - def test_SDL_GetSetRelativeMouseMode(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_CreateColorCursor(): + pass - def test_SDL_CreateFreeCursor(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_CreateSystemCursor(): + pass - def test_SDL_CreateColorCursor(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_SetCursor(): + pass - def test_SDL_CreateSystemCursor(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_GetCursor(): + pass - def test_SDL_GetSetCursor(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_GetDefaultCursor(): + pass - def test_SDL_GetDefaultCursor(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_FreeCursor(): + pass - def test_SDL_ShowCursor(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_ShowCursor(): + pass - def test_SDL_WarpMouseGlobal(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_WarpMouseGlobal(): + pass - def test_SDL_CaptureMouse(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_CaptureMouse(): + pass - def test_SDL_GetGlobalMouseState(self): - pass \ No newline at end of file +@pytest.mark.skip("not implemented") +def test_SDL_GetGlobalMouseState(): + pass diff --git a/sdl2/test/pixels_test.py b/sdl2/test/pixels_test.py index 4ba014c9..1e971d6d 100644 --- a/sdl2/test/pixels_test.py +++ b/sdl2/test/pixels_test.py @@ -2,487 +2,403 @@ import pytest import copy from ctypes import c_int, POINTER, byref, cast, ArgumentError -from sdl2 import SDL_Init, SDL_Quit, SDL_QuitSubSystem, SDL_INIT_EVERYTHING +import sdl2 +from sdl2 import SDL_Init, SDL_Quit, SDL_INIT_EVERYTHING, SDL_TRUE from sdl2 import pixels from sdl2.pixels import SDL_Color from sdl2.stdinc import Uint8, Uint16, Uint32 - - -class TestSDLPixels(object): +RGBA32 = [0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF] +RGBX32 = [0xFF000000, 0x00FF0000, 0x0000FF00, 0] +if sys.byteorder == "big": + RGBA32.reverse() + RGBX32.reverse() + + +# Test custom macros + +def test_SDL_FOURCC(): + assert pixels.SDL_FOURCC("0", "0", "0", "0") == 0x30303030 + assert pixels.SDL_FOURCC("1", "1", "1", "1") == 0x31313131 + assert pixels.SDL_FOURCC("1", "2", "3", "4") == 0x34333231 + assert pixels.SDL_FOURCC("4", "3", "2", "1") == 0x31323334 + with pytest.raises(TypeError): + pixels.SDL_FOURCC("a", "a", "a", None) + with pytest.raises(TypeError): + pixels.SDL_FOURCC("a", "a", "a", 1) + +def test_SDL_DEFINE_PIXELFORMAT(): + fmt = pixels.SDL_DEFINE_PIXELFORMAT( + pixels.SDL_PIXELTYPE_INDEX1, pixels.SDL_BITMAPORDER_4321, 0, 1, 0 + ) + assert fmt == pixels.SDL_PIXELFORMAT_INDEX1LSB + + fmt = pixels.SDL_DEFINE_PIXELFORMAT( + pixels.SDL_PIXELTYPE_PACKED16, + pixels.SDL_PACKEDORDER_XRGB, + pixels.SDL_PACKEDLAYOUT_4444, + 12, 2 + ) + assert fmt == pixels.SDL_PIXELFORMAT_RGB444 + + fmt = pixels.SDL_DEFINE_PIXELFORMAT( + pixels.SDL_PIXELTYPE_PACKED16, + pixels.SDL_PACKEDORDER_ABGR, + pixels.SDL_PACKEDLAYOUT_1555, + 16, 2 + ) + assert fmt == pixels.SDL_PIXELFORMAT_ABGR1555 + +def test_SDL_PIXELTYPE(): + expected = [ + (pixels.SDL_PIXELFORMAT_INDEX1LSB, pixels.SDL_PIXELTYPE_INDEX1), + (pixels.SDL_PIXELFORMAT_INDEX1MSB, pixels.SDL_PIXELTYPE_INDEX1), + (pixels.SDL_PIXELFORMAT_INDEX4LSB, pixels.SDL_PIXELTYPE_INDEX4), + (pixels.SDL_PIXELFORMAT_ARGB8888, pixels.SDL_PIXELTYPE_PACKED32) + ] + for fmt, pxtype in expected: + assert pixels.SDL_PIXELTYPE(fmt) == pxtype + +def test_SDL_PIXELORDER(): + expected = [ + (pixels.SDL_PIXELFORMAT_INDEX1LSB, pixels.SDL_BITMAPORDER_4321), + (pixels.SDL_PIXELFORMAT_INDEX1MSB, pixels.SDL_BITMAPORDER_1234), + (pixels.SDL_PIXELFORMAT_INDEX4LSB, pixels.SDL_BITMAPORDER_4321), + (pixels.SDL_PIXELFORMAT_ARGB8888, pixels.SDL_PACKEDORDER_ARGB) + ] + for fmt, pxorder in expected: + assert pixels.SDL_PIXELORDER(fmt) == pxorder + +def test_SDL_PIXELLAYOUT(): + expected = [ + (pixels.SDL_PIXELFORMAT_INDEX1LSB, pixels.SDL_PACKEDLAYOUT_NONE), + (pixels.SDL_PIXELFORMAT_RGB332, pixels.SDL_PACKEDLAYOUT_332), + (pixels.SDL_PIXELFORMAT_ARGB8888, pixels.SDL_PACKEDLAYOUT_8888) + ] + for fmt, pxlayout in expected: + assert pixels.SDL_PIXELLAYOUT(fmt) == pxlayout + +def test_SDL_BITSPERPIXEL(): + bitspp = pixels.SDL_BITSPERPIXEL + assert bitspp(pixels.SDL_PIXELFORMAT_INDEX1LSB) == 1 + assert bitspp(pixels.SDL_PIXELFORMAT_INDEX4LSB) == 4 + assert bitspp(pixels.SDL_PIXELFORMAT_RGB332) == 8 + assert bitspp(pixels.SDL_PIXELFORMAT_ARGB8888) == 32 + +def test_SDL_BYTESPERPIXEL(): + bytespp = pixels.SDL_BYTESPERPIXEL + assert bytespp(pixels.SDL_PIXELFORMAT_INDEX1LSB) == 0 + assert bytespp(pixels.SDL_PIXELFORMAT_INDEX4LSB) == 0 + assert bytespp(pixels.SDL_PIXELFORMAT_RGB332) == 1 + assert bytespp(pixels.SDL_PIXELFORMAT_ARGB8888) == 4 + assert bytespp(pixels.SDL_PIXELFORMAT_YUY2) == 2 + assert bytespp(pixels.SDL_PIXELFORMAT_IYUV) == 1 + assert bytespp(pixels.SDL_PIXELFORMAT_UYVY) == 2 + +def test_SDL_ISPIXELFORMAT_INDEXED(): + isindexed = pixels.SDL_ISPIXELFORMAT_INDEXED + assert isindexed(pixels.SDL_PIXELFORMAT_INDEX1LSB) + assert isindexed(pixels.SDL_PIXELFORMAT_INDEX1MSB) + assert isindexed(pixels.SDL_PIXELFORMAT_INDEX4LSB) + assert isindexed(pixels.SDL_PIXELFORMAT_INDEX4MSB) + assert isindexed(pixels.SDL_PIXELFORMAT_INDEX8) + assert not isindexed(pixels.SDL_PIXELFORMAT_RGB332) + assert not isindexed(pixels.SDL_PIXELFORMAT_ARGB8888) + assert not isindexed(pixels.SDL_PIXELFORMAT_YUY2) + +def test_SDL_ISPIXELFORMAT_ALPHA(): + isalpha = pixels.SDL_ISPIXELFORMAT_ALPHA + assert isalpha(pixels.SDL_PIXELFORMAT_ARGB8888) + assert isalpha(pixels.SDL_PIXELFORMAT_RGBA8888) + assert isalpha(pixels.SDL_PIXELFORMAT_RGBA4444) + assert isalpha(pixels.SDL_PIXELFORMAT_ABGR1555) + assert not isalpha(pixels.SDL_PIXELFORMAT_INDEX1LSB) + assert not isalpha(pixels.SDL_PIXELFORMAT_INDEX4MSB) + assert not isalpha(pixels.SDL_PIXELFORMAT_RGB332) + assert not isalpha(pixels.SDL_PIXELFORMAT_YUY2) + assert not isalpha(pixels.SDL_PIXELFORMAT_RGBX8888) + +def test_SDL_ISPIXELFORMAT_FOURCC(): + isfourcc = pixels.SDL_ISPIXELFORMAT_FOURCC + assert isfourcc(pixels.SDL_PIXELFORMAT_YV12) + assert isfourcc(pixels.SDL_PIXELFORMAT_IYUV) + assert isfourcc(pixels.SDL_PIXELFORMAT_YUY2) + assert isfourcc(pixels.SDL_PIXELFORMAT_UYVY) + assert isfourcc(pixels.SDL_PIXELFORMAT_YVYU) + assert not isfourcc(pixels.SDL_PIXELFORMAT_ARGB8888) + assert not isfourcc(pixels.SDL_PIXELFORMAT_ARGB4444) + assert not isfourcc(pixels.SDL_PIXELFORMAT_INDEX8) + + +# Test pixel format functions + +def test_SDL_GetPixelFormatName(): + expected = [ + (pixels.SDL_PIXELFORMAT_INDEX1LSB, b"SDL_PIXELFORMAT_INDEX1LSB"), + (pixels.SDL_PIXELFORMAT_UNKNOWN, b"SDL_PIXELFORMAT_UNKNOWN"), + (pixels.SDL_PIXELFORMAT_UYVY, b"SDL_PIXELFORMAT_UYVY"), + (99999, b"SDL_PIXELFORMAT_UNKNOWN") + ] + for fmt, name in expected: + assert pixels.SDL_GetPixelFormatName(fmt) == name + +def test_SDL_MasksToPixelFormatEnum(): + formats = [ + (pixels.SDL_PIXELFORMAT_RGBA8888, [32] + RGBA32), + (pixels.SDL_PIXELFORMAT_RGBX8888, [32] + RGBX32), + (pixels.SDL_PIXELFORMAT_INDEX1MSB, [1, 0, 0, 0, 0]), + ] + for fmt, expected in formats: + bpp, r, g, b, a = expected + enum = pixels.SDL_MasksToPixelFormatEnum(bpp, r, g, b, a) + assert enum == fmt + + enum = pixels.SDL_MasksToPixelFormatEnum(17, 3, 6, 64, 255) + assert enum == pixels.SDL_PIXELFORMAT_UNKNOWN + +def test_SDL_PixelFormatEnumToMasks(): + formats = [ + (pixels.SDL_PIXELFORMAT_RGBA8888, [32] + RGBA32), + (pixels.SDL_PIXELFORMAT_RGBX8888, [32] + RGBX32), + (pixels.SDL_PIXELFORMAT_INDEX1LSB, [1, 0, 0, 0, 0]), + (pixels.SDL_PIXELFORMAT_INDEX1MSB, [1, 0, 0, 0, 0]), + (pixels.SDL_PIXELFORMAT_UNKNOWN, [0, 0, 0, 0, 0]), + ] + bpp = c_int(0) + r, g, b, a = Uint32(0), Uint32(0), Uint32(0), Uint32(0) + for fmt, expected in formats: + ret = pixels.SDL_PixelFormatEnumToMasks( + fmt, byref(bpp), byref(r), byref(g), byref(b), byref(a) + ) + assert sdl2.SDL_GetError() == b"" + assert ret == SDL_TRUE + assert [x.value for x in (bpp, r, g, b, a)] == expected + +def test_SDL_AllocFreeFormat(): + formats = [ + [pixels.SDL_PIXELFORMAT_RGBA8888, (32, 4)], + [pixels.SDL_PIXELFORMAT_INDEX1LSB, (1, 1)], + [pixels.SDL_PIXELFORMAT_INDEX4MSB, (4, 1)], + [pixels.SDL_PIXELFORMAT_ARGB4444, (16, 2)], + ] + for fmt, info in formats: + bits_pp, bytes_pp = info + pixfmt = pixels.SDL_AllocFormat(fmt) + assert isinstance(pixfmt.contents, pixels.SDL_PixelFormat) + assert pixfmt.contents.format == fmt + assert pixfmt.contents.BitsPerPixel == bits_pp + assert pixfmt.contents.BytesPerPixel == bytes_pp + pixels.SDL_FreeFormat(pixfmt) + +def test_SDL_AllocFreePalette(): + palette = pixels.SDL_AllocPalette(10) + assert isinstance(palette.contents, pixels.SDL_Palette) + assert palette.contents.ncolors == 10 + + colors = palette.contents.colors + for x in range(palette.contents.ncolors): + assert isinstance(colors[x], SDL_Color) + colors[3].r = 70 + assert colors[3].r == 70 + + # Try modifying the palette + color = colors[4] + color.g = 33 + assert color.g == 33 + assert colors[4].g == 33 + + pixels.SDL_FreePalette(palette) + +def test_SDL_SetPaletteColors(): + colors = [] + for v in range(20): + colors.append(SDL_Color(v, v + 10, v + 20)) + col_array = (SDL_Color * len(colors))(*colors) + + palette = pixels.SDL_AllocPalette(20) + assert isinstance(palette.contents, pixels.SDL_Palette) + assert palette.contents.ncolors == 20 + + pixels.SDL_SetPaletteColors(palette, col_array, 0, 20) + for index in range(20): + rgb = palette.contents.colors[index] + assert rgb == colors[index] + + pixels.SDL_FreePalette(palette) + +def test_SDL_SetPixelFormatPalette(): + palette = pixels.SDL_AllocPalette(2) + assert isinstance(palette.contents, pixels.SDL_Palette) + palette.contents.colors[1].r = 128 + palette.contents.colors[1].g = 64 + palette.contents.colors[1].b = 0 + + pixfmt = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_INDEX1MSB) + assert isinstance(pixfmt.contents, pixels.SDL_PixelFormat) + ret = pixels.SDL_SetPixelFormatPalette(pixfmt, palette) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + + fmt_palette = pixfmt.contents.palette.contents + assert fmt_palette.colors[1].r == 128 + assert fmt_palette.colors[1].g == 64 + assert fmt_palette.colors[1].b == 0 + + pixels.SDL_FreeFormat(pixfmt) + pixels.SDL_FreePalette(palette) + +def test_SDL_CalculateGammaRamp(): + vals = (Uint16 * 256)() + pixels.SDL_CalculateGammaRamp(1.0, cast(vals, POINTER(Uint16))) + assert len(vals) == 256 + p = 0 + for x in vals: + assert x == p + p += 257 + + pixels.SDL_CalculateGammaRamp(0.0, cast(vals, POINTER(Uint16))) + assert len(vals) == 256 + for x in vals: + assert x == 0 + + gamma = 0.5 + pixels.SDL_CalculateGammaRamp(gamma, cast(vals, POINTER(Uint16))) + assert len(vals) == 256 + for i in range(len(vals)): + expected = int((i / 256.0) ** gamma * 65535 + 0.5) + vals[i] == expected + + # Test error on negative value + sdl2.SDL_ClearError() + pixels.SDL_CalculateGammaRamp(-1.0, cast(vals, POINTER(Uint16))) + assert sdl2.SDL_GetError() != b"" + sdl2.SDL_ClearError() + +def test_SDL_GetRGB(): + colors = [ + (0xFFAA8811, [0xFF, 0xAA, 0x88]), + (0x00000000, [0x00, 0x00, 0x00]), + (0xFFFFFFFF, [0xFF, 0xFF, 0xFF]), + (0x11223344, [0x11, 0x22, 0x33]), + ] + pixfmt = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_RGBA8888) + assert isinstance(pixfmt.contents, pixels.SDL_PixelFormat) + r, g, b = Uint8(0), Uint8(0), Uint8(0) + for col, expected in colors: + pixels.SDL_GetRGB(col, pixfmt, byref(r), byref(g), byref(b)) + assert [x.value for x in (r, g, b)] == expected + pixels.SDL_FreeFormat(pixfmt) + + # With a pallete format, first argument is index of color to retrieve + palette = pixels.SDL_AllocPalette(2) + palette.contents.colors[1].r = 128 + palette.contents.colors[1].g = 64 + palette.contents.colors[1].b = 32 + pixfmt = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_INDEX1MSB) + assert isinstance(pixfmt.contents, pixels.SDL_PixelFormat) + pixels.SDL_SetPixelFormatPalette(pixfmt, palette) + pixels.SDL_GetRGB(1, pixfmt, byref(r), byref(g), byref(b)) + assert [x.value for x in (r, g, b)] == [128, 64, 32] + + # With a pallete format, missing index returns all zeros + pixels.SDL_GetRGB(16, pixfmt, byref(r), byref(g), byref(b)) + assert [x.value for x in (r, g, b)] == [0, 0, 0] + pixels.SDL_FreeFormat(pixfmt) + pixels.SDL_FreePalette(palette) + +def test_SDL_GetRGBA(): + colors = [ + (0xFFAA8811, [0xFF, 0xAA, 0x88, 0x11]), + (0x00000000, [0x00, 0x00, 0x00, 0x00]), + (0xFFFFFFFF, [0xFF, 0xFF, 0xFF, 0xFF]), + (0x11223344, [0x11, 0x22, 0x33, 0x44]), + ] + pixfmt = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_RGBA8888) + assert isinstance(pixfmt.contents, pixels.SDL_PixelFormat) + r, g, b, a = Uint8(0), Uint8(0), Uint8(0), Uint8(0) + for col, expected in colors: + pixels.SDL_GetRGBA(col, pixfmt, byref(r), byref(g), byref(b), byref(a)) + assert [x.value for x in (r, g, b, a)] == expected + pixels.SDL_FreeFormat(pixfmt) + + # With a pallete format, first argument is index of color to retrieve + palette = pixels.SDL_AllocPalette(2) + palette.contents.colors[1].r = 128 + palette.contents.colors[1].g = 64 + palette.contents.colors[1].b = 32 + palette.contents.colors[1].a = 96 + pixfmt = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_INDEX1MSB) + assert isinstance(pixfmt.contents, pixels.SDL_PixelFormat) + pixels.SDL_SetPixelFormatPalette(pixfmt, palette) + pixels.SDL_GetRGBA(1, pixfmt, byref(r), byref(g), byref(b), byref(a)) + assert [x.value for x in (r, g, b, a)] == [128, 64, 32, 96] + + # With a pallete format, missing index returns all zeros + pixels.SDL_GetRGBA(16, pixfmt, byref(r), byref(g), byref(b), byref(a)) + assert [x.value for x in (r, g, b, a)] == [0, 0, 0, 0] + pixels.SDL_FreeFormat(pixfmt) + +def test_SDL_MapRGB(): + r, g, b = (0xFF, 0xAA, 0x88) + formats = [ + (pixels.SDL_PIXELFORMAT_RGBA8888, 0xFFAA88FF), + (pixels.SDL_PIXELFORMAT_BGRA8888, 0x88AAFFFF), + (pixels.SDL_PIXELFORMAT_ABGR8888, 0xFF88AAFF), + ] + for fmt, expected in formats: + pixfmt = pixels.SDL_AllocFormat(fmt) + assert isinstance(pixfmt.contents, pixels.SDL_PixelFormat) + col = pixels.SDL_MapRGB(pixfmt, r, g, b) + assert col == expected + pixels.SDL_FreeFormat(pixfmt) + +def test_SDL_MapRGBA(): + r, g, b, a = (0xFF, 0xAA, 0x88, 0x11) + formats = [ + (pixels.SDL_PIXELFORMAT_RGBA8888, 0xFFAA8811), + (pixels.SDL_PIXELFORMAT_BGRA8888, 0x88AAFF11), + (pixels.SDL_PIXELFORMAT_ABGR8888, 0x1188AAFF), + ] + for fmt, expected in formats: + pixfmt = pixels.SDL_AllocFormat(fmt) + assert isinstance(pixfmt.contents, pixels.SDL_PixelFormat) + col = pixels.SDL_MapRGBA(pixfmt, r, g, b, a) + assert col == expected + pixels.SDL_FreeFormat(pixfmt) + + +# Test structs and objects + +def test_SDL_PixelFormat(): + pixfmt = pixels.SDL_PixelFormat() + assert isinstance(pixfmt, pixels.SDL_PixelFormat) + +def test_SDL_Palette(): + palette = pixels.SDL_Palette() + assert isinstance(palette, pixels.SDL_Palette) + + +class TestSDLColor(object): __tags__ = ["sdl"] - @classmethod - def setup_class(cls): - SDL_Init(SDL_INIT_EVERYTHING) + def test_init(self): + col = SDL_Color() - @classmethod - def teardown_class(cls): - SDL_QuitSubSystem(SDL_INIT_EVERYTHING) - SDL_Quit() + # Check default values + assert col.r == 255 + assert col.g == 255 + assert col.b == 255 + assert col.a == 255 - def test_SDL_FOURCC(self): - with pytest.raises(TypeError): - pixels.SDL_FOURCC(None, None, None, None) - with pytest.raises(TypeError): - pixels.SDL_FOURCC("a", None, None, None) - with pytest.raises(TypeError): - pixels.SDL_FOURCC(None, "a", None, None) - with pytest.raises(TypeError): - pixels.SDL_FOURCC(None, None, "a", None) - with pytest.raises(TypeError): - pixels.SDL_FOURCC(None, None, None, "a") - with pytest.raises(TypeError): - pixels.SDL_FOURCC("a", "a", None, None) - with pytest.raises(TypeError): - pixels.SDL_FOURCC("a", "a", "a", None) - with pytest.raises(TypeError): - pixels.SDL_FOURCC("a", "a", "a", 1) - with pytest.raises(TypeError): - pixels.SDL_FOURCC("a", "a", 5, 1) - with pytest.raises(TypeError): - pixels.SDL_FOURCC("a", 17, 5, 1) - assert pixels.SDL_FOURCC("0", "0", "0", "0") == 0x30303030 - assert pixels.SDL_FOURCC("1", "1", "1", "1") == 0x31313131 - assert pixels.SDL_FOURCC("1", "2", "3", "4") == 0x34333231 - assert pixels.SDL_FOURCC("4", "3", "2", "1") == 0x31323334 - - def test_SDL_DEFINE_PIXELFORMAT(self): - fmt = pixels.SDL_DEFINE_PIXELFORMAT(pixels.SDL_PIXELTYPE_INDEX1, - pixels.SDL_BITMAPORDER_4321, 0, - 1, 0) - assert fmt == pixels.SDL_PIXELFORMAT_INDEX1LSB - - fmt = pixels.SDL_DEFINE_PIXELFORMAT(pixels.SDL_PIXELTYPE_PACKED16, - pixels.SDL_PACKEDORDER_XRGB, - pixels.SDL_PACKEDLAYOUT_4444, - 12, 2) - assert fmt == pixels.SDL_PIXELFORMAT_RGB444 - - fmt = pixels.SDL_DEFINE_PIXELFORMAT(pixels.SDL_PIXELTYPE_PACKED16, - pixels.SDL_PACKEDORDER_ABGR, - pixels.SDL_PACKEDLAYOUT_1555, - 16, 2) - assert fmt == pixels.SDL_PIXELFORMAT_ABGR1555 - - def test_SDL_PIXELTYPE(self): - expected = [ - (pixels.SDL_PIXELFORMAT_INDEX1LSB, pixels.SDL_PIXELTYPE_INDEX1), - (pixels.SDL_PIXELFORMAT_INDEX1MSB, pixels.SDL_PIXELTYPE_INDEX1), - (pixels.SDL_PIXELFORMAT_INDEX4LSB, pixels.SDL_PIXELTYPE_INDEX4), - (pixels.SDL_PIXELFORMAT_ARGB8888, pixels.SDL_PIXELTYPE_PACKED32) - ] - for fmt, pxtype in expected: - assert pixels.SDL_PIXELTYPE(fmt) == pxtype - - def test_SDL_PIXELORDER(self): - expected = [ - (pixels.SDL_PIXELFORMAT_INDEX1LSB, pixels.SDL_BITMAPORDER_4321), - (pixels.SDL_PIXELFORMAT_INDEX1MSB, pixels.SDL_BITMAPORDER_1234), - (pixels.SDL_PIXELFORMAT_INDEX4LSB, pixels.SDL_BITMAPORDER_4321), - (pixels.SDL_PIXELFORMAT_ARGB8888, pixels.SDL_PACKEDORDER_ARGB) - ] - for fmt, pxorder in expected: - assert pixels.SDL_PIXELORDER(fmt) == pxorder - - def test_SDL_PIXELLAYOUT(self): - expected = [ - (pixels.SDL_PIXELFORMAT_INDEX1LSB, pixels.SDL_PACKEDLAYOUT_NONE), - (pixels.SDL_PIXELFORMAT_RGB332, pixels.SDL_PACKEDLAYOUT_332), - (pixels.SDL_PIXELFORMAT_ARGB8888, pixels.SDL_PACKEDLAYOUT_8888) - ] - for fmt, pxlayout in expected: - assert pixels.SDL_PIXELLAYOUT(fmt) == pxlayout - - def test_SDL_BITSPERPIXEL(self): - bitspp = pixels.SDL_BITSPERPIXEL - assert bitspp(pixels.SDL_PIXELFORMAT_INDEX1LSB) == 1 - assert bitspp(pixels.SDL_PIXELFORMAT_INDEX4LSB) == 4 - assert bitspp(pixels.SDL_PIXELFORMAT_RGB332) == 8 - assert bitspp(pixels.SDL_PIXELFORMAT_ARGB8888) == 32 - # TODO: clarify - # self.assertEqual(bitspp(pixels.SDL_PIXELFORMAT_YUY2), 85) - # self.assertEqual(bitspp(pixels.SDL_PIXELFORMAT_IYUV), 89) - # self.assertEqual(bitspp(pixels.SDL_PIXELFORMAT_UYVY), 89) - - def test_SDL_BYTESPERPIXEL(self): - bytespp = pixels.SDL_BYTESPERPIXEL - assert bytespp(pixels.SDL_PIXELFORMAT_INDEX1LSB) == 0 - assert bytespp(pixels.SDL_PIXELFORMAT_INDEX4LSB) == 0 - assert bytespp(pixels.SDL_PIXELFORMAT_RGB332) == 1 - assert bytespp(pixels.SDL_PIXELFORMAT_ARGB8888) == 4 - assert bytespp(pixels.SDL_PIXELFORMAT_YUY2) == 2 - assert bytespp(pixels.SDL_PIXELFORMAT_IYUV) == 1 - assert bytespp(pixels.SDL_PIXELFORMAT_UYVY) == 2 - - def test_SDL_ISPIXELFORMAT_INDEXED(self): - isindexed = pixels.SDL_ISPIXELFORMAT_INDEXED - assert isindexed(pixels.SDL_PIXELFORMAT_INDEX1LSB) - assert isindexed(pixels.SDL_PIXELFORMAT_INDEX1MSB) - assert isindexed(pixels.SDL_PIXELFORMAT_INDEX4LSB) - assert isindexed(pixels.SDL_PIXELFORMAT_INDEX4MSB) - assert isindexed(pixels.SDL_PIXELFORMAT_INDEX8) - assert not isindexed(pixels.SDL_PIXELFORMAT_RGB332) - assert not isindexed(pixels.SDL_PIXELFORMAT_ARGB8888) - assert not isindexed(pixels.SDL_PIXELFORMAT_YUY2) - - def test_SDL_ISPIXELFORMAT_ALPHA(self): - isalpha = pixels.SDL_ISPIXELFORMAT_ALPHA - assert isalpha(pixels.SDL_PIXELFORMAT_ARGB8888) - assert isalpha(pixels.SDL_PIXELFORMAT_RGBA8888) - assert isalpha(pixels.SDL_PIXELFORMAT_RGBA4444) - assert isalpha(pixels.SDL_PIXELFORMAT_ABGR1555) - assert not isalpha(pixels.SDL_PIXELFORMAT_INDEX1LSB) - assert not isalpha(pixels.SDL_PIXELFORMAT_INDEX4MSB) - assert not isalpha(pixels.SDL_PIXELFORMAT_RGB332) - assert not isalpha(pixels.SDL_PIXELFORMAT_YUY2) - assert not isalpha(pixels.SDL_PIXELFORMAT_RGBX8888) - - def test_SDL_ISPIXELFORMAT_FOURCC(self): - isfourcc = pixels.SDL_ISPIXELFORMAT_FOURCC - assert isfourcc(pixels.SDL_PIXELFORMAT_YV12) - assert isfourcc(pixels.SDL_PIXELFORMAT_IYUV) - assert isfourcc(pixels.SDL_PIXELFORMAT_YUY2) - assert isfourcc(pixels.SDL_PIXELFORMAT_UYVY) - assert isfourcc(pixels.SDL_PIXELFORMAT_YVYU) - assert not isfourcc(pixels.SDL_PIXELFORMAT_ARGB8888) - assert not isfourcc(pixels.SDL_PIXELFORMAT_ARGB4444) - assert not isfourcc(pixels.SDL_PIXELFORMAT_INDEX8) - - def test_SDL_GetPixelFormatName(self): - expected = [ - (pixels.SDL_PIXELFORMAT_INDEX1LSB, b"SDL_PIXELFORMAT_INDEX1LSB"), - (pixels.SDL_PIXELFORMAT_UNKNOWN, b"SDL_PIXELFORMAT_UNKNOWN"), - (pixels.SDL_PIXELFORMAT_UYVY, b"SDL_PIXELFORMAT_UYVY"), - (99999, b"SDL_PIXELFORMAT_UNKNOWN") - ] - for fmt, name in expected: - assert pixels.SDL_GetPixelFormatName(fmt) == name - - def test_SDL_MasksToPixelFormatEnum(self): - if sys.byteorder == "little": - val = pixels.SDL_MasksToPixelFormatEnum(32, - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF) - else: - val = pixels.SDL_MasksToPixelFormatEnum(32, - 0x000000FF, - 0x0000FF00, - 0x00FF0000, - 0xFF000000) - assert val == pixels.SDL_PIXELFORMAT_RGBA8888 - if sys.byteorder == "little": - val = pixels.SDL_MasksToPixelFormatEnum(32, - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0) - else: - val = pixels.SDL_MasksToPixelFormatEnum(32, - 0, - 0x000000FF, - 0x0000FF00, - 0x00FF0000) - assert val == pixels.SDL_PIXELFORMAT_RGBX8888 - val = pixels.SDL_MasksToPixelFormatEnum(1, 0, 0, 0, 0) - assert val == pixels.SDL_PIXELFORMAT_INDEX1MSB # not LSB - val = pixels.SDL_MasksToPixelFormatEnum(17, 3, 6, 64, 255) - assert val == pixels.SDL_PIXELFORMAT_UNKNOWN - val = pixels.SDL_MasksToPixelFormatEnum(0, 0, 0, 0, 0) - assert val == pixels.SDL_PIXELFORMAT_UNKNOWN - - def test_SDL_PixelFormatEnumToMasks(self): - bpp = c_int() - r, g, b, a = Uint32(), Uint32(), Uint32(), Uint32() - pixels.SDL_PixelFormatEnumToMasks(pixels.SDL_PIXELFORMAT_INDEX1LSB, - byref(bpp), byref(r), byref(g), - byref(b), byref(a)) - assert (bpp.value, r.value, g.value, b.value, a.value) == \ - (1, 0, 0, 0, 0) - pixels.SDL_PixelFormatEnumToMasks(pixels.SDL_PIXELFORMAT_INDEX1MSB, - byref(bpp), byref(r), byref(g), - byref(b), byref(a)) - assert (bpp.value, r.value, g.value, b.value, a.value) == \ - (1, 0, 0, 0, 0) - - pixels.SDL_PixelFormatEnumToMasks(pixels.SDL_PIXELFORMAT_RGBA8888, - byref(bpp), byref(r), byref(g), - byref(b), byref(a)) - if sys.byteorder == "little": - assert (bpp.value, r.value, g.value, b.value, a.value) == \ - (32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF) - else: - assert (bpp.value, r.value, g.value, b.value, a.value) == \ - (32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000) - pixels.SDL_PixelFormatEnumToMasks(pixels.SDL_PIXELFORMAT_RGBX8888, - byref(bpp), byref(r), - byref(g), byref(b), - byref(a)) - if sys.byteorder == "little": - assert (bpp.value, r.value, g.value, b.value, a.value) == \ - (32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0) - else: - assert (bpp.value, r.value, g.value, b.value, a.value) == \ - (32, 0, 0x0000FF00, 0x00FF0000, 0xFF000000) - # self.assertRaises(sdl.SDLError, pixels.SDL_PixelFormatEnumToMasks, - # 99999) - - pixels.SDL_PixelFormatEnumToMasks(0, byref(bpp), byref(r), byref(g), - byref(b), byref(a)) - assert (bpp.value, r.value, g.value, b.value, a.value) == \ - (0, 0, 0, 0, 0) - pixels.SDL_PixelFormatEnumToMasks(pixels.SDL_PIXELFORMAT_UNKNOWN, - byref(bpp), byref(r), byref(g), - byref(b), byref(a)) - assert (bpp.value, r.value, g.value, b.value, a.value) == \ - (0, 0, 0, 0, 0) - - def test_SDL_AllocFreeFormat(self): - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_RGBA8888) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - assert pformat.contents.format == pixels.SDL_PIXELFORMAT_RGBA8888 - assert pformat.contents.BitsPerPixel == 32 - assert pformat.contents.BytesPerPixel == 4 - pixels.SDL_FreeFormat(pformat) - - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_INDEX1LSB) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - assert pformat.contents.format == pixels.SDL_PIXELFORMAT_INDEX1LSB - assert pformat.contents.BitsPerPixel == 1 - assert pformat.contents.BytesPerPixel == 1 - pixels.SDL_FreeFormat(pformat) - - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_INDEX4MSB) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - assert pformat.contents.format == pixels.SDL_PIXELFORMAT_INDEX4MSB - assert pformat.contents.BitsPerPixel == 4 - assert pformat.contents.BytesPerPixel == 1 - pixels.SDL_FreeFormat(pformat) - - # self.assertRaises(sdl.SDLError, pixels.SDL_AllocFormat, - # pixels.SDL_PIXELFORMAT_UYVY) - # self.assertRaises(sdl.SDLError, pixels.SDL_AllocFormat, - # pixels.SDL_PIXELFORMAT_YUY2) - - def test_SDL_AllocFreePalette(self): - with pytest.raises((ArgumentError, TypeError)): - pixels.SDL_AllocPalette(None) - with pytest.raises((ArgumentError, TypeError)): - pixels.SDL_AllocPalette("Test") - # self.assertRaises(ValueError, pixels.SDL_AllocPalette, -5) - - palette = pixels.SDL_AllocPalette(10) - assert isinstance(palette.contents, pixels.SDL_Palette) - assert palette.contents.ncolors == 10 - colors = palette.contents.colors - for x in range(palette.contents.ncolors): - assert isinstance(colors[x], SDL_Color) - colors[3].r = 70 - assert colors[3].r == 70 - color = colors[4] - assert colors[4].g == 255 - assert color.g == 255 - color.g = 33 - assert color.g == 33 - assert colors[4].g == 33 - pixels.SDL_FreePalette(palette) - - def test_SDL_CalculateGammaRamp(self): - # TODO: more tests - with pytest.raises(TypeError): - pixels.SDL_CalculateGammaRamp(None) - with pytest.raises(TypeError): - pixels.SDL_CalculateGammaRamp("Test") - with pytest.raises(TypeError): - pixels.SDL_CalculateGammaRamp(7) - with pytest.raises(TypeError): - pixels.SDL_CalculateGammaRamp(-0.00002) - vals = (Uint16 * 256)() - pixels.SDL_CalculateGammaRamp(0, cast(vals, POINTER(Uint16))) - assert len(vals) == 256 - for x in vals: - assert x == 0 - vals = (Uint16 * 256)() - pixels.SDL_CalculateGammaRamp(1, cast(vals, POINTER(Uint16))) - assert len(vals) == 256 - p = 0 - for x in vals: - assert x == p - p += 257 - vals = (Uint16 * 256)() - pixels.SDL_CalculateGammaRamp(0.5, cast(vals, POINTER(Uint16))) - assert len(vals) == 256 - p, step = 0, 1 - for x in vals: - if p == 33124: - # dubios rounding correction - is this really correct? - p = 33123 - assert x == p - p = x + step - step += 2 - - def test_SDL_GetRGB(self): - # TODO: invalid parameters - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_RGBA8888) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - r, g, b = Uint8(), Uint8(), Uint8() - pixels.SDL_GetRGB(0xFFAA8811, pformat, byref(r), byref(g), byref(b)) - assert (r.value, g.value, b.value) == (0xFF, 0xAA, 0x88) - pixels.SDL_GetRGB(0x00000000, pformat, byref(r), byref(g), byref(b)) - assert (r.value, g.value, b.value) == (0x00, 0x00, 0x00) - pixels.SDL_GetRGB(0xFFFFFFFF, pformat, byref(r), byref(g), byref(b)) - assert (r.value, g.value, b.value) == (0xFF, 0xFF, 0xFF) - pixels.SDL_GetRGB(0x11223344, pformat, byref(r), byref(g), byref(b)) - assert (r.value, g.value, b.value) == (0x11, 0x22, 0x33) - pixels.SDL_FreeFormat(pformat) - fmts = (pixels.SDL_PIXELFORMAT_INDEX1LSB, - pixels.SDL_PIXELFORMAT_INDEX1MSB) - for fmt in fmts: - pformat = pixels.SDL_AllocFormat(fmt) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - pixels.SDL_GetRGB(0x11223344, pformat, byref(r), byref(g), - byref(b)) - assert (r.value, g.value, b.value) == (0xFF, 0xFF, 0xFF) - pixels.SDL_GetRGB(0x00000000, pformat, byref(r), byref(g), - byref(b)) - # TODO: Seems to be always (0xFF, 0xFF, 0xFF)??? - # self.assertEqual(rgb,(0x00, 0x00, 0x00)) - pixels.SDL_FreeFormat(pformat) - fmts = (pixels.SDL_PIXELFORMAT_INDEX4LSB, - pixels.SDL_PIXELFORMAT_INDEX4MSB) - for fmt in fmts: - pformat = pixels.SDL_AllocFormat(fmt) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - # TODO - pixels.SDL_FreeFormat(pformat) - - def test_SDL_GetRGBA(self): - # TODO: invalid parameters - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_RGBA8888) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - r, g, b, a = Uint8(), Uint8(), Uint8(), Uint8() - pixels.SDL_GetRGBA(0xFFAA8811, pformat, byref(r), byref(g), byref(b), - byref(a)) - assert (r.value, g.value, b.value, a.value) == (0xFF, 0xAA, 0x88, 0x11) - pixels.SDL_GetRGBA(0x00000000, pformat, byref(r), byref(g), byref(b), - byref(a)) - assert (r.value, g.value, b.value, a.value) == (0x00, 0x00, 0x00, 0x00) - pixels.SDL_GetRGBA(0xFFFFFFFF, pformat, byref(r), byref(g), byref(b), - byref(a)) - assert (r.value, g.value, b.value, a.value) == (0xFF, 0xFF, 0xFF, 0xFF) - pixels.SDL_GetRGBA(0x11223344, pformat, byref(r), byref(g), byref(b), - byref(a)) - assert (r.value, g.value, b.value, a.value) == (0x11, 0x22, 0x33, 0x44) - pixels.SDL_FreeFormat(pformat) - fmts = (pixels.SDL_PIXELFORMAT_INDEX1LSB, - pixels.SDL_PIXELFORMAT_INDEX1MSB) - for fmt in fmts: - pformat = pixels.SDL_AllocFormat(fmt) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - pixels.SDL_GetRGBA(0x11223344, pformat, byref(r), byref(g), - byref(b), byref(a)) - assert (r.value, g.value, b.value, a.value) == \ - (0xFF, 0xFF, 0xFF, 0xFF) - pixels.SDL_GetRGBA(0x00000000, pformat, byref(r), byref(g), - byref(b), byref(a)) - # TODO: Seems to be always(0xFF, 0xFF, 0xFF) ??? - # self.assertEqual(rgb,(0x00, 0x00, 0x00)) - pixels.SDL_FreeFormat(pformat) - fmts = (pixels.SDL_PIXELFORMAT_INDEX4LSB, - pixels.SDL_PIXELFORMAT_INDEX4MSB) - for fmt in fmts: - pformat = pixels.SDL_AllocFormat(fmt) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - # TODO - pixels.SDL_FreeFormat(pformat) - - def test_SDL_MapRGB(self): - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_RGBA8888) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - val = pixels.SDL_MapRGB(pformat, 0xFF, 0xAA, 0x88) - assert val == 0xFFAA88FF - pixels.SDL_FreeFormat(pformat) - - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_UNKNOWN) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - assert pformat.contents.format == pixels.SDL_PIXELFORMAT_UNKNOWN - val = pixels.SDL_MapRGB(pformat, 0xFF, 0xAA, 0x88) - assert val == 0x0 - pixels.SDL_FreeFormat(pformat) - - def test_SDL_MapRGBA(self): - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_RGBA8888) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - val = pixels.SDL_MapRGBA(pformat, 0xFF, 0xAA, 0x88, 0x11) - assert val == 0xFFAA8811 - pixels.SDL_FreeFormat(pformat) - - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_UNKNOWN) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - assert pformat.contents.format == pixels.SDL_PIXELFORMAT_UNKNOWN - val = pixels.SDL_MapRGBA(pformat, 0xFF, 0xAA, 0x88, 0x11) - assert val == 0x0 - pixels.SDL_FreeFormat(pformat) - - def test_SDL_SetPaletteColors(self): - colors = [] - for v in range(20): - colors.append(SDL_Color(v, v + 10, v + 20)) - - palette = pixels.SDL_AllocPalette(10) - assert isinstance(palette.contents, pixels.SDL_Palette) - assert palette.contents.ncolors == 10 - colors = palette.contents.colors - for index in range(10): - rgb = colors[index] - assert (rgb.r, rgb.g, rgb.b) == (255, 255, 255) - pixels.SDL_SetPaletteColors(palette, colors, 0, 10) - for index in range(10): - rgb = palette.contents.colors[index] - assert rgb == colors[index] - pixels.SDL_SetPaletteColors(palette, colors, 5, 1000) - for index in range(10): - rgb = palette.contents.colors[index] - if index < 5: - assert rgb == colors[index] - elif index > 5: - assert rgb == colors[index - 5] - - pixels.SDL_FreePalette(palette) - - def test_SDL_SetPixelFormatPalette(self): - palette = pixels.SDL_AllocPalette(10) - assert isinstance(palette.contents, pixels.SDL_Palette) - pformat = pixels.SDL_AllocFormat(pixels.SDL_PIXELFORMAT_RGBA8888) - assert isinstance(pformat.contents, pixels.SDL_PixelFormat) - pixels.SDL_SetPixelFormatPalette(pformat, palette) - # TODO: improve tests - pixels.SDL_FreeFormat(pformat) - pixels.SDL_FreePalette(palette) - - def test_SDL_PixelFormat(self): - # test_alloc_SDL_FreeFormat() contains the real tests - pformat = pixels.SDL_PixelFormat() - assert isinstance(pformat, pixels.SDL_PixelFormat) - - def test_SDL_Palette(self): - # test_alloc_SDL_FreePalette() contains the real tests - palette = pixels.SDL_Palette() - assert isinstance(palette, pixels.SDL_Palette) - - def test_SDL_Color(self): - c1 = SDL_Color() - assert (c1.r, c1.g, c1.b, c1.a) == (0xFF, 0xFF, 0xFF, 0xFF) + # Test RGB and RGBA inputs + col_rgb = SDL_Color(128, 128, 128) + col_rgba = SDL_Color(128, 128, 128, 64) - c1 = SDL_Color() - c2 = SDL_Color() - c3 = SDL_Color(0, 127, 255, 33) - assert c1 == c2 - assert c1 != c3 + # Test errors on bad values + with pytest.raises(TypeError): + SDL_Color(0.1, 0, 0) - def test_SDL_Color__repr__(self): + def test___repr__(self): c1 = SDL_Color() assert "SDL_Color(r=255, g=255, b=255, a=255)" == repr(c1) c2 = eval(repr(c1)) @@ -490,16 +406,14 @@ def test_SDL_Color__repr__(self): c3 = eval(repr(c2)) assert c3 == c2 - def test_SDL_Color__copy__(self): - c = SDL_Color() - c2 = copy.copy(c) - assert c == c2 - + def test___copy__(self): c = SDL_Color(10, 20, 30) c2 = copy.copy(c) assert c == c2 + c.r = 100 + assert c != c2 - def test_SDL_Color__eq__(self): + def test___eq__(self): assert SDL_Color(255, 0, 0, 0) == SDL_Color(255, 0, 0, 0) assert SDL_Color(0, 255, 0, 0) == SDL_Color(0, 255, 0, 0) assert SDL_Color(0, 0, 255, 0) == SDL_Color(0, 0, 255, 0) @@ -511,7 +425,7 @@ def test_SDL_Color__eq__(self): assert not (SDL_Color(0, 0, 0, 0) == SDL_Color(0, 0, 255, 0)) assert not (SDL_Color(0, 0, 0, 0) == SDL_Color(0, 0, 0, 255)) - def test_SDL_Color__ne__(self): + def test___ne__(self): assert SDL_Color(0, 0, 0, 0) != SDL_Color(255, 0, 0, 0) assert SDL_Color(0, 0, 0, 0) != SDL_Color(0, 255, 0, 0) assert SDL_Color(0, 0, 0, 0) != SDL_Color(0, 0, 255, 0) @@ -523,74 +437,22 @@ def test_SDL_Color__ne__(self): assert not (SDL_Color(0, 0, 255, 0) != SDL_Color(0, 0, 255, 0)) assert not (SDL_Color(0, 0, 0, 255) != SDL_Color(0, 0, 0, 255)) - def test_SDL_Color_r(self): - c1 = SDL_Color() - - def setr(color, val): - color.r = val - - for x in range(0, 255): - c1.r = x - assert c1.r == x - - # TODO - # self.assertRaises(ValueError, setr, c1, -1) - # self.assertRaises(ValueError, setr, c1, 256) - with pytest.raises(TypeError): - setr(c1, "Test") - with pytest.raises(TypeError): - setr(c1, None) - - def test_SDL_Color_g(self): - c1 = SDL_Color() - - def setg(color, val): - color.g = val - - for x in range(0, 255): - c1.g = x - assert c1.g == x - - # TODO - # self.assertRaises(ValueError, setg, c1, -1) - # self.assertRaises(ValueError, setg, c1, 256) - with pytest.raises(TypeError): - setg(c1, "Test") - with pytest.raises(TypeError): - setg(c1, None) - - def test_SDL_Color_b(self): - c1 = SDL_Color() - - def setb(color, val): - color.b = val - - for x in range(0, 255): - c1.b = x - assert c1.b == x - - # TODO - # self.assertRaises(ValueError, setb, c1, -1) - # self.assertRaises(ValueError, setb, c1, 256) - with pytest.raises(TypeError): - setb(c1, "Test") - with pytest.raises(TypeError): - setb(c1, None) - - def test_SDL_Color_a(self): - c1 = SDL_Color() - - def seta(color, val): - color.a = val - - for x in range(0, 255): - c1.a = x - assert c1.a == x - - # TODO - # self.assertRaises(ValueError, seta, c1, -1) - # self.assertRaises(ValueError, seta, c1, 256) - with pytest.raises(TypeError): - seta(c1, "Test") - with pytest.raises(TypeError): - seta(c1, None) + def test_colors(self): + col = SDL_Color() + + # Check getting/setting values + for x in (0, 16, 32, 64, 128, 255): + col.r = x + col.g = x + col.b = x + col.a = x + assert col.r == x + assert col.g == x + assert col.b == x + assert col.a == x + + # Test wrap for out-of-bounds values + col.r = 256 + assert col.r == 0 + col.g = -1 + assert col.g == 255 diff --git a/sdl2/test/platform_test.py b/sdl2/test/platform_test.py index 55f9ecf6..5a8b68a8 100644 --- a/sdl2/test/platform_test.py +++ b/sdl2/test/platform_test.py @@ -3,18 +3,15 @@ from sdl2 import platform -class TestSDLPlatform(object): - __tags__ = ["sdl"] - - def test_SDL_GetPlatform(self): - retval = platform.SDL_GetPlatform() - if sys.platform in ("win32", "cygwin"): - assert retval == b"Windows" - elif sys.platform.startswith("linux"): - assert retval == b"Linux" - elif sys.platform.startswith("freebsd"): - assert retval == b"FreeBSD" - elif sys.platform.startswith("darwin"): - assert retval == b"Mac OS X" - # Do not check others atm, since we are unsure about what Python will - # return here. +def test_SDL_GetPlatform(): + retval = platform.SDL_GetPlatform() + if sys.platform in ("win32", "cygwin"): + assert retval == b"Windows" + elif sys.platform.startswith("linux"): + assert retval == b"Linux" + elif sys.platform.startswith("freebsd"): + assert retval == b"FreeBSD" + elif sys.platform.startswith("darwin"): + assert retval == b"Mac OS X" + # Do not check others atm, since we are unsure about what Python will + # return here. diff --git a/sdl2/test/power_test.py b/sdl2/test/power_test.py index d3244d27..166bb4da 100644 --- a/sdl2/test/power_test.py +++ b/sdl2/test/power_test.py @@ -5,25 +5,17 @@ from sdl2 import power -class TestSDLPower(object): - __tags__ = ["sdl"] - - # @interactive("Do the shown numbers match your power supply status?") - # def test_get_power_info(self): - # secs, percent = c_int(), c_int() - # retval = power.SDL_GetPowerInfo(byref(secs), byref(percent)) - # state = "Unknown" - # if retval == power.SDL_POWERSTATE_ON_BATTERY: - # state = "On battery" - # elif retval == power.SDL_POWERSTATE_NO_BATTERY: - # state = "No battery" - # elif retval == power.SDL_POWERSTATE_CHARGING: - # state = "Battery charging" - # elif retval == power.SDL_POWERSTATE_CHARGED: - # state = "Battery charged" - # output = "Power Status: %s" % state + os.linesep - # output += "Minutes left (-1 = undetermined): %d" % (secs.value / 60) - # output += os.linesep - # output += "Percent left (-1 = undetermined): %d" % percent.value - # output += os.linesep - # doprint(output) +def test_SDL_GetPowerInfo(): + has_battery = [ + power.SDL_POWERSTATE_ON_BATTERY, + power.SDL_POWERSTATE_CHARGING, + power.SDL_POWERSTATE_CHARGED + ] + remaining, pct = c_int(), c_int() + state = power.SDL_GetPowerInfo(byref(remaining), byref(pct)) + if state in has_battery: + assert pct.value <= 100 + assert pct.value > 0 + else: + assert remaining.value == -1 + assert pct.value == -1 diff --git a/sdl2/test/rect_test.py b/sdl2/test/rect_test.py index 1f6bb052..fc4f09cd 100644 --- a/sdl2/test/rect_test.py +++ b/sdl2/test/rect_test.py @@ -13,7 +13,7 @@ class TestSDLPoint(object): __tags__ = ["sdl"] - def test_SDL_Point(self): + def test_init(self): pt = rect.SDL_Point() assert (pt.x, pt.y) == (0, 0) for i in range(0, 100): @@ -22,7 +22,7 @@ def test_SDL_Point(self): pt = rect.SDL_Point(x, y) assert (pt.x, pt.y) == (x, y) - def test_SDL_Point_xy(self): + def test_xy(self): pt = rect.SDL_Point() for i in range(0, 50): x = random.randint(-1000, 1000) @@ -43,13 +43,13 @@ def test_SDL_Point_xy(self): with pytest.raises(TypeError): pt.y = None - def test_SDL_Point__repr__(self): + def test___repr__(self): pt = rect.SDL_Point(10, 12) pt2 = eval("rect.%s" % repr(pt)) assert pt == pt2 assert (pt.x, pt.y) == (pt2.x, pt2.y) - def test_SDL_Point__copy__(self): + def test___copy__(self): pt = rect.SDL_Point() pt2 = copy.copy(pt) assert pt == pt2 @@ -60,7 +60,7 @@ def test_SDL_Point__copy__(self): assert pt != pt2 assert pt3 == pt2 - def test_SDL_Point__eq__(self): + def test___eq__(self): assert rect.SDL_Point() == rect.SDL_Point() coords = [(0, 0), (10, 0), (0, 10), (12, 10), (7, 10)] for x1, y1 in coords: @@ -68,7 +68,7 @@ def test_SDL_Point__eq__(self): equal = rect.SDL_FPoint(x1, y1) == rect.SDL_FPoint(x2, y2) assert equal if (x1 == x2 and y1 == y2) else not equal - def test_SDL_Point__ne__(self): + def test___ne__(self): assert not rect.SDL_Point() != rect.SDL_Point() coords = [(0, 0), (10, 0), (0, 10), (12, 10), (7, 10)] for x1, y1 in coords: @@ -82,7 +82,7 @@ def test_SDL_Point__ne__(self): class TestSDLFPoint(object): __tags__ = ["sdl"] - def test_SDL_FPoint(self): + def test_init(self): pt = rect.SDL_FPoint() assert (pt.x, pt.y) == (0, 0) for i in range(0, 100): @@ -91,7 +91,7 @@ def test_SDL_FPoint(self): pt = rect.SDL_FPoint(x, y) assert (pt.x, pt.y) == pytest.approx((x, y)) - def test_SDL_FPoint_xy(self): + def test_xy(self): pt = rect.SDL_FPoint() for i in range(0, 50): x = random.uniform(-1000, 1000) @@ -108,13 +108,13 @@ def test_SDL_FPoint_xy(self): with pytest.raises(TypeError): pt.y = None - def test_SDL_FPoint__repr__(self): + def test___repr__(self): pt = rect.SDL_FPoint(3.24, 12.8) pt2 = eval("rect.%s" % repr(pt)) assert pt == pt2 assert (pt.x, pt.y) == (pt2.x, pt2.y) - def test_SDL_FPoint__copy__(self): + def test___copy__(self): pt = rect.SDL_FPoint() pt2 = copy.copy(pt) assert pt == pt2 @@ -125,7 +125,7 @@ def test_SDL_FPoint__copy__(self): assert pt != pt2 assert pt3 == pt2 - def test_SDL_FPoint__eq__(self): + def test___eq__(self): assert rect.SDL_FPoint() == rect.SDL_FPoint() coords = [(0, 0.5), (10, 0.5), (0, 10.5), (12, 10.5), (7, 10.5)] for x1, y1 in coords: @@ -133,7 +133,7 @@ def test_SDL_FPoint__eq__(self): equal = rect.SDL_FPoint(x1, y1) == rect.SDL_FPoint(x2, y2) assert equal if (x1 == x2 and y1 == y2) else not equal - def test_SDL_FPoint__ne__(self): + def test___ne__(self): assert not rect.SDL_FPoint() != rect.SDL_FPoint() coords = [(0, 0.5), (10, 0.5), (0, 10.5), (12, 10.5), (7, 10.5)] for x1, y1 in coords: @@ -145,7 +145,7 @@ def test_SDL_FPoint__ne__(self): class TestSDLRect(object): __tags__ = ["sdl"] - def test_SDL_Rect(self): + def test_init(self): rt = rect.SDL_Rect() assert (rt.x, rt.y, rt.w, rt.h) == (0, 0, 0, 0) for i in range(0, 50): @@ -156,7 +156,7 @@ def test_SDL_Rect(self): rt = rect.SDL_Rect(x, y, w, h) assert (rt.x, rt.y, rt.w, rt.h) == (x, y, w, h) - def test_SDL_Rect_xywh(self): + def test_xywh(self): rt = rect.SDL_Rect() for i in range(0, 50): x = random.randint(-1000, 1000) @@ -168,38 +168,25 @@ def test_SDL_Rect_xywh(self): rt.w = w rt.h = h assert (rt.x, rt.y, rt.w, rt.h) == (x, y, w, h) - with pytest.raises(TypeError): - rt.x = 10.4 - with pytest.raises(TypeError): - rt.y = 10.4 - with pytest.raises(TypeError): - rt.w = 10.4 - with pytest.raises(TypeError): - rt.h = 10.4 - with pytest.raises(TypeError): - rt.x = "point" - with pytest.raises(TypeError): - rt.y = "point" - with pytest.raises(TypeError): - rt.w = "point" - with pytest.raises(TypeError): - rt.h = "point" - with pytest.raises(TypeError): - rt.x = None - with pytest.raises(TypeError): - rt.y = None - with pytest.raises(TypeError): - rt.w = None - with pytest.raises(TypeError): - rt.h = None - def test_SDL_Rect__repr__(self): + bad_inputs = [10.4, "point", None] + for val in bad_inputs: + with pytest.raises(TypeError): + rt.x = val + with pytest.raises(TypeError): + rt.y = val + with pytest.raises(TypeError): + rt.w = val + with pytest.raises(TypeError): + rt.h = val + + def test___repr__(self): rt = rect.SDL_Rect(1, 2, 3, 4) rt2 = eval("rect.%s" % repr(rt)) assert (rt.x, rt.y, rt.w, rt.h) == (rt2.x, rt2.y, rt2.w, rt2.h) assert rt == rt2 - def test_SDL_Rect__copy__(self): + def test___copy__(self): rt = rect.SDL_Rect() rt2 = copy.copy(rt) assert rt == rt2 @@ -212,7 +199,7 @@ def test_SDL_Rect__copy__(self): assert rt != rt2 assert rt3 == rt2 - def test_SDL_Rect__eq__(self): + def test___eq__(self): sdlr = rect.SDL_Rect assert sdlr() == sdlr() rects = [ @@ -225,7 +212,7 @@ def test_SDL_Rect__eq__(self): equal = sdlr(x1, y1, w1, h1) == sdlr(x2, y2, w2, h2) assert equal if same else not equal - def test_SDL_Rect__ne__(self): + def test___ne__(self): sdlr = rect.SDL_Rect assert sdlr() == sdlr() rects = [ @@ -243,7 +230,7 @@ def test_SDL_Rect__ne__(self): class TestSDLFRect(object): __tags__ = ["sdl"] - def test_SDL_FRect(self): + def test_init(self): rt = rect.SDL_FRect() assert (rt.x, rt.y, rt.w, rt.h) == (0, 0, 0, 0) for i in range(0, 50): @@ -254,7 +241,7 @@ def test_SDL_FRect(self): rt = rect.SDL_FRect(x, y, w, h) assert (rt.x, rt.y, rt.w, rt.h) == pytest.approx((x, y, w, h)) - def test_SDL_FRect_xywh(self): + def test_xywh(self): rt = rect.SDL_FRect() for i in range(0, 50): x = random.uniform(-1000, 1000) @@ -266,30 +253,25 @@ def test_SDL_FRect_xywh(self): rt.w = w rt.h = h assert (rt.x, rt.y, rt.w, rt.h) == pytest.approx((x, y, w, h)) - with pytest.raises(TypeError): - rt.x = "point" - with pytest.raises(TypeError): - rt.y = "point" - with pytest.raises(TypeError): - rt.w = "point" - with pytest.raises(TypeError): - rt.h = "point" - with pytest.raises(TypeError): - rt.x = None - with pytest.raises(TypeError): - rt.y = None - with pytest.raises(TypeError): - rt.w = None - with pytest.raises(TypeError): - rt.h = None - def test_SDL_FRect__repr__(self): + bad_inputs = ["point", None] + for val in bad_inputs: + with pytest.raises(TypeError): + rt.x = val + with pytest.raises(TypeError): + rt.y = val + with pytest.raises(TypeError): + rt.w = val + with pytest.raises(TypeError): + rt.h = val + + def test___repr__(self): rt = rect.SDL_FRect(1.5, 2.2, 3.8, 4.9) rt2 = eval("rect.%s" % repr(rt)) assert (rt.x, rt.y, rt.w, rt.h) == (rt2.x, rt2.y, rt2.w, rt2.h) assert rt == rt2 - def test_SDL_FRect__copy__(self): + def test___copy__(self): rt = rect.SDL_FRect() rt2 = copy.copy(rt) assert rt == rt2 @@ -302,7 +284,7 @@ def test_SDL_FRect__copy__(self): assert rt != rt2 assert rt3 == rt2 - def test_SDL_FRect__eq__(self): + def test___eq__(self): sdlr = rect.SDL_FRect assert sdlr() == sdlr() rects = [ @@ -315,7 +297,7 @@ def test_SDL_FRect__eq__(self): equal = sdlr(x1, y1, w1, h1) == sdlr(x2, y2, w2, h2) assert equal if same else not equal - def test_SDL_FRect__ne__(self): + def test___ne__(self): sdlr = rect.SDL_FRect assert sdlr() == sdlr() rects = [ diff --git a/sdl2/test/render_test.py b/sdl2/test/render_test.py index c79faa22..07be3a7f 100644 --- a/sdl2/test/render_test.py +++ b/sdl2/test/render_test.py @@ -13,16 +13,86 @@ from sdl2.ext.compat import byteify, stringify from sdl2.ext.pixelaccess import PixelView -# TODO: Ensure all functions in module have corresponding tests # TODO: Write tests for more functions -# TODO: Mostly positive tests, improve this! -_ISPYPY = hasattr(sys, "pypy_version_info") -if _ISPYPY: - import gc - dogc = gc.collect -else: - dogc = lambda: None +def _create_window(pos, size, flags=video.SDL_WINDOW_HIDDEN): + # Convenience function to create renderer and window for tests + sdl2.SDL_ClearError() + window = video.SDL_CreateWindow( + b"Test", pos[0], pos[1], size[0], size[1], video.SDL_WINDOW_HIDDEN + ) + assert SDL_GetError() == b"" + assert isinstance(window.contents, video.SDL_Window) + return window + +def _get_renderflags(): + flags = render.SDL_RENDERER_ACCELERATED + if video.SDL_GetCurrentVideoDriver() == b"dummy": + flags = render.SDL_RENDERER_SOFTWARE + return flags + +@pytest.fixture +def testsurf(with_sdl): + # Create a solid black surface for tests + sf = surface.SDL_CreateRGBSurface( + 0, 100, 100, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF + ) + assert SDL_GetError() == b"" + pixfmt = sf.contents.format.contents + fill = pixels.SDL_MapRGBA(pixfmt, 0, 0, 0, 255) + surface.SDL_FillRect(sf, None, fill) + assert SDL_GetError() == b"" + yield sf + surface.SDL_FreeSurface(sf) + +@pytest.fixture +def sw_renderer(testsurf): + renderer = render.SDL_CreateSoftwareRenderer(testsurf) + assert SDL_GetError() == b"" + assert isinstance(renderer.contents, render.SDL_Renderer) + yield (renderer, testsurf) + render.SDL_DestroyRenderer(renderer) + +@pytest.fixture +def with_renderer(with_sdl): + flags = _get_renderflags() + sdl2.SDL_ClearError() + window = video.SDL_CreateWindow( + b"Test", 30, 30, 100, 100, video.SDL_WINDOW_HIDDEN + ) + assert SDL_GetError() == b"" + renderer = render.SDL_CreateRenderer(window, -1, flags) + assert SDL_GetError() == b"" + yield (renderer, window) + render.SDL_DestroyRenderer(renderer) + video.SDL_DestroyWindow(window) + +@pytest.fixture +def texture(with_renderer): + renderer, win = with_renderer + fmt = pixels.SDL_PIXELFORMAT_ARGB8888 + access = render.SDL_TEXTUREACCESS_STREAMING + tx = render.SDL_CreateTexture(renderer, fmt, access, 16, 16) + assert SDL_GetError() == b"" + assert isinstance(tx.contents, render.SDL_Texture) + yield tx + render.SDL_DestroyTexture(tx) + + +# Test structs and classes + +def test_SDL_RendererInfo(): + # Tested extensively in SDL_GetRenderDriverInfo + info = render.SDL_RendererInfo() + assert isinstance(info, render.SDL_RendererInfo) + +def test_SDL_Renderer(): + val = render.SDL_Renderer() + assert isinstance(val, render.SDL_Renderer) + +def test_SDL_Texture(): + val = render.SDL_Texture() + assert isinstance(val, render.SDL_Texture) class TestSDLVertex(object): @@ -74,1087 +144,727 @@ def test_copy(self): assert vtx.tex_coord != vtx2.tex_coord +# Test SDL2 renderer bindings -def _create_renderer(pos, size, renderer_num, flags): - # Convenience function to create renderer and window for tests - sdl2.SDL_ClearError() - window = video.SDL_CreateWindow( - b"Test", pos[0], pos[1], size[0], size[1], video.SDL_WINDOW_HIDDEN - ) - assert SDL_GetError() == b"" - renderer = render.SDL_CreateRenderer(window, renderer_num, flags) - assert SDL_GetError() == b"" - return (renderer, window) - -def _software_renderer(height, width): - # Convenience function to create a renderer and its target surface - sdl2.SDL_ClearError() - target = surface.SDL_CreateRGBSurface(0, height, width, 32, 0, 0, 0, 0) - assert SDL_GetError() == b"" - renderer = render.SDL_CreateSoftwareRenderer(target) - assert SDL_GetError() == b"" - return (renderer, target) - -def _cleanup_renderer(renderer, target): - sdl2.SDL_DestroyRenderer(renderer) - if type(target.contents) == sdl2.SDL_Window: - video.SDL_DestroyWindow(target) - else: - sdl2.SDL_FreeSurface(target) - dogc() - +def test_SDL_GetNumRenderDrivers(with_sdl): + val = render.SDL_GetNumRenderDrivers() + assert val >= 1 -class TestSDLRender(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - cls._RENDERFLAGS = render.SDL_RENDERER_ACCELERATED - SDL_Init(SDL_INIT_EVERYTHING) - driver = video.SDL_GetCurrentVideoDriver() - if driver is None: - raise pytest.skip('Video subsystem not supported') - if driver == b"dummy": - cls._RENDERFLAGS = render.SDL_RENDERER_SOFTWARE - - @classmethod - def teardown_class(cls): - SDL_Quit() - - def setup_method(self): +def test_SDL_GetRenderDriverInfo(with_sdl): + renderers = [] + errs = [] + pxformats = {} + drivers = render.SDL_GetNumRenderDrivers() + for x in range(drivers): sdl2.SDL_ClearError() - - def test_SDL_RendererInfo(self): info = render.SDL_RendererInfo() - assert isinstance(info, render.SDL_RendererInfo) - - def test_SDL_Renderer(self): - val = render.SDL_Renderer() - assert isinstance(val, render.SDL_Renderer) - - def test_SDL_Texture(self): - val = render.SDL_Texture() - assert isinstance(val, render.SDL_Texture) - - def test_SDL_GetNumRenderDrivers(self): - val = render.SDL_GetNumRenderDrivers() - assert val >= 1 - - def test_SDL_GetRenderDriverInfo(self): - renderers = [] - errs = [] - pxformats = {} - drivers = render.SDL_GetNumRenderDrivers() - for x in range(drivers): - sdl2.SDL_ClearError() - info = render.SDL_RendererInfo() - ret = render.SDL_GetRenderDriverInfo(x, info) - if ret != 0: - err = stringify(sdl2.SDL_GetError()) - errs.append("Renderer {0} error: {1}".format(x, err)) - continue - rname = stringify(info.name) - renderers.append(rname) - pxformats[rname] = [] - for i in range(info.num_texture_formats): - fmt_name = pixels.SDL_GetPixelFormatName(info.texture_formats[i]) - pxformats[rname].append(stringify(fmt_name).split("_")[-1]) - assert len(renderers) - assert "software" in renderers - print("Render drivers supported by current SDL2 binary:") - print(renderers) - print("\nTexture formats supported by each renderer:") - for rname in renderers: - print(rname) - print(" - " + " ".join(pxformats[rname])) - - def test_SDL_CreateWindowAndRenderer(self): - window = POINTER(video.SDL_Window)() - renderer = POINTER(render.SDL_Renderer)() - ret = render.SDL_CreateWindowAndRenderer \ - (10, 10, video.SDL_WINDOW_HIDDEN, byref(window), byref(renderer)) - assert ret == 0 - - render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - dogc() - - def test_SDL_CreateDestroyRenderer(self): - failed = 0 - rcount = render.SDL_GetNumRenderDrivers() - for i in range(rcount): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_SHOWN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, i, self._RENDERFLAGS) - if not (renderer and renderer.contents): - failed += 1 - video.SDL_DestroyWindow(window) - continue + ret = render.SDL_GetRenderDriverInfo(x, info) + if ret != 0: + err = stringify(sdl2.SDL_GetError()) + errs.append("Renderer {0} error: {1}".format(x, err)) + continue + rname = stringify(info.name) + renderers.append(rname) + pxformats[rname] = [] + for i in range(info.num_texture_formats): + fmt_name = pixels.SDL_GetPixelFormatName(info.texture_formats[i]) + pxformats[rname].append(stringify(fmt_name).split("_")[-1]) + assert len(renderers) + assert "software" in renderers + print("Render drivers supported by current SDL2 binary:") + print(renderers) + print("\nTexture formats supported by each renderer:") + for rname in renderers: + print(rname) + print(" - " + " ".join(pxformats[rname])) + +def test_SDL_CreateWindowAndRenderer(with_sdl): + window = POINTER(video.SDL_Window)() + renderer = POINTER(render.SDL_Renderer)() + ret = render.SDL_CreateWindowAndRenderer( + 10, 10, video.SDL_WINDOW_HIDDEN, byref(window), byref(renderer) + ) + render.SDL_DestroyRenderer(renderer) + video.SDL_DestroyWindow(window) + assert SDL_GetError() == b"" + assert ret == 0 + +def test_SDL_CreateDestroyRenderer(with_sdl): + flags = _get_renderflags() + errs = {} + rcount = render.SDL_GetNumRenderDrivers() + for i in range(rcount): + window = _create_window((30, 30), (100, 100)) + renderer = render.SDL_CreateRenderer(window, i, flags) + if (renderer and renderer.contents): assert isinstance(renderer.contents, render.SDL_Renderer) render.SDL_DestroyRenderer(renderer) + else: + name = "Renderer {0}".format(i) + errs[name] = stringify(sdl2.SDL_GetError()) + video.SDL_DestroyWindow(window) + assert rcount > len(errs.keys()) # Make sure at least one working renderer - # TODO: using -1 as index for the call below leads to random - # access violations on Win32 - renderer = render.SDL_CreateRenderer(window, i, - render.SDL_RENDERER_SOFTWARE) - assert isinstance(renderer.contents, render.SDL_Renderer) - render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - assert not (failed == rcount), "could not create a renderer" - dogc() - - def test_SDL_CreateSoftwareRenderer(self): - sf = surface.SDL_CreateRGBSurface(0, 100, 100, 32, - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF) - renderer = render.SDL_CreateSoftwareRenderer(sf) - assert isinstance(renderer.contents, render.SDL_Renderer) - render.SDL_DestroyRenderer(renderer) - surface.SDL_FreeSurface(sf) - - #self.assertRaises((AttributeError, TypeError), - # render.SDL_CreateSoftwareRenderer, None) - #self.assertRaises((AttributeError, TypeError), - # render.SDL_CreateSoftwareRenderer, 1234) - - def test_SDL_GetRenderer(self): - failed = 0 - rcount = render.SDL_GetNumRenderDrivers() - for i in range(rcount): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_GetRenderer(window) - assert not renderer - renderer = render.SDL_CreateRenderer(window, i, self._RENDERFLAGS) - if not (renderer and renderer.contents): - failed += 1 - video.SDL_DestroyWindow(window) - continue +def test_SDL_CreateSoftwareRenderer(with_sdl): + sf = surface.SDL_CreateRGBSurface( + 0, 100, 100, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF + ) + renderer = render.SDL_CreateSoftwareRenderer(sf) + assert SDL_GetError() == b"" + assert isinstance(renderer.contents, render.SDL_Renderer) + render.SDL_DestroyRenderer(renderer) + surface.SDL_FreeSurface(sf) + +def test_SDL_GetRenderer(with_sdl): + flags = _get_renderflags() + usable = 0 + rcount = render.SDL_GetNumRenderDrivers() + for i in range(rcount): + window = _create_window((30, 30), (100, 100)) + renderer = render.SDL_CreateRenderer(window, i, flags) + if (renderer and renderer.contents): + usable += 1 ren = render.SDL_GetRenderer(window) + assert SDL_GetError() == b"" assert isinstance(ren.contents, render.SDL_Renderer) render.SDL_DestroyRenderer(renderer) assert not render.SDL_GetRenderer(window) - - video.SDL_DestroyWindow(window) - assert not render.SDL_GetRenderer(window) - #self.assertRaises((AttributeError, TypeError), - # render.SDL_GetRenderer, None) - #self.assertRaises((AttributeError, TypeError), - # render.SDL_GetRenderer, "Test") - assert not (failed == rcount), "could not create a renderer" - dogc() - - def test_SDL_GetRendererInfo(self): - renderers = [] - max_sizes = {} - errs = [] - rcount = render.SDL_GetNumRenderDrivers() - for i in range(rcount): - sdl2.SDL_ClearError() - window = video.SDL_CreateWindow( - b"Test", 10, 10, 10, 10, video.SDL_WINDOW_HIDDEN - ) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, i, self._RENDERFLAGS) - if not (renderer and renderer.contents): - err = stringify(sdl2.SDL_GetError()) - errs.append("Unable to create renderer {0}: {1}".format(i, err)) - video.SDL_DestroyWindow(window) - continue - assert isinstance(renderer.contents, render.SDL_Renderer) - info = render.SDL_RendererInfo() - ret = render.SDL_GetRendererInfo(renderer, byref(info)) - if ret == 0: - rname = stringify(info.name) - max_size = (info.max_texture_width, info.max_texture_height) - renderers.append(rname) - max_sizes[rname] = max_size - else: - err = stringify(sdl2.SDL_GetError()) - errs.append("Renderer {0} error: {1}".format(i, err)) - render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - dogc() - - assert len(renderers) - assert "software" in renderers - print("Render drivers loadable on the current system:") - for rname in renderers: - w, h = max_sizes[rname] - print(" - " + rname + " (max texture size: {0}x{1})".format(w, h)) - - def test_SDL_CreateDestroyTexture(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, -1, self._RENDERFLAGS) - assert isinstance(renderer.contents, render.SDL_Renderer) - - formats = (pixels.SDL_PIXELFORMAT_ARGB8888, - pixels.SDL_PIXELFORMAT_RGB555, - pixels.SDL_PIXELFORMAT_RGBA4444, - pixels.SDL_PIXELFORMAT_RGBA8888, - pixels.SDL_PIXELFORMAT_ARGB2101010, - pixels.SDL_PIXELFORMAT_YUY2 - ) - access = (render.SDL_TEXTUREACCESS_STATIC, - render.SDL_TEXTUREACCESS_STREAMING, - render.SDL_TEXTUREACCESS_TARGET) - for fmt in formats: - for acc in access: - for w in range(1, 300, 5): - for h in range(1, 300, 5): - tex = render.SDL_CreateTexture(renderer, fmt, acc, - w, h) - assert isinstance(tex.contents, render.SDL_Texture) - render.SDL_DestroyTexture(tex) - if (w % 50) == 0: - dogc() - - #self.assertRaises(sdl.SDLError, render.SDL_CreateTexture, renderer, - # pixels.SDL_PIXELFORMAT_RGB555, 1, -10, 10) - #self.assertRaises(sdl.SDLError, render.SDL_CreateTexture, renderer, - # pixels.SDL_PIXELFORMAT_RGB555, 1, 10, -10) - #self.assertRaises(sdl.SDLError, render.SDL_CreateTexture, renderer, - # pixels.SDL_PIXELFORMAT_RGB555, 1, -10, -10) - #self.assertRaises(ValueError, render.SDL_CreateTexture, renderer, - # pixels.SDL_PIXELFORMAT_RGB555, -5, 10, 10) - #self.assertRaises(ValueError, render.SDL_CreateTexture, renderer, - # - 10, 1, 10, 10) - #self.assertRaises((AttributeError, TypeError), - # render.SDL_CreateTexture, None, - # pixels.SDL_PIXELFORMAT_RGB555, 1, 10, 10) - #self.assertRaises((AttributeError, TypeError), - # render.SDL_CreateTexture, "Test", - # pixels.SDL_PIXELFORMAT_RGB555, 1, 10, 10) - #self.assertRaises(ValueError, render.SDL_CreateTexture, renderer, - # "Test", 1, 10, 10) - #self.assertRaises(ValueError, render.SDL_CreateTexture, renderer, - # pixels.SDL_PIXELFORMAT_RGB555, None, 10, 10) - #self.assertRaises(ValueError, render.SDL_CreateTexture, renderer, - # pixels.SDL_PIXELFORMAT_RGB555, "Test", 10, 10) - - render.SDL_DestroyRenderer(renderer) - #self.assertRaises(sdl.SDLError, render.SDL_CreateTexture, renderer, - # pixels.SDL_PIXELFORMAT_RGB555, 1, 10, 10) - video.SDL_DestroyWindow(window) - dogc() - - def test_SDL_CreateTextureFromSurface(self): - sf = surface.SDL_CreateRGBSurface(0, 100, 100, 32, 0xFF000000, - 0x00FF0000, 0x0000FF00, 0x000000FF) - assert isinstance(sf.contents, surface.SDL_Surface) - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, -1, self._RENDERFLAGS) - assert isinstance(renderer.contents, render.SDL_Renderer) - tex = render.SDL_CreateTextureFromSurface(renderer, sf) - assert isinstance(tex.contents, render.SDL_Texture) - dogc() - - def test_SDL_QueryTexture(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, -1, self._RENDERFLAGS) - assert isinstance(renderer.contents, render.SDL_Renderer) - - formats = (pixels.SDL_PIXELFORMAT_ARGB8888, - pixels.SDL_PIXELFORMAT_RGB555, - pixels.SDL_PIXELFORMAT_RGBA4444, - pixels.SDL_PIXELFORMAT_ARGB2101010, - pixels.SDL_PIXELFORMAT_YUY2 - ) - access = (render.SDL_TEXTUREACCESS_STATIC, - render.SDL_TEXTUREACCESS_STREAMING, - render.SDL_TEXTUREACCESS_TARGET) - for fmt in formats: - for acc in access: - for w in range(1, 300, 5): - for h in range(1, 300, 5): - tex = render.SDL_CreateTexture(renderer, fmt, acc, - w, h) - assert isinstance(tex.contents, render.SDL_Texture) - qf, qa, qw, qh = Uint32(), c_int(), c_int(), c_int() - ret = render.SDL_QueryTexture(tex, byref(qf), - byref(qa), byref(qw), - byref(qh)) - assert ret == 0 - assert qf.value == fmt - assert qa.value == acc - assert qw.value == w - assert qh.value == h - render.SDL_DestroyTexture(tex) - if _ISPYPY and (w % 50) == 0: - gc.collect() - - render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - dogc() - - def test_SDL_GetSetTextureColorMod(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, -1, self._RENDERFLAGS) - assert isinstance(renderer.contents, render.SDL_Renderer) - - tex = render.SDL_CreateTexture(renderer, - pixels.SDL_PIXELFORMAT_ARGB8888, - render.SDL_TEXTUREACCESS_STREAMING, - 10, 10) - assert isinstance(tex.contents, render.SDL_Texture) - colors = ((16, 22, 185), - (32, 64, 128), - (64, 32, 128), - (64, 32, 255), - (255, 32, 64), - (255, 32, 128), - (0, 0, 0), - (255, 255, 255), - (128, 128, 128), - ) - for r, g, b in colors: - ret = render.SDL_SetTextureColorMod(tex, r, g, b) - assert ret == 0 - tr, tg, tb = Uint8(), Uint8(), Uint8() - ret = render.SDL_GetTextureColorMod(tex, byref(tr), byref(tg), - byref(tb)) - assert ret == 0 - assert (tr.value, tg.value, tb.value) == (r, g, b) - - render.SDL_DestroyTexture(tex) - #self.assertRaises(sdl.SDLError, render.SDL_SetTextureColorMod, tex, - # 10, 20, 30) - #self.assertRaises(sdl.SDLError, render.SDL_GetTextureColorMod, tex) - - render.SDL_DestroyRenderer(renderer) video.SDL_DestroyWindow(window) - dogc() - - def test_SDL_GetSetTextureAlphaMod(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, -1, self._RENDERFLAGS) - assert isinstance(renderer.contents, render.SDL_Renderer) - - tex = render.SDL_CreateTexture(renderer, - pixels.SDL_PIXELFORMAT_ARGB8888, - render.SDL_TEXTUREACCESS_STREAMING, - 10, 10) - assert isinstance(tex.contents, render.SDL_Texture) - - for alpha in range(0, 255): - ret = render.SDL_SetTextureAlphaMod(tex, alpha) - assert ret == 0 - talpha = Uint8() - ret = render.SDL_GetTextureAlphaMod(tex, byref(talpha)) - assert ret == 0 - assert talpha.value == alpha - - render.SDL_DestroyTexture(tex) - #self.assertRaises(sdl.SDLError, render.SDL_SetTextureColorMod, tex, - # 10, 20, 30) - #self.assertRaises(sdl.SDLError, render.SDL_GetTextureColorMod, tex) - - render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - dogc() - - def test_SDL_GetSetTextureBlendMode(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, -1, self._RENDERFLAGS) + assert usable > 0 + +def test_SDL_GetRendererInfo(with_sdl): + renderers = [] + max_sizes = {} + errs = [] + flags = _get_renderflags() + rcount = render.SDL_GetNumRenderDrivers() + for i in range(rcount): + sdl2.SDL_ClearError() + window = _create_window((30, 30), (100, 100)) + renderer = render.SDL_CreateRenderer(window, i, flags) + if not (renderer and renderer.contents): + err = stringify(sdl2.SDL_GetError()) + errs.append("Unable to create renderer {0}: {1}".format(i, err)) + video.SDL_DestroyWindow(window) + continue assert isinstance(renderer.contents, render.SDL_Renderer) - - tex = render.SDL_CreateTexture(renderer, - pixels.SDL_PIXELFORMAT_ARGB8888, - render.SDL_TEXTUREACCESS_STREAMING, - 10, 10) - assert isinstance(tex.contents, render.SDL_Texture) - - modes = (blendmode.SDL_BLENDMODE_NONE, - blendmode.SDL_BLENDMODE_ADD, - blendmode.SDL_BLENDMODE_BLEND, - blendmode.SDL_BLENDMODE_MOD, - ) - for mode in modes: - ret = render.SDL_SetTextureBlendMode(tex, mode) - assert ret == 0 - tmode = blendmode.SDL_BlendMode() - ret = render.SDL_GetTextureBlendMode(tex, byref(tmode)) - assert ret == 0 - assert tmode.value == mode - - render.SDL_DestroyTexture(tex) - #self.assertRaises(sdl.SDLError, render.SDL_SetTextureBlendMode, tex, - # modes[2]) - #self.assertRaises(sdl.SDLError, render.SDL_GetTextureBlendMode, tex) - + info = render.SDL_RendererInfo() + ret = render.SDL_GetRendererInfo(renderer, byref(info)) + if ret == 0: + rname = stringify(info.name) + max_size = (info.max_texture_width, info.max_texture_height) + renderers.append(rname) + max_sizes[rname] = max_size + else: + err = stringify(sdl2.SDL_GetError()) + errs.append("Renderer {0} error: {1}".format(i, err)) render.SDL_DestroyRenderer(renderer) video.SDL_DestroyWindow(window) - dogc() - - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_GetSetTextureScaleMode(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, -1, self._RENDERFLAGS) - assert isinstance(renderer.contents, render.SDL_Renderer) - - tex = render.SDL_CreateTexture( - renderer, pixels.SDL_PIXELFORMAT_ARGB8888, - render.SDL_TEXTUREACCESS_STREAMING, 10, 10 + assert len(renderers) + assert "software" in renderers + print("Render drivers loadable on the current system:") + for rname in renderers: + w, h = max_sizes[rname] + print(" - " + rname + " (max texture size: {0}x{1})".format(w, h)) + +@pytest.mark.skip("not implemented") +def test_SDL_GetRendererOutputSize(self): + pass + +def test_SDL_CreateDestroyTexture(with_renderer): + renderer, win = with_renderer + formats = ( + pixels.SDL_PIXELFORMAT_ARGB8888, + pixels.SDL_PIXELFORMAT_RGB555, + pixels.SDL_PIXELFORMAT_RGBA4444, + pixels.SDL_PIXELFORMAT_RGBA8888, + pixels.SDL_PIXELFORMAT_ARGB2101010, + pixels.SDL_PIXELFORMAT_YUY2, + ) + access = ( + render.SDL_TEXTUREACCESS_STATIC, + render.SDL_TEXTUREACCESS_STREAMING, + render.SDL_TEXTUREACCESS_TARGET, + ) + sizes = [(4, 4), (7, 7), (64, 32), (256, 256), (512, 512)] + for fmt in formats: + for acc in access: + for w, h in sizes: + tx = render.SDL_CreateTexture(renderer, fmt, acc, w, h) + assert SDL_GetError() == b"" + assert isinstance(tx.contents, render.SDL_Texture) + render.SDL_DestroyTexture(tx) + # Test SDL error on bad input + render.SDL_CreateTexture( + renderer, pixels.SDL_PIXELFORMAT_RGB555, 1, -8, 8 + ) + assert len(SDL_GetError()) > 0 + +def test_SDL_CreateTextureFromSurface(with_renderer, testsurf): + renderer, win = with_renderer + tx = render.SDL_CreateTextureFromSurface(renderer, testsurf) + if sdl2.dll.version != 2008: # Weird non-fatal colorkey error on 2.0.8 + assert SDL_GetError() == b"" + assert isinstance(tx.contents, render.SDL_Texture) + render.SDL_DestroyTexture(tx) + +def test_SDL_QueryTexture(with_renderer): + renderer, win = with_renderer + formats = ( + pixels.SDL_PIXELFORMAT_ARGB8888, + pixels.SDL_PIXELFORMAT_RGB555, + pixels.SDL_PIXELFORMAT_RGBA4444, + pixels.SDL_PIXELFORMAT_RGBA8888, + pixels.SDL_PIXELFORMAT_ARGB2101010, + pixels.SDL_PIXELFORMAT_YUY2, + ) + access = ( + render.SDL_TEXTUREACCESS_STATIC, + render.SDL_TEXTUREACCESS_STREAMING, + render.SDL_TEXTUREACCESS_TARGET, + ) + sizes = [(4, 4), (7, 7), (64, 32), (256, 256), (512, 512)] + for fmt in formats: + for acc in access: + for w, h in sizes: + tx = render.SDL_CreateTexture(renderer, fmt, acc, w, h) + assert isinstance(tx.contents, render.SDL_Texture) + txf, txa, txw, txh = Uint32(0), c_int(0), c_int(0), c_int(0) + ret = render.SDL_QueryTexture( + tx, byref(txf), byref(txa), byref(txw), byref(txh) + ) + assert SDL_GetError() == b"" + assert ret == 0 + assert txf.value == fmt + assert txa.value == acc + assert txw.value == w + assert txh.value == h + render.SDL_DestroyTexture(tx) + +def test_SDL_GetSetTextureColorMod(texture): + colors = [ + (16, 22, 185), + (32, 64, 128), + (64, 32, 128), + (64, 32, 255), + (255, 32, 128), + (255, 255, 255), + (128, 128, 128), + (0, 0, 0), + ] + for r, g, b in colors: + ret = render.SDL_SetTextureColorMod(texture, r, g, b) + assert SDL_GetError() == b"" + assert ret == 0 + tr, tg, tb = Uint8(0), Uint8(0), Uint8(0) + ret = render.SDL_GetTextureColorMod( + texture, byref(tr), byref(tg), byref(tb) ) - assert isinstance(tex.contents, render.SDL_Texture) - - modes = (render.SDL_ScaleModeNearest, render.SDL_ScaleModeLinear, - render.SDL_ScaleModeBest) - for mode in modes: - ret = render.SDL_SetTextureScaleMode(tex, mode) - assert ret == 0 - tmode = render.SDL_ScaleMode() - ret = render.SDL_GetTextureScaleMode(tex, byref(tmode)) - assert ret == 0 - assert tmode.value == mode - - render.SDL_DestroyTexture(tex) - render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - dogc() + assert SDL_GetError() == b"" + assert ret == 0 + assert (tr.value, tg.value, tb.value) == (r, g, b) - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_GetSetTextureUserData(self): - renderer, win = _create_renderer( - (30, 30), (100, 100), -1, self._RENDERFLAGS - ) - tex = render.SDL_CreateTexture( - renderer, pixels.SDL_PIXELFORMAT_ARGB8888, - render.SDL_TEXTUREACCESS_STREAMING, 10, 10 - ) +def test_SDL_GetSetTextureAlphaMod(texture): + for alpha in range(0, 255, 7): + ret = render.SDL_SetTextureAlphaMod(texture, alpha) assert SDL_GetError() == b"" - # Create some user data and add it to the texture - dat_raw = ctypes.c_char_p(b"hello!") - dat = ctypes.cast(dat_raw, ctypes.c_void_p) - ret = render.SDL_SetTextureUserData(tex, dat) + assert ret == 0 + talpha = Uint8(0) + ret = render.SDL_GetTextureAlphaMod(texture, byref(talpha)) assert SDL_GetError() == b"" assert ret == 0 - # Try retrieving the user data - dat_ptr = render.SDL_GetTextureUserData(tex) + assert talpha.value == alpha + +def test_SDL_GetSetTextureBlendMode(texture): + modes = ( + blendmode.SDL_BLENDMODE_NONE, + blendmode.SDL_BLENDMODE_ADD, + blendmode.SDL_BLENDMODE_BLEND, + blendmode.SDL_BLENDMODE_MOD, + ) + for mode in modes: + ret = render.SDL_SetTextureBlendMode(texture, mode) assert SDL_GetError() == b"" - assert dat_ptr != None - dat_out = ctypes.cast(dat_ptr, ctypes.c_char_p) - assert dat_raw.value == dat_out.value - render.SDL_DestroyTexture(tex) - _cleanup_renderer(renderer, win) - - @pytest.mark.skip("not implemented") - def test_SDL_UpdateTexture(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_UpdateYUVTexture(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_UpdateNVTexture(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") - def test_SDL_LockTextureToSurface(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_LockUnlockTexture(self): - pass - - def test_SDL_RenderTargetSupported(self): - failed = 0 - rcount = render.SDL_GetNumRenderDrivers() - for i in range(rcount): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, i, self._RENDERFLAGS) - if not (renderer and renderer.contents): - failed += 1 - video.SDL_DestroyWindow(window) - continue + assert ret == 0 + tmode = blendmode.SDL_BlendMode() + ret = render.SDL_GetTextureBlendMode(texture, byref(tmode)) + assert SDL_GetError() == b"" + assert ret == 0 + assert tmode.value == mode + +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_GetSetTextureScaleMode(texture): + modes = ( + render.SDL_ScaleModeNearest, + render.SDL_ScaleModeLinear, + render.SDL_ScaleModeBest, + ) + for mode in modes: + ret = render.SDL_SetTextureScaleMode(texture, mode) + assert SDL_GetError() == b"" + assert ret == 0 + tmode = render.SDL_ScaleMode() + ret = render.SDL_GetTextureScaleMode(texture, byref(tmode)) + assert SDL_GetError() == b"" + assert ret == 0 + assert tmode.value == mode + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_GetSetTextureUserData(texture): + # Create some user data and add it to the texture + dat_raw = ctypes.c_char_p(b"hello!") + dat = ctypes.cast(dat_raw, ctypes.c_void_p) + ret = render.SDL_SetTextureUserData(texture, dat) + assert SDL_GetError() == b"" + assert ret == 0 + # Try retrieving the user data + dat_ptr = render.SDL_GetTextureUserData(texture) + assert SDL_GetError() == b"" + assert dat_ptr != None + dat_out = ctypes.cast(dat_ptr, ctypes.c_char_p) + assert dat_raw.value == dat_out.value + +@pytest.mark.skip("not implemented") +def test_SDL_UpdateTexture(texture): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_UpdateYUVTexture(with_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_UpdateNVTexture(with_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_LockUnlockTexture(texture): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2012, reason="not available") +def test_SDL_LockTextureToSurface(texture): + pass + +def test_SDL_RenderTargetSupported(with_sdl): + flags = _get_renderflags() + usable = 0 + rcount = render.SDL_GetNumRenderDrivers() + for i in range(rcount): + window = _create_window((30, 30), (100, 100)) + renderer = render.SDL_CreateRenderer(window, i, flags) + if (renderer and renderer.contents): + usable += 1 assert isinstance(renderer.contents, render.SDL_Renderer) - val = render.SDL_RenderTargetSupported(renderer) + assert SDL_GetError() == b"" assert val in (SDL_TRUE, SDL_FALSE) render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - assert not (failed == rcount), "could not create a renderer" - dogc() - - def test_SDL_GetSetRenderTarget(self): - skipcount = 0 - failed = 0 - rcount = render.SDL_GetNumRenderDrivers() - for i in range(rcount): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, i, self._RENDERFLAGS) - if not (renderer and renderer.contents): - failed += 1 - video.SDL_DestroyWindow(window) - continue - assert isinstance(renderer.contents, render.SDL_Renderer) - - supported = render.SDL_RenderTargetSupported(renderer) - if not supported: - skipcount += 1 - render.SDL_DestroyRenderer(renderer) - continue - - ret = render.SDL_SetRenderTarget(renderer, None) - assert ret == 0 - assert not render.SDL_GetRenderTarget(renderer) - - tex = render.SDL_CreateTexture(renderer, - pixels.SDL_PIXELFORMAT_ARGB8888, - render.SDL_TEXTUREACCESS_TARGET, - 10, 10) - ret = render.SDL_SetRenderTarget(renderer, tex) - assert ret == 0 - tgt = render.SDL_GetRenderTarget(renderer) - assert isinstance(tgt.contents, render.SDL_Texture) - render.SDL_DestroyTexture(tex) - - # TODO: Check in the SDL codebase, why the code below does - # not fail... - # tex2 = render.SDL_CreateTexture(renderer, - # pixels.SDL_PIXELFORMAT_ARGB8888, - # render.SDL_TEXTUREACCESS_STREAMING, - # 10, 10) - # self.assertRaises(SDLError, render.SDL_SetRenderTarget, renderer, - # tex2) - # render.SDL_DestroyTexture(tex2) - - render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - - assert not (failed == rcount), "could not create a renderer" - if skipcount == rcount: - pytest.skip("None of the renderers supports render targets") - dogc() - - def test_SDL_RenderGetSetViewport(self): - rects = (rect.SDL_Rect(0, 0, 0, 0), - rect.SDL_Rect(0, 0, 10, 10), - rect.SDL_Rect(3, 3, 5, 5), - rect.SDL_Rect(-5, -5, 10, 10), - rect.SDL_Rect(10, 10, 10, 10), - rect.SDL_Rect(0, 0, -10, -10), - rect.SDL_Rect(-10, 0, 10, 10), - rect.SDL_Rect(0, -10, 10, 10), - rect.SDL_Rect(-10, -10, 10, 10), - ) - failcount = 0 - port = rect.SDL_Rect() - failed = 0 - rcount = render.SDL_GetNumRenderDrivers() - for i in range(rcount): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN | - video.SDL_WINDOW_BORDERLESS) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, i, self._RENDERFLAGS) - if not (renderer and renderer.contents): - failed += 1 - video.SDL_DestroyWindow(window) - continue - assert isinstance(renderer.contents, render.SDL_Renderer) - ret = render.SDL_RenderSetViewport(renderer, None) - assert ret == 0 - render.SDL_RenderGetViewport(renderer, byref(port)) - assert port == rect.SDL_Rect(0, 0, 10, 10) - for r in rects: - if r.w == r.h == 0: - # http://bugzilla.libsdl.org/show_bug.cgi?id=1622 - # OpenGL renderers cause a exception here. - continue - ret = render.SDL_RenderSetViewport(renderer, r) - assert ret == 0 - render.SDL_RenderGetViewport(renderer, byref(port)) - if port != r: - failcount += 1 - - render.SDL_DestroyRenderer(renderer) - video.SDL_DestroyWindow(window) - - assert not (failed == rcount), "could not create a renderer" - errmsg = ("For some reason, even with correct values, this seems to " - "fail on creating the second renderer of the window, if any") - if failcount > 0: - pytest.skip(errmsg) - dogc() - - def test_SDL_GetSetRenderDrawColor(self): - failed = 0 - rcount = render.SDL_GetNumRenderDrivers() - for i in range(rcount): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, i, self._RENDERFLAGS) - if not (renderer and renderer.contents): - failed += 1 - video.SDL_DestroyWindow(window) - continue - assert isinstance(renderer.contents, render.SDL_Renderer) - - colors = ((16, 22, 185, 217), - (32, 64, 128, 255), - (64, 32, 128, 255), - (64, 32, 255, 128), - (255, 32, 64, 128), - (255, 32, 128, 64), - (0, 0, 0, 0), - (255, 255, 255, 255), - (128, 128, 128, 255), - ) - for r, g, b, a in colors: - ret = render.SDL_SetRenderDrawColor(renderer, r, g, b, a) - assert ret == 0 - dr, dg, db, da = Uint8(), Uint8(), Uint8(), Uint8() - ret = render.SDL_GetRenderDrawColor(renderer, byref(dr), - byref(dg), byref(db), - byref(da)) - assert ret == 0 - assert (dr.value, dg.value, db.value, da.value) == (r, g, b, a) - render.SDL_DestroyRenderer(renderer) - #self.assertRaises(sdl.SDLError, render.SDL_SetRenderDrawColor, - # renderer, 10, 20, 30, 40) - #self.assertRaises(sdl.SDLError, render.SDL_GetRenderDrawColor, - # renderer) - video.SDL_DestroyWindow(window) - assert not (failed == rcount), "could not create a renderer" - dogc() - - def test_SDL_GetSetRenderDrawBlendMode(self): - failed = 0 - rcount = render.SDL_GetNumRenderDrivers() - for i in range(rcount): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, i, self._RENDERFLAGS) - if not (renderer and renderer.contents): - failed += 1 - video.SDL_DestroyWindow(window) - continue + video.SDL_DestroyWindow(window) + assert usable > 0 + +def test_SDL_GetSetRenderTarget(with_sdl): + # First, determine which renderers support render targets + flags = _get_renderflags() + usable = 0 + supports_targets = [] + rcount = render.SDL_GetNumRenderDrivers() + for i in range(rcount): + window = _create_window((30, 30), (100, 100)) + renderer = render.SDL_CreateRenderer(window, i, flags) + if (renderer and renderer.contents): + usable += 1 assert isinstance(renderer.contents, render.SDL_Renderer) - - modes = (blendmode.SDL_BLENDMODE_NONE, - blendmode.SDL_BLENDMODE_ADD, - blendmode.SDL_BLENDMODE_BLEND, - blendmode.SDL_BLENDMODE_MOD, - ) - for mode in modes: - ret = render.SDL_SetRenderDrawBlendMode(renderer, mode) - bmode = blendmode.SDL_BlendMode() - ret = render.SDL_GetRenderDrawBlendMode(renderer, byref(bmode)) - assert ret == 0 - assert bmode.value == mode + if render.SDL_RenderTargetSupported(renderer) == SDL_TRUE: + supports_targets.append(i) render.SDL_DestroyRenderer(renderer) - #self.assertRaises(sdl.SDLError, render.SDL_SetRenderDrawBlendMode, - # renderer, video.SDL_BLENDMODE_ADD) - #self.assertRaises(sdl.SDLError, render.SDL_GetRenderDrawBlendMode, - # renderer) - video.SDL_DestroyWindow(window) - assert not (failed == rcount), "could not create a renderer" - dogc() - - def test_SDL_RenderClear(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - assert isinstance(window.contents, video.SDL_Window) - renderer = render.SDL_CreateRenderer(window, -1, self._RENDERFLAGS) - assert isinstance(renderer.contents, render.SDL_Renderer) - - ret = render.SDL_RenderClear(renderer) - assert ret == 0 - render.SDL_DestroyRenderer(renderer) - #self.assertRaises(sdl.SDLError, render.SDL_RenderClear, renderer) -# self.assertRaises((AttributeError, TypeError), -# render.SDL_RenderClear, None) -# self.assertRaises((AttributeError, TypeError), -# render.SDL_RenderClear, "Test") -# self.assertRaises((AttributeError, TypeError), -# render.SDL_RenderClear, 123456) - dogc() - - def test_SDL_RenderDrawPoint(self): - points = ((-4, -3), (-4, 3), (4, -3), - (0, 0), (1, 1), (10, 10), (99, 99), - (4, 22), (57, 88), (45, 15), - (100, 100) - ) - r, g, b, a = 0xAA, 0xBB, 0xCC, 0xDD - w, h = 100, 100 - sf = surface.SDL_CreateRGBSurface(0, w, h, 32, 0xFF000000, 0x00FF0000, - 0x0000FF00, 0x000000FF) - color = pixels.SDL_MapRGBA(sf.contents.format, r, g, b, a) - renderer = render.SDL_CreateSoftwareRenderer(sf) - assert isinstance(renderer.contents, render.SDL_Renderer) - ret = render.SDL_SetRenderDrawColor(renderer, r, g, b, a) - assert ret == 0 - for x, y in points: - ret = render.SDL_RenderDrawPoint(renderer, x, y) - assert ret == 0 - render.SDL_RenderPresent(renderer) - view = PixelView(sf.contents) - for x, y in points: - npx = max(x + 1, w) - npy = max(y + 1, h) - ppx = max(x - 1, 0) - ppy = max(y - 1, 0) - if x < 0 or x >= w or y < 0 or y >= h: - continue - assert hex(view[y][x]) == hex(color) - if (npx, npy) not in points: - assert hex(view[npy][npx]) != hex(color) - if (ppx, ppy) not in points: - assert hex(view[ppy][ppx]) != hex(color) - render.SDL_DestroyRenderer(renderer) - del view - surface.SDL_FreeSurface(sf) - - @pytest.mark.skip("not implemented") - def test_SDL_RenderDrawPoints(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderDrawLine(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderDrawLines(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderDrawRect(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderDrawRects(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderFillRect(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderFillRects(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderCopy(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderCopyEx(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderDrawPointF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderDrawPointsF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderDrawLineF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderDrawLinesF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderDrawRectF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderDrawRectsF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderFillRectF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderFillRectsF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderCopyF(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderCopyExF(self): - pass - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_RenderGeometry(self): - renderer, target = _software_renderer(100, 100) - # Create vertices for rendering - RED = (255, 0, 0, 255) - vertices = [ - render.SDL_Vertex((0, 0), RED), - render.SDL_Vertex((0, 50), RED), - render.SDL_Vertex((50, 50), RED) - ] - # Try rendering the vertices - vtx = (render.SDL_Vertex * len(vertices))(*vertices) - ret = render.SDL_RenderGeometry( - renderer, None, vtx, len(vertices), None, 0 + video.SDL_DestroyWindow(window) + assert usable > 0 + if len(supports_targets) == 0: + pytest.skip("No available renderer supports targets") + + # For renderers that support render targets, try setting/getting one + pixfmt = pixels.SDL_PIXELFORMAT_ARGB8888 + for i in supports_targets: + window = _create_window((30, 30), (100, 100)) + renderer = render.SDL_CreateRenderer(window, i, flags) + # Try setting a texture as the render target + tex = render.SDL_CreateTexture( + renderer, pixfmt, render.SDL_TEXTUREACCESS_TARGET, 10, 10 ) + ret = render.SDL_SetRenderTarget(renderer, tex) assert SDL_GetError() == b"" assert ret == 0 - # TODO: Actually check the surface for the rendered triangle - _cleanup_renderer(renderer, target) - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_RenderGeometryRaw(self): - renderer, target = _software_renderer(100, 100) - # Create vertices for rendering - RED = SDL_Color(255, 0, 0, 255) - points = [0, 0, 0, 50, 50, 50] - colors = [RED, RED, RED] - tex_coords = [0, 0, 0, 0, 0, 0] - # Convert vertices to ctypes-friendly format - xy_size = sizeof(c_float) * 2 - col_size = sizeof(SDL_Color) - xy = (c_float * len(points))(*points) - col = (SDL_Color * len(colors))(*colors) - uv = (c_float * len(tex_coords))(*tex_coords) - # Try rendering the vertices - ret = render.SDL_RenderGeometryRaw( - renderer, None, - xy, xy_size, - col, col_size, - uv, xy_size, - 3, None, 0, 1 - ) + tgt = render.SDL_GetRenderTarget(renderer) assert SDL_GetError() == b"" + assert isinstance(tgt.contents, render.SDL_Texture) + # Try setting NULL as the render target (resets target to window) + ret = render.SDL_SetRenderTarget(renderer, None) assert ret == 0 - # TODO: Actually check the surface for the rendered triangle - _cleanup_renderer(renderer, target) - - @pytest.mark.skip("not implemented") - def test_SDL_RenderReadPixels(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderPresent(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_RenderFlush(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderGetSetScale(self): - pass - - def test_SDL_RenderGetSetLogicalSize(self): - w, h = 100, 100 - sf = surface.SDL_CreateRGBSurface(0, w, h, 32, - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF) - - renderer = render.SDL_CreateSoftwareRenderer(sf) - view = PixelView(sf.contents) - - magenta = 255, 0, 255, 255 - green = 0, 255, 0, 255 - - magenta_int = sum(c << (i * 8) for i, c in enumerate(reversed(magenta))) - green_int = sum(c << (i * 8) for i, c in enumerate(reversed(green))) - - def clear_green(): - ret = render.SDL_SetRenderDrawColor(renderer, green[0], green[1], - green[2], green[3]) - assert ret == 0 - ret = render.SDL_RenderClear(renderer) - assert ret == 0 - - def draw_magenta_pixel(x, y): - ret = render.SDL_SetRenderDrawColor(renderer, magenta[0], - magenta[1], magenta[2], - magenta[3]) - assert ret == 0 - ret = render.SDL_RenderDrawPoint(renderer, x, y) - assert ret == 0 - - # Test 1 - # If we set the logical renderer size to 1 x 1, drawing a point - # at 0, 0 should have the same effect as filling the entire - # (square) window with magenta - no green should show through. - got_width, got_height = c_int(), c_int() - - ret = render.SDL_RenderSetLogicalSize(renderer, 1, 1) - assert ret == 0 - render.SDL_RenderGetLogicalSize(renderer, byref(got_width), - byref(got_height)) - assert got_width.value == 1 - assert got_height.value == 1 - - clear_green() - draw_magenta_pixel(0, 0) - - for x, y in itertools.product(range(w), range(h)): - assert view[y][x] == magenta_int, 'No pixel should be green' + assert not render.SDL_GetRenderTarget(renderer) + # Clean up before the next renderer + render.SDL_DestroyTexture(tex) + render.SDL_DestroyRenderer(renderer) + video.SDL_DestroyWindow(window) - # Test 2 - # Reset the logical size to the original target by using 0, 0 - # only the first and last pixel should be magenta. The rest - # should be green. - got_width, got_height = c_int(), c_int() +def test_SDL_RenderGetSetLogicalSize(sw_renderer): + renderer, sf = sw_renderer + BLACK_RGBA = 0x000000FF + GREEN_RGBA = 0x00FF00FF - ret = render.SDL_RenderSetLogicalSize(renderer, 0, 0) + # Try setting the logical size to 1/10 of normal + ret = render.SDL_RenderSetLogicalSize(renderer, 10, 10) + assert SDL_GetError() == b"" + assert ret == 0 + lw, lh = c_int(0), c_int(0) + render.SDL_RenderGetLogicalSize(renderer, byref(lw), byref(lh)) + assert [lw.value, lh.value] == [10, 10] + + # Try drawing a single pixel to the renderer and see if fills 10x10 + ret = render.SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255) + assert ret == 0 + render.SDL_RenderDrawPoint(renderer, 1, 1) + view = PixelView(sf) + assert view[1][1] == BLACK_RGBA + assert view[10][10] == GREEN_RGBA + assert view[19][19] == GREEN_RGBA + assert view[9][9] == BLACK_RGBA + assert view[20][20] == BLACK_RGBA + + # Reset the logical size back to its original values and try drawing again + ret = render.SDL_RenderSetLogicalSize(renderer, 0, 0) + assert ret == 0 + render.SDL_RenderDrawPoint(renderer, 1, 1) + assert view[1][1] == GREEN_RGBA + assert view[0][0] == BLACK_RGBA + assert view[2][2] == BLACK_RGBA + del view + +def test_SDL_RenderGetSetViewport(sw_renderer): + renderer, sf = sw_renderer + rects = ( + rect.SDL_Rect(1, 1, 1, 1), + rect.SDL_Rect(0, 0, 10, 10), + rect.SDL_Rect(3, 3, 5, 5), + rect.SDL_Rect(-5, -5, 10, 10), + rect.SDL_Rect(10, 10, 20, 20), + rect.SDL_Rect(50, 50, 20, 30), + rect.SDL_Rect(0, -10, 10, 10), + ) + # First, try setting viewport to whole window + ret = render.SDL_RenderSetViewport(renderer, None) + assert SDL_GetError() == b"" + assert ret == 0 + vport = rect.SDL_Rect() + render.SDL_RenderGetViewport(renderer, byref(vport)) + assert vport == rect.SDL_Rect(0, 0, 100, 100) + # Then, try setting it to different sizes + for r in rects: + ret = render.SDL_RenderSetViewport(renderer, r) + assert SDL_GetError() == b"" assert ret == 0 - - render.SDL_RenderGetLogicalSize(renderer, byref(got_width), - byref(got_height)) - assert got_width.value == 0 - assert got_height.value == 0 - - clear_green() - - draw_magenta_pixel(0, 0) - draw_magenta_pixel(w - 1, h - 1) - - for x, y in itertools.product(range(w), range(h)): - if (x, y) == (0, 0) or (x, y) == (w - 1, h - 1): - assert view[y][x] == magenta_int, \ - 'First and last pixel should be magenta' - else: - assert view[y][x] == green_int, \ - 'All other pixels should be green' - - # Test 3 - # Set the logical size to 1/10, making a logical pixel draw be - # 10 x 10 real pixel blocks. - got_width, got_height = c_int(), c_int() - - ret = render.SDL_RenderSetLogicalSize(renderer, w//10, h//10) + render.SDL_RenderGetViewport(renderer, byref(vport)) + assert vport == r + +@pytest.mark.skip("not implemented") +def test_SDL_RenderGetSetClipRect(with_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderIsClipEnabled(with_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderGetSetScale(with_renderer): + pass + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_RenderWindowToLogical(with_renderer): + renderer, win = with_renderer + wx, wy = (c_int(0), c_int(0)) # window coords + lx, ly = (c_float(0), c_float(0)) # renderer coords + # Test without resizing + render.SDL_RenderWindowToLogical(renderer, 50, 50, byref(lx), byref(ly)) + assert lx.value == 50 + assert ly.value == 50 + render.SDL_RenderLogicalToWindow(renderer, 50, 50, byref(wx), byref(wy)) + assert wx.value == 50 + assert wy.value == 50 + # Set custom scaling on the renderer + ret = render.SDL_RenderSetScale(renderer, 2.0, 0.5) + assert SDL_GetError() == b"" + assert ret == 0 + # Test again after resizing + render.SDL_RenderWindowToLogical(renderer, 50, 50, byref(lx), byref(ly)) + assert lx.value == 25 + assert ly.value == 100 + render.SDL_RenderLogicalToWindow(renderer, 50, 50, byref(wx), byref(wy)) + assert wx.value == 100 + assert wy.value == 25 + +def test_SDL_RenderGetSetIntegerScale(with_renderer): + renderer, win = with_renderer + assert render.SDL_RenderGetIntegerScale(renderer) == SDL_FALSE + assert render.SDL_RenderSetIntegerScale(renderer, SDL_FALSE) == 0 + assert render.SDL_RenderGetIntegerScale(renderer) == SDL_FALSE + assert render.SDL_RenderSetIntegerScale(renderer, SDL_TRUE) == 0 + assert render.SDL_RenderGetIntegerScale(renderer) == SDL_TRUE + assert render.SDL_RenderSetIntegerScale(renderer, SDL_FALSE) == 0 + assert render.SDL_RenderGetIntegerScale(renderer) == SDL_FALSE + +def test_SDL_GetSetRenderDrawColor(with_renderer): + renderer, win = with_renderer + colors = ( + (16, 22, 185, 217), + (32, 64, 128, 255), + (64, 32, 128, 255), + (255, 32, 64, 128), + (255, 255, 255, 255), + (128, 128, 128, 255), + (0, 0, 0, 0), + ) + for r, g, b, a in colors: + ret = render.SDL_SetRenderDrawColor(renderer, r, g, b, a) + assert SDL_GetError() == b"" assert ret == 0 - - render.SDL_RenderGetLogicalSize(renderer, byref(got_width), - byref(got_height)) - assert got_width.value == w//10 - assert got_height.value == h//10 - - clear_green() - - draw_magenta_pixel(0, 0) - for x, y in itertools.product(range(w), range(h)): - if x < 10 and y < 10: - assert view[y][x] == magenta_int, \ - 'Top-left 10 x 10 pixel block should be magenta' - else: - assert view[y][x] == green_int, \ - 'All other pixels should be green' - - render.SDL_DestroyRenderer(renderer) - del view - surface.SDL_FreeSurface(sf) - - @pytest.mark.skip("not implemented") - def test_SDL_RenderGetSetClipRect(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GetRendererOutputSize(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_RenderIsClipEnabled(self): - pass - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_RenderWindowToLogical(self): - renderer, win = _create_renderer( - (30, 30), (100, 100), -1, self._RENDERFLAGS + rr, rg, rb, ra = Uint8(0), Uint8(0), Uint8(0), Uint8(0) + ret = render.SDL_GetRenderDrawColor( + renderer, byref(rr), byref(rg), byref(rb), byref(ra) ) - wx, wy = (c_int(0), c_int(0)) # window coords - lx, ly = (c_float(0), c_float(0)) # renderer coords - # Test without resizing - render.SDL_RenderWindowToLogical(renderer, 50, 50, byref(lx), byref(ly)) - assert lx.value == 50 - assert ly.value == 50 - render.SDL_RenderLogicalToWindow(renderer, 50, 50, byref(wx), byref(wy)) - assert wx.value == 50 - assert wy.value == 50 - # Set custom scaling on the renderer - ret = render.SDL_RenderSetScale(renderer, 2.0, 0.5) + assert ret == 0 + assert [v.value for v in (rr, rg, rb, ra)] == [r, g, b, a] + +def test_SDL_GetSetRenderDrawBlendMode(with_renderer): + renderer, win = with_renderer + modes = [ + blendmode.SDL_BLENDMODE_NONE, + blendmode.SDL_BLENDMODE_ADD, + blendmode.SDL_BLENDMODE_BLEND, + blendmode.SDL_BLENDMODE_MOD, + ] + for mode in modes: + ret = render.SDL_SetRenderDrawBlendMode(renderer, mode) assert SDL_GetError() == b"" assert ret == 0 - # Test again after resizing - render.SDL_RenderWindowToLogical(renderer, 50, 50, byref(lx), byref(ly)) - assert lx.value == 25 - assert ly.value == 100 - render.SDL_RenderLogicalToWindow(renderer, 50, 50, byref(wx), byref(wy)) - assert wx.value == 100 - assert wy.value == 25 - _cleanup_renderer(renderer, win) - - def test_SDL_RenderGetSetIntegerScale(self): - sf = surface.SDL_CreateRGBSurface(0, 100, 100, 32, - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF) - renderer = render.SDL_CreateSoftwareRenderer(sf) - assert isinstance(renderer.contents, render.SDL_Renderer) - assert render.SDL_RenderGetIntegerScale(renderer) == SDL_FALSE - assert render.SDL_RenderSetIntegerScale(renderer, SDL_FALSE) == 0 - assert render.SDL_RenderGetIntegerScale(renderer) == SDL_FALSE - assert render.SDL_RenderSetIntegerScale(renderer, SDL_TRUE) == 0 - assert render.SDL_RenderGetIntegerScale(renderer) == SDL_TRUE - assert render.SDL_RenderSetIntegerScale(renderer, SDL_FALSE) == 0 - assert render.SDL_RenderGetIntegerScale(renderer) == SDL_FALSE - render.SDL_DestroyRenderer(renderer) - surface.SDL_FreeSurface(sf) - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_RenderSetVSync(self): - renderer, win = _create_renderer( - (30, 30), (100, 100), -1, self._RENDERFLAGS - ) - # Not super thorough, but hard to test more extensively - ret = render.SDL_RenderSetVSync(renderer, 1) - assert ret <= 0 - ret = render.SDL_RenderSetVSync(renderer, 0) - assert ret <= 0 - _cleanup_renderer(renderer, win) + bmode = blendmode.SDL_BlendMode() + ret = render.SDL_GetRenderDrawBlendMode(renderer, byref(bmode)) + assert ret == 0 + assert bmode.value == mode + +def test_SDL_RenderClear(sw_renderer): + renderer, sf = sw_renderer + # Create a pixel view for the target surface and verify it's black + view = PixelView(sf) + assert view[0][0] == 0x000000FF + # Set renderer draw color to white and then clear the renderer + ret = render.SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255) + assert ret == 0 + ret = render.SDL_RenderClear(renderer) + assert ret == 0 + # Check whether the target surface is now white + assert view[0][0] == 0xFFFFFFFF + del view + +def test_SDL_RenderDrawPoint(sw_renderer): + renderer, sf = sw_renderer + points = ( + (1, 1), (4, 6), (10, 10), (96, 92), + (4, 22), (57, 88), (45, 15) + ) + r, g, b, a = 0xAA, 0xBB, 0xCC, 0xDD + color = pixels.SDL_MapRGBA(sf.contents.format, r, g, b, a) + ret = render.SDL_SetRenderDrawColor(renderer, r, g, b, a) + assert ret == 0 + for x, y in points: + ret = render.SDL_RenderDrawPoint(renderer, x, y) + assert ret == 0 + render.SDL_RenderPresent(renderer) + # Check whether the points were actually drawn + view = PixelView(sf) + for x, y in points: + # NOTE: Assumes no points are adjacent or on surface edge + assert hex(view[y][x]) == hex(color) + assert hex(view[y+1][x+1]) != hex(color) + assert hex(view[y-1][x-1]) != hex(color) + del view + +@pytest.mark.skip("not implemented") +def test_SDL_RenderDrawPoints(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderDrawLine(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderDrawLines(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderDrawRect(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderDrawRects(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderFillRect(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderFillRects(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderCopy(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderCopyEx(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderDrawPointF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderDrawPointsF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderDrawLineF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderDrawLinesF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderDrawRectF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderDrawRectsF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderFillRectF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderFillRectsF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderCopyF(sw_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderCopyExF(sw_renderer): + pass + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_RenderGeometry(sw_renderer): + renderer, target = sw_renderer + # Create vertices for rendering + RED = (255, 0, 0, 255) + vertices = [ + render.SDL_Vertex((0, 0), RED), + render.SDL_Vertex((0, 50), RED), + render.SDL_Vertex((50, 50), RED) + ] + # Try rendering the vertices + vtx = (render.SDL_Vertex * len(vertices))(*vertices) + ret = render.SDL_RenderGeometry( + renderer, None, vtx, len(vertices), None, 0 + ) + assert SDL_GetError() == b"" + assert ret == 0 + # TODO: Actually check the surface for the rendered triangle + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_RenderGeometryRaw(sw_renderer): + renderer, target = sw_renderer + # Create vertices for rendering + RED = SDL_Color(255, 0, 0, 255) + points = [0, 0, 0, 50, 50, 50] + colors = [RED, RED, RED] + tex_coords = [0, 0, 0, 0, 0, 0] + # Convert vertices to ctypes-friendly format + xy_size = sizeof(c_float) * 2 + col_size = sizeof(SDL_Color) + xy = (c_float * len(points))(*points) + col = (SDL_Color * len(colors))(*colors) + uv = (c_float * len(tex_coords))(*tex_coords) + # Try rendering the vertices + ret = render.SDL_RenderGeometryRaw( + renderer, None, + xy, xy_size, + col, col_size, + uv, xy_size, + 3, None, 0, 1 + ) + assert SDL_GetError() == b"" + assert ret == 0 + # Check the surface for the rendered triangle + RED_RGBA = 0xFF0000FF + BLACK_RGBA = 0x000000FF + view = PixelView(target) + assert view[25][5] == RED_RGBA + assert view[99][99] == BLACK_RGBA + del view + +@pytest.mark.skip("not implemented") +def test_SDL_RenderReadPixels(with_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_RenderPresent(with_renderer): + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +def test_SDL_RenderFlush(with_renderer): + pass + +@pytest.mark.skip("not implemented") +def test_SDL_GL_BindTexture(with_sdl): + # NOTE: Needs OpenGL renderer + pass + +@pytest.mark.skip("not implemented") +def test_SDL_GL_UnbindTexture(with_sdl): + # NOTE: Needs OpenGL renderer + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2008, reason="not available") +def test_SDL_RendererGetMetalLayer(with_renderer): + # NOTE: Needs metal renderer + pass + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2008, reason="not available") +def test_SDL_RendererGetMetalCommandEncoder(with_renderer): + # NOTE: Needs metal renderer + pass + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_RenderSetVSync(with_renderer): + renderer, win = with_renderer + # Not super thorough, but hard to test more extensively + ret = render.SDL_RenderSetVSync(renderer, 1) + assert ret <= 0 + ret = render.SDL_RenderSetVSync(renderer, 0) + assert ret <= 0 diff --git a/sdl2/test/sdl2ext_array_test.py b/sdl2/test/sdl2ext_array_test.py index e21d5b30..17375646 100644 --- a/sdl2/test/sdl2ext_array_test.py +++ b/sdl2/test/sdl2ext_array_test.py @@ -7,22 +7,23 @@ singlebyteseq = [x for x in range(0x100)] doublebyteseq = [x for x in range(0x10000)] -quadbyteseq = [0x00000000, - 0x000000FF, - 0x0000FF00, - 0x0000FFFF, - 0x00FF0000, - 0x00FF00FF, - 0x00FFFF00, - 0x00FFFFFF, - 0xFF000000, - 0xFF0000FF, - 0xFF00FF00, - 0xFFFF0000, - 0xFFFF00FF, - 0xFFFFFF00, - 0xFFFFFFFF - ] +quadbyteseq = [ + 0x00000000, + 0x000000FF, + 0x0000FF00, + 0x0000FFFF, + 0x00FF0000, + 0x00FF00FF, + 0x00FFFF00, + 0x00FFFFFF, + 0xFF000000, + 0xFF0000FF, + 0xFF00FF00, + 0xFFFF0000, + 0xFFFF00FF, + 0xFFFFFF00, + 0xFFFFFFFF, +] singlebytebuf = array.array("B", singlebyteseq) doublebytebuf = array.array("H", doublebyteseq) @@ -32,14 +33,12 @@ UINT_SIZE = struct.calcsize("I") UBYTE_SIZE = struct.calcsize("B") - def create_16b(seq, offset): if sys.byteorder == 'little': return (seq[offset] | seq[offset + 1] << 8) else: return (seq[offset] << 8 | seq[offset + 1]) - def create_32b(seq, size, offset): if sys.byteorder == 'little': if size == 1: @@ -58,7 +57,6 @@ def create_32b(seq, size, offset): elif size == 2: return (seq[offset] << 16 | seq[offset + 1]) - def create_64b(seq, size, offset): if sys.byteorder == 'little': if size == 1: @@ -96,23 +94,18 @@ def create_64b(seq, size, offset): elif size == 4: return (seq[offset] << 32 | seq[offset]) - def lobyte16(val): return val & 0x00FF - def hibyte16(val): return val >> 8 & 0x00FF - def lobytes32(val): return val & 0x0000FFFF - def hibytes32(val): return val >> 16 & 0x0000FFFF - def ltrbyte32(val, pos): if sys.byteorder == 'little': if pos == 0: @@ -138,22 +131,25 @@ def ltrbyte32(val, pos): raise IndexError("invalid position") -class TestSDL2ExtArray(object): +def test_to_ctypes(): + for seq, dtype in ( + (singlebyteseq, ctypes.c_ubyte), + (singlebytebuf, ctypes.c_ubyte), + (doublebyteseq, ctypes.c_ushort), + (doublebytebuf, ctypes.c_ushort), + (quadbyteseq, ctypes.c_uint), + (quadbytebuf, ctypes.c_uint), + ): + bytebuf, size = sdlextarray.to_ctypes(seq, dtype) + assert size == len(seq) + for index, x in enumerate(bytebuf): + assert x == seq[index] + + +class TestExtCTypesView(object): __tags__ = ["sdl2ext"] - def test_to_ctypes(self): - for seq, dtype in ((singlebyteseq, ctypes.c_ubyte), - (singlebytebuf, ctypes.c_ubyte), - (doublebyteseq, ctypes.c_ushort), - (doublebytebuf, ctypes.c_ushort), - (quadbyteseq, ctypes.c_uint), - (quadbytebuf, ctypes.c_uint)): - bytebuf, size = sdlextarray.to_ctypes(seq, dtype) - assert size == len(seq) - for index, x in enumerate(bytebuf): - assert x == seq[index] - - def test_CTypesView__singlebytes(self): + def test__singlebytes(self): buf1 = sdlextarray.CTypesView(singlebyteseq, docopy=True) buf2 = sdlextarray.CTypesView(singlebytebuf, docopy=False) for singlebytes, shared in ((buf1, False), (buf2, True)): @@ -181,7 +177,7 @@ def test_CTypesView__singlebytes(self): assert val == seqval offset += 8 - def test_CTypesView__doublebytes(self): + def test_doublebytes(self): buf1 = sdlextarray.CTypesView(doublebyteseq, USHORT_SIZE, docopy=True) buf2 = sdlextarray.CTypesView(doublebytebuf, USHORT_SIZE, docopy=False) for singlebytes, shared in ((buf1, False), (buf2, True)): @@ -216,7 +212,7 @@ def test_CTypesView__doublebytes(self): assert val == seqval offset += 4 - def test_CTypesView__quadbytes(self): + def test_quadbytes(self): buf1 = sdlextarray.CTypesView(quadbyteseq, UINT_SIZE, docopy=True) buf2 = sdlextarray.CTypesView(quadbytebuf, UINT_SIZE, docopy=False) for singlebytes, shared in ((buf1, False), (buf2, True)): @@ -255,25 +251,29 @@ def test_CTypesView__quadbytes(self): assert val == seqval offset += 2 - def test_CTypesView__repr__(self): - seqs = ((singlebyteseq, UBYTE_SIZE, 1, False), - (doublebyteseq, USHORT_SIZE, 2, False), - (quadbyteseq, UINT_SIZE, 4, False), - (singlebytebuf, UBYTE_SIZE, 1, True), - (doublebytebuf, USHORT_SIZE, 2, True), - (quadbytebuf, UINT_SIZE, 4, True), - ) + def test___repr__(self): + seqs = ( + (singlebyteseq, UBYTE_SIZE, 1, False), + (doublebyteseq, USHORT_SIZE, 2, False), + (quadbyteseq, UINT_SIZE, 4, False), + (singlebytebuf, UBYTE_SIZE, 1, True), + (doublebytebuf, USHORT_SIZE, 2, True), + (quadbytebuf, UINT_SIZE, 4, True), + ) for seq, size, factor, shared in seqs: buf = sdlextarray.CTypesView(seq, size, not shared) otype = type(seq).__name__ if not shared: otype = 'array' - text = "CTypesView(type=%s, bytesize=%d, shared=%s)" % \ (otype, len(seq) * factor, shared) assert text == repr(buf) - def test_MemoryView(self): + +class TestExtMemoryView(object): + __tags__ = ["sdl2ext"] + + def test_init(self): with pytest.raises(TypeError): sdlextarray.MemoryView(5, 1, (1,)) with pytest.raises(TypeError): @@ -306,7 +306,7 @@ def test_MemoryView(self): with pytest.raises(IndexError): view[10] - def test_MemoryView_ndim_strides(self): + def test_ndim_strides(self): source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) assert view.ndim == 1 @@ -321,54 +321,55 @@ def test_MemoryView_ndim_strides(self): assert view.ndim == 3 assert view.strides == (2, 2, 2) - def test_MemoryView_itemsize(self): + def test_itemsize(self): source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) assert view.itemsize == 1 view = sdlextarray.MemoryView(source, 7, (1, 7)) assert view.itemsize == 7 - def test_MemoryView_size(self): + def test_size(self): source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) assert view.size == len(source) view = sdlextarray.MemoryView(source, 7, (1, 7)) assert view.size == len(source) - def test_MemoryView_source(self): + def test_source(self): source = "Example buffer" view = sdlextarray.MemoryView(source, 1, (len(source),)) assert view.source == source - def test_to_tuple(self): - ar = (ctypes.c_int * 20)() - for i in range(20): - ar[i] = i - vtuple = sdlextarray.to_tuple(ar) - assert isinstance(vtuple, tuple) - for index, value in enumerate(vtuple): - assert value == ar[index] - - def test_to_list(self): - ar = (ctypes.c_int * 20)() - for i in range(20): - ar[i] = i - vlist = sdlextarray.to_list(ar) - assert isinstance(vlist, list) - for index, value in enumerate(vlist): - assert value == ar[index] - - def test_create_array(self): - barr = bytes(bytearray(singlebyteseq)) - for i in (1, 2, 4, 8): - parr = sdlextarray.create_array(barr, i) - assert isinstance(parr, array.array) - if i == 1: - assert parr[0] == 0x0 - elif i == 2: - assert parr[0] == 0x0100 - elif i == 4: - assert parr[0] == 0x03020100 - for i in (0, 3, 5, 6, 7, 9, 10, 12, "test", self): - with pytest.raises(TypeError): - sdlextarray.create_array(barr, i) + +def test_to_tuple(): + ar = (ctypes.c_int * 20)() + for i in range(20): + ar[i] = i + vtuple = sdlextarray.to_tuple(ar) + assert isinstance(vtuple, tuple) + for index, value in enumerate(vtuple): + assert value == ar[index] + +def test_to_list(): + ar = (ctypes.c_int * 20)() + for i in range(20): + ar[i] = i + vlist = sdlextarray.to_list(ar) + assert isinstance(vlist, list) + for index, value in enumerate(vlist): + assert value == ar[index] + +def test_create_array(): + barr = bytes(bytearray(singlebyteseq)) + for i in (1, 2, 4, 8): + parr = sdlextarray.create_array(barr, i) + assert isinstance(parr, array.array) + if i == 1: + assert parr[0] == 0x0 + elif i == 2: + assert parr[0] == 0x0100 + elif i == 4: + assert parr[0] == 0x03020100 + for i in (0, 3, 5, 6, 7, 9, 10, 12, "test"): + with pytest.raises(TypeError): + sdlextarray.create_array(barr, i) diff --git a/sdl2/test/sdl2ext_color_test.py b/sdl2/test/sdl2ext_color_test.py index c1c7db1c..f7b7f5cc 100644 --- a/sdl2/test/sdl2ext_color_test.py +++ b/sdl2/test/sdl2ext_color_test.py @@ -5,62 +5,35 @@ from sdl2.ext.color import Color from sdl2.ext.compat import * -combs = [0, 1, 2, 4, 8, 16, 32, 62, 63, 64, 126, 127, 128, 255] -all_combos = [(r, g, b, a) for r in combs - for g in combs - for b in combs - for a in combs] - - -def color_combos(): - for x in all_combos: - yield Color(*x) - - -def hex_combos(): - for r, g, b, a in all_combos: - yield "0x%.2x%.2x%.2x%.2x" % (r, g, b, a) - - -def hash_combos(): - for r, g, b, a in all_combos: - yield "#%.2x%.2x%.2x%.2x" % (r, g, b, a) - - -def rgba_combos(): - for r, g, b, a in all_combos: - yield (r << 24 | g << 16 | b << 8 | a) - - -def argb_combos(): - for r, g, b, a in all_combos: - yield (a << 24 | r << 16 | g << 8 | b) - - -def _assignr(x, y): - x.r = y - - -def _assigng(x, y): - x.g = y - - -def _assignb(x, y): - x.b = y - - -def _assigna(x, y): - x.a = y - - -def _assign_item(x, p, y): - x[p] = y - - -class TestSDL2ExtColor(object): +@pytest.fixture(scope="module") +def test_colors(): + # Define some RGB colors for testing + rgb = [ + (0, 0, 0), (255, 255, 255), + (255, 0, 0), (0, 255, 0), (0, 0, 255), + (128, 64, 0), (1, 2, 3), (5, 5, 5) + ] + # Use those colors to create RGBA test colors in different formats + colors = [] + for vals in rgb: + r, g, b, = vals + for a in (0, 128, 255): + col = Color(r, g, b, a) + formats = { + 'hex': "0x%.2x%.2x%.2x%.2x" % (r, g, b, a), + 'hash': "#%.2x%.2x%.2x%.2x" % (r, g, b, a), + 'rgba': (r << 24 | g << 16 | b << 8 | a), + 'argb': (a << 24 | r << 16 | g << 8 | b), + } + colors.append([col, formats]) + yield colors + + + +class TestExtColor(object): __tags__ = ["sdl2ext"] - def test_Color(self): + def test_init(self): c = Color(10, 20, 30, 40) assert c.r == 10 assert c.g == 20 @@ -70,23 +43,19 @@ def test_Color(self): with pytest.raises(ValueError): Color(257, 10, 105, 44) with pytest.raises(ValueError): - Color(10, 257, 105, 44) - with pytest.raises(ValueError): - Color(10, 105, 257, 44) - with pytest.raises(ValueError): - Color(10, 105, 44, 257) + Color(-1, 257, 105, 44) - def test_Color__copy__(self): + def test__copy__(self, test_colors): copy_copy = copy.copy - for c in color_combos(): + for c, formats in test_colors: c2 = copy_copy(c) assert c == c2 c2 = ~c2 assert c != c2 - def test_Color__eq__(self): + def test__eq__(self): assert Color(255, 0, 0, 0) == Color(255, 0, 0, 0) assert Color(0, 255, 0, 0) == Color(0, 255, 0, 0) assert Color(0, 0, 255, 0) == Color(0, 0, 255, 0) @@ -118,7 +87,7 @@ def test_Color__eq__(self): assert not (int(Color(0, 0, 0, 0)) == 0x000000ff) - def test_Color__ne__(self): + def test__ne__(self): assert Color(0, 0, 0, 0) != Color(255, 0, 0, 0) assert Color(0, 0, 0, 0) != Color(0, 255, 0, 0) assert Color(0, 0, 0, 0) != Color(0, 0, 255, 0) @@ -150,13 +119,13 @@ def test_Color__ne__(self): assert not (int(Color(0, 0, 0, 255)) != 0x000000ff) - def test_Color__repr__(self): + def test__repr__(self): c = Color(68, 38, 26, 69) c1 = eval(repr(c)) assert c == c1 - def test_Color__int__(self): + def test__int__(self): c = Color(0x00, 0xCC, 0x00, 0xCC) assert c.r == 0x00 assert c.g == 0xCC @@ -172,7 +141,7 @@ def test_Color__int__(self): assert int(c) == int(0x72759233) - def test_Color__long__(self): + def test__long__(self): c = Color(0x00, 0xCC, 0x00, 0xCC) assert c.r == 0x00 assert c.g == 0xCC @@ -188,7 +157,7 @@ def test_Color__long__(self): assert long(c) == long(0x72759233) - def test_Color__float__(self): + def test__float__(self): c = Color(0x00, 0xCC, 0x00, 0xCC) assert c.r == 0x00 assert c.g == 0xCC @@ -204,7 +173,7 @@ def test_Color__float__(self): assert float(c) == float(0x72759233) - def test_Color__oct__(self): + def test__oct__(self): c = Color(0x00, 0xCC, 0x00, 0xCC) assert c.r == 0x00 assert c.g == 0xCC @@ -220,7 +189,7 @@ def test_Color__oct__(self): assert oct(c) == oct(0x72759233) - def test_Color__hex__(self): + def test__hex__(self): c = Color(0x00, 0xCC, 0x00, 0xCC) assert c.r == 0x00 assert c.g == 0xCC @@ -236,7 +205,7 @@ def test_Color__hex__(self): assert hex(c) == hex(0x72759233) - def test_Color__invert__(self): + def test__invert__(self): assert ~Color() == Color(0, 0, 0, 0) assert ~Color(0, 0, 0, 0) == Color(255, 255, 255, 255) assert ~Color(255, 0, 0, 0) == Color(0, 255, 255, 255) @@ -249,7 +218,7 @@ def test_Color__invert__(self): assert ~Color(127, 127, 127, 0) == Color(128, 128, 128, 255) - def test_Color__mod__(self): + def test__mod__(self): c1 = Color() assert c1.r == 255 assert c1.g == 255 @@ -269,7 +238,7 @@ def test_Color__mod__(self): assert c3.a == 15 - def test_Color__div__(self): + def test__div__(self): c1 = Color(128, 128, 128, 128) assert c1.r == 128 assert c1.g == 128 @@ -295,7 +264,7 @@ def test_Color__div__(self): assert c3.a == 0 - def test_Color__mul__(self): + def test__mul__(self): c1 = Color(1, 1, 1, 1) assert c1.r == 1 assert c1.g == 1 @@ -321,7 +290,7 @@ def test_Color__mul__(self): assert c3.a == 255 - def test_Color__sub__(self): + def test__sub__(self): c1 = Color(255, 255, 255, 255) assert c1.r == 255 assert c1.g == 255 @@ -347,7 +316,7 @@ def test_Color__sub__(self): assert c3.a == 0 - def test_Color__add__(self): + def test__add__(self): c1 = Color(0, 0, 0, 0) assert c1.r == 0 assert c1.g == 0 @@ -373,14 +342,14 @@ def test_Color__add__(self): assert c3.a == 255 - def test_Color__len__(self): + def test__len__(self): c = Color(204, 38, 194, 55) assert len(c) == 4 assert len(Color()) == 4 assert len(Color(2)) == 4 - def test_Color__getitem__(self): + def test__getitem__(self): c = Color(204, 38, 194, 55) assert c[0] == 204 assert c[1] == 38 @@ -388,7 +357,7 @@ def test_Color__getitem__(self): assert c[3] == 55 - def test_Color__setitem(self): + def test__setitem(self): c = Color(204, 38, 194, 55) assert c[0] == 204 assert c[1] == 38 @@ -406,132 +375,37 @@ def test_Color__setitem(self): # Now try some 'invalid' ones with pytest.raises(ValueError): - _assign_item(c, 1, -83) + c[1] = -1 assert c[1] == 48 with pytest.raises(TypeError): - _assign_item(c, 2, "Hello") + c[2] = "Hello" assert c[2] == 173 - def test_Color_r(self): - c = Color(100, 100, 100) - assert c.r == 100 - + def test_rgba(self): c = Color(100, 100, 100, 100) - assert c.r == 100 - - c = Color(100, 100, 100) - assert c.r == 100 - c.r = 200 - assert c.r == 200 - c.r += 22 - assert c.r == 222 - - - def test_Color_g(self): - c = Color(100, 100, 100) - assert c.g == 100 - - c = Color(100, 100, 100, 100) - assert c.g == 100 - - c = Color(100, 100, 100) - assert c.g == 100 - c.g = 200 - assert c.g == 200 + for val in [c.r, c.g, c.b, c.a]: + assert val == 100 + c.r = 255 + c.g = 128 + c.b = 64 + c.a = 32 + assert c.r == 255 + assert c.g == 128 + assert c.b == 64 + assert c.a == 32 + c.r -= 55 c.g += 22 - assert c.g == 222 - - - def test_Color_b(self): - c = Color(100, 100, 100) - assert c.b == 100 - - c = Color(100, 100, 100, 100) - assert c.b == 100 - - c = Color(100, 100, 100) - assert c.b == 100 - c.b = 200 - assert c.b == 200 - c.b += 22 - assert c.b == 222 - - - def test_Color_a(self): - c = Color(100, 100, 100) - assert c.a == 255 - - c = Color(100, 100, 100, 100) - assert c.a == 100 - - c = Color(100, 100, 100) - assert c.a == 255 - c.a = 200 - assert c.a == 200 - c.a += 22 - assert c.a == 222 - - - def test_Color_rgba(self): - c = Color(0) - assert c.r == 0 - assert c.g == 255 - assert c.b == 255 - assert c.a == 255 - - # Test simple assignments - c.r = 123 - assert c.r == 123 - with pytest.raises(ValueError): - _assignr(c, 537) - assert c.r == 123 - with pytest.raises(ValueError): - _assignr(c, -3) - assert c.r == 123 - assert c.g == 255 - assert c.b == 255 - assert c.a == 255 - - c.g = 55 - assert c.g == 55 - with pytest.raises(ValueError): - _assigng(c, 348) - assert c.g == 55 - with pytest.raises(ValueError): - _assigng(c, -44) - assert c.g == 55 - assert c.r == 123 - assert c.b == 255 - assert c.a == 255 - - c.b = 77 - assert c.b == 77 - with pytest.raises(ValueError): - _assignb(c, 256) - assert c.b == 77 - with pytest.raises(ValueError): - _assignb(c, -12) - assert c.b == 77 - assert c.r == 123 - assert c.g == 55 - assert c.a == 255 - - c.a = 251 - assert c.a == 251 - with pytest.raises(ValueError): - _assigna(c, 312) - assert c.a == 251 - with pytest.raises(ValueError): - _assigna(c, -10) - assert c.a == 251 - assert c.r == 123 - assert c.g == 55 - assert c.b == 77 + c.b -= 14 + c.a += 32 + assert c.r == 200 + assert c.g == 150 + assert c.b == 50 + assert c.a == 64 - def test_Color_hsva(self): - for c in color_combos(): + def test_hsva(self, test_colors): + for c, formats in test_colors: h, s, v, a = c.hsva assert 0 <= h <= 360 assert 0 <= s <= 100 @@ -550,8 +424,8 @@ def test_Color_hsva(self): assert abs(c2.a - c.a <= 1), err - def test_Color_hsla(self): - for c in color_combos(): + def test_hsla(self, test_colors): + for c, formats in test_colors: h, s, l, a = c.hsla assert 0 <= h <= 360 assert 0 <= s <= 100 @@ -570,8 +444,8 @@ def test_Color_hsla(self): assert abs(c2.a - c.a <= 1), err - def test_Color_i1i2i3(self): - for c in color_combos(): + def test_i1i2i3(self, test_colors): + for c, formats in test_colors: i1, i2, i3 = c.i1i2i3 assert 0 <= i1 <= 1 assert -0.5 <= i2 <= 0.5 @@ -589,8 +463,8 @@ def test_Color_i1i2i3(self): assert abs(c2.b - c.b <= 1), err - def test_Color_cmy(self): - for val in color_combos(): + def test_cmy(self, test_colors): + for val, formats in test_colors: c, m, y = val.cmy assert 0 <= c <= 1 assert 0 <= m <= 1 @@ -608,7 +482,7 @@ def test_Color_cmy(self): assert abs(c2.b - val.b <= 1), err - def test_Color_normalize(self): + def test_normalize(self): c = Color(204, 38, 194, 55) assert c.r == 204 assert c.g == 38 @@ -640,171 +514,99 @@ def test_Color_normalize(self): assert round(abs(t[3]-0.2), 2) == 0 - def test_is_rgb_color(self): - for v in color_combos(): - assert color.is_rgba_color(v) - - for v in rgba_combos(): - assert not color.is_rgba_color(v) - for v in argb_combos(): - assert not color.is_rgba_color(v) - for v in hex_combos(): - assert not color.is_rgba_color(v) - for v in hash_combos(): - assert not color.is_rgba_color(v) - - - def test_is_rgba_color(self): - for v in color_combos(): - assert color.is_rgba_color(v) - - for v in rgba_combos(): - assert not color.is_rgba_color(v) - for v in argb_combos(): - assert not color.is_rgba_color(v) - for v in hex_combos(): - assert not color.is_rgba_color(v) - for v in hash_combos(): - assert not color.is_rgba_color(v) - - - def test_rgba_argb_to_color(self): - - assert color.RGBA == color.rgba_to_color - assert color.ARGB == color.argb_to_color - - cvals = list(color_combos()) - for index, val in enumerate(rgba_combos()): - c = cvals[index] - if c.r == c.g == c.b == c.a: - assert color.RGBA(val) == c - assert color.ARGB(val) == c - continue - - assert color.RGBA(val) == c, "Failed for '%s'" % val - assert not color.ARGB(val) == c, "Failed for '0x%.8x'" % val - - for index, val in enumerate(argb_combos()): - c = cvals[index] - if c.r == c.g == c.b == c.a: - assert color.RGBA(val) == c - assert color.ARGB(val) == c - continue - - assert color.ARGB(val) == c, "Failed for '%s'" % val - assert not color.RGBA(val) == c, "Failed for '0x%.8x'" % val - - - def test_string_to_color(self): - for method in (color.string_to_color, color.convert_to_color, - color.COLOR): - assert method('#00000000').r == 0x00 - assert method('#10000000').r == 0x10 - assert method('#20000000').r == 0x20 - assert method('#30000000').r == 0x30 - assert method('#40000000').r == 0x40 - assert method('#50000000').r == 0x50 - assert method('#60000000').r == 0x60 - assert method('#70000000').r == 0x70 - assert method('#80000000').r == 0x80 - assert method('#90000000').r == 0x90 - assert method('#A0000000').r == 0xA0 - assert method('#B0000000').r == 0xB0 - assert method('#C0000000').r == 0xC0 - assert method('#D0000000').r == 0xD0 - assert method('#E0000000').r == 0xE0 - assert method('#F0000000').r == 0xF0 - assert method('#01000000').r == 0x01 - assert method('#02000000').r == 0x02 - assert method('#03000000').r == 0x03 - assert method('#04000000').r == 0x04 - assert method('#05000000').r == 0x05 - assert method('#06000000').r == 0x06 - assert method('#07000000').r == 0x07 - assert method('#08000000').r == 0x08 - assert method('#09000000').r == 0x09 - assert method('#0A000000').r == 0x0A - assert method('#0B000000').r == 0x0B - assert method('#0C000000').r == 0x0C - assert method('#0D000000').r == 0x0D - assert method('#0E000000').r == 0x0E - assert method('#0F000000').r == 0x0F - - with pytest.raises(ValueError): - method("0x12345") - with pytest.raises(ValueError): - method("0x1234567") - with pytest.raises(ValueError): - method("#123456789") - with pytest.raises(ValueError): - method("#12345") - with pytest.raises(ValueError): - method("#1234567") - with pytest.raises(ValueError): - method("#123456789") - - with pytest.raises(ValueError): - method("# f000000") - with pytest.raises(ValueError): - method("#f 000000") - with pytest.raises(ValueError): - method("#-f000000") - with pytest.raises(ValueError): - method("-#f000000") - - with pytest.raises(ValueError): - method("0x f000000") - with pytest.raises(ValueError): - method("0xf 000000") - with pytest.raises(ValueError): - method("0x-f000000") +def test_is_rgb_color(test_colors): + for col, formats in test_colors: + assert color.is_rgba_color(col) + assert color.is_rgba_color(tuple(col)) + assert not color.is_rgba_color(formats['rgba']) + assert not color.is_rgba_color(formats['argb']) + assert not color.is_rgba_color(formats['hex']) + assert not color.is_rgba_color(formats['hash']) + + +def test_is_rgba_color(test_colors): + for col, formats in test_colors: + assert color.is_rgba_color(col) + assert color.is_rgba_color(tuple(col)) + assert not color.is_rgba_color(tuple(col)[:3]) + assert not color.is_rgba_color(formats['rgba']) + assert not color.is_rgba_color(formats['argb']) + assert not color.is_rgba_color(formats['hex']) + assert not color.is_rgba_color(formats['hash']) + + +def test_rgba_argb_to_color(test_colors): + # Test aliases + assert color.RGBA == color.rgba_to_color + assert color.ARGB == color.argb_to_color + # Test RGBA/ARGB int conversion + for c, formats in test_colors: + from_rgba = color.RGBA(formats['rgba']) + from_argb = color.ARGB(formats['argb']) + assert from_rgba == from_argb + assert from_rgba == c + + +def test_string_to_color(test_colors): + for col, formats in test_colors: + assert color.string_to_color(formats['hex']) == col + assert color.string_to_color(formats['hash']) == col + + for method in (color.string_to_color, color.convert_to_color): + assert method('#00000000').r == 0x00 + assert method('#10000000').r == 0x10 + assert method('#20000000').r == 0x20 + assert method('#30000000').r == 0x30 + assert method('#40000000').r == 0x40 + assert method('#50000000').r == 0x50 + assert method('#60000000').r == 0x60 + assert method('#70000000').r == 0x70 + assert method('#80000000').r == 0x80 + assert method('#90000000').r == 0x90 + assert method('#A0000000').r == 0xA0 + assert method('#B0000000').r == 0xB0 + assert method('#C0000000').r == 0xC0 + assert method('#D0000000').r == 0xD0 + assert method('#E0000000').r == 0xE0 + assert method('#F0000000').r == 0xF0 + assert method('#01000000').r == 0x01 + assert method('#02000000').r == 0x02 + assert method('#03000000').r == 0x03 + assert method('#04000000').r == 0x04 + assert method('#05000000').r == 0x05 + assert method('#06000000').r == 0x06 + assert method('#07000000').r == 0x07 + assert method('#08000000').r == 0x08 + assert method('#09000000').r == 0x09 + assert method('#0A000000').r == 0x0A + assert method('#0B000000').r == 0x0B + assert method('#0C000000').r == 0x0C + assert method('#0D000000').r == 0x0D + assert method('#0E000000').r == 0x0E + assert method('#0F000000').r == 0x0F + + bad_strs = ["0x12345", "#1234567", "# f000000", "0xAABBCCQQ", "Red"] + for bad in bad_strs: with pytest.raises(ValueError): - method("-0xf000000") - - with pytest.raises(ValueError): - method("#cc00qq") - with pytest.raises(ValueError): - method("0xcc00qq") - with pytest.raises(ValueError): - method("09abcdef") - with pytest.raises(ValueError): - method("09abcde") - with pytest.raises(ValueError): - method("quarky") - - cvals = list(color_combos()) - for index, val in enumerate(hex_combos()): - assert method(val) == cvals[index], "Failed for '%s'" % val - for index, val in enumerate(hash_combos()): - assert method(val) == cvals[index], "Failed for '%s'" % val - - with pytest.raises(TypeError): - color.string_to_color(0xff000000) - with pytest.raises(TypeError): - color.string_to_color(Color()) - - - def test_convert_to_color(self): - assert color.COLOR == color.convert_to_color - cvals = list(color_combos()) - - for index, val in enumerate(hex_combos()): - assert color.COLOR(val) == cvals[index], "Failed for '%s'" % val - - for index, val in enumerate(hash_combos()): - assert color.COLOR(val) == cvals[index], "Failed for '%s'" % val - - for index, val in enumerate(hex_combos()): - assert color.COLOR(val) == cvals[index], "Failed for '%s'" % val - - for index, val in enumerate(argb_combos()): - assert color.COLOR(val) == cvals[index], "Failed for '0x%.8x'" % val - - for index, val in enumerate(color_combos()): - assert color.COLOR(val) == cvals[index], "Failed for '%s'" % val - - with pytest.raises(ValueError): - color.convert_to_color(self) - - with pytest.raises(ValueError): - color.convert_to_color("Test") + method(bad) + + with pytest.raises(TypeError): + color.string_to_color(0xff000000) + with pytest.raises(TypeError): + color.string_to_color(Color()) + + +def test_convert_to_color(test_colors): + assert color.COLOR == color.convert_to_color + + for col, formats in test_colors: + assert color.COLOR(formats['hex']) == col + assert color.COLOR(formats['hash']) == col + assert color.COLOR(formats['argb']) == col + assert color.COLOR(tuple(col)) == col + assert color.COLOR(col) == col + + with pytest.raises(ValueError): + color.convert_to_color((255, 255, -1)) + with pytest.raises(ValueError): + color.convert_to_color("Mauve") diff --git a/sdl2/test/sdl2ext_draw_test.py b/sdl2/test/sdl2ext_draw_test.py index 87e4cb0c..35f1c275 100644 --- a/sdl2/test/sdl2ext_draw_test.py +++ b/sdl2/test/sdl2ext_draw_test.py @@ -1,8 +1,10 @@ import sys import pytest -from sdl2.surface import SDL_CreateRGBSurface +from sdl2.surface import SDL_CreateRGBSurface, SDL_FreeSurface from sdl2.rect import SDL_Rect +from sdl2.error import SDL_GetError from sdl2.ext.color import Color, COLOR +from sdl2.ext.surface import _create_surface from sdl2 import ext as sdl2ext try: @@ -11,140 +13,132 @@ except: _HASNUMPY = False -class TestSDL2ExtDraw(object): - __tags__ = ["sdl", "sdl2ext"] - - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - sdl2ext.quit() - - @pytest.mark.skipif(not _HASNUMPY, reason="pixels3d requires numpy module") - def test_fill(self): - # Initialize colour and surface/view - WHITE = (255, 255, 255) - BLACK = (0, 0, 0) - sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) - view = sdl2ext.pixels3d(sf.contents, False) - - # Test with no provided fill area - sdl2ext.fill(sf.contents, WHITE, None) - assert all(x == 255 for x in view[0][0][:3]) - assert all(x == 255 for x in view[-1][-1][:3]) - - # Test with SDL_Rect fill area - sdl2ext.fill(sf.contents, BLACK, None) # reset surface - r = SDL_Rect(0, 0, 5, 5) - sdl2ext.fill(sf.contents, WHITE, r) - assert all(x == 255 for x in view[0][0][:3]) - assert all(x == 255 for x in view[4][4][:3]) - assert all(x == 0 for x in view[-1][-1][:3]) - - # Test with tuple fill area - sdl2ext.fill(sf.contents, BLACK, None) # reset surface - r = (5, 5, 5, 5) - sdl2ext.fill(sf.contents, WHITE, r) - assert all(x == 0 for x in view[4][4][:3]) - assert all(x == 255 for x in view[5][5][:3]) - assert all(x == 255 for x in view[-1][-1][:3]) - - # Test with multiple fill areas - sdl2ext.fill(sf.contents, BLACK, None) # reset surface - rects = [(0, 0, 10, 5), SDL_Rect(0, 0, 3, 10), (7, 7, 3, 10)] - sdl2ext.fill(sf.contents, WHITE, rects) - assert all(x == 255 for x in view[0][0][:3]) - assert all(x == 255 for x in view[0][-1][:3]) - assert all(x == 255 for x in view[-1][-1][:3]) - assert all(x == 0 for x in view[-1][4][:3]) - - # Test exception on bad input - with pytest.raises(ValueError): - sdl2ext.fill(sf.contents, WHITE, (1, 2, 3)) - - @pytest.mark.skipif(not _HASNUMPY, reason="pixels3d requires numpy module") - def test_line(self): - # Initialize colour and surface/view - WHITE = (255, 255, 255) - BLACK = (0, 0, 0) - sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) - view = sdl2ext.pixels3d(sf.contents, False) - - # Test with a single straight line - sdl2ext.line(sf.contents, WHITE, (0, 0, 11, 0)) - assert all(x == 255 for x in view[0][0][:3]) - assert all(x == 255 for x in view[0][-1][:3]) - assert all(x == 0 for x in view[1][0][:3]) - - # Test specifying line width - sdl2ext.line(sf.contents, WHITE, (0, 5, 11, 5), width=4) - assert all(x == 255 for x in view[3][0][:3]) - assert all(x == 255 for x in view[6][-1][:3]) - assert all(x == 0 for x in view[2][0][:3]) - - # Test with a single diagonal line - sdl2ext.fill(sf.contents, BLACK, None) # reset surface - sdl2ext.line(sf.contents, WHITE, (1, 1, 9, 9)) - assert all(x == 255 for x in view[2][2][:3]) - assert all(x == 255 for x in view[3][3][:3]) - assert all(x == 0 for x in view[4][6][:3]) - - # Test with multiple lines - lines = [(0, 0, 0, 10), (0, 0, 10, 0), (0, 0, 10, 10)] - sdl2ext.fill(sf.contents, BLACK, None) # reset surface - sdl2ext.line(sf.contents, WHITE, lines) - assert all(x == 255 for x in view[0][-1][:3]) - assert all(x == 255 for x in view[-1][0][:3]) - assert all(x == 255 for x in view[-1][-1][:3]) - assert all(x == 0 for x in view[1][5][:3]) - - # Test with multiple lines (old weird method) - lines = (0, 0, 0, 10, 0, 0, 10, 0, 0, 0, 10, 10) - sdl2ext.fill(sf.contents, BLACK, None) # reset surface - sdl2ext.line(sf.contents, WHITE, lines) - assert all(x == 255 for x in view[0][-1][:3]) - assert all(x == 255 for x in view[-1][0][:3]) - assert all(x == 255 for x in view[-1][-1][:3]) - assert all(x == 0 for x in view[1][5][:3]) - - # Test exception on bad input - with pytest.raises(ValueError): - sdl2ext.line(sf.contents, WHITE, (1, 2, 3)) - - def test_prepare_color(self): - rcolors = (Color(0, 0, 0, 0), - Color(255, 255, 255, 255), - Color(8, 55, 110, 220), - ) - icolors = (0x00000000, - 0xFFFFFFFF, - 0xAABBCCDD, - ) - scolors = ("#000", - "#FFF", - "#AABBCCDD", - ) - - factory = sdl2ext.SpriteFactory(sdl2ext.SOFTWARE) - sprite = factory.create_sprite(size=(10, 10), bpp=32, - masks=(0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF)) - - for color in rcolors: - c = sdl2ext.prepare_color(color, sprite) - assert c == int(color) - for color in icolors: - c = sdl2ext.prepare_color(color, sprite) - cc = COLOR(color) - assert c == int(cc) - for color in scolors: - c = sdl2ext.prepare_color(color, sprite) - cc = COLOR(color) - assert c == int(cc) + +@pytest.fixture +def testsurf(with_sdl): + sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) + assert SDL_GetError() == b"" + yield sf + SDL_FreeSurface(sf) + + +@pytest.mark.skipif(not _HASNUMPY, reason="pixels3d requires numpy module") +def test_fill(testsurf): + # Initialize colour and surface/view + WHITE = (255, 255, 255) + BLACK = (0, 0, 0) + sf = testsurf + view = sdl2ext.pixels3d(sf.contents, False) + + # Test with no provided fill area + sdl2ext.fill(sf.contents, WHITE, None) + assert all(x == 255 for x in view[0][0][:3]) + assert all(x == 255 for x in view[-1][-1][:3]) + + # Test with SDL_Rect fill area + sdl2ext.fill(sf.contents, BLACK, None) # reset surface + r = SDL_Rect(0, 0, 5, 5) + sdl2ext.fill(sf.contents, WHITE, r) + assert all(x == 255 for x in view[0][0][:3]) + assert all(x == 255 for x in view[4][4][:3]) + assert all(x == 0 for x in view[-1][-1][:3]) + + # Test with tuple fill area + sdl2ext.fill(sf.contents, BLACK, None) # reset surface + r = (5, 5, 5, 5) + sdl2ext.fill(sf.contents, WHITE, r) + assert all(x == 0 for x in view[4][4][:3]) + assert all(x == 255 for x in view[5][5][:3]) + assert all(x == 255 for x in view[-1][-1][:3]) + + # Test with multiple fill areas + sdl2ext.fill(sf.contents, BLACK, None) # reset surface + rects = [(0, 0, 10, 5), SDL_Rect(0, 0, 3, 10), (7, 7, 3, 10)] + sdl2ext.fill(sf.contents, WHITE, rects) + assert all(x == 255 for x in view[0][0][:3]) + assert all(x == 255 for x in view[0][-1][:3]) + assert all(x == 255 for x in view[-1][-1][:3]) + assert all(x == 0 for x in view[-1][4][:3]) + + # Test exception on bad input + with pytest.raises(ValueError): + sdl2ext.fill(sf.contents, WHITE, (1, 2, 3)) + +@pytest.mark.skipif(not _HASNUMPY, reason="pixels3d requires numpy module") +def test_line(testsurf): + # Initialize colour and surface/view + WHITE = (255, 255, 255) + BLACK = (0, 0, 0) + sf = testsurf + view = sdl2ext.pixels3d(sf.contents, False) + + # Test with a single straight line + sdl2ext.line(sf.contents, WHITE, (0, 0, 11, 0)) + assert all(x == 255 for x in view[0][0][:3]) + assert all(x == 255 for x in view[0][-1][:3]) + assert all(x == 0 for x in view[1][0][:3]) + + # Test specifying line width + sdl2ext.line(sf.contents, WHITE, (0, 5, 11, 5), width=4) + assert all(x == 255 for x in view[3][0][:3]) + assert all(x == 255 for x in view[6][-1][:3]) + assert all(x == 0 for x in view[2][0][:3]) + + # Test with a single diagonal line + sdl2ext.fill(sf.contents, BLACK, None) # reset surface + sdl2ext.line(sf.contents, WHITE, (1, 1, 9, 9)) + assert all(x == 255 for x in view[2][2][:3]) + assert all(x == 255 for x in view[3][3][:3]) + assert all(x == 0 for x in view[4][6][:3]) + + # Test with multiple lines + lines = [(0, 0, 0, 10), (0, 0, 10, 0), (0, 0, 10, 10)] + sdl2ext.fill(sf.contents, BLACK, None) # reset surface + sdl2ext.line(sf.contents, WHITE, lines) + assert all(x == 255 for x in view[0][-1][:3]) + assert all(x == 255 for x in view[-1][0][:3]) + assert all(x == 255 for x in view[-1][-1][:3]) + assert all(x == 0 for x in view[1][5][:3]) + + # Test with multiple lines (old weird method) + lines = (0, 0, 0, 10, 0, 0, 10, 0, 0, 0, 10, 10) + sdl2ext.fill(sf.contents, BLACK, None) # reset surface + sdl2ext.line(sf.contents, WHITE, lines) + assert all(x == 255 for x in view[0][-1][:3]) + assert all(x == 255 for x in view[-1][0][:3]) + assert all(x == 255 for x in view[-1][-1][:3]) + assert all(x == 0 for x in view[1][5][:3]) + + # Test exception on bad input + with pytest.raises(ValueError): + sdl2ext.line(sf.contents, WHITE, (1, 2, 3)) + +def test_prepare_color(with_sdl): + rcolors = ( + Color(0, 0, 0, 0), + Color(255, 255, 255, 255), + Color(8, 55, 110, 220), + ) + icolors = ( + 0x00000000, + 0xFFFFFFFF, + 0xAABBCCDD, + ) + scolors = ( + "#000", + "#FFF", + "#AABBCCDD", + ) + sf = _create_surface((10, 10), fmt="RGBA8888") + for color in rcolors: + c = sdl2ext.prepare_color(color, sf) + assert c == int(color) + for color in icolors: + c = sdl2ext.prepare_color(color, sf) + cc = COLOR(color) + assert c == int(cc) + for color in scolors: + c = sdl2ext.prepare_color(color, sf) + cc = COLOR(color) + assert c == int(cc) + SDL_FreeSurface(sf) \ No newline at end of file diff --git a/sdl2/test/sdl2ext_ebs_test.py b/sdl2/test/sdl2ext_ebs_test.py index ea399bfb..bc3fd8cd 100644 --- a/sdl2/test/sdl2ext_ebs_test.py +++ b/sdl2/test/sdl2ext_ebs_test.py @@ -3,6 +3,8 @@ from sdl2.ext.ebs import Entity, System, Applicator, World +# Define some classes for testing the module + class Position(object): def __init__(self, x=0, y=0): self.x = x @@ -11,29 +13,24 @@ def __init__(self, x=0, y=0): def __eq__(self, other): return self.x == other.x and self.y == other.y - class Movement(object): def __init__(self, vx=0, vy=0): self.vx = vx self.vy = vy - class PositionEntity(Entity): def __init__(self, world, x=0, y=0): self.position = Position(x, y) - class MovingEntity(Entity): def __init__(self, world, x=0, y=0, vx=0, vy=0): self.position = Position(x, y) self.movement = Movement(vx, vy) - class PosEntity(Entity): def __init__(self, world, x=0, y=0): self.pos = Position(x, y) - class PositionSystem(System): def __init__(self): super(PositionSystem, self).__init__() @@ -44,7 +41,6 @@ def process(self, world, components): c.x += 1 c.y += 1 - class MovementApplicator(Applicator): def __init__(self): super(MovementApplicator, self).__init__() @@ -56,10 +52,12 @@ def process(self, world, componentsets): p.y += m.vy -class TestSDL2ExtEBS(object): +# Test the classes of the module + +class TestExtEntity(object): __tags__ = ["ebs", "sdl2ext"] - def test_Entity(self): + def test_init(self): world = World() world.add_system(PositionSystem()) @@ -73,13 +71,13 @@ def test_Entity(self): assert isinstance(p, PositionEntity) assert isinstance(p, Entity) - def test_Entity_id(self): + def test_id(self): world = World() ent1 = Entity(world) ent2 = Entity(world) assert ent1.id != ent2.id - def test_Entity_world(self): + def test_world(self): world = World() world2 = World() ent1 = Entity(world) @@ -90,7 +88,7 @@ def test_Entity_world(self): assert ent2.world != world assert ent1.world != ent2.world - def test_Entity_delete(self): + def test_delete(self): w = World() e1 = Entity(w) e2 = Entity(w) @@ -105,7 +103,7 @@ def test_Entity_delete(self): e1.delete() e2.delete() - def test_Entity__inheritance(self): + def test__inheritance(self): world = World() pos1 = PositionEntity(world) @@ -115,7 +113,7 @@ def test_Entity__inheritance(self): assert isinstance(p, Entity) assert isinstance(p.position, Position) - def test_Entity__access(self): + def test__access(self): world = World() pos1 = PositionEntity(world) pos2 = PosEntity(world) @@ -128,11 +126,15 @@ def sx(p, v): with pytest.raises(AttributeError): sx(pos2, 10) - def test_World(self): + +class TestExtWorld(object): + __tags__ = ["ebs", "sdl2ext"] + + def test_init(self): w = World() assert isinstance(w, World) - def test_World_add_remove_system(self): + def test_add_remove_system(self): world = World() assert isinstance(world, World) @@ -172,7 +174,7 @@ def process(self, world, components): # system has been removed. assert isinstance(entity.position, Position) - def test_World_entities(self): + def test_entities(self): w = World() assert len(w.entities) == 0 @@ -180,7 +182,7 @@ def test_World_entities(self): Entity(w) assert len(w.entities) == 100 - def test_World_delete(self): + def test_delete(self): w = World() e1 = Entity(w) e2 = Entity(w) @@ -195,7 +197,7 @@ def test_World_delete(self): w.delete(e1) w.delete(e2) - def test_World_delete_entities(self): + def test_delete_entities(self): w = World() e1 = Entity(w) e2 = Entity(w) @@ -206,7 +208,7 @@ def test_World_delete_entities(self): # The next should have no effect w.delete_entities((e1, e2)) - def test_World_get_entities(self): + def test_get_entities(self): w = World() e1 = PositionEntity(w, 1, 1) e2 = PositionEntity(w, 1, 2) @@ -214,7 +216,11 @@ def test_World_get_entities(self): e2.position.y = 1 assert len(w.get_entities(e1.position)) == 2 - def test_System(self): + +class TestExtSystem(object): + __tags__ = ["ebs", "sdl2ext"] + + def test_init(self): world = World() with pytest.raises(ValueError): world.add_system(None) @@ -237,7 +243,7 @@ def __init__(self): world.add_system(psystem) assert psystem in world.systems - def test_System_process(self): + def test_process(self): world = World() class ErrornousSystem(System): @@ -268,7 +274,11 @@ def __init__(self): assert c.x == 2 assert c.y == 2 - def test_Applicator(self): + +class TestExtApplicator(object): + __tags__ = ["ebs", "sdl2ext"] + + def test_init(self): world = World() class ErrornousApplicator(Applicator): @@ -285,7 +295,7 @@ def __init__(self): world.add_system(mapplicator) assert mapplicator in world.systems - def test_Applicator_process(self): + def test_process(self): world = World() class ErrornousApplicator(Applicator): diff --git a/sdl2/test/sdl2ext_events_test.py b/sdl2/test/sdl2ext_events_test.py index 6b9d2a7a..ffab8b66 100644 --- a/sdl2/test/sdl2ext_events_test.py +++ b/sdl2/test/sdl2ext_events_test.py @@ -1,5 +1,6 @@ import sys import pytest + try: import multiprocessing _HASMP = True @@ -13,10 +14,10 @@ def mp_do_nothing(sender, *args): pass -class TestSDL2ExtEvents(object): +class TestExtEventHandler(object): __tags__ = ["sdl2ext"] - def test_EventHandler(self): + def test_init(self): with pytest.raises(TypeError): events.EventHandler() assert isinstance(events.EventHandler(None), events.EventHandler) @@ -30,7 +31,7 @@ def test_EventHandler(self): assert len(ev) == 0 assert len(ev.callbacks) == 0 - def test_EventHandler_add__iadd__(self): + def test_add__iadd__(self): ev = events.EventHandler(None) def doadd(ev, cb): @@ -67,7 +68,7 @@ def callback(): ev.add(callback) assert len(ev) == 10 - def test_EventHandler_remove__isub__(self): + def test_remove__isub__(self): ev = events.EventHandler(None) def doremove(ev, cb): @@ -97,7 +98,7 @@ def callback(): ev -= callback assert len(ev) == 2 - def test_EventHandler__call__(self): + def test__call__(self): ev = events.EventHandler("Test") testsum = [] @@ -116,8 +117,12 @@ def callback(sender, sumval): for v in results: assert v is None - @pytest.mark.skipif(not _HASMP, reason="multiprocessing is not supported") - def test_MPEventHandler(self): + +@pytest.mark.skipif(not _HASMP, reason="multiprocessing is not supported") +class TestExtMPEventHandler(object): + __tags__ = ["sdl2ext"] + + def test_init(self): with pytest.raises(TypeError): events.MPEventHandler() assert isinstance(events.MPEventHandler(None), events.MPEventHandler) @@ -131,8 +136,7 @@ def test_MPEventHandler(self): assert len(ev) == 0 assert len(ev.callbacks) == 0 - @pytest.mark.skipif(not _HASMP, reason="multiprocessing is not supported") - def test_MPEventHandler_add__iadd__(self): + def test_add__iadd__(self): ev = events.MPEventHandler(None) def doadd(ev, cb): @@ -169,8 +173,7 @@ def callback(): ev.add(callback) assert len(ev) == 10 - @pytest.mark.skipif(not _HASMP, reason="multiprocessing is not supported") - def test_MPEventHandler_remove__isub__(self): + def test_remove__isub__(self): ev = events.MPEventHandler(None) def doremove(ev, cb): @@ -203,7 +206,7 @@ def callback(): @pytest.mark.skipif(not _HASMP, reason="multiprocessing is not supported") @pytest.mark.skipif(sys.platform == "win32", reason="relative import will create a fork bomb") - def test_MPEventHandler__call__(self): + def test__call__(self): ev = events.MPEventHandler("Test") for x in range(10): diff --git a/sdl2/test/sdl2ext_font_test.py b/sdl2/test/sdl2ext_font_test.py index 4386c3c6..9d48bf40 100644 --- a/sdl2/test/sdl2ext_font_test.py +++ b/sdl2/test/sdl2ext_font_test.py @@ -9,7 +9,7 @@ _HASSDLTTF = True try: - from .. import sdlttf + from sdl2 import sdlttf except ImportError: _HASSDLTTF = False diff --git a/sdl2/test/sdl2ext_image_test.py b/sdl2/test/sdl2ext_image_test.py index 85a77564..3afdb5ab 100644 --- a/sdl2/test/sdl2ext_image_test.py +++ b/sdl2/test/sdl2ext_image_test.py @@ -58,193 +58,179 @@ 'white': color.Color(255, 255, 255, 255) } - -class TestSDL2ExtImage(object): - __tags__ = ["sdl", "sdl2ext"] - - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - sdl2ext.quit() - - - def check_image_contents(self, img): - # Test different coordinates on surface - pxview = sdl2ext.PixelView(img) - img_red = color.ARGB(pxview[0][0]) - img_blue = color.ARGB(pxview[0][16]) - img_white = color.ARGB(pxview[0][31]) - img_black = color.ARGB(pxview[31][31]) - assert img_red == colors['red'] - assert img_blue == colors['blue'] - assert img_white == colors['white'] - assert img_black == colors['black'] - - def test_load_bmp(self): - # Test loading a basic BMP image - img_path = os.path.join(resource_path, "surfacetest.bmp") - sf = sdl2ext.load_bmp(img_path) +def check_image_contents(img): + # Test different coordinates on surface + pxview = sdl2ext.PixelView(img) + img_red = color.ARGB(pxview[0][0]) + img_blue = color.ARGB(pxview[0][16]) + img_white = color.ARGB(pxview[0][31]) + img_black = color.ARGB(pxview[31][31]) + assert img_red == colors['red'] + assert img_blue == colors['blue'] + assert img_white == colors['white'] + assert img_black == colors['black'] + + + +def test_load_bmp(with_sdl): + # Test loading a basic BMP image + img_path = os.path.join(resource_path, "surfacetest.bmp") + sf = sdl2ext.load_bmp(img_path) + assert isinstance(sf, surf.SDL_Surface) + check_image_contents(sf) + surf.SDL_FreeSurface(sf) + + # Test exception on missing file + bad_path = os.path.join(resource_path, "doesnt_exist.bmp") + with pytest.raises(IOError): + sdl2ext.load_bmp(bad_path) + + # Test exception on bad file type + bad_type = os.path.join(resource_path, "surfacetest.png") + with pytest.raises(sdl2ext.SDLError): + sdl2ext.load_bmp(bad_type) + + +def test_save_bmp(with_sdl, tmpdir): + # Open a BMP that we can re-save + img_path = os.path.join(resource_path, "surfacetest.bmp") + sf = sdl2ext.load_bmp(img_path) + assert isinstance(sf, surf.SDL_Surface) + + # Try saving the BMP to a new folder and re-loading it + outpath = os.path.join(str(tmpdir), "save_test.bmp") + sdl2ext.save_bmp(sf, outpath) + assert os.path.exists(outpath) + sf_saved = sdl2ext.load_bmp(outpath) + assert isinstance(sf_saved, surf.SDL_Surface) + check_image_contents(sf_saved) + + # Try modifying/overwriting the existing BMP + sdl2ext.fill(sf, (0, 255, 0, 255)) + sdl2ext.save_bmp(sf, outpath, overwrite=True) + sf_saved2 = sdl2ext.load_bmp(outpath) + assert isinstance(sf_saved2, surf.SDL_Surface) + with pytest.raises(AssertionError): + check_image_contents(sf_saved2) + + surf.SDL_FreeSurface(sf) + surf.SDL_FreeSurface(sf_saved) + surf.SDL_FreeSurface(sf_saved2) + + # Test existing file exception with overwrite=False + with pytest.raises(RuntimeError): + sdl2ext.save_bmp(sf_saved, outpath, overwrite=False) + + # Test exception with non-existent save directory + bad_path = os.path.join(resource_path, "doesnt_exist", "tst.bmp") + with pytest.raises(IOError): + sdl2ext.save_bmp(sf_saved, bad_path) + + +@pytest.mark.skipif(not _HASSDLIMAGE, reason="Requires SDL2_image") +def test_load_img(with_sdl): + # Test loading all test images, with and without ARGB conversion + resources = os.listdir(resource_path) + test_imgs = [f for f in resources if f[:11] == "surfacetest"] + for img in test_imgs: + img_path = os.path.join(resource_path, img) + fmt = img.split(".")[-1] + if fmt in skip_formats: + continue + + sf = sdl2ext.load_img(img_path) assert isinstance(sf, surf.SDL_Surface) - self.check_image_contents(sf) + assert sf.format.contents.format == pixels.SDL_PIXELFORMAT_ARGB8888 + if fmt not in skip_color_check: + check_image_contents(sf) surf.SDL_FreeSurface(sf) - # Test exception on missing file - bad_path = os.path.join(resource_path, "doesnt_exist.bmp") - with pytest.raises(IOError): - sdl2ext.load_bmp(bad_path) - - # Test exception on bad file type - bad_type = os.path.join(resource_path, "surfacetest.png") - with pytest.raises(sdl2ext.SDLError): - sdl2ext.load_bmp(bad_type) - - - def test_save_bmp(self, tmpdir): - # Open a BMP that we can re-save - img_path = os.path.join(resource_path, "surfacetest.bmp") - sf = sdl2ext.load_bmp(img_path) - assert isinstance(sf, surf.SDL_Surface) - - # Try saving the BMP to a new folder and re-loading it - outpath = os.path.join(str(tmpdir), "save_test.bmp") - sdl2ext.save_bmp(sf, outpath) - assert os.path.exists(outpath) - sf_saved = sdl2ext.load_bmp(outpath) - assert isinstance(sf_saved, surf.SDL_Surface) - self.check_image_contents(sf_saved) - - # Try modifying/overwriting the existing BMP - sdl2ext.fill(sf, (0, 255, 0, 255)) - sdl2ext.save_bmp(sf, outpath, overwrite=True) - sf_saved2 = sdl2ext.load_bmp(outpath) - assert isinstance(sf_saved2, surf.SDL_Surface) - with pytest.raises(AssertionError): - self.check_image_contents(sf_saved2) - - surf.SDL_FreeSurface(sf) - surf.SDL_FreeSurface(sf_saved) - surf.SDL_FreeSurface(sf_saved2) - - # Test existing file exception with overwrite=False - with pytest.raises(RuntimeError): - sdl2ext.save_bmp(sf_saved, outpath, overwrite=False) - - # Test exception with non-existent save directory - bad_path = os.path.join(resource_path, "doesnt_exist", "tst.bmp") - with pytest.raises(IOError): - sdl2ext.save_bmp(sf_saved, bad_path) - - - @pytest.mark.skipif(not _HASSDLIMAGE, reason="Requires SDL2_image") - def test_load_img(self): - # Test loading all test images, with and without ARGB conversion - resources = os.listdir(resource_path) - test_imgs = [f for f in resources if f[:11] == "surfacetest"] - for img in test_imgs: - img_path = os.path.join(resource_path, img) - fmt = img.split(".")[-1] - if fmt in skip_formats: - continue - - sf = sdl2ext.load_img(img_path) - assert isinstance(sf, surf.SDL_Surface) - assert sf.format.contents.format == pixels.SDL_PIXELFORMAT_ARGB8888 - if fmt not in skip_color_check: - self.check_image_contents(sf) - surf.SDL_FreeSurface(sf) - - sf2 = sdl2ext.load_img(img_path, as_argb=False) - assert isinstance(sf2, surf.SDL_Surface) - surf.SDL_FreeSurface(sf2) - - # Test exception on missing file - bad_path = os.path.join(resource_path, "doesnt_exist.bmp") - with pytest.raises(IOError): - sdl2ext.load_img(bad_path) - - # Test exception on bad file type - bad_type = os.path.join(resource_path, "tuffy.ttf") - with pytest.raises(sdl2ext.SDLError): - sdl2ext.load_img(bad_type) - - - @pytest.mark.skipif(not _HASPIL, reason="Pillow library is not installed") - def test_pillow_to_image(self): - # Import an image using Pillow - from PIL import Image - img_path = os.path.join(resource_path, "surfacetest.bmp") - pil_img = Image.open(img_path) - - # Convert the image to an SDL surface and verify it worked + sf2 = sdl2ext.load_img(img_path, as_argb=False) + assert isinstance(sf2, surf.SDL_Surface) + surf.SDL_FreeSurface(sf2) + + # Test exception on missing file + bad_path = os.path.join(resource_path, "doesnt_exist.bmp") + with pytest.raises(IOError): + sdl2ext.load_img(bad_path) + + # Test exception on bad file type + bad_type = os.path.join(resource_path, "tuffy.ttf") + with pytest.raises(sdl2ext.SDLError): + sdl2ext.load_img(bad_type) + + +@pytest.mark.skipif(not _HASPIL, reason="Pillow library is not installed") +def test_pillow_to_image(with_sdl): + # Import an image using Pillow + from PIL import Image + img_path = os.path.join(resource_path, "surfacetest.bmp") + pil_img = Image.open(img_path) + + # Convert the image to an SDL surface and verify it worked + sf = sdl2ext.pillow_to_surface(pil_img) + assert isinstance(sf, surf.SDL_Surface) + check_image_contents(sf) + surf.SDL_FreeSurface(sf) + + # Try converting a palette image + palette_img = pil_img.convert("P", palette=Image.WEB) + sfp = sdl2ext.pillow_to_surface(palette_img) + pxformat = sfp.format.contents + assert isinstance(sfp, surf.SDL_Surface) + check_image_contents(sfp) + assert pxformat.BytesPerPixel == 4 + surf.SDL_FreeSurface(sfp) + + # Try converting a palette image without ARGB conversion + sfp2 = sdl2ext.pillow_to_surface(palette_img, False) + pxformat = sfp2.format.contents + assert isinstance(sfp2, surf.SDL_Surface) + assert pxformat.BytesPerPixel == 1 + sdl_palette = pxformat.palette.contents + pil_palette = palette_img.getpalette() + assert sdl_palette.colors[0].r == pil_palette[0] + assert sdl_palette.colors[0].g == pil_palette[1] + assert sdl_palette.colors[0].b == pil_palette[2] + surf.SDL_FreeSurface(sfp2) + + # Test loading all supported test images and compare against reference + resources = os.listdir(resource_path) + test_imgs = [f for f in resources if f[:11] == "surfacetest"] + for img in test_imgs: + fmt = img.split(".")[-1] + if fmt in ("webp", "xcf", "lbm", "svg"): + continue + pil_img = Image.open(os.path.join(resource_path, img)) sf = sdl2ext.pillow_to_surface(pil_img) assert isinstance(sf, surf.SDL_Surface) - self.check_image_contents(sf) + assert sf.format.contents.format == pixels.SDL_PIXELFORMAT_ARGB8888 + if fmt not in skip_color_check: + check_image_contents(sf) surf.SDL_FreeSurface(sf) - # Try converting a palette image - palette_img = pil_img.convert("P", palette=Image.WEB) - sfp = sdl2ext.pillow_to_surface(palette_img) - pxformat = sfp.format.contents - assert isinstance(sfp, surf.SDL_Surface) - self.check_image_contents(sfp) - assert pxformat.BytesPerPixel == 4 - surf.SDL_FreeSurface(sfp) - - # Try converting a palette image without ARGB conversion - sfp2 = sdl2ext.pillow_to_surface(palette_img, False) - pxformat = sfp2.format.contents - assert isinstance(sfp2, surf.SDL_Surface) - assert pxformat.BytesPerPixel == 1 - sdl_palette = pxformat.palette.contents - pil_palette = palette_img.getpalette() - assert sdl_palette.colors[0].r == pil_palette[0] - assert sdl_palette.colors[0].g == pil_palette[1] - assert sdl_palette.colors[0].b == pil_palette[2] - surf.SDL_FreeSurface(sfp2) - - # Test loading all supported test images and compare against reference - resources = os.listdir(resource_path) - test_imgs = [f for f in resources if f[:11] == "surfacetest"] - for img in test_imgs: - fmt = img.split(".")[-1] - if fmt in ("webp", "xcf", "lbm", "svg"): - continue - pil_img = Image.open(os.path.join(resource_path, img)) - sf = sdl2ext.pillow_to_surface(pil_img) - assert isinstance(sf, surf.SDL_Surface) - assert sf.format.contents.format == pixels.SDL_PIXELFORMAT_ARGB8888 - if fmt not in skip_color_check: - self.check_image_contents(sf) - surf.SDL_FreeSurface(sf) - - @pytest.mark.skipif(not _HASSDLIMAGE, reason="Requires SDL2_image") - def test_load_image(self): - resources = os.listdir(resource_path) - test_imgs = [f for f in resources if f[:11] == "surfacetest"] - for img in test_imgs: - img_path = os.path.join(resource_path, img) - fmt = img.split(".")[-1] - if fmt in skip_formats: - continue - - # Try normal loading - sf = sdl2ext.load_image(img_path) - assert isinstance(sf, surf.SDL_Surface) - - # Force only PIL - if _HASPIL and fmt not in ("webp", "xcf", "lbm", "svg"): - sf = sdl2ext.load_image(img_path, enforce="PIL") - assert isinstance(sf, surf.SDL_Surface) +@pytest.mark.skipif(not _HASSDLIMAGE, reason="Requires SDL2_image") +def test_load_image(with_sdl): + resources = os.listdir(resource_path) + test_imgs = [f for f in resources if f[:11] == "surfacetest"] + for img in test_imgs: + img_path = os.path.join(resource_path, img) + fmt = img.split(".")[-1] + if fmt in skip_formats: + continue + + # Try normal loading + sf = sdl2ext.load_image(img_path) + assert isinstance(sf, surf.SDL_Surface) - # Force only sdlimage - sf = sdl2ext.load_image(img_path, enforce="SDL") + # Force only PIL + if _HASPIL and fmt not in ("webp", "xcf", "lbm", "svg"): + sf = sdl2ext.load_image(img_path, enforce="PIL") assert isinstance(sf, surf.SDL_Surface) - # Clean up surface now that we're done with it - surf.SDL_FreeSurface(sf) + # Force only sdlimage + sf = sdl2ext.load_image(img_path, enforce="SDL") + assert isinstance(sf, surf.SDL_Surface) + + # Clean up surface now that we're done with it + surf.SDL_FreeSurface(sf) diff --git a/sdl2/test/sdl2ext_msgbox_test.py b/sdl2/test/sdl2ext_msgbox_test.py index d694a3e2..9db48fdd 100644 --- a/sdl2/test/sdl2ext_msgbox_test.py +++ b/sdl2/test/sdl2ext_msgbox_test.py @@ -4,83 +4,67 @@ from sdl2 import ext as sdl2ext from sdl2 import messagebox as mb -class TestSDL2ExtMessageBox(object): - __tags__ = ["sdl", "sdl2ext"] - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') +def test_MessageBoxTheme(with_sdl): + # Test using RGB color tuples + theme = sdl2ext.MessageBoxTheme(text=(255, 255, 255)) + text_col = theme._get_theme().colors[1] + assert text_col.r == 255 and text_col.g == 255 - @classmethod - def teardown_class(cls): - sdl2ext.quit() + # Test using Color objects + BLACK = sdl2ext.Color(0, 0, 0) + theme = sdl2ext.MessageBoxTheme(btn=BLACK) + btn_col = theme._get_theme().colors[3] + assert btn_col.r == 0 and btn_col.b == 0 - def setup_method(self): - SDL_ClearError() + # Test exceptions on bad input + with pytest.raises(TypeError): + sdl2ext.MessageBoxTheme(bg=(255, 255)) + with pytest.raises(ValueError): + sdl2ext.MessageBoxTheme(bg=(256, 255, 255)) - def test_MessageBoxTheme(self): - # Test using RGB color tuples - theme = sdl2ext.MessageBoxTheme(text=(255, 255, 255)) - text_col = theme._get_theme().colors[1] - assert text_col.r == 255 and text_col.g == 255 +def test_MessageBox(with_sdl): + # Test initialization of the class + box = sdl2ext.MessageBox( + "Test", "Did it work?", ["Yes", "No"], default="Yes", msgtype="info" + ) + sdl_box = box._get_msgbox() + assert sdl_box.flags & mb.SDL_MESSAGEBOX_INFORMATION + assert sdl_box.title.decode('utf-8') == "Test" + assert sdl_box.message.decode('utf-8') == "Did it work?" + assert sdl_box.numbuttons == 2 + b1 = sdl_box.buttons.contents # Only gets first button for some reason + assert b1.text.decode('utf-8') == "Yes" + assert b1.flags & mb.SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT - # Test using Color objects - BLACK = sdl2ext.Color(0, 0, 0) - theme = sdl2ext.MessageBoxTheme(btn=BLACK) - btn_col = theme._get_theme().colors[3] - assert btn_col.r == 0 and btn_col.b == 0 + # Test internal generation w/ an associated window + win = sdl2ext.Window(b"Test", (640, 480)) + sdl_box = box._get_msgbox(win) + assert isinstance(sdl_box.window.contents, SDL_Window) + win.close() - # Test exceptions on bad input - with pytest.raises(TypeError): - sdl2ext.MessageBoxTheme(bg=(255, 255)) - with pytest.raises(ValueError): - sdl2ext.MessageBoxTheme(bg=(256, 255, 255)) + # Test initialization with theme + mbtheme = sdl2ext.MessageBoxTheme(text=(255, 0, 0)) + box2 = sdl2ext.MessageBox( + "Test", "Did it work?", ["Yes", "No"], theme=mbtheme + ) + sdl_box2 = box2._get_msgbox() + text_col = sdl_box2.colorScheme.contents.colors[1] + assert text_col.r == 255 and text_col.g == 0 - def test_MessageBox(self): - # Test initialization of the class - box = sdl2ext.MessageBox( - "Test", "Did it work?", ["Yes", "No"], default="Yes", msgtype="info" - ) - sdl_box = box._get_msgbox() - assert sdl_box.flags & mb.SDL_MESSAGEBOX_INFORMATION - assert sdl_box.title.decode('utf-8') == "Test" - assert sdl_box.message.decode('utf-8') == "Did it work?" - assert sdl_box.numbuttons == 2 - b1 = sdl_box.buttons.contents # Only gets first button for some reason - assert b1.text.decode('utf-8') == "Yes" - assert b1.flags & mb.SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT + # Test exceptions on bad input + with pytest.raises(TypeError): + sdl2ext.MessageBox("Title", "Some text", "A button") + with pytest.raises(ValueError): + sdl2ext.MessageBox("Title", "Some text", []) + with pytest.raises(ValueError): + box._get_window_pointer("not a window") - # Test internal generation w/ an associated window - win = sdl2ext.Window(b"Test", (640, 480)) - sdl_box = box._get_msgbox(win) - assert isinstance(sdl_box.window.contents, SDL_Window) - win.close() +@pytest.mark.skip("not implemented, requires GUI interaction") +def test_show_messagebox(self): + # Could implement a test using mock, but not sure how useful that'd be + pass - # Test initialization with theme - mbtheme = sdl2ext.MessageBoxTheme(text=(255, 0, 0)) - box2 = sdl2ext.MessageBox( - "Test", "Did it work?", ["Yes", "No"], theme=mbtheme - ) - sdl_box2 = box2._get_msgbox() - text_col = sdl_box2.colorScheme.contents.colors[1] - assert text_col.r == 255 and text_col.g == 0 - - # Test exceptions on bad input - with pytest.raises(TypeError): - sdl2ext.MessageBox("Title", "Some text", "A button") - with pytest.raises(ValueError): - sdl2ext.MessageBox("Title", "Some text", []) - with pytest.raises(ValueError): - box._get_window_pointer("not a window") - - @pytest.mark.skip("not implemented, requires GUI interaction") - def test_show_messagebox(self): - # Could implement a test using mock, but not sure how useful that'd be - pass - - @pytest.mark.skip("not implemented, requires GUI interaction") - def test_show_alert(self): - pass +@pytest.mark.skip("not implemented, requires GUI interaction") +def test_show_alert(self): + pass diff --git a/sdl2/test/sdl2ext_particles_test.py b/sdl2/test/sdl2ext_particles_test.py index ae415d26..51cfe803 100644 --- a/sdl2/test/sdl2ext_particles_test.py +++ b/sdl2/test/sdl2ext_particles_test.py @@ -3,10 +3,10 @@ from sdl2.ext import particles -class TestSDL2ExtParticles(object): +class TestExtParticle(object): __tags__ = ["sdl2ext"] - def test_Particle(self): + def test_init(self): p = particles.Particle(0, 0, 0) assert isinstance(p, particles.Particle) assert p.x == p.y == p.life == 0 @@ -16,7 +16,7 @@ def test_Particle(self): assert p.y == 2 assert p.life == 3 - def test_Particle_xy_position(self): + def test_xy_position(self): for x in range(-100, 100): for y in range(-100, 100): p = particles.Particle(x, y, 1) @@ -36,12 +36,16 @@ def test_Particle_xy_position(self): assert p.x == x assert p.y == y - def test_Particle_life(self): + def test_life(self): for life in range(-100, 100): p = particles.Particle(0, 0, life) assert p.life == life - def test_ParticleEngine(self): + +class TestExtParticleEngine(object): + __tags__ = ["sdl2ext"] + + def test_init(self): engine = particles.ParticleEngine() assert isinstance(engine, particles.ParticleEngine) assert particles.Particle in engine.componenttypes @@ -49,7 +53,7 @@ def test_ParticleEngine(self): assert engine.deletefunc is None assert engine.updatefunc is None - def test_ParticleEngine_createfunc(self): + def test_createfunc(self): def func(w, c): pass engine = particles.ParticleEngine() @@ -66,7 +70,7 @@ def setf(x, f): with pytest.raises(TypeError): setf(engine, 1234) - def test_ParticleEngine_deletefunc(self): + def test_deletefunc(self): def func(w, c): pass engine = particles.ParticleEngine() @@ -83,7 +87,7 @@ def setf(x, f): with pytest.raises(TypeError): setf(engine, 1234) - def test_ParticleEngine_updatefunc(self): + def test_updatefunc(self): def func(w, c): pass engine = particles.ParticleEngine() @@ -100,7 +104,7 @@ def setf(x, f): with pytest.raises(TypeError): setf(engine, 1234) - def test_ParticleEngine_process(self): + def test_process(self): def cfunc(w, c): assert len(c) == w["runs"] for p in c: diff --git a/sdl2/test/sdl2ext_pixelaccess_test.py b/sdl2/test/sdl2ext_pixelaccess_test.py index 43208cc4..636e635a 100644 --- a/sdl2/test/sdl2ext_pixelaccess_test.py +++ b/sdl2/test/sdl2ext_pixelaccess_test.py @@ -20,151 +20,127 @@ 'white': color.Color(255, 255, 255, 255) } - -class TestSDL2ExtPixelAccess(object): - __tags__ = ["sdl", "sdl2ext"] - - @classmethod - def setup_class(cls): - cls.testfile = os.path.join( - os.path.dirname(os.path.abspath(__file__)), - "resources", "surfacetest.bmp" - ) - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - sdl2ext.quit() - - - def test_PixelView(self): - # Import test image and open pixel view - imgsurf = surface.SDL_LoadBMP(self.testfile.encode("utf-8")) - pxview = sdl2ext.PixelView(imgsurf.contents) - - # Test different coordinates on surface - assert color.ARGB(pxview[0][0]) == colors['red'] - assert color.ARGB(pxview[0][16]) == colors['blue'] - assert color.ARGB(pxview[0][31]) == colors['white'] - assert color.ARGB(pxview[31][31]) == colors['black'] - - # Try modifying surface, test if changes persist - pxview[31][0] = 0xFF808080 # medium grey in ARGB - pxview2 = sdl2ext.PixelView(imgsurf) - assert pxview2[31][0] == 0xFF808080 - - # Test that negative indexing works as expected - assert color.ARGB(pxview[0][-1]) == colors['white'] - assert color.ARGB(pxview[-1][-1]) == colors['black'] - - # Test out-of-bounds exceptions for indices - with pytest.raises(IndexError): - pxview[32][32] - - # Test exception on use with a 3 byte per pixel surface - sf_rgb24 = _create_surface((16, 16), fmt="RGB24") - with pytest.raises(RuntimeError): - sdl2ext.PixelView(sf_rgb24) - - surface.SDL_FreeSurface(sf_rgb24) - surface.SDL_FreeSurface(imgsurf) - - - @pytest.mark.skipif(not _HASNUMPY, reason="numpy module is not supported") - def test_pixels2d(self): - # Import test image and open pixels2d view - imgsurf = surface.SDL_LoadBMP(self.testfile.encode("utf-8")) - nparray = sdl2ext.pixels2d(imgsurf.contents, transpose=False) - assert nparray.shape == (32, 32) - - # Test different coordinates on surface - assert color.ARGB(nparray[0][0]) == colors['red'] - assert color.ARGB(nparray[0][16]) == colors['blue'] - assert color.ARGB(nparray[0][31]) == colors['white'] - assert color.ARGB(nparray[31][31]) == colors['black'] - - # Try modifying surface, test if changes persist - nparray[31][0] = 0xFF808080 # medium grey in ARGB - nparray2 = sdl2ext.pixels2d(imgsurf, transpose=False) - assert nparray2[31][0] == 0xFF808080 - - # Test exception on use with a 3 byte per pixel surface - sf_rgb24 = _create_surface((16, 16), fmt="RGB24") - with pytest.raises(RuntimeError): - sdl2ext.pixels2d(sf_rgb24) - - surface.SDL_FreeSurface(sf_rgb24) - surface.SDL_FreeSurface(imgsurf) - - - @pytest.mark.skipif(not _HASNUMPY, reason="numpy module is not supported") - def test_pixels3d(self): - # Import test image and convert to RGBA - rgba = pixels.SDL_PIXELFORMAT_ABGR8888 - imgsurf = surface.SDL_LoadBMP(self.testfile.encode("utf-8")) - imgsurf = surface.SDL_ConvertSurfaceFormat(imgsurf.contents, rgba, 0) - - # Create view and test different coordinates on surface - nparray = sdl2ext.pixels3d(imgsurf.contents, transpose=False) - assert nparray.shape == (32, 32, 4) - assert color.Color(*nparray[0][0]) == colors['red'] - assert color.Color(*nparray[0][16]) == colors['blue'] - assert color.Color(*nparray[0][31]) == colors['white'] - assert color.Color(*nparray[31][31]) == colors['black'] - - # Create transposed view and test different coordinates on surface - nptrans = sdl2ext.pixels3d(imgsurf.contents, transpose=True) - assert nptrans.shape == (32, 32, 4) - assert color.Color(*nptrans[0][0]) == colors['red'] - assert color.Color(*nptrans[16][0]) == colors['blue'] - assert color.Color(*nptrans[31][0]) == colors['white'] - assert color.Color(*nptrans[31][31]) == colors['black'] - - # Try modifying surface, test if changes persist - grey = [128, 128, 128, 255] - nparray[31][0][:] = grey - nparray2 = sdl2ext.pixels3d(imgsurf, transpose=False) - assert color.Color(*nparray2[31][0]) == color.Color(*grey) - - # Test usage with a 3 bytes-per-pixel surface - sf_rgb24 = _create_surface((16, 16), grey, fmt="RGB24") - nparray_rgb24 = sdl2ext.pixels3d(sf_rgb24) - assert color.Color(*nparray_rgb24[0][0]) == color.Color(*grey) - - surface.SDL_FreeSurface(sf_rgb24) - surface.SDL_FreeSurface(imgsurf) - - - @pytest.mark.skipif(not _HASNUMPY, reason="numpy module is not supported") - def test_surface_to_ndarray(self): - # Import test image & create an RGBA copy - rgba = pixels.SDL_PIXELFORMAT_ABGR8888 - imgsurf = surface.SDL_LoadBMP(self.testfile.encode("utf-8")) - rgbasurf = surface.SDL_ConvertSurfaceFormat(imgsurf.contents, rgba, 0) - - # Create a 2D ndarray from the surface & test different coordinates - arr_2d = sdl2ext.surface_to_ndarray(imgsurf.contents, ndim=2) - assert color.ARGB(arr_2d[0][0]) == colors['red'] - assert color.ARGB(arr_2d[0][16]) == colors['blue'] - assert color.ARGB(arr_2d[0][31]) == colors['white'] - assert color.ARGB(arr_2d[31][31]) == colors['black'] - - # Create a 3D ndarray from the surface & test different coordinates - arr_3d = sdl2ext.surface_to_ndarray(rgbasurf.contents) - assert arr_3d.shape == (32, 32, 4) - assert color.Color(*arr_3d[0][0]) == colors['red'] - assert color.Color(*arr_3d[0][16]) == colors['blue'] - assert color.Color(*arr_3d[0][31]) == colors['white'] - assert color.Color(*arr_3d[31][31]) == colors['black'] - - # Try modifying surface, make sure changes don't persist - grey = [128, 128, 128, 255] - arr_3d[31][0][:] = grey - arr_view = sdl2ext.pixels3d(rgbasurf, transpose=False) - assert color.Color(*arr_view[31][0]) != color.Color(*grey) - - surface.SDL_FreeSurface(imgsurf) - surface.SDL_FreeSurface(rgbasurf) +@pytest.fixture +def imgsurf(with_sdl): + parent_dir = os.path.dirname(os.path.abspath(__file__)) + testfile = os.path.join(parent_dir, "resources", "surfacetest.bmp") + sf = surface.SDL_LoadBMP(testfile.encode("utf-8")) + yield sf + surface.SDL_FreeSurface(sf) + +@pytest.fixture +def rgbasurf(imgsurf): + rgba = pixels.SDL_PIXELFORMAT_ABGR8888 + rgbasurf = surface.SDL_ConvertSurfaceFormat(imgsurf.contents, rgba, 0) + yield rgbasurf + surface.SDL_FreeSurface(rgbasurf) + +@pytest.fixture +def surf_rgb24(with_sdl): + grey = [128, 128, 128, 255] + sf = _create_surface((16, 16), grey, fmt="RGB24") + yield sf + surface.SDL_FreeSurface(sf) + + +def test_PixelView(imgsurf, surf_rgb24): + # Open pixel view for test image + pxview = sdl2ext.PixelView(imgsurf.contents) + + # Test different coordinates on surface + assert color.ARGB(pxview[0][0]) == colors['red'] + assert color.ARGB(pxview[0][16]) == colors['blue'] + assert color.ARGB(pxview[0][31]) == colors['white'] + assert color.ARGB(pxview[31][31]) == colors['black'] + + # Try modifying surface, test if changes persist + pxview[31][0] = 0xFF808080 # medium grey in ARGB + pxview2 = sdl2ext.PixelView(imgsurf) + assert pxview2[31][0] == 0xFF808080 + + # Test that negative indexing works as expected + assert color.ARGB(pxview[0][-1]) == colors['white'] + assert color.ARGB(pxview[-1][-1]) == colors['black'] + + # Test out-of-bounds exceptions for indices + with pytest.raises(IndexError): + pxview[32][32] + + # Test exception on use with a 3 byte per pixel surface + with pytest.raises(RuntimeError): + sdl2ext.PixelView(surf_rgb24) + + +@pytest.mark.skipif(not _HASNUMPY, reason="numpy module is not supported") +def test_pixels2d(imgsurf, surf_rgb24): + # Open pixels2d view for test image + nparray = sdl2ext.pixels2d(imgsurf.contents, transpose=False) + assert nparray.shape == (32, 32) + + # Test different coordinates on surface + assert color.ARGB(nparray[0][0]) == colors['red'] + assert color.ARGB(nparray[0][16]) == colors['blue'] + assert color.ARGB(nparray[0][31]) == colors['white'] + assert color.ARGB(nparray[31][31]) == colors['black'] + + # Try modifying surface, test if changes persist + nparray[31][0] = 0xFF808080 # medium grey in ARGB + nparray2 = sdl2ext.pixels2d(imgsurf, transpose=False) + assert nparray2[31][0] == 0xFF808080 + + # Test exception on use with a 3 byte per pixel surface + with pytest.raises(RuntimeError): + sdl2ext.pixels2d(surf_rgb24) + + +@pytest.mark.skipif(not _HASNUMPY, reason="numpy module is not supported") +def test_pixels3d(rgbasurf, surf_rgb24): + # Create view and test different coordinates on surface + nparray = sdl2ext.pixels3d(rgbasurf.contents, transpose=False) + assert nparray.shape == (32, 32, 4) + assert color.Color(*nparray[0][0]) == colors['red'] + assert color.Color(*nparray[0][16]) == colors['blue'] + assert color.Color(*nparray[0][31]) == colors['white'] + assert color.Color(*nparray[31][31]) == colors['black'] + + # Create transposed view and test different coordinates on surface + nptrans = sdl2ext.pixels3d(rgbasurf.contents, transpose=True) + assert nptrans.shape == (32, 32, 4) + assert color.Color(*nptrans[0][0]) == colors['red'] + assert color.Color(*nptrans[16][0]) == colors['blue'] + assert color.Color(*nptrans[31][0]) == colors['white'] + assert color.Color(*nptrans[31][31]) == colors['black'] + + # Try modifying surface, test if changes persist + grey = [128, 128, 128, 255] + nparray[31][0][:] = grey + nparray2 = sdl2ext.pixels3d(rgbasurf, transpose=False) + assert color.Color(*nparray2[31][0]) == color.Color(*grey) + + # Test usage with a 3 bytes-per-pixel surface + nparray_rgb24 = sdl2ext.pixels3d(surf_rgb24) + assert color.Color(*nparray_rgb24[0][0]) == color.Color(*grey) + + +@pytest.mark.skipif(not _HASNUMPY, reason="numpy module is not supported") +def test_surface_to_ndarray(imgsurf, rgbasurf): + # Create a 2D ndarray from the surface & test different coordinates + arr_2d = sdl2ext.surface_to_ndarray(imgsurf.contents, ndim=2) + assert color.ARGB(arr_2d[0][0]) == colors['red'] + assert color.ARGB(arr_2d[0][16]) == colors['blue'] + assert color.ARGB(arr_2d[0][31]) == colors['white'] + assert color.ARGB(arr_2d[31][31]) == colors['black'] + + # Create a 3D ndarray from the surface & test different coordinates + arr_3d = sdl2ext.surface_to_ndarray(rgbasurf.contents) + assert arr_3d.shape == (32, 32, 4) + assert color.Color(*arr_3d[0][0]) == colors['red'] + assert color.Color(*arr_3d[0][16]) == colors['blue'] + assert color.Color(*arr_3d[0][31]) == colors['white'] + assert color.Color(*arr_3d[31][31]) == colors['black'] + + # Try modifying surface, make sure changes don't persist + grey = [128, 128, 128, 255] + arr_3d[31][0][:] = grey + arr_view = sdl2ext.pixels3d(rgbasurf, transpose=False) + assert color.Color(*arr_view[31][0]) != color.Color(*grey) diff --git a/sdl2/test/sdl2ext_renderer_test.py b/sdl2/test/sdl2ext_renderer_test.py index 149d2063..c1ba94fa 100644 --- a/sdl2/test/sdl2ext_renderer_test.py +++ b/sdl2/test/sdl2ext_renderer_test.py @@ -9,68 +9,56 @@ from sdl2.render import SDL_Renderer, SDL_Texture from sdl2.surface import SDL_CreateRGBSurface, SDL_FreeSurface - -class TestSDL2ExtRenderer(object): +# NOTE: These tests still have some legacy cruft to clean + +def check_pixels(view, w, h, sprite, c1, c2, cx=0, cy=0): + msg = "color mismatch at %d,%d: %d not in %s" + cx = cx + sprite.x + cy = cy + sprite.y + cw, ch = sprite.size + cmy = cy + ch + cmx = cx + cw + for y in range(w): + for x in range(h): + if cy <= y < cmy and cx <= x < cmx: + assert view[y][x] == c1, msg % (x, y, view[y][x], c1) + else: + assert view[y][x] in c2, msg % (x, y, view[y][x], c2) + +def check_areas(view, w, h, rects, c1, c2): + def _inarea(x, y, rs): + for r in rs: + if (x >= r[0] and x < (r[0] + r[2]) and + y >= r[1] and y < (r[1] + r[3])): + return True + return False + msg = "color mismatch at %d,%d: %d not in %s" + for y in range(w): + for x in range(h): + if _inarea(x, y, rects): + assert view[y][x] == c1, msg % (x, y, view[y][x], c1) + else: + assert view[y][x] in c2, msg % (x, y, view[y][x], c2) + +def check_lines(view, w, h, points, c1, c2): + def _online(x, y, pts): + for p1, p2 in pts: + if sdl2ext.point_on_line(p1, p2, (x, y)): + return True + return False + msg = "color mismatch at %d,%d: %d not in %s" + for y in range(w): + for x in range(h): + if _online(x, y, points): + assert view[y][x] == c1, msg % (x, y, view[y][x], c1) + else: + assert view[y][x] in c2, msg % (x, y, view[y][x], c2) + + +class TestExtRenderer(object): __tags__ = ["sdl", "sdl2ext"] - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - sdl2ext.quit() - - def teardown_method(self): - gc.collect() - - def check_pixels(self, view, w, h, sprite, c1, c2, cx=0, cy=0): - msg = "color mismatch at %d,%d: %d not in %s" - cx = cx + sprite.x - cy = cy + sprite.y - cw, ch = sprite.size - cmy = cy + ch - cmx = cx + cw - for y in range(w): - for x in range(h): - if cy <= y < cmy and cx <= x < cmx: - assert view[y][x] == c1, msg % (x, y, view[y][x], c1) - else: - assert view[y][x] in c2, msg % (x, y, view[y][x], c2) - - def check_areas(self, view, w, h, rects, c1, c2): - def _inarea(x, y, rs): - for r in rs: - if (x >= r[0] and x < (r[0] + r[2]) and - y >= r[1] and y < (r[1] + r[3])): - return True - return False - msg = "color mismatch at %d,%d: %d not in %s" - for y in range(w): - for x in range(h): - if _inarea(x, y, rects): - assert view[y][x] == c1, msg % (x, y, view[y][x], c1) - else: - assert view[y][x] in c2, msg % (x, y, view[y][x], c2) - - def check_lines(self, view, w, h, points, c1, c2): - def _online(x, y, pts): - for p1, p2 in pts: - if sdl2ext.point_on_line(p1, p2, (x, y)): - return True - return False - msg = "color mismatch at %d,%d: %d not in %s" - for y in range(w): - for x in range(h): - if _online(x, y, points): - assert view[y][x] == c1, msg % (x, y, view[y][x], c1) - else: - assert view[y][x] in c2, msg % (x, y, view[y][x], c2) - - def test_init(self): + def test_init(self, with_sdl): sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) # Create renderer with SDL_Surface @@ -117,9 +105,9 @@ def test_init(self): with pytest.raises(TypeError): sdl2ext.Renderer("test") - def test_logical_size(self): - sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) - window = sdl2ext.Window("Test", size=(10, 10)) + def test_logical_size(self, with_sdl): + sf = SDL_CreateRGBSurface(0, 150, 50, 32, 0, 0, 0, 0) + window = sdl2ext.Window("Test", size=(150, 50)) sprite = sdl2ext.SoftwareSprite(sf.contents, True) targets = { @@ -133,58 +121,19 @@ def test_logical_size(self): target_name = name renderer = sdl2ext.Renderer(target) assert isinstance(renderer.sdlrenderer.contents, SDL_Renderer) - assert renderer.logical_size == (10, 10) - renderer.logical_size = (20, 30) - assert renderer.logical_size == (20, 30) + assert renderer.logical_size == (150, 50) + renderer.logical_size = (200, 100) + assert renderer.logical_size == (200, 100) renderer.reset_logical_size() - assert renderer.logical_size == (10, 10) + assert renderer.logical_size == (150, 50) renderer.destroy() window.close() - - def test_Texture(self): - # Create renderer and test surface - rendertarget = SDL_CreateRGBSurface(0, 100, 100, 32, 0, 0, 0, 0) - renderer = sdl2ext.Renderer(rendertarget.contents) + + def test_color(self, with_sdl): sf = SDL_CreateRGBSurface( - 0, 16, 16, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF + 0, 10, 10, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF ) - - # Test creation with surface pointer - tx = sdl2ext.Texture(renderer, sf) - assert isinstance(tx.tx.contents, SDL_Texture) - - # Test destruction and associated behaviour - tx.destroy() - with pytest.raises(RuntimeError): - sdl_tx = tx.tx - - # Test creation with surface contents - tx = sdl2ext.Texture(renderer, sf.contents) - assert isinstance(tx.tx.contents, SDL_Texture) - - # Test texture size - assert tx.size == (16, 16) - - # Test exception on bad input - with pytest.raises(TypeError): - sdl2ext.Texture(sf, sf) - with pytest.raises(TypeError): - sdl2ext.Texture(renderer, renderer) - - # Test exception when accessing Texture with destroyed Renderer - renderer.destroy() - with pytest.raises(RuntimeError): - sdl_tx = tx.tx - tx.destroy() # Ensure texture destruction method doesn't error - SDL_FreeSurface(sf) - - def test_Renderer_color(self): - sf = SDL_CreateRGBSurface(0, 10, 10, 32, - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF) renderer = sdl2ext.Renderer(sf.contents) assert isinstance(renderer.color, sdl2ext.Color) assert renderer.color == sdl2ext.Color(0, 0, 0, 0) @@ -192,22 +141,26 @@ def test_Renderer_color(self): assert renderer.color == sdl2ext.Color(0xFF, 0, 0, 0) renderer.clear() view = sdl2ext.PixelView(sf.contents) - self.check_areas(view, 10, 10, [[0, 0, 10, 10]], 0xFF000000, (0x0,)) + check_areas(view, 10, 10, [[0, 0, 10, 10]], 0xFF000000, (0x0,)) del view renderer.color = 0xAABBCCDD assert renderer.color == sdl2ext.Color(0xBB, 0xCC, 0xDD, 0xAA) renderer.clear() view = sdl2ext.PixelView(sf.contents) - self.check_areas(view, 10, 10, [[0, 0, 10, 10]], 0xBBCCDDAA, (0x0,)) + check_areas(view, 10, 10, [[0, 0, 10, 10]], 0xBBCCDDAA, (0x0,)) del view renderer.destroy() SDL_FreeSurface(sf) @pytest.mark.skip("not implemented") - def test_Renderer_blendmode(self): + def test_blendmode(self, with_sdl): pass - def test_Renderer_clear(self): + @pytest.mark.skip("not implemented") + def test_scale(self, with_sdl): + pass + + def test_clear(self, with_sdl): sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0xFF000000, 0x00FF0000, @@ -220,17 +173,17 @@ def test_Renderer_clear(self): assert renderer.color == sdl2ext.Color(0xFF, 0, 0, 0) renderer.clear() view = sdl2ext.PixelView(sf.contents) - self.check_areas(view, 10, 10, [[0, 0, 10, 10]], 0xFF000000, (0x0,)) + check_areas(view, 10, 10, [[0, 0, 10, 10]], 0xFF000000, (0x0,)) del view renderer.clear(0xAABBCCDD) assert renderer.color == sdl2ext.Color(0xFF, 0, 0, 0) view = sdl2ext.PixelView(sf.contents) - self.check_areas(view, 10, 10, [[0, 0, 10, 10]], 0xBBCCDDAA, (0x0,)) + check_areas(view, 10, 10, [[0, 0, 10, 10]], 0xBBCCDDAA, (0x0,)) del view renderer.destroy() SDL_FreeSurface(sf) - def test_Renderer_copy(self): + def test_copy(self, with_sdl): # Initialize target surface and renderer surface = SDL_CreateRGBSurface(0, 128, 128, 32, 0, 0, 0, 0).contents renderer = sdl2ext.Renderer(surface) @@ -290,21 +243,21 @@ def test_Renderer_copy(self): sp = factory.from_color(0xFF0000, (w, h)) sp.x, sp.y = 40, 50 renderer.copy(sp, (0, 0, w, h), (sp.x, sp.y, w, h)) - self.check_pixels(view, 128, 128, sp, 0xFF0000, (0x0,)) + check_pixels(view, 128, 128, sp, 0xFF0000, (0x0,)) del view - def test_Renderer_draw_line(self): + def test_draw_line(self, with_sdl): surface = SDL_CreateRGBSurface(0, 128, 128, 32, 0, 0, 0, 0).contents sdl2ext.fill(surface, 0x0) renderer = sdl2ext.Renderer(surface) renderer.draw_line((20, 10, 20, 86), 0x0000FF) view = sdl2ext.PixelView(surface) - self.check_lines(view, 128, 128, + check_lines(view, 128, 128, [((20, 10), (20, 86))], 0x0000FF, (0x0,)) del view - def test_Renderer_draw_point(self): + def test_draw_point(self, with_sdl): # Initialize target surface and renderer surface = SDL_CreateRGBSurface(0, 128, 128, 32, 0, 0, 0, 0).contents sdl2ext.fill(surface, 0x0) @@ -340,14 +293,13 @@ def test_Renderer_draw_point(self): with pytest.raises(ValueError): renderer.draw_point([(0, 0), (1, 2, 3)], 0x0000FF) - - def test_Renderer_draw_rect(self): + def test_draw_rect(self, with_sdl): surface = SDL_CreateRGBSurface(0, 128, 128, 32, 0, 0, 0, 0).contents sdl2ext.fill(surface, 0x0) renderer = sdl2ext.Renderer(surface) renderer.draw_rect((40, 50, 32, 32), 0x0000FF) view = sdl2ext.PixelView(surface) - self.check_lines(view, 128, 128, [ + check_lines(view, 128, 128, [ ((40, 50), (71, 50)), ((40, 50), (40, 81)), ((40, 81), (71, 81)), @@ -356,7 +308,7 @@ def test_Renderer_draw_rect(self): sdl2ext.fill(surface, 0x0) renderer.draw_rect([(5, 5, 10, 10), (20, 15, 8, 10)], 0x0000FF) view = sdl2ext.PixelView(surface) - self.check_lines(view, 128, 128, [ + check_lines(view, 128, 128, [ ((5, 5), (14, 5)), ((5, 5), (5, 14)), ((5, 14), (14, 14)), @@ -367,7 +319,7 @@ def test_Renderer_draw_rect(self): ((27, 15), (27, 24))], 0x0000FF, (0x0,)) del view - def test_Renderer_fill(self): + def test_fill(self, with_sdl): surface = SDL_CreateRGBSurface(0, 128, 128, 32, 0, 0, 0, 0).contents sdl2ext.fill(surface, 0x0) renderer = sdl2ext.Renderer(surface) @@ -377,12 +329,66 @@ def test_Renderer_fill(self): sp.x, sp.y = 40, 50 renderer.fill((sp.x, sp.y, w, h), 0x0000FF) view = sdl2ext.PixelView(surface) - self.check_pixels(view, 128, 128, sp, 0x0000FF, (0x0,)) + check_pixels(view, 128, 128, sp, 0x0000FF, (0x0,)) del view sdl2ext.fill(surface, 0x0) renderer.fill([(5, 5, 10, 10), (20, 15, 8, 10)], 0x0000FF) view = sdl2ext.PixelView(surface) - self.check_areas(view, 128, 128, [(5, 5, 10, 10), (20, 15, 8, 10)], + check_areas(view, 128, 128, [(5, 5, 10, 10), (20, 15, 8, 10)], 0x0000FF, (0x0,)) del view + + +class TestExtTexture(object): + __tags__ = ["sdl", "sdl2ext"] + + def test_init_destroy(self): + # Create renderer and test surface + rendertarget = SDL_CreateRGBSurface(0, 100, 100, 32, 0, 0, 0, 0) + renderer = sdl2ext.Renderer(rendertarget.contents) + sf = SDL_CreateRGBSurface( + 0, 16, 16, 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF + ) + + # Test creation with surface pointer + tx = sdl2ext.Texture(renderer, sf) + assert isinstance(tx.tx.contents, SDL_Texture) + + # Test destruction and associated behaviour + tx.destroy() + with pytest.raises(RuntimeError): + sdl_tx = tx.tx + + # Test creation with surface contents + tx = sdl2ext.Texture(renderer, sf.contents) + assert isinstance(tx.tx.contents, SDL_Texture) + + # Test texture size + assert tx.size == (16, 16) + + # Test exception on bad input + with pytest.raises(TypeError): + sdl2ext.Texture(sf, sf) + with pytest.raises(TypeError): + sdl2ext.Texture(renderer, renderer) + + # Test exception when accessing Texture with destroyed Renderer + renderer.destroy() + with pytest.raises(RuntimeError): + sdl_tx = tx.tx + tx.destroy() # Ensure texture destruction method doesn't error + SDL_FreeSurface(sf) + + @pytest.mark.skip("not implemented") + def test_size(self, with_sdl): + pass + + @pytest.mark.skip("not implemented") + def test_scale_mode(self, with_sdl): + pass + + +@pytest.mark.skip("not implemented") +def test_set_texture_scale_quality(with_sdl): + pass diff --git a/sdl2/test/sdl2ext_resources_test.py b/sdl2/test/sdl2ext_resources_test.py index eb5fda08..62eff82d 100644 --- a/sdl2/test/sdl2ext_resources_test.py +++ b/sdl2/test/sdl2ext_resources_test.py @@ -9,105 +9,106 @@ from sdl2.ext import resources -class TestSDL2ExtResources(object): - __tags__ = ["sdl2ext"] - - def test_open_zipfile(self): - fpath = os.path.join(os.path.dirname(__file__), "resources") - zfile = os.path.join(fpath, "resources.zip") - - # resources.zip is a packed version of resources/, which at - # least contains - # - # resources/rwopstest.txt - # resources/surfacetest.bmp - - resfile = resources.open_zipfile(zfile, "rwopstest.txt", "resources") - assert resfile is not None - resfile = resources.open_zipfile(zfile, "resources/rwopstest.txt") - assert resfile is not None - - with pytest.raises(KeyError): - resources.open_zipfile(zfile, "invalid") - with pytest.raises(KeyError): - resources.open_zipfile(zfile, None) - with pytest.raises(KeyError): - resources.open_zipfile(zfile, - "rwopstest.txt", "data") - with pytest.raises(KeyError): - resources.open_zipfile(zfile, - "rwopstest.txt", 1234) - with pytest.raises(KeyError): - resources.open_zipfile(zfile, - None, None) - - with pytest.raises(TypeError): - resources.open_zipfile(None, - "rwopstest.txt") - with pytest.raises(TypeError): - resources.open_zipfile(None, None) - with pytest.raises(TypeError): - resources.open_zipfile(None, - "rwopstest.txt", "resources") - - def test_open_tarfile(self): - fpath = os.path.join(os.path.dirname(__file__), "resources") - tfile = os.path.join(fpath, "resources.tar.gz") - - # resources.tar.gz is a packed version of resources/, which at - # least contains - # - # resources/rwopstest.txt - # resources/surfacetest.bmp - - resfile = resources.open_tarfile(tfile, "rwopstest.txt", "resources") - assert resfile is not None - resfile = resources.open_tarfile(tfile, "resources/rwopstest.txt") - assert resfile is not None - - # TODO: refine the error handling in open_tarfile() - with pytest.raises(KeyError): - resources.open_tarfile(tfile, "invalid") - with pytest.raises(AttributeError): - resources.open_tarfile(tfile, None) - with pytest.raises(KeyError): - resources.open_tarfile(tfile, - "rwopstest.txt", "data") - with pytest.raises(KeyError): - resources.open_tarfile(tfile, - "rwopstest.txt", 1234) - with pytest.raises(AttributeError): - resources.open_tarfile(tfile, - None, None) +def test_open_zipfile(): + fpath = os.path.join(os.path.dirname(__file__), "resources") + zfile = os.path.join(fpath, "resources.zip") + + # resources.zip is a packed version of resources/, which at + # least contains + # + # resources/rwopstest.txt + # resources/surfacetest.bmp + + resfile = resources.open_zipfile(zfile, "rwopstest.txt", "resources") + assert resfile is not None + resfile = resources.open_zipfile(zfile, "resources/rwopstest.txt") + assert resfile is not None + + with pytest.raises(KeyError): + resources.open_zipfile(zfile, "invalid") + with pytest.raises(KeyError): + resources.open_zipfile(zfile, None) + with pytest.raises(KeyError): + resources.open_zipfile(zfile, + "rwopstest.txt", "data") + with pytest.raises(KeyError): + resources.open_zipfile(zfile, + "rwopstest.txt", 1234) + with pytest.raises(KeyError): + resources.open_zipfile(zfile, + None, None) + + with pytest.raises(TypeError): + resources.open_zipfile(None, + "rwopstest.txt") + with pytest.raises(TypeError): + resources.open_zipfile(None, None) + with pytest.raises(TypeError): + resources.open_zipfile(None, + "rwopstest.txt", "resources") + +def test_open_tarfile(): + fpath = os.path.join(os.path.dirname(__file__), "resources") + tfile = os.path.join(fpath, "resources.tar.gz") + + # resources.tar.gz is a packed version of resources/, which at + # least contains + # + # resources/rwopstest.txt + # resources/surfacetest.bmp + + resfile = resources.open_tarfile(tfile, "rwopstest.txt", "resources") + assert resfile is not None + resfile = resources.open_tarfile(tfile, "resources/rwopstest.txt") + assert resfile is not None + + # TODO: refine the error handling in open_tarfile() + with pytest.raises(KeyError): + resources.open_tarfile(tfile, "invalid") + with pytest.raises(AttributeError): + resources.open_tarfile(tfile, None) + with pytest.raises(KeyError): + resources.open_tarfile(tfile, + "rwopstest.txt", "data") + with pytest.raises(KeyError): + resources.open_tarfile(tfile, + "rwopstest.txt", 1234) + with pytest.raises(AttributeError): + resources.open_tarfile(tfile, + None, None) + + with pytest.raises(ValueError): + resources.open_tarfile(None, + "rwopstest.txt") + with pytest.raises(ValueError): + resources.open_tarfile(None, None) + with pytest.raises(ValueError): + resources.open_tarfile(None, + "rwopstest.txt", "resources") + +def test_open_url(): + if sys.version_info[0] < 3: + p2url = urllib.pathname2url + else: + p2url = urllib2.pathname2url + + fpath = os.path.join(os.path.dirname(__file__), "resources") + fpath = os.path.abspath(fpath) + tfile = os.path.join(fpath, "rwopstest.txt") + urlpath = "file:%s" % p2url(tfile) + resfile = resources.open_url(urlpath) + assert resfile is not None + + tfile = os.path.join(fpath, "invalid") + urlpath = "file:%s" % p2url(tfile) + with pytest.raises(urllib2.URLError): + resources.open_url(urlpath) - with pytest.raises(ValueError): - resources.open_tarfile(None, - "rwopstest.txt") - with pytest.raises(ValueError): - resources.open_tarfile(None, None) - with pytest.raises(ValueError): - resources.open_tarfile(None, - "rwopstest.txt", "resources") - def test_open_url(self): - if sys.version_info[0] < 3: - p2url = urllib.pathname2url - else: - p2url = urllib2.pathname2url +class TestSDL2ExtResources(object): + __tags__ = ["sdl2ext"] - fpath = os.path.join(os.path.dirname(__file__), "resources") - fpath = os.path.abspath(fpath) - tfile = os.path.join(fpath, "rwopstest.txt") - urlpath = "file:%s" % p2url(tfile) - resfile = resources.open_url(urlpath) - assert resfile is not None - - tfile = os.path.join(fpath, "invalid") - urlpath = "file:%s" % p2url(tfile) - with pytest.raises(urllib2.URLError): - resources.open_url(urlpath) - - def test_Resources(self): + def test_init(self): with pytest.raises(ValueError): resources.Resources("invalid") @@ -129,7 +130,7 @@ def test_Resources(self): assert res3.get("rwopstest.txt") is not None assert res3.get("surfacetest.bmp") is not None - def test_Resources_add(self): + def test_add(self): fpath = os.path.join(os.path.dirname(__file__), "resources") sfile = os.path.join(fpath, "surfacetest.bmp") zfile = os.path.join(fpath, "resources.zip") @@ -149,7 +150,7 @@ def test_Resources_add(self): with pytest.raises(ValueError): res.add("invalid_name.txt") - def test_Resources_add_file(self): + def test_add_file(self): fpath = os.path.join(os.path.dirname(__file__), "resources") sfile = os.path.join(fpath, "surfacetest.bmp") zfile = os.path.join(fpath, "resources.zip") @@ -168,7 +169,7 @@ def test_Resources_add_file(self): with pytest.raises(ValueError): res.add_file("invalid_name.txt") - def test_Resources_add_archive(self): + def test_add_archive(self): fpath = os.path.join(os.path.dirname(__file__), "resources") zfile = os.path.join(fpath, "resources.zip") tfile = os.path.join(fpath, "resources.tar.gz") @@ -193,7 +194,7 @@ def test_Resources_add_archive(self): with pytest.raises(KeyError): res.get("resources.tar.gz") - def test_Resources_get(self): + def test_get(self): fpath = os.path.join(os.path.dirname(__file__), "resources") for path in (fpath, None): @@ -214,7 +215,7 @@ def test_Resources_get(self): assert res.get("surfacetest.bmp") is not None assert res.get("rwopstest.txt") is not None - def test_Resources_get_filelike(self): + def test_get_filelike(self): fpath = os.path.join(os.path.dirname(__file__), "resources") zfile = os.path.join(fpath, "resources.zip") pfile = os.path.join(fpath, "rwopstest.txt") @@ -239,7 +240,7 @@ def test_Resources_get_filelike(self): with pytest.raises(KeyError): res.get_filelike(1234) - def test_Resources_get_path(self): + def test_get_path(self): fpath = os.path.join(os.path.dirname(__file__), "resources") zfile = os.path.join(fpath, "resources.zip") pfile = os.path.join(fpath, "rwopstest.txt") @@ -261,7 +262,7 @@ def test_Resources_get_path(self): with pytest.raises(KeyError): res.get_path(1234) - def test_Resources_scan(self): + def test_scan(self): fpath = os.path.join(os.path.dirname(__file__)) res = resources.Resources() res.scan(fpath) diff --git a/sdl2/test/sdl2ext_sprite_test.py b/sdl2/test/sdl2ext_sprite_test.py index d53a5f43..9816637f 100644 --- a/sdl2/test/sdl2ext_sprite_test.py +++ b/sdl2/test/sdl2ext_sprite_test.py @@ -11,10 +11,9 @@ from sdl2.surface import SDL_CreateRGBSurface from sdl2.video import SDL_Window, SDL_WINDOW_HIDDEN, SDL_DestroyWindow -_ISPYPY = hasattr(sys, "pypy_version_info") - class MSprite(sdl2ext.Sprite): + def __init__(self, w=0, h=0): super(MSprite, self).__init__() self._size = w, h @@ -24,52 +23,53 @@ def size(self): return self._size -class TestSDL2ExtSprite(object): +@pytest.fixture +def positions(): + test_positions = [] + for x in range(-50, 50, 5): + for y in range(-50, 50, 5): + test_positions.append((x, y)) + return test_positions + +@pytest.fixture +def sizes(): + test_sizes = [(4, 4)] + for w in range(16, 256, 16): + for h in range(16, 256, 16): + test_sizes.append((w, h)) + return test_sizes + + +class TestExtSprite(object): __tags__ = ["sdl", "sdl2ext"] - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - cls.positions = [(x, y) for x in range(-50, 50) for y in range(-50, 50)] - test_sizes = [] - for w in range(5, 200, 5): - for h in range(5, 200, 5): - test_sizes.append((w, h)) - cls.sizes = test_sizes - - @classmethod - def teardown_class(cls): - sdl2ext.quit() - - def teardown_method(self): - gc.collect() - - def test_Sprite(self): + def test_init(self): sprite = MSprite() assert isinstance(sprite, MSprite) assert isinstance(sprite, sdl2ext.Sprite) - def test_Sprite_position_xy(self): + def test_position_xy(self, positions): sprite = MSprite() - for x, y in self.positions: + for x, y in positions: sprite.position = x, y assert sprite.position == (x, y) sprite.x = x + 1 sprite.y = y + 1 assert sprite.position == (x + 1, y + 1) - def test_Sprite_area(self): - for w, h in self.sizes: + def test_area(self, sizes): + for w, h in sizes: sprite = MSprite(w, h) assert sprite.size == (w, h) assert sprite.area == (0, 0, w, h) sprite.position = w, h assert sprite.area == (w, h, 2 * w, 2 * h) - def test_SoftwareSprite(self): + +class TestExtSoftwareSprite(object): + __tags__ = ["sdl", "sdl2ext"] + + def test_init(self, with_sdl): sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) # Test with SDL_Surface @@ -85,51 +85,53 @@ def test_SoftwareSprite(self): with pytest.raises(TypeError): sdl2ext.SoftwareSprite(None, True) - def test_SoftwareSprite_repr(self): + def test___repr__(self, with_sdl): sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) sprite = sdl2ext.SoftwareSprite(sf.contents, True) assert repr(sprite) == "SoftwareSprite(size=(10, 10), bpp=32)" - def test_SoftwareSprite_position_xy(self): + def test_position_xy(self, with_sdl, positions): sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) sprite = sdl2ext.SoftwareSprite(sf.contents, True) assert isinstance(sprite, sdl2ext.SoftwareSprite) assert sprite.position == (0, 0) - for x, y in self.positions: + for x, y in positions: sprite.position = x, y assert sprite.position == (x, y) sprite.x = x + 1 sprite.y = y + 1 assert sprite.position == (x + 1, y + 1) - def test_SoftwareSprite_size(self): - for w, h in self.sizes: + def test_size(self, with_sdl, sizes): + for w, h in sizes: sf = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0) sprite = sdl2ext.SoftwareSprite(sf.contents, True) assert isinstance(sprite, sdl2ext.SoftwareSprite) assert sprite.size == (w, h) - def test_SoftwareSprite_area(self): + def test_area(self, with_sdl): sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) sprite = sdl2ext.SoftwareSprite(sf.contents, True) assert sprite.area == (0, 0, 10, 10) - + sprite.position = 7, 3 + assert sprite.area == (7, 3, 17, 13) + sprite.position = -22, 99 + assert sprite.area == (-22, 99, -12, 109) def setarea(s, v): s.area = v with pytest.raises(AttributeError): setarea(sprite, (1, 2, 3, 4)) - sprite.position = 7, 3 - assert sprite.area == (7, 3, 17, 13) - sprite.position = -22, 99 - assert sprite.area == (-22, 99, -12, 109) - def test_TextureSprite(self): +class TestExtTextureSprite(object): + __tags__ = ["sdl", "sdl2ext"] + + def test_init(self, with_sdl): window = POINTER(SDL_Window)() renderer = POINTER(SDL_Renderer)() - SDL_CreateWindowAndRenderer(10, 10, SDL_WINDOW_HIDDEN, - byref(window), byref(renderer)) - + SDL_CreateWindowAndRenderer( + 10, 10, SDL_WINDOW_HIDDEN, byref(window), byref(renderer) + ) tex = SDL_CreateTexture(renderer, 0, 0, 10, 10) assert isinstance(tex.contents, SDL_Texture) sprite = sdl2ext.TextureSprite(tex.contents) @@ -137,17 +139,18 @@ def test_TextureSprite(self): SDL_DestroyRenderer(renderer) SDL_DestroyWindow(window) - def test_TextureSprite_position_xy(self): + def test_position_xy(self, with_sdl, positions): window = POINTER(SDL_Window)() renderer = POINTER(SDL_Renderer)() - SDL_CreateWindowAndRenderer(10, 10, SDL_WINDOW_HIDDEN, - byref(window), byref(renderer)) + SDL_CreateWindowAndRenderer( + 10, 10, SDL_WINDOW_HIDDEN, byref(window), byref(renderer) + ) tex = SDL_CreateTexture(renderer, 0, 0, 10, 10) assert isinstance(tex.contents, SDL_Texture) sprite = sdl2ext.TextureSprite(tex.contents) assert isinstance(sprite, sdl2ext.TextureSprite) assert sprite.position == (0, 0) - for x, y in self.positions: + for x, y in positions: sprite.position = x, y assert sprite.position == (x, y) sprite.x = x + 1 @@ -156,12 +159,13 @@ def test_TextureSprite_position_xy(self): SDL_DestroyRenderer(renderer) SDL_DestroyWindow(window) - def test_TextureSprite_size(self): + def test_size(self, with_sdl, sizes): window = POINTER(SDL_Window)() renderer = POINTER(SDL_Renderer)() - SDL_CreateWindowAndRenderer(10, 10, SDL_WINDOW_HIDDEN, - byref(window), byref(renderer)) - for w, h in self.sizes: + SDL_CreateWindowAndRenderer( + 10, 10, SDL_WINDOW_HIDDEN, byref(window), byref(renderer) + ) + for w, h in sizes: tex = SDL_CreateTexture(renderer, 0, 0, w, h) assert isinstance(tex.contents, SDL_Texture) sprite = sdl2ext.TextureSprite(tex.contents) @@ -171,25 +175,24 @@ def test_TextureSprite_size(self): SDL_DestroyRenderer(renderer) SDL_DestroyWindow(window) - def test_TextureSprite_area(self): + def test_area(self, with_sdl): window = POINTER(SDL_Window)() renderer = POINTER(SDL_Renderer)() - SDL_CreateWindowAndRenderer(10, 10, SDL_WINDOW_HIDDEN, - byref(window), byref(renderer)) + SDL_CreateWindowAndRenderer( + 10, 10, SDL_WINDOW_HIDDEN, byref(window), byref(renderer) + ) tex = SDL_CreateTexture(renderer, 0, 0, 10, 20) assert isinstance(tex.contents, SDL_Texture) sprite = sdl2ext.TextureSprite(tex.contents) assert isinstance(sprite, sdl2ext.TextureSprite) assert sprite.area == (0, 0, 10, 20) - - def setarea(s, v): - s.area = v - - with pytest.raises(AttributeError): - setarea(sprite, (1, 2, 3, 4)) sprite.position = 7, 3 assert sprite.area == (7, 3, 17, 23) sprite.position = -22, 99 assert sprite.area == (-22, 99, -12, 119) + def setarea(s, v): + s.area = v + with pytest.raises(AttributeError): + setarea(sprite, (1, 2, 3, 4)) SDL_DestroyRenderer(renderer) SDL_DestroyWindow(window) diff --git a/sdl2/test/sdl2ext_spritesystem_test.py b/sdl2/test/sdl2ext_spritesystem_test.py index 44543849..060aad01 100644 --- a/sdl2/test/sdl2ext_spritesystem_test.py +++ b/sdl2/test/sdl2ext_spritesystem_test.py @@ -2,49 +2,48 @@ import sys import pytest from ctypes import ArgumentError - from sdl2 import ext as sdl2ext from sdl2.ext.resources import Resources from sdl2.render import ( SDL_TEXTUREACCESS_STATIC, SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_TARGET ) from sdl2.surface import SDL_Surface, SDL_CreateRGBSurface, SDL_FreeSurface +from sdl2.pixels import SDL_MapRGBA +from sdl2.error import SDL_GetError, SDL_ClearError RESOURCES = Resources(__file__, "resources") - -class TestSDL2ExtSpriteSystem(object): +BLACK = (0, 0, 0, 255) +RED = (255, 0, 0, 255) +BLUE = (0, 0, 255, 255) + +sprite_test_sizes = [ + (1, 1), (100, 100), (16, 32), (55, 77), (20, 4) +] + + +def check_pixels(surf, w, h, sprite, c1, c2, cx=0, cy=0): + cx = cx + sprite.x + cy = cy + sprite.y + cw, ch = sprite.size + cmy = cy + ch + cmx = cx + cw + c1 = SDL_MapRGBA(surf.format, c1[0], c1[1], c1[2], c1[3]) + c2 = [SDL_MapRGBA(surf.format, c[0], c[1], c[2], c[3]) for c in c2] + view = sdl2ext.PixelView(surf) + for y in range(w): + for x in range(h): + if cy <= y < cmy and cx <= x < cmx: + assert view[y][x] == c1 + else: + assert view[y][x] in c2 + del view + + +class TestSpriteFactory(object): __tags__ = ["sdl", "sdl2ext"] - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - sdl2ext.quit() - - def teardown_method(self): - gc.collect() - - def check_pixels(self, view, w, h, sprite, c1, c2, cx=0, cy=0): - msg = "color mismatch at %d,%d: %d not in %s" - cx = cx + sprite.x - cy = cy + sprite.y - cw, ch = sprite.size - cmy = cy + ch - cmx = cx + cw - for y in range(w): - for x in range(h): - if cy <= y < cmy and cx <= x < cmx: - assert view[y][x] == c1, msg % (x, y, view[y][x], c1) - else: - assert view[y][x] in c2, msg % (x, y, view[y][x], c2) - - def test_SpriteFactory(self): + def test_init(self, with_sdl): factory = sdl2ext.SpriteFactory(sdl2ext.SOFTWARE) assert isinstance(factory, sdl2ext.SpriteFactory) assert factory.default_args == {} @@ -53,7 +52,7 @@ def test_SpriteFactory(self): assert isinstance(factory, sdl2ext.SpriteFactory) assert factory.default_args == {"bananas": "tasty"} - window = sdl2ext.Window("Test", size=(1, 1)) + window = sdl2ext.Window("Test", size=(10, 10)) renderer = sdl2ext.Renderer(window) factory = sdl2ext.SpriteFactory(sdl2ext.TEXTURE, renderer=renderer) @@ -67,41 +66,33 @@ def test_SpriteFactory(self): sdl2ext.SpriteFactory("Test") with pytest.raises(ValueError): sdl2ext.SpriteFactory(-456) - with pytest.raises(ValueError): - sdl2ext.SpriteFactory(123) - with pytest.raises(ValueError): - sdl2ext.SpriteFactory(sdl2ext.TEXTURE) - def test_SpriteFactory_create_sprite(self): - window = sdl2ext.Window("Test", size=(1, 1)) + def test_create_sprite(self, with_sdl): + window = sdl2ext.Window("Test", size=(10, 10)) renderer = sdl2ext.Renderer(window) tfactory = sdl2ext.SpriteFactory(sdl2ext.TEXTURE, renderer=renderer) sfactory = sdl2ext.SpriteFactory(sdl2ext.SOFTWARE) - for w in range(0, 100): - for h in range(0, 100): - for bpp in (1, 4, 8, 12, 15, 16, 24, 32): - sprite = sfactory.create_sprite(size=(w, h), bpp=bpp) - assert isinstance(sprite, sdl2ext.SoftwareSprite) + for w, h in sprite_test_sizes: + for bpp in (1, 4, 8, 12, 15, 16, 24, 32): + sprite = sfactory.create_sprite(size=(w, h), bpp=bpp) + assert isinstance(sprite, sdl2ext.SoftwareSprite) + assert SDL_GetError() == b"" + sprite = tfactory.create_sprite(size=(w, h)) + assert isinstance(sprite, sdl2ext.TextureSprite) + assert SDL_GetError() == b"" - if w == 0 or h == 0: - with pytest.raises(sdl2ext.SDLError): - tfactory.create_sprite(size=(w, h)) - continue - sprite = tfactory.create_sprite(size=(w, h)) - assert isinstance(sprite, sdl2ext.TextureSprite) + with pytest.raises(sdl2ext.SDLError): + tfactory.create_sprite(size=(0, 1)) - def test_SpriteFactory_create_software_sprite(self): + def test_create_software_sprite(self, with_sdl): factory = sdl2ext.SpriteFactory(sdl2ext.SOFTWARE) - for w in range(0, 100): - for h in range(0, 100): - for bpp in (1, 4, 8, 12, 15, 16, 24, 32): - sprite = factory.create_software_sprite((w, h), bpp) - assert isinstance(sprite, sdl2ext.SoftwareSprite) - - #self.assertRaises(ValueError, factory.create_software_sprite, (-1,-1)) - #self.assertRaises(ValueError, factory.create_software_sprite, (-10,5)) - #self.assertRaises(ValueError, factory.create_software_sprite, (10,-5)) + for w, h in sprite_test_sizes: + for bpp in (1, 4, 8, 12, 15, 16, 24, 32): + sprite = factory.create_software_sprite((w, h), bpp) + assert isinstance(sprite, sdl2ext.SoftwareSprite) + assert SDL_GetError() == b"" + with pytest.raises(TypeError): factory.create_software_sprite(size=None) with pytest.raises(sdl2ext.SDLError): @@ -109,32 +100,39 @@ def test_SpriteFactory_create_software_sprite(self): with pytest.raises(TypeError): factory.create_software_sprite(masks=5) with pytest.raises((ArgumentError, TypeError)): - factory.create_software_sprite(size=(10, 10), - masks=(None, None, None, None)) + factory.create_software_sprite( + size=(10, 10), masks=(None, None, None, None) + ) with pytest.raises((ArgumentError, TypeError)): - factory.create_software_sprite(size=(10, 10), - masks=("Test", 1, 2, 3)) + factory.create_software_sprite( + size=(10, 10), masks=("Test", 1, 2, 3) + ) - def test_SpriteFactory_create_texture_sprite(self): - window = sdl2ext.Window("Test", size=(1, 1)) + def test_create_texture_sprite(self, with_sdl): + window = sdl2ext.Window("Test", size=(10, 10)) renderer = sdl2ext.Renderer(window) factory = sdl2ext.SpriteFactory(sdl2ext.TEXTURE, renderer=renderer) - for w in range(1, 100): - for h in range(1, 100): - sprite = factory.create_texture_sprite(renderer, size=(w, h)) - assert isinstance(sprite, sdl2ext.TextureSprite) - del sprite + for w, h in sprite_test_sizes: + sprite = factory.create_texture_sprite(renderer, size=(w, h)) + assert isinstance(sprite, sdl2ext.TextureSprite) + assert SDL_GetError() == b"" + del sprite # Test different access flags - for flag in (SDL_TEXTUREACCESS_STATIC, SDL_TEXTUREACCESS_STREAMING, - SDL_TEXTUREACCESS_TARGET): - sprite = factory.create_texture_sprite(renderer, size=(64, 64), - access=flag) + for flag in ( + SDL_TEXTUREACCESS_STATIC, + SDL_TEXTUREACCESS_STREAMING, + SDL_TEXTUREACCESS_TARGET + ): + sprite = factory.create_texture_sprite( + renderer, size=(64, 64), access=flag + ) assert isinstance(sprite, sdl2ext.TextureSprite) + assert SDL_GetError() == b"" del sprite - def test_SpriteFactory_from_image(self): - window = sdl2ext.Window("Test", size=(1, 1)) + def test_from_image(self, with_sdl): + window = sdl2ext.Window("Test", size=(10, 10)) renderer = sdl2ext.Renderer(window) tfactory = sdl2ext.SpriteFactory(sdl2ext.TEXTURE, renderer=renderer) sfactory = sdl2ext.SpriteFactory(sdl2ext.SOFTWARE) @@ -153,14 +151,14 @@ def test_SpriteFactory_from_image(self): factory.from_image(12345) @pytest.mark.skip("not implemented") - def test_SpriteFactory_from_object(self): - window = sdl2ext.Window("Test", size=(1, 1)) + def test_from_object(self, with_sdl): + window = sdl2ext.Window("Test", size=(10, 10)) renderer = sdl2ext.Renderer(window) tfactory = sdl2ext.SpriteFactory(sdl2ext.TEXTURE, renderer=renderer) sfactory = sdl2ext.SpriteFactory(sdl2ext.SOFTWARE) - def test_SpriteFactory_from_surface(self): - window = sdl2ext.Window("Test", size=(1, 1)) + def test_from_surface(self, with_sdl): + window = sdl2ext.Window("Test", size=(10, 10)) renderer = sdl2ext.Renderer(window) tfactory = sdl2ext.SpriteFactory(sdl2ext.TEXTURE, renderer=renderer) sfactory = sdl2ext.SpriteFactory(sdl2ext.SOFTWARE) @@ -178,11 +176,8 @@ def test_SpriteFactory_from_surface(self): factory.from_surface(None) with pytest.raises((AttributeError, ArgumentError, TypeError)): factory.from_surface("test") - # TODO: crashes pypy 2.0 - #self.assertRaises((AttributeError, ArgumentError, TypeError), - # factory.from_surface, 1234) - def test_SpriteFactory_from_text(self): + def test_from_text(self, with_sdl): sfactory = sdl2ext.SpriteFactory(sdl2ext.SOFTWARE) fm = sdl2ext.FontManager(RESOURCES.get_path("tuffy.ttf")) @@ -198,21 +193,25 @@ def test_SpriteFactory_from_text(self): assert isinstance(sprite, sdl2ext.SoftwareSprite) # Get text from a texture sprite factory - window = sdl2ext.Window("Test", size=(1, 1)) + window = sdl2ext.Window("Test", size=(10, 10)) renderer = sdl2ext.Renderer(window) - tfactory = sdl2ext.SpriteFactory(sdl2ext.TEXTURE, - renderer=renderer, - fontmanager=fm) + tfactory = sdl2ext.SpriteFactory( + sdl2ext.TEXTURE, renderer=renderer, fontmanager=fm + ) sprite = tfactory.from_text("Test", alias="tuffy") assert isinstance(sprite, sdl2ext.TextureSprite) - def test_SpriteRenderSystem(self): + +class TestSpriteRenderSystem(object): + __tags__ = ["sdl", "sdl2ext"] + + def test_init(self, with_sdl): renderer = sdl2ext.SpriteRenderSystem() assert isinstance(renderer, sdl2ext.SpriteRenderSystem) assert renderer.sortfunc is not None assert sdl2ext.Sprite in renderer.componenttypes - def test_SpriteRenderSystem_sortfunc(self): + def test_sortfunc(self, with_sdl): def func(p): pass @@ -231,24 +230,19 @@ def setf(x, f): setf(renderer, 1234) @pytest.mark.skip("not implemented") - def test_SpriteRenderSystem_render(self): + def test_render(self, with_sdl): pass @pytest.mark.skip("not implemented") - def test_SpriteRenderSystem_process(self): + def test_process(self, with_sdl): pass - def test_SoftwareSpriteRenderSystem(self): - with pytest.raises(TypeError): - sdl2ext.SoftwareSpriteRenderSystem() - with pytest.raises(TypeError): - sdl2ext.SoftwareSpriteRenderSystem(None) - with pytest.raises(TypeError): - sdl2ext.SoftwareSpriteRenderSystem("Test") - with pytest.raises(TypeError): - sdl2ext.SoftwareSpriteRenderSystem(12345) - window = sdl2ext.Window("Test", size=(1, 1)) +class TestSoftwareSpriteRenderSystem(object): + __tags__ = ["sdl", "sdl2ext"] + + def test_init(self, with_sdl): + window = sdl2ext.Window("Test", size=(10, 10)) renderer = sdl2ext.SoftwareSpriteRenderSystem(window) assert isinstance(renderer, sdl2ext.SpriteRenderSystem) assert renderer.window == window.window @@ -263,80 +257,83 @@ def test_SoftwareSpriteRenderSystem(self): assert not (sdl2ext.Sprite in renderer.componenttypes) assert sdl2ext.SoftwareSprite in renderer.componenttypes - def test_SoftwareSpriteRenderSystem_render(self): + with pytest.raises(TypeError): + sdl2ext.SoftwareSpriteRenderSystem() + with pytest.raises(TypeError): + sdl2ext.SoftwareSpriteRenderSystem(None) + + def test_render(self, with_sdl): + # Create two software sprites for testing sf1 = SDL_CreateRGBSurface(0, 12, 7, 32, 0, 0, 0, 0) sp1 = sdl2ext.SoftwareSprite(sf1.contents, True) - sdl2ext.fill(sp1, 0xFF0000) - + sdl2ext.fill(sp1, RED) sf2 = SDL_CreateRGBSurface(0, 3, 9, 32, 0, 0, 0, 0) sp2 = sdl2ext.SoftwareSprite(sf2.contents, True) - sdl2ext.fill(sp2, 0x00FF00) + sdl2ext.fill(sp2, BLUE) sprites = [sp1, sp2] + # Create a window and renderer for the tests window = sdl2ext.Window("Test", size=(20, 20)) renderer = sdl2ext.SoftwareSpriteRenderSystem(window) assert isinstance(renderer, sdl2ext.SpriteRenderSystem) + sdl2ext.fill(renderer.surface, BLACK) - with pytest.raises(AttributeError): - renderer.render(None, None, None) - with pytest.raises(AttributeError): - renderer.render([None, None], - None, None) - + # Test rendering a single sprite to different locations + surf = renderer.surface for x, y in ((0, 0), (3, 3), (20, 20), (1, 12), (5, 6)): sp1.position = x, y renderer.render(sp1) - view = sdl2ext.PixelView(renderer.surface) - self.check_pixels(view, 20, 20, sp1, 0xFF0000, (0x0,)) - del view - sdl2ext.fill(renderer.surface, 0x0) + check_pixels(surf, 20, 20, sp1, RED, [BLACK]) + sdl2ext.fill(surf, BLACK) + + # Test rendering multiple sprites in different positions sp1.position = 0, 0 sp2.position = 14, 1 renderer.render(sprites) - view = sdl2ext.PixelView(renderer.surface) - self.check_pixels(view, 20, 20, sp1, 0xFF0000, (0x0, 0x00FF00)) - self.check_pixels(view, 20, 20, sp2, 0x00FF00, (0x0, 0xFF0000)) - del view - sdl2ext.fill(renderer.surface, 0x0) + check_pixels(surf, 20, 20, sp1, RED, [BLACK, BLUE]) + check_pixels(surf, 20, 20, sp2, BLUE, [BLACK, RED]) + sdl2ext.fill(surf, BLACK) + + # Test rendering multiple sprites with an x/y offset renderer.render(sprites, 1, 2) - view = sdl2ext.PixelView(renderer.surface) - self.check_pixels(view, 20, 20, sp1, 0xFF0000, (0x0, 0x00FF00), 1, 2) - self.check_pixels(view, 20, 20, sp2, 0x00FF00, (0x0, 0xFF0000), 1, 2) - del view + check_pixels(surf, 20, 20, sp1, RED, [BLACK, BLUE], 1, 2) + check_pixels(surf, 20, 20, sp2, BLUE, [BLACK, RED], 1, 2) - def test_SoftwareSpriteRenderSystem_process(self): + def test_process(self, with_sdl): + # Create two software sprites for testing & give them depths sf1 = SDL_CreateRGBSurface(0, 5, 10, 32, 0, 0, 0, 0) sp1 = sdl2ext.SoftwareSprite(sf1.contents, True) - sp1.depth = 0 - sdl2ext.fill(sp1, 0xFF0000) - + sdl2ext.fill(sp1, RED) sf2 = SDL_CreateRGBSurface(0, 5, 10, 32, 0, 0, 0, 0) sp2 = sdl2ext.SoftwareSprite(sf2.contents, True) + sdl2ext.fill(sp2, BLUE) + sp1.depth = 0 sp2.depth = 99 - sdl2ext.fill(sp2, 0x00FF00) sprites = [sp1, sp2] + # Create a window and renderer for the tests window = sdl2ext.Window("Test", size=(20, 20)) renderer = sdl2ext.SoftwareSpriteRenderSystem(window) + assert isinstance(renderer, sdl2ext.SpriteRenderSystem) + sdl2ext.fill(renderer.surface, BLACK) + # Make sure only sp2 visible on surface, since its depth is higher renderer.process("fakeworld", sprites) - view = sdl2ext.PixelView(renderer.surface) - # Only sp2 wins, since its depth is higher - self.check_pixels(view, 20, 20, sp1, 0x00FF00, (0x0,)) - self.check_pixels(view, 20, 20, sp2, 0x00FF00, (0x0,)) - del view + check_pixels(renderer.surface, 20, 20, sp1, BLUE, [BLACK]) + check_pixels(renderer.surface, 20, 20, sp2, BLUE, [BLACK]) - with pytest.raises(TypeError): - renderer.process(None, None) + +class TestTextureSpriteRenderSystem(object): + __tags__ = ["sdl", "sdl2ext"] @pytest.mark.skip("not implemented") - def test_TextureSpriteRenderSystem(self): + def test_init(self, with_sdl): pass @pytest.mark.skip("not implemented") - def test_TextureSpriteRenderSystem_render(self): + def test_render(self, with_sdl): pass @pytest.mark.skip("not implemented") - def test_TextureSpriteRenderSystem_process(self): + def test_process(self, with_sdl): pass diff --git a/sdl2/test/sdl2ext_surface_test.py b/sdl2/test/sdl2ext_surface_test.py index c575b338..44bf8fde 100644 --- a/sdl2/test/sdl2ext_surface_test.py +++ b/sdl2/test/sdl2ext_surface_test.py @@ -4,56 +4,49 @@ from sdl2.ext.draw import prepare_color, fill from sdl2 import ext as sdl2ext - -class TestSDL2ExtSurface(object): - __tags__ = ["sdl", "sdl2ext"] - - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - sdl2ext.quit() - - def test_subsurface(self): - # Initialize colour and surface/view - sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) - WHITE = prepare_color((255, 255, 255), sf) - - # Test creation of subsurface from parent - ssf = sdl2ext.subsurface(sf.contents, (0, 0, 5, 5)) - assert ssf.w == 5 and ssf.h == 5 - - # Test shared pixels between surface - fill(ssf, (255, 255, 255)) - view = sdl2ext.pixels3d(sf.contents, False) - assert all(x == 255 for x in view[0][0][:3]) - assert all(x == 255 for x in view[4][4][:3]) - assert all(x == 0 for x in view[5][5][:3]) - SDL_FreeSurface(ssf) - - # Test creation of subsurface using an SDL_Rect - subsurf_rect = SDL_Rect(2, 2, 6, 6) - ssf = sdl2ext.subsurface(sf.contents, subsurf_rect) - assert ssf.w == 6 and ssf.h == 6 - SDL_FreeSurface(ssf) - - # Test creation of subsurface using a surface pointer - ssf = sdl2ext.subsurface(sf, (0, 0, 5, 5)) - assert ssf.w == 5 and ssf.h == 5 - SDL_FreeSurface(ssf) - - # Test exceptions on bad input - with pytest.raises(TypeError): - sdl2ext.subsurface(WHITE, (0, 0, 5, 5)) - with pytest.raises(TypeError): - sdl2ext.subsurface(sf, (0, 0, 5)) - with pytest.raises(ValueError): - sdl2ext.subsurface(sf, (0, 0, 50, 50)) - - # Clean up after tests - SDL_FreeSurface(sf) \ No newline at end of file +try: + import numpy + _HASNUMPY = True +except: + _HASNUMPY = False + + +@pytest.mark.skipif(not _HASNUMPY, reason="Numpy not available") +def test_subsurface(with_sdl): + # Initialize colour and surface/view + sf = SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) + WHITE = prepare_color((255, 255, 255), sf) + + # Test creation of subsurface from parent + ssf = sdl2ext.subsurface(sf.contents, (0, 0, 5, 5)) + assert ssf.w == 5 and ssf.h == 5 + + # Test shared pixels between surface + fill(ssf, (255, 255, 255)) + view = sdl2ext.pixels3d(sf.contents, False) + assert all(x == 255 for x in view[0][0][:3]) + assert all(x == 255 for x in view[4][4][:3]) + assert all(x == 0 for x in view[5][5][:3]) + SDL_FreeSurface(ssf) + + # Test creation of subsurface using an SDL_Rect + subsurf_rect = SDL_Rect(2, 2, 6, 6) + ssf = sdl2ext.subsurface(sf.contents, subsurf_rect) + assert ssf.w == 6 and ssf.h == 6 + SDL_FreeSurface(ssf) + + # Test creation of subsurface using a surface pointer + ssf = sdl2ext.subsurface(sf, (0, 0, 5, 5)) + assert ssf.w == 5 and ssf.h == 5 + SDL_FreeSurface(ssf) + + # Test exceptions on bad input + with pytest.raises(TypeError): + sdl2ext.subsurface(WHITE, (0, 0, 5, 5)) + with pytest.raises(TypeError): + sdl2ext.subsurface(sf, (0, 0, 5)) + with pytest.raises(ValueError): + sdl2ext.subsurface(sf, (0, 0, 50, 50)) + + # Clean up after tests + SDL_FreeSurface(sf) diff --git a/sdl2/test/sdl2ext_test.py b/sdl2/test/sdl2ext_test.py index 6962e386..e5d00b28 100644 --- a/sdl2/test/sdl2ext_test.py +++ b/sdl2/test/sdl2ext_test.py @@ -4,62 +4,46 @@ from sdl2 import SDL_WasInit, SDL_INIT_VIDEO, SDL_FlushEvent, SDL_USEREVENT, \ SDL_FIRSTEVENT, SDL_LASTEVENT, SDL_Event, SDL_UserEvent, SDL_PushEvent +@pytest.fixture(scope="module") +def with_sdl_ext(): + sdl2ext.init() + yield + sdl2ext.quit() -class TestSDL2Ext(object): - __tags__ = ["sdl", "sdl2ext"] - def test_init_quit(self): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - assert SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO - sdl2ext.quit() - assert SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO +def test_init_quit(): + # NOTE: Currently init only inits the video subsystem, but quit shuts down + # SDL2 and ttf/image/mixer libraries. This latter function should be tested. + try: sdl2ext.init() - sdl2ext.init() - sdl2ext.init() - assert SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO - sdl2ext.quit() - assert SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO - sdl2ext.quit() - sdl2ext.quit() - sdl2ext.quit() - assert SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO - - def test_get_events(self): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - SDL_FlushEvent(SDL_FIRSTEVENT, SDL_LASTEVENT) - for x in range(10): - event = SDL_Event() - event.type = SDL_USEREVENT + 1 - event.user = SDL_UserEvent(type=event.type, timestamp=0, - windowID=0, code=0) - SDL_PushEvent(event) - results = sdl2ext.get_events() - assert len(results) == 10 - for ev in results: - assert ev.type == (SDL_USEREVENT + 1) + except sdl2ext.SDLError: + raise pytest.skip('Video subsystem not supported') + assert SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO + sdl2ext.quit() + assert SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO + sdl2ext.init() + sdl2ext.init() + sdl2ext.init() + assert SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO + sdl2ext.quit() + assert SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO - def test_get_events_issue_6(self): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - SDL_FlushEvent(SDL_FIRSTEVENT, SDL_LASTEVENT) - for x in range(12): - event = SDL_Event() - event.type = SDL_USEREVENT + x - event.user = SDL_UserEvent(type=event.type, timestamp=0, - windowID=0, code=0) - SDL_PushEvent(event) - results = sdl2ext.get_events() - for idx, r in enumerate(results): - assert idx == r.type - SDL_USEREVENT +def test_get_events(with_sdl_ext): + SDL_FlushEvent(SDL_FIRSTEVENT, SDL_LASTEVENT) + for x in range(12): + event = SDL_Event() + event.type = SDL_USEREVENT + x + event.user = SDL_UserEvent( + type=event.type, timestamp=0, windowID=0, code=0 + ) + SDL_PushEvent(event) + results = sdl2ext.get_events() + assert len(results) == 12 + for idx, r in enumerate(results): + assert idx == r.type - SDL_USEREVENT - def test_TestEventProcessor(self): - proc = sdl2ext.TestEventProcessor() - assert isinstance(proc, sdl2ext.TestEventProcessor) +def test_TestEventProcessor(with_sdl_ext): + # NOTE: This doesn't really test functionality, but since I don't think + # it's terribly useful I'm not going to bother expanding it + proc = sdl2ext.TestEventProcessor() + assert isinstance(proc, sdl2ext.TestEventProcessor) diff --git a/sdl2/test/sdl2ext_uisystem_test.py b/sdl2/test/sdl2ext_uisystem_test.py index 384a1747..df6a6f44 100644 --- a/sdl2/test/sdl2ext_uisystem_test.py +++ b/sdl2/test/sdl2ext_uisystem_test.py @@ -2,84 +2,68 @@ import pytest from sdl2 import ext as sdl2ext -class TestSDL2ExtUISystem(object): - __tags__ = ["sdl", "sdl2ext"] - - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') +# NOTE: Deprecated, so I'm not writing tests for it - @classmethod - def teardown_class(cls): - sdl2ext.quit() - @pytest.mark.skip("not implemented") - def test_UIFactory(self): - pass +class TestExtUIFactory(object): + __tags__ = ["sdl", "sdl2ext"] @pytest.mark.skip("not implemented") - def test_UIFactory_create_button(self): + def test_init(self): pass @pytest.mark.skip("not implemented") - def test_UIFactory_create_checkbutton(self): + def test_create_button(self): pass @pytest.mark.skip("not implemented") - def test_UIFactory_create_text_entry(self): + def test_create_checkbutton(self): pass @pytest.mark.skip("not implemented") - def test_Button(self): + def test_create_text_entry(self): pass - @pytest.mark.skip("not implemented") - def test_CheckButton(self): - pass - @pytest.mark.skip("not implemented") - def test_TextEntry(self): - pass +class TestExtUIProcessor(object): + __tags__ = ["sdl", "sdl2ext"] @pytest.mark.skip("not implemented") - def test_UIProcessor(self): + def test_init(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_activate(self): + def test_activate(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_deactivate(self): + def test_deactivate(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_dispatch(self): + def test_dispatch(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_mousedown(self): + def test_mousedown(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_mouseup(self): + def test_mouseup(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_mousemotion(self): + def test_mousemotion(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_passevent(self): + def test_passevent(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_process(self): + def test_process(self): pass @pytest.mark.skip("not implemented") - def test_UIProcessor_textinput(self): + def test_textinput(self): pass diff --git a/sdl2/test/sdl2ext_window_test.py b/sdl2/test/sdl2ext_window_test.py index 2baf06f1..006c0e2e 100644 --- a/sdl2/test/sdl2ext_window_test.py +++ b/sdl2/test/sdl2ext_window_test.py @@ -1,117 +1,110 @@ import sys import pytest +import sdl2 +from sdl2 import SDL_WINDOW_SHOWN from sdl2 import ext as sdl2ext from sdl2 import surface, video - - -class TestSDL2ExtWindow(object): +from .conftest import SKIP_ANNOYING + +# Some tests don't work properly with some video drivers, so check the name +DRIVER_DUMMY = False +DRIVER_X11 = False +try: + sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) + driver_name = video.SDL_GetCurrentVideoDriver() + sdl2.SDL_Quit() + DRIVER_DUMMY = driver_name == b"dummy" + DRIVER_X11 = driver_name == b"x11" +except: + pass + + +class TestExtWindow(object): __tags__ = ["sdl", "sdl2ext"] - @classmethod - def setup_class(cls): - try: - sdl2ext.init() - except sdl2ext.SDLError: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - sdl2ext.quit() - - def test_Window(self): + def test_init(self, with_sdl): flags = video.SDL_WINDOW_BORDERLESS - sizes = ((1, 1), (10, 10), (10, 20), (200, 17), (640, 480), (800, 600)) + sizes = ((1, 1), (10, 10), (10, 20), (200, 17), (640, 480)) for w, h in sizes: window = sdl2ext.Window("Window", size=(w, h), flags=flags) assert window.size == (w, h) window.close() - with pytest.raises(TypeError): - sdl2ext.Window("Test", None, None, None) - with pytest.raises(TypeError): - sdl2ext.Window("Test", None, None) - with pytest.raises(TypeError): - sdl2ext.Window("Test", None) - - - def test_Window_title(self): + def test_title(self, with_sdl): window = sdl2ext.Window("Window", size=(10, 10)) assert window.title == "Window" - window.title = "Test1234" + window.title = b"Test1234" assert window.title == "Test1234" window.close() - #window.title = None - #self.assertEqual(window.title, "None") - #window.title = 1234 - #self.assertEqual(window.title, "1234") - -# @interactive("Was the window shown?") -# def test_Window_show(self): -# window = sdl2ext.Window("Test Show Window", size=(200, 200)) -# window.show() -# doprint("""Please check, if a window with the title -# 'Test Show Window' is shown""") - -# @interactive("Did the window vanish from your sight and pop up again?") -# def test_Window_hide(self): -# window = sdl2ext.Window("Test Hide Window", size=(200, 200)) -# window.show() -# doprint("""Please check, if a window with the title -# 'Test Hide Window' is shown""") -# window.hide() -# doprint("Please check, that the window is not shown anymore") -# window.show() -# doprint("Please check, if the window is shown again") + def test_show_hide(self, with_sdl): + get_flags = video.SDL_GetWindowFlags + window = sdl2ext.Window("Test Show Window", size=(200, 200)) + assert get_flags(window.window) & SDL_WINDOW_SHOWN != SDL_WINDOW_SHOWN + window.show() + assert get_flags(window.window) & SDL_WINDOW_SHOWN == SDL_WINDOW_SHOWN + window.hide() + assert get_flags(window.window) & SDL_WINDOW_SHOWN != SDL_WINDOW_SHOWN + window.close() -# @interactive("Was the window maximized?") -# def test_Window_maximize(self): -# window = sdl2ext.Window("Test Maximize Window", size=(200, 200), -# flags=video.SDL_WINDOW_RESIZABLE) -# window.show() -# doprint("""Please check, that a window with the title -# 'Test Maximize Window' is shown""") -# window.maximize() -# doprint("Please check, if the window was maximized properly") + @pytest.mark.skipif(SKIP_ANNOYING, reason="Skip unless requested") + def test_maximize(self, with_sdl): + get_flags = video.SDL_GetWindowFlags + max_flag = video.SDL_WINDOW_MAXIMIZED + flags = video.SDL_WINDOW_RESIZABLE + window = sdl2ext.Window("Test", size=(200, 200), flags=flags) + window.show() + assert get_flags(window.window) & max_flag != max_flag + window.maximize() + if not DRIVER_DUMMY: + assert get_flags(window.window) & max_flag == max_flag + window.close() -# @interactive("Was the window minimized?") -# def test_Window_minimize(self): -# window = sdl2ext.Window("Test Minimize Window", size=(200, 200)) -# window.show() -# doprint("""Please check, that a window with the title -# 'Test Minimize Window' is shown""") -# window.minimize() -# doprint("Please check, if the window was minimized properly") + @pytest.mark.skipif(SKIP_ANNOYING, reason="Skip unless requested") + def test_minimize_restore(self, with_sdl): + get_flags = video.SDL_GetWindowFlags + min_flag = video.SDL_WINDOW_MINIMIZED + window = sdl2ext.Window("Test", size=(200, 200)) + window.show() + assert get_flags(window.window) & min_flag != min_flag + window.minimize() + if not (DRIVER_DUMMY or DRIVER_X11): + assert get_flags(window.window) & min_flag == min_flag + window.restore() + assert get_flags(window.window) & min_flag != min_flag + window.close() @pytest.mark.skip("not implemented") - def test_Window_refresh(self): + def test_refresh(self, with_sdl): pass - def test_Window_get_surface(self): + def test_get_surface(self, with_sdl): window = sdl2ext.Window("Surface", size=(200, 200)) sf = window.get_surface() assert isinstance(sf, surface.SDL_Surface) window.close() - @pytest.mark.skip("not implemented") - def test_Window_open(self): - pass - - @pytest.mark.skip("not implemented") - def test_Window_close(self): - pass + def test_open_close(self, with_sdl): + get_flags = video.SDL_GetWindowFlags + window = sdl2ext.Window("Test", size=(200, 200)) + window.close() + assert window.window == None + window.open() + assert isinstance(window.window, video.SDL_Window) + assert get_flags(window.window) & SDL_WINDOW_SHOWN == SDL_WINDOW_SHOWN + window.close() - def test_Window_position(self): + def test_position(self, with_sdl): window = sdl2ext.Window("Position", size=(200, 200), position=(100, 100)) assert window.position == (100, 100) window.position = 70, 300 assert window.position == (70, 300) window.close() - @pytest.mark.skip("not implemented") - def test_Window_size(self): + def test_size(self, with_sdl): # This may fail for fullscreen WMs or Win10 tablet modes - window = sdl2ext.Window("Size", size=(200, 200), flags=video.SDL_WINDOW_RESIZABLE) + flags = video.SDL_WINDOW_RESIZABLE + window = sdl2ext.Window("Size", size=(200, 200), flags=flags) assert window.size == (200, 200) window.size = 150, 77 assert window.size == (150, 77) diff --git a/sdl2/test/sdl_test.py b/sdl2/test/sdl_test.py index 91bd04a9..2d2399d3 100644 --- a/sdl2/test/sdl_test.py +++ b/sdl2/test/sdl_test.py @@ -1,58 +1,62 @@ import sys import pytest -from sdl2 import SDL_Init, SDL_WasInit, SDL_InitSubSystem, SDL_QuitSubSystem, \ - SDL_Quit, SDL_INIT_AUDIO, SDL_INIT_EVERYTHING, SDL_INIT_GAMECONTROLLER, \ - SDL_INIT_HAPTIC, SDL_INIT_JOYSTICK, SDL_INIT_NOPARACHUTE, SDL_INIT_TIMER, \ - SDL_INIT_VIDEO, SDL_GetError - - -class TestSDL(object): - __tags__ = ["sdl"] - - def setup_method(self): - SDL_Init(0) - - def teardown_method(self): - SDL_Quit() - - def test_SDL_INIT_TIMER(self): - ret = SDL_Init(SDL_INIT_TIMER) - if ret != 0: - pytest.skip('Timer subsystem not supported') - ret = SDL_WasInit(SDL_INIT_TIMER) - assert ret == SDL_INIT_TIMER - SDL_QuitSubSystem(SDL_INIT_TIMER) - - def test_SDL_INIT_AUDIO(self): - ret = SDL_Init(SDL_INIT_AUDIO) - if ret != 0: - pytest.skip('Audio subsystem not supported') - ret = SDL_WasInit(SDL_INIT_AUDIO) - assert ret == SDL_INIT_AUDIO - SDL_QuitSubSystem(SDL_INIT_AUDIO) - - def test_SDL_INIT_VIDEO(self): - ret = SDL_Init(SDL_INIT_VIDEO) - if ret != 0: - pytest.skip('Video subsystem not supported') - ret = SDL_WasInit(SDL_INIT_VIDEO) - assert ret == SDL_INIT_VIDEO - SDL_QuitSubSystem(SDL_INIT_VIDEO) - - def test_SDL_INIT_JOYSTICK(self): - ret = SDL_Init(SDL_INIT_JOYSTICK) - if ret != 0: - pytest.skip('Joystick subsystem not supported') - ret = SDL_WasInit(SDL_INIT_JOYSTICK) - assert ret == SDL_INIT_JOYSTICK - SDL_QuitSubSystem(SDL_INIT_JOYSTICK) - - @pytest.mark.skipif(sys.platform.startswith("freebsd"), - reason="FreeBSD des not support haptic input yet") - def test_SDL_INIT_HAPTIC(self): - ret = SDL_Init(SDL_INIT_HAPTIC) - if ret != 0: - pytest.skip('Haptic subsystem not supported') - ret = SDL_WasInit(SDL_INIT_HAPTIC) - assert ret == SDL_INIT_HAPTIC - SDL_QuitSubSystem(SDL_INIT_HAPTIC) +import sdl2 +from sdl2 import ( + SDL_INIT_TIMER, SDL_INIT_AUDIO, SDL_INIT_VIDEO, SDL_INIT_JOYSTICK, SDL_INIT_HAPTIC, + SDL_INIT_GAMECONTROLLER, SDL_INIT_EVENTS, SDL_INIT_SENSOR, SDL_INIT_EVERYTHING +) + +subsystems = { + 'timer': SDL_INIT_TIMER, + 'audio': SDL_INIT_AUDIO, + 'video': SDL_INIT_VIDEO, + 'joystick': SDL_INIT_JOYSTICK, + 'haptic': SDL_INIT_HAPTIC, + 'gamecontroller': SDL_INIT_GAMECONTROLLER, + 'events': SDL_INIT_EVENTS, + 'sensor': SDL_INIT_SENSOR, +} + + +def test_SDL_Init(): + supported = [] + sdl2.SDL_ClearError() + for name, flags in subsystems.items(): + ret = sdl2.SDL_Init(flags) + err = sdl2.SDL_GetError() + if name in ['timer', 'audio', 'video', 'events']: + assert ret == 0 + if err: + err = err.decode('utf-8') + print("Error loading {0} subsystem: {1}".format(name, err)) + sdl2.SDL_ClearError() + else: + if ret == 0 and sdl2.SDL_WasInit(0) & flags == flags: + supported.append(name) + sdl2.SDL_Quit() + print("Supported SDL2 subsystems:") + print(supported) + +def test_SDL_InitSubSystem(): + sdl2.SDL_ClearError() + ret = sdl2.SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + # Test initializing an additional subsystem + assert sdl2.SDL_WasInit(0) & SDL_INIT_TIMER != SDL_INIT_TIMER + ret = sdl2.SDL_InitSubSystem(SDL_INIT_TIMER) + assert sdl2.SDL_GetError() == b"" + assert sdl2.SDL_WasInit(0) & SDL_INIT_TIMER == SDL_INIT_TIMER + # Test shutting down a single subsystem + sdl2.SDL_QuitSubSystem(SDL_INIT_AUDIO) + assert sdl2.SDL_WasInit(0) & SDL_INIT_AUDIO != SDL_INIT_AUDIO + remaining = SDL_INIT_VIDEO | SDL_INIT_TIMER + assert sdl2.SDL_WasInit(remaining) == remaining + # Shut down all subsystems once complete + sdl2.SDL_Quit() + assert sdl2.SDL_WasInit(0) == 0 + +def test_SDL_INIT_EVERYTHING(): + # Make sure all the other flags are in the everything flag + for name, flags in subsystems.items(): + assert sdl2.SDL_INIT_EVERYTHING & flags == flags diff --git a/sdl2/test/sdlgfx_test.py b/sdl2/test/sdlgfx_test.py index 6b8c7fc0..4c15d30a 100644 --- a/sdl2/test/sdlgfx_test.py +++ b/sdl2/test/sdlgfx_test.py @@ -9,9 +9,6 @@ sdlgfx = pytest.importorskip("sdl2.sdlgfx") -# Framerate test doesn't work right on Github Actions macOS CI -is_macos_ci = sys.platform == "darwin" and "PYSDL2_DLL_VERSION" in os.environ - @pytest.fixture(scope="module") def with_sdl(): @@ -72,7 +69,7 @@ def test_SDL_getFramecount(self): sdlgfx.SDL_framerateDelay(manager) assert sdlgfx.SDL_getFramecount(manager) == 1 - @pytest.mark.skipif(is_macos_ci, reason="Github macOS CI has wonky timing") + @pytest.mark.xfail(reason="Timing can be super wonky on CI platforms") def test_SDL_framerateDelay(self): manager = sdlgfx.FPSManager() sdlgfx.SDL_initFramerate(manager) diff --git a/sdl2/test/sdlimage_test.py b/sdl2/test/sdlimage_test.py index 0e833731..f6189f41 100644 --- a/sdl2/test/sdlimage_test.py +++ b/sdl2/test/sdlimage_test.py @@ -56,6 +56,35 @@ # JPG saving requires SDL2_image >= 2.0.2 and isn't in official mac binaries no_jpeg_save = sdlimage.dll.version < 2002 or ismacos +@pytest.fixture(scope="module") +def with_sdl_image(with_sdl): + flags = ( + sdlimage.IMG_INIT_JPG | sdlimage.IMG_INIT_PNG | + sdlimage.IMG_INIT_TIF | sdlimage.IMG_INIT_WEBP + ) + sdlimage.IMG_Init(flags) + yield + sdlimage.IMG_Quit() + +@pytest.fixture +def sw_renderer(with_sdl_image): + sf = surface.SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) + rd = render.SDL_CreateSoftwareRenderer(sf) + yield rd + render.SDL_DestroyRenderer(rd) + surface.SDL_FreeSurface(sf) + +def _get_image_path(fmt): + fname = "surfacetest.{0}".format(fmt) + testdir = os.path.dirname(os.path.abspath(__file__)) + return os.path.join(testdir, "resources", fname) + +def _verify_img_load(surf): + if not surf: + assert sdlimage.IMG_GetError() == b"" + assert surf + assert isinstance(surf.contents, surface.SDL_Surface) + def test_IMG_Linked_Version(): v = sdlimage.IMG_Linked_Version() @@ -88,474 +117,443 @@ def test_IMG_Init(): print(supported) assert len(supported) == len(libs.keys()) - -def _get_image_path(fmt): - fname = "surfacetest.{0}".format(fmt) - testdir = os.path.dirname(os.path.abspath(__file__)) - return os.path.join(testdir, "resources", fname) - - -class TestSDLImage(object): - __tags__ = ["sdl", "sdlimage"] - - @classmethod - def setup_class(cls): - flags = ( - sdlimage.IMG_INIT_JPG | sdlimage.IMG_INIT_PNG | - sdlimage.IMG_INIT_TIF | sdlimage.IMG_INIT_WEBP - ) - SDL_Init(0) - sdlimage.IMG_Init(flags) - - @classmethod - def teardown_class(cls): - sdlimage.IMG_Quit() - SDL_Quit() - - def setup_method(self): - sdl2.SDL_ClearError() - - def test_IMG_Load(self): - for fmt in formats: - fpath = _get_image_path(fmt) - sf = sdlimage.IMG_Load(fpath.encode("utf-8")) - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_Load_RW(self): - skip = ['tga'] # TGA broken for Load_RW - for fmt in formats: - if fmt in skip: - continue - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - sf = sdlimage.IMG_Load_RW(rwops.rw_from_object(fp), False) - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadTexture(self): - sf = surface.SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) - rd = render.SDL_CreateSoftwareRenderer(sf) - skip = [] - for fmt in formats: - if fmt in skip: - continue - fpath = _get_image_path(fmt) - tex = sdlimage.IMG_LoadTexture(rd, fpath.encode("utf-8")) - assert isinstance(tex.contents, render.SDL_Texture) - render.SDL_DestroyTexture(tex) - - render.SDL_DestroyRenderer(rd) +def test_IMG_Load(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + sf = sdlimage.IMG_Load(fpath.encode("utf-8")) + _verify_img_load(sf) surface.SDL_FreeSurface(sf) - def test_IMG_LoadTexture_RW(self): - sf = surface.SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) - rd = render.SDL_CreateSoftwareRenderer(sf) - skip = ['svg', 'tga'] # TGA & SVG broken for LoadTexture_RW - for fmt in formats: - if fmt in skip: - continue - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - tex = sdlimage.IMG_LoadTexture_RW(rd, rwops.rw_from_object(fp), 0) - assert tex is not None - assert isinstance(tex.contents, render.SDL_Texture) - render.SDL_DestroyTexture(tex) - - render.SDL_DestroyRenderer(rd) +def test_IMG_Load_RW(with_sdl_image): + skip = ['tga'] # TGA broken for Load_RW + for fmt in formats: + if fmt in skip: + continue + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + sf = sdlimage.IMG_Load_RW(rwops.rw_from_object(fp), False) + _verify_img_load(sf) surface.SDL_FreeSurface(sf) - def test_IMG_LoadTextureTyped_RW(self): - sf = surface.SDL_CreateRGBSurface(0, 10, 10, 32, 0, 0, 0, 0) - rd = render.SDL_CreateSoftwareRenderer(sf) - skip = ['svg'] # SVG broken for LoadTextureTyped_RW - for fmt in formats: - if fmt in skip: - continue - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - rw = rwops.rw_from_object(fp) - fmtx = fmt.upper().encode("utf-8") - tex = sdlimage.IMG_LoadTextureTyped_RW(rd, rw, 0, fmtx) - assert tex is not None - assert isinstance(tex.contents, render.SDL_Texture) +def test_IMG_LoadTexture(sw_renderer): + rd = sw_renderer + skip = [] + for fmt in formats: + if fmt in skip: + continue + fpath = _get_image_path(fmt) + tex = sdlimage.IMG_LoadTexture(rd, fpath.encode("utf-8")) + if not tex: + assert sdlimage.IMG_GetError() == b"" + assert tex + assert isinstance(tex.contents, render.SDL_Texture) + render.SDL_DestroyTexture(tex) + +def test_IMG_LoadTexture_RW(sw_renderer): + rd = sw_renderer + skip = ['svg', 'tga'] # TGA & SVG broken for LoadTexture_RW + for fmt in formats: + if fmt in skip: + continue + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + tex = sdlimage.IMG_LoadTexture_RW(rd, rwops.rw_from_object(fp), 0) + if not tex: + assert sdlimage.IMG_GetError() == b"" + assert tex + assert isinstance(tex.contents, render.SDL_Texture) render.SDL_DestroyTexture(tex) - render.SDL_DestroyRenderer(rd) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadTyped_RW(self): - skip = [] - for fmt in formats: - if fmt in skip: - continue - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - sf = sdlimage.IMG_LoadTyped_RW( - rwops.rw_from_object(fp), False, fmt.upper().encode("utf-8") - ) - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadBMP_RW(self): - fp = open(_get_image_path("bmp"), "rb") - sf = sdlimage.IMG_LoadBMP_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadCUR_RW(self): - fp = open(_get_image_path("cur"), "rb") - sf = sdlimage.IMG_LoadCUR_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadGIF_RW(self): - fp = open(_get_image_path("gif"), "rb") - sf = sdlimage.IMG_LoadGIF_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadICO_RW(self): - fp = open(_get_image_path("ico"), "rb") - sf = sdlimage.IMG_LoadICO_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadJPG_RW(self): - fp = open(_get_image_path("jpg"), "rb") - sf = sdlimage.IMG_LoadJPG_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadLBM_RW(self): - fp = open(_get_image_path("lbm"), "rb") - sf = sdlimage.IMG_LoadLBM_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadPCX_RW(self): - fp = open(_get_image_path("pcx"), "rb") - sf = sdlimage.IMG_LoadPCX_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadPNG_RW(self): - fp = open(_get_image_path("png"), "rb") - sf = sdlimage.IMG_LoadPNG_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - def test_IMG_LoadPNM_RW(self): - fp = open(_get_image_path("pnm"), "rb") - sf = sdlimage.IMG_LoadPNM_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - @pytest.mark.skipif(sdlimage.dll.version < 2002, reason="Added in 2.0.2") - @pytest.mark.xfail(isconda and iswindows, reason="Broken w/ win64 Conda") - def test_IMG_LoadSVG_RW(self): - fp = open(_get_image_path("svg"), "rb") - sf = sdlimage.IMG_LoadSVG_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadTGA_RW(self): - fp = open(_get_image_path("tga"), "rb") - sf = sdlimage.IMG_LoadTGA_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadTIF_RW(self): - fp = open(_get_image_path("tif"), "rb") - sf = sdlimage.IMG_LoadTIF_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - @pytest.mark.xfail(bad_webp, reason="WEBP broken in 2.0.2 binaries for 32-bit Windows") - def test_IMG_LoadWEBP_RW(self): - fp = open(_get_image_path("webp"), "rb") - sf = sdlimage.IMG_LoadWEBP_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - @pytest.mark.xfail(bad_xcf, reason="XCF currently broken on some platforms") - def test_IMG_LoadXCF_RW(self): - fp = open(_get_image_path("xcf"), "rb") - sf = sdlimage.IMG_LoadXCF_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_LoadXPM_RW(self): - fp = open(_get_image_path("xpm"), "rb") - sf = sdlimage.IMG_LoadXPM_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - @pytest.mark.skip("not implemented") - def test_IMG_LoadXV_RW(self): - fp = open(_get_image_path("xv"), "rb") - sf = sdlimage.IMG_LoadXV_RW(rwops.rw_from_object(fp)) - fp.close() - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) +def test_IMG_LoadTextureTyped_RW(sw_renderer): + rd = sw_renderer + skip = ['svg'] # SVG broken for LoadTextureTyped_RW + for fmt in formats: + if fmt in skip: + continue + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + rw = rwops.rw_from_object(fp) + fmtx = fmt.upper().encode("utf-8") + tex = sdlimage.IMG_LoadTextureTyped_RW(rd, rw, 0, fmtx) + if not tex: + assert sdlimage.IMG_GetError() == b"" + assert tex + assert isinstance(tex.contents, render.SDL_Texture) + render.SDL_DestroyTexture(tex) + +def test_IMG_LoadTyped_RW(with_sdl_image): + skip = [] + for fmt in formats: + if fmt in skip: + continue + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + sf = sdlimage.IMG_LoadTyped_RW( + rwops.rw_from_object(fp), False, fmt.upper().encode("utf-8") + ) + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) - def test_IMG_isBMP(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "bmp": - assert sdlimage.IMG_isBMP(imgrw) - else: - assert not sdlimage.IMG_isBMP(imgrw) - - def test_IMG_isCUR(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "cur": - assert sdlimage.IMG_isCUR(imgrw) - else: - assert not sdlimage.IMG_isCUR(imgrw) - - def test_IMG_isGIF(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "gif": - assert sdlimage.IMG_isGIF(imgrw) - else: - assert not sdlimage.IMG_isGIF(imgrw) - - def test_IMG_isICO(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "ico": - assert sdlimage.IMG_isICO(imgrw) - else: - assert not sdlimage.IMG_isICO(imgrw) - - def test_IMG_isJPG(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "jpg": - assert sdlimage.IMG_isJPG(imgrw) - else: - assert not sdlimage.IMG_isJPG(imgrw) - - def test_IMG_isLBM(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "lbm": - assert sdlimage.IMG_isLBM(imgrw) - else: - assert not sdlimage.IMG_isLBM(imgrw) - - def test_IMG_isPCX(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "pcx": - assert sdlimage.IMG_isPCX(imgrw) - else: - assert not sdlimage.IMG_isPCX(imgrw) - - def test_IMG_isPNG(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "png": - assert sdlimage.IMG_isPNG(imgrw) - else: - assert not sdlimage.IMG_isPNG(imgrw) - - def test_IMG_isPNM(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt in ("pnm", "pbm", "ppm", "pgm"): - assert sdlimage.IMG_isPNM(imgrw) - else: - assert not sdlimage.IMG_isPNM(imgrw) - - @pytest.mark.skipif(sdlimage.dll.version < 2002, reason="Added in 2.0.2") - @pytest.mark.xfail(isconda and iswindows, reason="Broken w/ win64 Conda") - def test_IMG_isSVG(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "svg": - assert sdlimage.IMG_isSVG(imgrw) - else: - assert not sdlimage.IMG_isSVG(imgrw) - - def test_IMG_isTIF(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "tif": - assert sdlimage.IMG_isTIF(imgrw) - else: - assert not sdlimage.IMG_isTIF(imgrw) - - def test_IMG_isWEBP(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "webp": - assert sdlimage.IMG_isWEBP(imgrw) - else: - assert not sdlimage.IMG_isWEBP(imgrw) - - @pytest.mark.xfail(bad_xcf, reason="XCF currently broken on some platforms") - def test_IMG_isXCF(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "xcf": - assert sdlimage.IMG_isXCF(imgrw) - else: - assert not sdlimage.IMG_isXCF(imgrw) - - def test_IMG_isXPM(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "xpm": - assert sdlimage.IMG_isXPM(imgrw) - else: - assert not sdlimage.IMG_isXPM(imgrw) - - @pytest.mark.skip("not implemented") - def test_IMG_isXV(self): - for fmt in formats: - fpath = _get_image_path(fmt) - with open(fpath, "rb") as fp: - imgrw = rwops.rw_from_object(fp) - if fmt == "xv": - assert sdlimage.IMG_isXV(imgrw) - else: - assert not sdlimage.IMG_isXV(imgrw) - - @pytest.mark.skipif(hasattr(sys, "pypy_version_info"), - reason="PyPy's ctypes fails to pass a correct string array") - def test_IMG_ReadXPMFromArray(self): - fp = open(_get_image_path("xpm"), "rb") - xpm = b"" - fp.readline() # /* XPM */ - fp.readline() # static char * surfacetest_xpm[] = { - lbuf = fp.readlines() - fp.close() - for line in lbuf: - if line.endswith(b"};"): - xpm += line[1:-4] +def test_IMG_LoadBMP_RW(with_sdl_image): + fp = open(_get_image_path("bmp"), "rb") + sf = sdlimage.IMG_LoadBMP_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadCUR_RW(with_sdl_image): + fp = open(_get_image_path("cur"), "rb") + sf = sdlimage.IMG_LoadCUR_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadGIF_RW(with_sdl_image): + fp = open(_get_image_path("gif"), "rb") + sf = sdlimage.IMG_LoadGIF_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadICO_RW(with_sdl_image): + fp = open(_get_image_path("ico"), "rb") + sf = sdlimage.IMG_LoadICO_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadJPG_RW(with_sdl_image): + fp = open(_get_image_path("jpg"), "rb") + sf = sdlimage.IMG_LoadJPG_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadLBM_RW(with_sdl_image): + fp = open(_get_image_path("lbm"), "rb") + sf = sdlimage.IMG_LoadLBM_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadPCX_RW(with_sdl_image): + fp = open(_get_image_path("pcx"), "rb") + sf = sdlimage.IMG_LoadPCX_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadPNG_RW(with_sdl_image): + fp = open(_get_image_path("png"), "rb") + sf = sdlimage.IMG_LoadPNG_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadPNM_RW(with_sdl_image): + fp = open(_get_image_path("pnm"), "rb") + sf = sdlimage.IMG_LoadPNM_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +@pytest.mark.skipif(sdlimage.dll.version < 2002, reason="Added in 2.0.2") +@pytest.mark.xfail(isconda and iswindows, reason="Broken w/ win64 Conda") +def test_IMG_LoadSVG_RW(with_sdl_image): + fp = open(_get_image_path("svg"), "rb") + sf = sdlimage.IMG_LoadSVG_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadTGA_RW(with_sdl_image): + fp = open(_get_image_path("tga"), "rb") + sf = sdlimage.IMG_LoadTGA_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadTIF_RW(with_sdl_image): + fp = open(_get_image_path("tif"), "rb") + sf = sdlimage.IMG_LoadTIF_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +@pytest.mark.xfail(bad_webp, reason="WEBP broken in 2.0.2 binaries for 32-bit Windows") +def test_IMG_LoadWEBP_RW(with_sdl_image): + fp = open(_get_image_path("webp"), "rb") + sf = sdlimage.IMG_LoadWEBP_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +@pytest.mark.xfail(bad_xcf, reason="XCF currently broken on some platforms") +def test_IMG_LoadXCF_RW(with_sdl_image): + fp = open(_get_image_path("xcf"), "rb") + sf = sdlimage.IMG_LoadXCF_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_LoadXPM_RW(with_sdl_image): + fp = open(_get_image_path("xpm"), "rb") + sf = sdlimage.IMG_LoadXPM_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +@pytest.mark.skip("not implemented") +def test_IMG_LoadXV_RW(with_sdl_image): + fp = open(_get_image_path("xv"), "rb") + sf = sdlimage.IMG_LoadXV_RW(rwops.rw_from_object(fp)) + fp.close() + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_isBMP(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "bmp": + assert sdlimage.IMG_isBMP(imgrw) else: - xpm += line[1:-3] - pxpm = ctypes.c_char_p(xpm) - sf = sdlimage.IMG_ReadXPMFromArray(ctypes.byref(pxpm)) - assert isinstance(sf.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - - def test_IMG_SavePNG(self, tmpdir): - # Open a PNG that we can re-save - fpath = _get_image_path("png") - sf = sdlimage.IMG_Load(fpath.encode("utf-8")) - assert isinstance(sf.contents, surface.SDL_Surface) - - # Try saving the PNG to a new folder - outpath = os.path.join(str(tmpdir), "save_test.png") - ret = sdlimage.IMG_SavePNG(sf, outpath.encode("utf-8")) - assert sdl2.SDL_GetError() == b"" - assert ret == 0 - assert os.path.exists(outpath) - surface.SDL_FreeSurface(sf) - - @pytest.mark.skip("not working yet") - def test_IMG_SavePNG_RW(self, tmpdir): - # Open a PNG that we can re-save - fpath = _get_image_path("png") - sf = sdlimage.IMG_Load(fpath.encode("utf-8")) - assert isinstance(sf.contents, surface.SDL_Surface) - - # Try saving the PNG to a new folder - outpath = os.path.join(str(tmpdir), "save_test.png") - rw = rwops.SDL_RWFromFile(outpath.encode("utf-8"), b"wb") - ret = sdlimage.IMG_SavePNG_RW(sf, rw, 0) - assert sdl2.SDL_GetError() == b"" - assert ret == 0 - assert os.path.exists(outpath) - - # Try reopening the RW as a PNG - sf2 = sdlimage.IMG_LoadPNG_RW(rw) - assert sdl2.SDL_GetError() == b"" - assert isinstance(sf2.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - surface.SDL_FreeSurface(sf2) - - @pytest.mark.skipif(no_jpeg_save, reason="Added in 2.0.2, not in macOS bnaries") - def test_IMG_SaveJPG(self, tmpdir): - # Open a PNG that we can save to JPG - fpath = _get_image_path("png") - sf = sdlimage.IMG_Load(fpath.encode("utf-8")) - assert isinstance(sf.contents, surface.SDL_Surface) - - # Try saving as JPG to a new folder - outpath = os.path.join(str(tmpdir), "save_test.jpg") - ret = sdlimage.IMG_SaveJPG(sf, outpath.encode("utf-8"), 90) - assert sdl2.SDL_GetError() == b"" - assert ret == 0 - assert os.path.exists(outpath) - surface.SDL_FreeSurface(sf) - - @pytest.mark.skip("not working yet") - @pytest.mark.skipif(no_jpeg_save, reason="Added in 2.0.2, not in macOS bnaries") - def test_IMG_SaveJPG_RW(self, tmpdir): - # Open a PNG that we can save to JPG - fpath = _get_image_path("png") - sf = sdlimage.IMG_Load(fpath.encode("utf-8")) - assert isinstance(sf.contents, surface.SDL_Surface) - - # Try saving as JPG to a new folder - outpath = os.path.join(str(tmpdir), "save_test.jpg") - rw = rwops.SDL_RWFromFile(outpath.encode("utf-8"), b"wb") - ret = sdlimage.IMG_SaveJPG_RW(sf, rw, 0, 90) - assert sdl2.SDL_GetError() == b"" - assert ret == 0 - assert os.path.exists(outpath) - - # Try reopening the RW as a JPG - sf2 = sdlimage.IMG_LoadJPG_RW(rw) - assert sdl2.SDL_GetError() == b"" - assert isinstance(sf2.contents, surface.SDL_Surface) - surface.SDL_FreeSurface(sf) - surface.SDL_FreeSurface(sf2) + assert not sdlimage.IMG_isBMP(imgrw) + +def test_IMG_isCUR(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "cur": + assert sdlimage.IMG_isCUR(imgrw) + else: + assert not sdlimage.IMG_isCUR(imgrw) + +def test_IMG_isGIF(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "gif": + assert sdlimage.IMG_isGIF(imgrw) + else: + assert not sdlimage.IMG_isGIF(imgrw) + +def test_IMG_isICO(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "ico": + assert sdlimage.IMG_isICO(imgrw) + else: + assert not sdlimage.IMG_isICO(imgrw) + +def test_IMG_isJPG(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "jpg": + assert sdlimage.IMG_isJPG(imgrw) + else: + assert not sdlimage.IMG_isJPG(imgrw) + +def test_IMG_isLBM(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "lbm": + assert sdlimage.IMG_isLBM(imgrw) + else: + assert not sdlimage.IMG_isLBM(imgrw) + +def test_IMG_isPCX(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "pcx": + assert sdlimage.IMG_isPCX(imgrw) + else: + assert not sdlimage.IMG_isPCX(imgrw) + +def test_IMG_isPNG(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "png": + assert sdlimage.IMG_isPNG(imgrw) + else: + assert not sdlimage.IMG_isPNG(imgrw) + +def test_IMG_isPNM(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt in ("pnm", "pbm", "ppm", "pgm"): + assert sdlimage.IMG_isPNM(imgrw) + else: + assert not sdlimage.IMG_isPNM(imgrw) + +@pytest.mark.skipif(sdlimage.dll.version < 2002, reason="Added in 2.0.2") +@pytest.mark.xfail(isconda and iswindows, reason="Broken w/ win64 Conda") +def test_IMG_isSVG(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "svg": + assert sdlimage.IMG_isSVG(imgrw) + else: + assert not sdlimage.IMG_isSVG(imgrw) + +def test_IMG_isTIF(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "tif": + assert sdlimage.IMG_isTIF(imgrw) + else: + assert not sdlimage.IMG_isTIF(imgrw) + +def test_IMG_isWEBP(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "webp": + assert sdlimage.IMG_isWEBP(imgrw) + else: + assert not sdlimage.IMG_isWEBP(imgrw) + +@pytest.mark.xfail(bad_xcf, reason="XCF currently broken on some platforms") +def test_IMG_isXCF(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "xcf": + assert sdlimage.IMG_isXCF(imgrw) + else: + assert not sdlimage.IMG_isXCF(imgrw) + +def test_IMG_isXPM(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "xpm": + assert sdlimage.IMG_isXPM(imgrw) + else: + assert not sdlimage.IMG_isXPM(imgrw) + +@pytest.mark.skip("not implemented") +def test_IMG_isXV(with_sdl_image): + for fmt in formats: + fpath = _get_image_path(fmt) + with open(fpath, "rb") as fp: + imgrw = rwops.rw_from_object(fp) + if fmt == "xv": + assert sdlimage.IMG_isXV(imgrw) + else: + assert not sdlimage.IMG_isXV(imgrw) + +@pytest.mark.skipif(hasattr(sys, "pypy_version_info"), + reason="PyPy's ctypes fails to pass a correct string array") +def test_IMG_ReadXPMFromArray(with_sdl_image): + fp = open(_get_image_path("xpm"), "rb") + xpm = b"" + fp.readline() # /* XPM */ + fp.readline() # static char * surfacetest_xpm[] = { + lbuf = fp.readlines() + fp.close() + for line in lbuf: + if line.endswith(b"};"): + xpm += line[1:-4] + else: + xpm += line[1:-3] + pxpm = ctypes.c_char_p(xpm) + sf = sdlimage.IMG_ReadXPMFromArray(ctypes.byref(pxpm)) + _verify_img_load(sf) + surface.SDL_FreeSurface(sf) + +def test_IMG_SavePNG(tmpdir): + # Open a PNG that we can re-save + fpath = _get_image_path("png") + sf = sdlimage.IMG_Load(fpath.encode("utf-8")) + assert isinstance(sf.contents, surface.SDL_Surface) + + # Try saving the PNG to a new folder + outpath = os.path.join(str(tmpdir), "save_test.png") + ret = sdlimage.IMG_SavePNG(sf, outpath.encode("utf-8")) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + assert os.path.exists(outpath) + surface.SDL_FreeSurface(sf) + +@pytest.mark.skip("not working yet") +def test_IMG_SavePNG_RW(tmpdir): + # Open a PNG that we can re-save + fpath = _get_image_path("png") + sf = sdlimage.IMG_Load(fpath.encode("utf-8")) + assert isinstance(sf.contents, surface.SDL_Surface) + + # Try saving the PNG to a new folder + outpath = os.path.join(str(tmpdir), "save_test.png") + rw = rwops.SDL_RWFromFile(outpath.encode("utf-8"), b"wb") + ret = sdlimage.IMG_SavePNG_RW(sf, rw, 0) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + assert os.path.exists(outpath) + + # Try reopening the RW as a PNG + sf2 = sdlimage.IMG_LoadPNG_RW(rw) + assert sdl2.SDL_GetError() == b"" + assert isinstance(sf2.contents, surface.SDL_Surface) + surface.SDL_FreeSurface(sf) + surface.SDL_FreeSurface(sf2) + +@pytest.mark.skipif(no_jpeg_save, reason="Added in 2.0.2, not in macOS bnaries") +def test_IMG_SaveJPG(tmpdir): + # Open a PNG that we can save to JPG + fpath = _get_image_path("png") + sf = sdlimage.IMG_Load(fpath.encode("utf-8")) + assert isinstance(sf.contents, surface.SDL_Surface) + + # Try saving as JPG to a new folder + outpath = os.path.join(str(tmpdir), "save_test.jpg") + ret = sdlimage.IMG_SaveJPG(sf, outpath.encode("utf-8"), 90) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + assert os.path.exists(outpath) + surface.SDL_FreeSurface(sf) + +@pytest.mark.skip("not working yet") +@pytest.mark.skipif(no_jpeg_save, reason="Added in 2.0.2, not in macOS bnaries") +def test_IMG_SaveJPG_RW(tmpdir): + # Open a PNG that we can save to JPG + fpath = _get_image_path("png") + sf = sdlimage.IMG_Load(fpath.encode("utf-8")) + assert isinstance(sf.contents, surface.SDL_Surface) + + # Try saving as JPG to a new folder + outpath = os.path.join(str(tmpdir), "save_test.jpg") + rw = rwops.SDL_RWFromFile(outpath.encode("utf-8"), b"wb") + ret = sdlimage.IMG_SaveJPG_RW(sf, rw, 0, 90) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + assert os.path.exists(outpath) + + # Try reopening the RW as a JPG + sf2 = sdlimage.IMG_LoadJPG_RW(rw) + assert sdl2.SDL_GetError() == b"" + assert isinstance(sf2.contents, surface.SDL_Surface) + surface.SDL_FreeSurface(sf) + surface.SDL_FreeSurface(sf2) diff --git a/sdl2/test/sdlttf_test.py b/sdl2/test/sdlttf_test.py index 0fae7c02..9fa0f21c 100644 --- a/sdl2/test/sdlttf_test.py +++ b/sdl2/test/sdlttf_test.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- import os -import sys +import gc import pytest from struct import unpack from ctypes import byref, c_int, c_uint16 @@ -9,361 +9,361 @@ sdlttf = pytest.importorskip("sdl2.sdlttf") - -fontfile = os.path.join(os.path.dirname(os.path.abspath(__file__)), - "resources", "tuffy.ttf").encode("utf-8") - -class TestSDLTTF(object): - __tags__ = ["sdl", "sdlttf"] - - @classmethod - def setup_class(cls): - SDL_Init(0) - sdlttf.TTF_Init() - cls.test_sizes = [6, 16, 26] - - @classmethod - def teardown_class(cls): +parent_dir = os.path.dirname(os.path.abspath(__file__)) +fontfile = os.path.join(parent_dir, "resources", "tuffy.ttf").encode("utf-8") +font_test_sizes = [6, 16, 26] + +@pytest.fixture(scope="module") +def with_sdl_ttf(with_sdl): + ret = sdlttf.TTF_Init() + assert sdlttf.TTF_GetError() == b"" + assert ret == 0 + yield + while sdlttf.TTF_WasInit() > 0: sdlttf.TTF_Quit() - SDL_Quit() - - def setup_method(self): - sdl2.SDL_ClearError() - - def test_TTF_Linked_Version(self): - v = sdlttf.TTF_Linked_Version() - assert isinstance(v.contents, version.SDL_version) - assert v.contents.major == 2 - assert v.contents.minor == 0 - assert v.contents.patch >= 12 - - def test_TTF_ByteSwappedUNICODE(self): - sdlttf.TTF_ByteSwappedUNICODE(0) - sdlttf.TTF_ByteSwappedUNICODE(1) - - def test_TTF_Font(self): - font = sdlttf.TTF_Font() - assert isinstance(font, sdlttf.TTF_Font) - - def test_TTF_InitQuit(self): - # Every time TTF_Init() is run, internal number increments by 1, - # every time TTF_Quit() is run, internal number decrements by 1 and - # only actually quits when internal number == 0 - sdlttf.TTF_Init() - sdlttf.TTF_Init() - assert sdlttf.TTF_WasInit() - sdlttf.TTF_Quit() - sdlttf.TTF_Quit() - sdlttf.TTF_Quit() - assert not sdlttf.TTF_WasInit() - sdlttf.TTF_Init() - assert sdlttf.TTF_WasInit() - - def test_TTF_OpenCloseFont(self): - for x in self.test_sizes: - font = sdlttf.TTF_OpenFont(fontfile, x) - assert isinstance(font.contents, sdlttf.TTF_Font) - sdlttf.TTF_CloseFont(font) - - def test_TTF_OpenFontIndex(self): - for x in self.test_sizes: - font = sdlttf.TTF_OpenFontIndex(fontfile, x, 0) - assert isinstance(font.contents, sdlttf.TTF_Font) - sdlttf.TTF_CloseFont(font) - - def test_TTF_OpenFontRW(self): - fp = open(fontfile, "rb") - fontrw = rwops.rw_from_object(fp) - for x in self.test_sizes: - fp.seek(0) - font = sdlttf.TTF_OpenFontRW(fontrw, 0, x) - assert isinstance(font.contents, sdlttf.TTF_Font) - sdlttf.TTF_CloseFont(font) - fp.close() - - def test_TTF_OpenFontIndexRW(self): - fp = open(fontfile, "rb") - fontrw = rwops.rw_from_object(fp) - for x in self.test_sizes: - fp.seek(0) - font = sdlttf.TTF_OpenFontIndexRW(fontrw, 0, x, 0) - assert isinstance(font.contents, sdlttf.TTF_Font) - sdlttf.TTF_CloseFont(font) - fp.close() - - def test_TTF_GetSetFontStyle(self): - normal = sdlttf.TTF_STYLE_NORMAL - bold = sdlttf.TTF_STYLE_BOLD - italic = sdlttf.TTF_STYLE_ITALIC - underline = sdlttf.TTF_STYLE_UNDERLINE - font = sdlttf.TTF_OpenFont(fontfile, 10) - assert isinstance(font.contents, sdlttf.TTF_Font) - assert sdlttf.TTF_GetFontStyle(font) == normal - sdlttf.TTF_SetFontStyle(font, bold) - assert sdlttf.TTF_GetFontStyle(font) == bold - sdlttf.TTF_SetFontStyle(font, bold | italic) - assert sdlttf.TTF_GetFontStyle(font) == bold | italic - sdlttf.TTF_SetFontStyle(font, bold | underline) - assert sdlttf.TTF_GetFontStyle(font) == bold | underline - sdlttf.TTF_CloseFont(font) - - def test_TTF_GetSetFontOutline(self): - font = sdlttf.TTF_OpenFont(fontfile, 10) - assert sdlttf.TTF_GetFontOutline(font) == 0 - for x in range(1, 11): - sdlttf.TTF_SetFontOutline(font, x) - assert sdlttf.TTF_GetFontOutline(font) == x - sdlttf.TTF_CloseFont(font) - - def test_TTF_GetSetFontHinting(self): - font = sdlttf.TTF_OpenFont(fontfile, 10) - assert sdlttf.TTF_GetFontHinting(font) == sdlttf.TTF_HINTING_NORMAL - for hint in (sdlttf.TTF_HINTING_NORMAL, sdlttf.TTF_HINTING_LIGHT, - sdlttf.TTF_HINTING_MONO, sdlttf.TTF_HINTING_NONE): - sdlttf.TTF_SetFontHinting(font, hint) - assert sdlttf.TTF_GetFontHinting(font) == hint - sdlttf.TTF_CloseFont(font) - - def test_TTF_FontHeight(self): - last = cur = 0 - for ptsize in self.test_sizes: - font = sdlttf.TTF_OpenFont(fontfile, ptsize) - cur = sdlttf.TTF_FontHeight(font) - assert cur >= last - last = cur - sdlttf.TTF_CloseFont(font) - - def test_TTF_FontAscent(self): - last = cur = 0 - for ptsize in self.test_sizes: - font = sdlttf.TTF_OpenFont(fontfile, ptsize) - cur = sdlttf.TTF_FontAscent(font) - assert cur >= last - last = cur - sdlttf.TTF_CloseFont(font) - - def test_TTF_FontDescent(self): - last = cur = 0 - for ptsize in self.test_sizes: - font = sdlttf.TTF_OpenFont(fontfile, ptsize) - cur = sdlttf.TTF_FontDescent(font) - assert cur <= last - last = cur - sdlttf.TTF_CloseFont(font) - - def test_TTF_FontLineSkip(self): - last = cur = 0 - for ptsize in self.test_sizes: - font = sdlttf.TTF_OpenFont(fontfile, ptsize) - cur = sdlttf.TTF_FontLineSkip(font) - assert cur >= last - last = cur - sdlttf.TTF_CloseFont(font) - - def test_TTF_GetSetFontKerning(self): - font = sdlttf.TTF_OpenFont(fontfile, 10) - assert sdlttf.TTF_GetFontKerning(font) == 1 - sdlttf.TTF_SetFontKerning(font, 0) - assert sdlttf.TTF_GetFontKerning(font) == 0 - sdlttf.TTF_SetFontKerning(font, 1) - assert sdlttf.TTF_GetFontKerning(font) == 1 - sdlttf.TTF_SetFontKerning(font, 0) - assert sdlttf.TTF_GetFontKerning(font) == 0 - sdlttf.TTF_CloseFont(font) - def test_TTF_FontFaces(self): - font = sdlttf.TTF_OpenFont(fontfile, 10) - assert sdlttf.TTF_FontFaces(font) >= 1 - sdlttf.TTF_CloseFont(font) - - def test_TTF_FontFaceIsFixedWidth(self): - font = sdlttf.TTF_OpenFont(fontfile, 10) - assert not sdlttf.TTF_FontFaceIsFixedWidth(font) - sdlttf.TTF_CloseFont(font) - - def test_TTF_FontFaceFamilyName(self): - font = sdlttf.TTF_OpenFont(fontfile, 10) - assert sdlttf.TTF_FontFaceFamilyName(font) == b"Tuffy" - sdlttf.TTF_CloseFont(font) - - def test_TTF_FontFaceStyleName(self): - font = sdlttf.TTF_OpenFont(fontfile, 10) - assert sdlttf.TTF_FontFaceStyleName(font) == b"Regular" - sdlttf.TTF_CloseFont(font) - - def test_TTF_GlyphIsProvided(self): - font = sdlttf.TTF_OpenFont(fontfile, 10) +@pytest.fixture() +def with_font(with_sdl_ttf): + sdl2.SDL_ClearError() + font = sdlttf.TTF_OpenFont(fontfile, 20) + assert sdlttf.TTF_GetError() == b"" + assert font + yield font + sdlttf.TTF_CloseFont(font) + gc.collect() + + +def test_TTF_Font(): + font = sdlttf.TTF_Font() + assert isinstance(font, sdlttf.TTF_Font) + +def test_TTF_InitQuit(with_sdl): + # Test that init and quit actually work + ret = sdlttf.TTF_Init() + assert sdlttf.TTF_GetError() == b"" + assert ret == 0 + assert sdlttf.TTF_WasInit() + sdlttf.TTF_Quit() + assert not sdlttf.TTF_WasInit() + # Every time TTF_Init() is run, internal number increments by 1, + # every time TTF_Quit() is run, internal number decrements by 1 and + # only actually quits when internal number == 0 + sdlttf.TTF_Init() + sdlttf.TTF_Init() + sdlttf.TTF_Quit() + assert sdlttf.TTF_WasInit() + sdlttf.TTF_Quit() + assert not sdlttf.TTF_WasInit() + +def test_TTF_Linked_Version(with_sdl_ttf): + v = sdlttf.TTF_Linked_Version() + assert isinstance(v.contents, version.SDL_version) + assert v.contents.major == 2 + assert v.contents.minor == 0 + assert v.contents.patch >= 12 + +def test_TTF_ByteSwappedUNICODE(with_sdl_ttf): + sdlttf.TTF_ByteSwappedUNICODE(0) + sdlttf.TTF_ByteSwappedUNICODE(1) + +def test_TTF_OpenCloseFont(with_sdl_ttf): + for x in font_test_sizes: + font = sdlttf.TTF_OpenFont(fontfile, x) + assert sdlttf.TTF_GetError() == b"" assert isinstance(font.contents, sdlttf.TTF_Font) - for ch in range(32, 127): - assert sdlttf.TTF_GlyphIsProvided(font, ch) - assert not sdlttf.TTF_GlyphIsProvided(font, 0) - assert not sdlttf.TTF_GlyphIsProvided(font, 0x0ff9) sdlttf.TTF_CloseFont(font) - def test_TTF_GlyphMetrics(self): - expected = { - 'A': [1, 25, 0, 29, 25], - 'j': [-3, 7, -9, 28, 9], - '.': [2, 7, -1, 4, 8] - } - font = sdlttf.TTF_OpenFont(fontfile, 40) - minX, maxX, minY, maxY = c_int(0), c_int(0), c_int(0), c_int(0) - adv = c_int(0) - for char in expected.keys(): - sdlttf.TTF_GlyphMetrics( - font, ord(char), - byref(minX), byref(maxX), byref(minY), byref(maxY), byref(adv) - ) - results = [x.value for x in (minX, maxX, minY, maxY, adv)] - assert results == expected[char] +def test_TTF_OpenFontIndex(with_sdl_ttf): + for x in font_test_sizes: + font = sdlttf.TTF_OpenFontIndex(fontfile, x, 0) + assert sdlttf.TTF_GetError() == b"" + assert isinstance(font.contents, sdlttf.TTF_Font) sdlttf.TTF_CloseFont(font) - def test_TTF_SizeText(self): - font = sdlttf.TTF_OpenFont(fontfile, 20) - min_expected_w = 69 # SDL2_ttf 2.0.18 - max_expected_w = 70 # SDL2_ttf <= 2.0.15 - min_expected_h = 21 # SDL2_ttf 2.0.15 with FreeType 2.10.1 - max_expected_h = 25 # SDL2_ttf < 2.0.15 - w, h = c_int(0), c_int(0) - sdlttf.TTF_SizeText(font, b"Hi there!", byref(w), byref(h)) - assert w.value >= min_expected_w - assert w.value <= max_expected_w - assert h.value >= min_expected_h - assert h.value <= max_expected_h +def test_TTF_OpenFontRW(with_sdl_ttf): + fp = open(fontfile, "rb") + fontrw = rwops.rw_from_object(fp) + for x in font_test_sizes: + fp.seek(0) + font = sdlttf.TTF_OpenFontRW(fontrw, 0, x) + assert sdlttf.TTF_GetError() == b"" + assert isinstance(font.contents, sdlttf.TTF_Font) sdlttf.TTF_CloseFont(font) - - def test_TTF_SizeUTF8(self): - font = sdlttf.TTF_OpenFont(fontfile, 20) - min_expected_w = 72 # SDL2_ttf 2.0.18 - max_expected_w = 73 # SDL2_ttf <= 2.0.15 - min_expected_h = 21 # SDL2_ttf 2.0.15 with FreeType 2.10.1 - max_expected_h = 25 # SDL2_ttf < 2.0.15 - w, h = c_int(0), c_int(0) - sdlttf.TTF_SizeUTF8(font, u"Hï thère!".encode('utf-8'), byref(w), byref(h)) - assert w.value >= min_expected_w - assert w.value <= max_expected_w - assert h.value >= min_expected_h - assert h.value <= max_expected_h + fp.close() + +def test_TTF_OpenFontIndexRW(with_sdl_ttf): + fp = open(fontfile, "rb") + fontrw = rwops.rw_from_object(fp) + for x in font_test_sizes: + fp.seek(0) + font = sdlttf.TTF_OpenFontIndexRW(fontrw, 0, x, 0) + assert sdlttf.TTF_GetError() == b"" + assert isinstance(font.contents, sdlttf.TTF_Font) sdlttf.TTF_CloseFont(font) - - @pytest.mark.xfail(reason="Highly unstable under pytest for some reason") - def test_TTF_SizeUNICODE(self): - font = sdlttf.TTF_OpenFont(fontfile, 20) - min_expected_w = 69 # SDL2_ttf 2.0.18 - max_expected_w = 70 # SDL2_ttf <= 2.0.15 - min_expected_h = 21 # SDL2_ttf 2.0.15 with FreeType 2.10.1 - max_expected_h = 25 # SDL2_ttf < 2.0.15 - w, h = c_int(0), c_int(0) - teststr = u"Hi there!" - strlen = len(teststr) + 1 # +1 for byte-order mark - intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) - strarr = (c_uint16 * (strlen + 1))(*intstr) - sdlttf.TTF_SizeUNICODE(font, strarr, byref(w), byref(h)) - print(list(strarr)) - print("w = {0}, h = {1}".format(w.value, h.value)) - assert w.value >= min_expected_w - assert w.value <= max_expected_w - assert h.value >= min_expected_h - assert h.value <= max_expected_h + fp.close() + +def test_TTF_GetSetFontStyle(with_font): + normal = sdlttf.TTF_STYLE_NORMAL + bold = sdlttf.TTF_STYLE_BOLD + italic = sdlttf.TTF_STYLE_ITALIC + underline = sdlttf.TTF_STYLE_UNDERLINE + # Test out getting/setting different font styles + font = with_font + assert sdlttf.TTF_GetFontStyle(font) == normal + sdlttf.TTF_SetFontStyle(font, bold) + assert sdlttf.TTF_GetFontStyle(font) == bold + sdlttf.TTF_SetFontStyle(font, bold | italic) + assert sdlttf.TTF_GetFontStyle(font) == bold | italic + sdlttf.TTF_SetFontStyle(font, bold | underline) + assert sdlttf.TTF_GetFontStyle(font) == bold | underline + +def test_TTF_GetSetFontOutline(with_font): + font = with_font + assert sdlttf.TTF_GetFontOutline(font) == 0 + for x in range(1, 11, 2): + sdlttf.TTF_SetFontOutline(font, x) + assert sdlttf.TTF_GetFontOutline(font) == x + +def test_TTF_GetSetFontHinting(with_font): + font = with_font + hints = [ + sdlttf.TTF_HINTING_NORMAL, sdlttf.TTF_HINTING_LIGHT, + sdlttf.TTF_HINTING_MONO, sdlttf.TTF_HINTING_NONE + ] + assert sdlttf.TTF_GetFontHinting(font) == sdlttf.TTF_HINTING_NORMAL + for hint in hints: + sdlttf.TTF_SetFontHinting(font, hint) + assert sdlttf.TTF_GetFontHinting(font) == hint + +def test_TTF_FontHeight(with_sdl_ttf): + last = cur = 0 + for ptsize in font_test_sizes: + font = sdlttf.TTF_OpenFont(fontfile, ptsize) + cur = sdlttf.TTF_FontHeight(font) + assert cur >= last + last = cur sdlttf.TTF_CloseFont(font) - def test_TTF_Render_Solid(self): - font = sdlttf.TTF_OpenFont(fontfile, 20) - color = SDL_Color(0, 0, 0) - # Test TTF_RenderText_Solid - sf = sdlttf.TTF_RenderText_Solid(font, b"Hi there!", color) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderUTF8_Solid - teststr = u"Hï thère!".encode('utf-8') - sf = sdlttf.TTF_RenderUTF8_Solid(font, teststr, color) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderUNICODE_Solid - # NOTE: no unicode chars because number -> glyph lookup is os-dependent - teststr = u"Hi there!" - strlen = len(teststr) + 1 # +1 for byte-order mark - intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) - strarr = (c_uint16 * (strlen + 1))(*intstr) - sf = sdlttf.TTF_RenderUNICODE_Solid(font, strarr, color) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderGlyph_Solid - sf = sdlttf.TTF_RenderGlyph_Solid(font, ord("A"), color) - assert isinstance(sf.contents, surface.SDL_Surface) - - def test_TTF_Render_Shaded(self): - font = sdlttf.TTF_OpenFont(fontfile, 20) - color = SDL_Color(0, 0, 0) - bgcolor = SDL_Color(255, 255, 255) - # Test TTF_RenderText_Shaded - sf = sdlttf.TTF_RenderText_Shaded(font, b"Hi there!", color, bgcolor) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderUTF8_Shaded - teststr = u"Hï thère!".encode('utf-8') - sf = sdlttf.TTF_RenderUTF8_Shaded(font, teststr, color, bgcolor) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderUNICODE_Shaded - # NOTE: no unicode chars because number -> glyph lookup is os-dependent - teststr = u"Hi there!" - strlen = len(teststr) + 1 # +1 for byte-order mark - intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) - strarr = (c_uint16 * (strlen + 1))(*intstr) - sf = sdlttf.TTF_RenderUNICODE_Shaded(font, strarr, color, bgcolor) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderGlyph_Shaded - sf = sdlttf.TTF_RenderGlyph_Shaded(font, ord("A"), color, bgcolor) - assert isinstance(sf.contents, surface.SDL_Surface) +def test_TTF_FontAscent(with_sdl_ttf): + last = cur = 0 + for ptsize in font_test_sizes: + font = sdlttf.TTF_OpenFont(fontfile, ptsize) + cur = sdlttf.TTF_FontAscent(font) + assert cur >= last + last = cur sdlttf.TTF_CloseFont(font) - def test_TTF_Render_Blended(self): - font = sdlttf.TTF_OpenFont(fontfile, 20) - color = SDL_Color(0, 0, 0, 255) - # Test TTF_RenderText_Blended - sf = sdlttf.TTF_RenderText_Blended(font, b"Hi there!", color) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderUTF8_Blended - teststr = u"Hï thère!".encode('utf-8') - sf = sdlttf.TTF_RenderUTF8_Blended(font, teststr, color) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderUNICODE_Blended - # NOTE: no unicode chars because number -> glyph lookup is os-dependent - teststr = u"Hi there!" - strlen = len(teststr) + 1 # +1 for byte-order mark - intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) - strarr = (c_uint16 * (strlen + 1))(*intstr) - sf = sdlttf.TTF_RenderUNICODE_Blended(font, strarr, color) - assert isinstance(sf.contents, surface.SDL_Surface) - # Test TTF_RenderGlyph_Blended - sf = sdlttf.TTF_RenderGlyph_Blended(font, ord("A"), color) - assert isinstance(sf.contents, surface.SDL_Surface) +def test_TTF_FontDescent(with_sdl_ttf): + last = cur = 0 + for ptsize in font_test_sizes: + font = sdlttf.TTF_OpenFont(fontfile, ptsize) + cur = sdlttf.TTF_FontDescent(font) + assert cur <= last + last = cur sdlttf.TTF_CloseFont(font) - def test_TTF_Render_Blended_Wrapped(self): - font = sdlttf.TTF_OpenFont(fontfile, 20) - color = SDL_Color(0, 0, 0, 255) - # Test TTF_RenderText_Blended_Wrapped - teststr = b"Hi there, this is a long line!" - sf = sdlttf.TTF_RenderText_Blended_Wrapped(font, teststr, color, 100) - assert isinstance(sf.contents, surface.SDL_Surface) - assert sf.contents.h > 30 - # Test TTF_RenderUTF8_Blended_Wrapped - teststr = u"Hï thère, this is a long line!".encode('utf-8') - sf = sdlttf.TTF_RenderUTF8_Blended_Wrapped(font, teststr, color, 100) - assert isinstance(sf.contents, surface.SDL_Surface) - assert sf.contents.h > 30 - # Test TTF_RenderUNICODE_Blended_Wrapped - # NOTE: no unicode chars because number -> glyph lookup is os-dependent - teststr = u"Hi there, this is a long line!" - strlen = len(teststr) + 1 # +1 for byte-order mark - intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) - strarr = (c_uint16 * (strlen + 1))(*intstr) - sf = sdlttf.TTF_RenderUNICODE_Blended_Wrapped(font, strarr, color, 100) - assert isinstance(sf.contents, surface.SDL_Surface) - assert sf.contents.h > 30 +def test_TTF_FontLineSkip(with_sdl_ttf): + last = cur = 0 + for ptsize in font_test_sizes: + font = sdlttf.TTF_OpenFont(fontfile, ptsize) + cur = sdlttf.TTF_FontLineSkip(font) + assert cur >= last + last = cur sdlttf.TTF_CloseFont(font) - @pytest.mark.skipif(sdlttf.dll.version < 2014, reason="not available") - def test_TTF_GetFontKerningSizeGlyphs(self): - font = sdlttf.TTF_OpenFont(fontfile, 40) - # NOTE: Test font (tuffy) has no kerning info, so retval is always 0 - sz = sdlttf.TTF_GetFontKerningSizeGlyphs(font, ord("A"), ord("B")) - assert sz == 0 - sdlttf.TTF_CloseFont(font) +def test_TTF_GetSetFontKerning(with_font): + font = with_font + assert sdlttf.TTF_GetFontKerning(font) == 1 + sdlttf.TTF_SetFontKerning(font, 0) + assert sdlttf.TTF_GetFontKerning(font) == 0 + sdlttf.TTF_SetFontKerning(font, 1) + assert sdlttf.TTF_GetFontKerning(font) == 1 + sdlttf.TTF_SetFontKerning(font, 0) + assert sdlttf.TTF_GetFontKerning(font) == 0 + +def test_TTF_FontFaces(with_font): + font = with_font + assert sdlttf.TTF_FontFaces(font) >= 1 + +def test_TTF_FontFaceIsFixedWidth(with_font): + font = with_font + assert not sdlttf.TTF_FontFaceIsFixedWidth(font) + +def test_TTF_FontFaceFamilyName(with_font): + font = with_font + assert sdlttf.TTF_FontFaceFamilyName(font) == b"Tuffy" + +def test_TTF_FontFaceStyleName(with_font): + font = with_font + assert sdlttf.TTF_FontFaceStyleName(font) == b"Regular" + +def test_TTF_GlyphIsProvided(with_font): + font = with_font + assert isinstance(font.contents, sdlttf.TTF_Font) + for ch in range(32, 127): + assert sdlttf.TTF_GlyphIsProvided(font, ch) + assert not sdlttf.TTF_GlyphIsProvided(font, 0) + assert not sdlttf.TTF_GlyphIsProvided(font, 0x0ff9) + +def test_TTF_GlyphMetrics(with_sdl_ttf): + expected = { + 'A': [1, 25, 0, 29, 25], + 'j': [-3, 7, -9, 28, 9], + '.': [2, 7, -1, 4, 8] + } + font = sdlttf.TTF_OpenFont(fontfile, 40) + minX, maxX, minY, maxY = c_int(0), c_int(0), c_int(0), c_int(0) + adv = c_int(0) + for char in expected.keys(): + ret = sdlttf.TTF_GlyphMetrics( + font, ord(char), + byref(minX), byref(maxX), byref(minY), byref(maxY), byref(adv) + ) + results = [x.value for x in (minX, maxX, minY, maxY, adv)] + assert sdlttf.TTF_GetError() == b"" + assert ret == 0 + assert results == expected[char] + sdlttf.TTF_CloseFont(font) + +def test_TTF_SizeText(with_font): + font = with_font + min_expected_w = 69 # SDL2_ttf 2.0.18 + max_expected_w = 70 # SDL2_ttf <= 2.0.15 + min_expected_h = 21 # SDL2_ttf 2.0.15 with FreeType 2.10.1 + max_expected_h = 25 # SDL2_ttf < 2.0.15 + w, h = c_int(0), c_int(0) + sdlttf.TTF_SizeText(font, b"Hi there!", byref(w), byref(h)) + assert w.value >= min_expected_w + assert w.value <= max_expected_w + assert h.value >= min_expected_h + assert h.value <= max_expected_h + +def test_TTF_SizeUTF8(with_font): + font = with_font + min_expected_w = 72 # SDL2_ttf 2.0.18 + max_expected_w = 73 # SDL2_ttf <= 2.0.15 + min_expected_h = 21 # SDL2_ttf 2.0.15 with FreeType 2.10.1 + max_expected_h = 25 # SDL2_ttf < 2.0.15 + w, h = c_int(0), c_int(0) + sdlttf.TTF_SizeUTF8(font, u"Hï thère!".encode('utf-8'), byref(w), byref(h)) + assert w.value >= min_expected_w + assert w.value <= max_expected_w + assert h.value >= min_expected_h + assert h.value <= max_expected_h + +def test_TTF_SizeUNICODE(with_font): + font = with_font + min_expected_w = 69 # SDL2_ttf 2.0.18 + max_expected_w = 70 # SDL2_ttf <= 2.0.15 + min_expected_h = 21 # SDL2_ttf 2.0.15 with FreeType 2.10.1 + max_expected_h = 25 # SDL2_ttf < 2.0.15 + w, h = c_int(0), c_int(0) + teststr = u"Hi there!" + strlen = len(teststr) + 1 # +1 for byte-order mark + intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) + strarr = (c_uint16 * (strlen + 1))(*intstr) + sdlttf.TTF_SizeUNICODE(font, strarr, byref(w), byref(h)) + # For debug purposes + #print(list(strarr)) + #print("w = {0}, h = {1}".format(w.value, h.value)) + assert w.value >= min_expected_w + assert w.value <= max_expected_w + assert h.value >= min_expected_h + assert h.value <= max_expected_h + +def test_TTF_Render_Solid(with_font): + font = with_font + color = SDL_Color(0, 0, 0) + # Test TTF_RenderText_Solid + sf = sdlttf.TTF_RenderText_Solid(font, b"Hi there!", color) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderUTF8_Solid + teststr = u"Hï thère!".encode('utf-8') + sf = sdlttf.TTF_RenderUTF8_Solid(font, teststr, color) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderUNICODE_Solid + # NOTE: no unicode chars because number -> glyph lookup is os-dependent + teststr = u"Hi there!" + strlen = len(teststr) + 1 # +1 for byte-order mark + intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) + strarr = (c_uint16 * (strlen + 1))(*intstr) + sf = sdlttf.TTF_RenderUNICODE_Solid(font, strarr, color) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderGlyph_Solid + sf = sdlttf.TTF_RenderGlyph_Solid(font, ord("A"), color) + assert isinstance(sf.contents, surface.SDL_Surface) + +def test_TTF_Render_Shaded(with_font): + font = with_font + color = SDL_Color(0, 0, 0) + bgcolor = SDL_Color(255, 255, 255) + # Test TTF_RenderText_Shaded + sf = sdlttf.TTF_RenderText_Shaded(font, b"Hi there!", color, bgcolor) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderUTF8_Shaded + teststr = u"Hï thère!".encode('utf-8') + sf = sdlttf.TTF_RenderUTF8_Shaded(font, teststr, color, bgcolor) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderUNICODE_Shaded + # NOTE: no unicode chars because number -> glyph lookup is os-dependent + teststr = u"Hi there!" + strlen = len(teststr) + 1 # +1 for byte-order mark + intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) + strarr = (c_uint16 * (strlen + 1))(*intstr) + sf = sdlttf.TTF_RenderUNICODE_Shaded(font, strarr, color, bgcolor) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderGlyph_Shaded + sf = sdlttf.TTF_RenderGlyph_Shaded(font, ord("A"), color, bgcolor) + assert isinstance(sf.contents, surface.SDL_Surface) + +def test_TTF_Render_Blended(with_font): + font = with_font + color = SDL_Color(0, 0, 0, 255) + # Test TTF_RenderText_Blended + sf = sdlttf.TTF_RenderText_Blended(font, b"Hi there!", color) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderUTF8_Blended + teststr = u"Hï thère!".encode('utf-8') + sf = sdlttf.TTF_RenderUTF8_Blended(font, teststr, color) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderUNICODE_Blended + # NOTE: no unicode chars because number -> glyph lookup is os-dependent + teststr = u"Hi there!" + strlen = len(teststr) + 1 # +1 for byte-order mark + intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) + strarr = (c_uint16 * (strlen + 1))(*intstr) + sf = sdlttf.TTF_RenderUNICODE_Blended(font, strarr, color) + assert isinstance(sf.contents, surface.SDL_Surface) + # Test TTF_RenderGlyph_Blended + sf = sdlttf.TTF_RenderGlyph_Blended(font, ord("A"), color) + assert isinstance(sf.contents, surface.SDL_Surface) + +def test_TTF_Render_Blended_Wrapped(with_font): + font = with_font + color = SDL_Color(0, 0, 0, 255) + # Test TTF_RenderText_Blended_Wrapped + teststr = b"Hi there, this is a long line!" + sf = sdlttf.TTF_RenderText_Blended_Wrapped(font, teststr, color, 100) + assert isinstance(sf.contents, surface.SDL_Surface) + assert sf.contents.h > 30 + # Test TTF_RenderUTF8_Blended_Wrapped + teststr = u"Hï thère, this is a long line!".encode('utf-8') + sf = sdlttf.TTF_RenderUTF8_Blended_Wrapped(font, teststr, color, 100) + assert isinstance(sf.contents, surface.SDL_Surface) + assert sf.contents.h > 30 + # Test TTF_RenderUNICODE_Blended_Wrapped + # NOTE: no unicode chars because number -> glyph lookup is os-dependent + teststr = u"Hi there, this is a long line!" + strlen = len(teststr) + 1 # +1 for byte-order mark + intstr = unpack('H' * strlen, teststr.encode('utf-16')) + (0, ) + strarr = (c_uint16 * (strlen + 1))(*intstr) + sf = sdlttf.TTF_RenderUNICODE_Blended_Wrapped(font, strarr, color, 100) + assert isinstance(sf.contents, surface.SDL_Surface) + assert sf.contents.h > 30 + +@pytest.mark.skipif(sdlttf.dll.version < 2014, reason="not available") +def test_TTF_GetFontKerningSizeGlyphs(with_font): + font = with_font + # NOTE: Test font (tuffy) has no kerning info, so retval is always 0 + sz = sdlttf.TTF_GetFontKerningSizeGlyphs(font, ord("A"), ord("B")) + assert sz == 0 diff --git a/sdl2/test/syswm_test.py b/sdl2/test/syswm_test.py index bc30c4c5..e3178fcb 100644 --- a/sdl2/test/syswm_test.py +++ b/sdl2/test/syswm_test.py @@ -1,41 +1,41 @@ +import os import sys import pytest import ctypes from sdl2.stdinc import SDL_TRUE -from sdl2 import video, syswm, version +from sdl2 import video, syswm, version, SDL_GetError +# Check if using dummy video driver +DRIVER_DUMMY = os.getenv("SDL_VIDEODRIVER", "") == "dummy" -class TestSDLSysWM(object): - __tags__ = ["sdl"] - @classmethod - def setup_class(cls): - if video.SDL_VideoInit(None) != 0: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - video.SDL_VideoQuit() - - def test_SDL_GetWindowWMInfo(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("cannot retrieve WM information for the dummy video driver") - - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, - video.SDL_WINDOW_HIDDEN) - wminfo = syswm.SDL_SysWMinfo() - version.SDL_VERSION(wminfo.version) - ret = syswm.SDL_GetWindowWMInfo(window, ctypes.byref(wminfo)) - assert ret == SDL_TRUE - if sys.platform in ("win32", "cygwin"): - assert wminfo.subsystem == syswm.SDL_SYSWM_WINDOWS - elif sys.platform.startswith("linux"): - assert wminfo.subsystem in \ - (syswm.SDL_SYSWM_X11, syswm.SDL_SYSWM_DIRECTFB) - elif sys.platform.startswith("freebsd"): - assert wminfo.subsystem in \ - (syswm.SDL_SYSWM_X11, syswm.SDL_SYSWM_DIRECTFB) - elif sys.platform.startswith("darwin"): - assert wminfo.subsystem == syswm.SDL_SYSWM_COCOA - video.SDL_DestroyWindow(window) - # TODO: not sure, what to test here specifically +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GetWindowWMInfo(with_sdl): + unix_wms = [ + syswm.SDL_SYSWM_X11, syswm.SDL_SYSWM_DIRECTFB, + syswm.SDL_SYSWM_WAYLAND, syswm.SDL_SYSWM_KMSDRM, + ] + platform_wms = { + "windows": [syswm.SDL_SYSWM_WINDOWS], + "darwin": [syswm.SDL_SYSWM_COCOA], + "unixlike": unix_wms, + "os2": [syswm.SDL_SYSWM_OS2], + } + # Create a window and retrieve the current window manager info + window = video.SDL_CreateWindow( + b"Test", 10, 10, 10, 10, video.SDL_WINDOW_HIDDEN + ) + wminfo = syswm.SDL_SysWMinfo() + version.SDL_VERSION(wminfo.version) + ret = syswm.SDL_GetWindowWMInfo(window, ctypes.byref(wminfo)) + video.SDL_DestroyWindow(window) + assert SDL_GetError() == b"" + assert ret == SDL_TRUE + # Test window manager types for different platforms + platform = sys.platform + if platform in ("win32", "cygwin", "msys"): + platform = "windows" + elif "linux" in platform or "bsd" in platform: + platform = "unixlike" + if platform in platform_wms.keys(): + assert wminfo.subsystem in platform_wms[platform] diff --git a/sdl2/test/timer_test.py b/sdl2/test/timer_test.py index 54f92c75..f917db29 100644 --- a/sdl2/test/timer_test.py +++ b/sdl2/test/timer_test.py @@ -2,90 +2,73 @@ import time import pytest import sdl2 -from sdl2 import SDL_Init, SDL_Quit, SDL_QuitSubSystem, SDL_INIT_TIMER from sdl2 import timer - if sys.version_info[0] >= 3: long = int -calls = [] - - -class TestSDLTimer(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - if SDL_Init(SDL_INIT_TIMER) != 0: - raise pytest.skip('Timer subsystem not supported') - - @classmethod - def teardown_class(cls): - SDL_QuitSubSystem(SDL_INIT_TIMER) - SDL_Quit() - - def test_SDL_GetTicks(self): - ticks = timer.SDL_GetTicks() - time.sleep(0.1) - ticks2 = timer.SDL_GetTicks() - time.sleep(0.1) - ticks3 = timer.SDL_GetTicks() - - assert ticks2 > ticks - assert ticks3 > ticks2 - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_GetTicks64(self): - ticks = timer.SDL_GetTicks64() - time.sleep(0.1) - ticks2 = timer.SDL_GetTicks64() - time.sleep(0.1) - ticks3 = timer.SDL_GetTicks64() - assert ticks2 > ticks - assert ticks3 > ticks2 - - def test_SDL_GetPerformanceCounter(self): - perf = timer.SDL_GetPerformanceCounter() - assert type(perf) in (int, long) - - def test_SDL_GetPerformanceFrequency(self): - freq = timer.SDL_GetPerformanceFrequency() - assert type(freq) in (int, long) - - @pytest.mark.skip("precision problems") - def test_SDL_Delay(self): - # NOTE: Try removing skip here? - for wait in range(5, 200, 5): - start = time.time() * 1000 - timer.SDL_Delay(wait) - end = time.time() * 1000 - sm = (end - start) - err = "%f is not <= 3 for %f and %f" % (abs(wait - sm), wait, sm) - assert abs(wait - sm) <= 3, err - - @pytest.mark.skipif(hasattr(sys, "pypy_version_info"), - reason="PyPy can't access other vars properly from a separate thread") - def test_SDL_AddRemoveTimer(self): - calls = [] - - def timerfunc(interval, param): - calls.append(param) - return interval - - callback = timer.SDL_TimerCallback(timerfunc) - timerid = timer.SDL_AddTimer(100, callback, "Test") +def test_SDL_GetTicks(with_sdl): + ticks = timer.SDL_GetTicks() + time.sleep(0.05) + ticks2 = timer.SDL_GetTicks() + time.sleep(0.05) + ticks3 = timer.SDL_GetTicks() + assert ticks2 > ticks + assert ticks3 > ticks2 + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_GetTicks64(with_sdl): + ticks = timer.SDL_GetTicks64() + time.sleep(0.05) + ticks2 = timer.SDL_GetTicks64() + time.sleep(0.05) + ticks3 = timer.SDL_GetTicks64() + assert ticks2 > ticks + assert ticks3 > ticks2 + +def test_SDL_GetPerformanceCounter(with_sdl): + perf = timer.SDL_GetPerformanceCounter() + assert type(perf) in (int, long) + assert perf > 0 + +def test_SDL_GetPerformanceFrequency(with_sdl): + freq = timer.SDL_GetPerformanceFrequency() + assert type(freq) in (int, long) + assert freq > 0 + +@pytest.mark.xfail(reason="Unreliable on CI runners") +def test_SDL_Delay(with_sdl): + for wait in [5, 10, 50, 100]: start = timer.SDL_GetTicks() - end = long(start) - while (end - start) < 1100: - # One second wait - end = timer.SDL_GetTicks() - # check for <=11, since it can happen that a last call is still - # executing - assert len(calls) <= 11 - timer.SDL_RemoveTimer(timerid) - assert len(calls) <= 11 - timer.SDL_RemoveTimer(timerid) - # Wait a bit, so the last executing handlers can finish + timer.SDL_Delay(wait) + end = timer.SDL_GetTicks() + actual = (end - start) + assert (wait - 2) <= actual <= (wait + 2) + +@pytest.mark.skipif(hasattr(sys, "pypy_version_info"), + reason="PyPy can't access other vars properly from a separate thread") +@pytest.mark.xfail(reason="Unreliable on CI runners") +def test_SDL_AddRemoveTimer(with_sdl): + # Create a timer callback that adds a value to a Python list + calls = [] + def timerfunc(interval, param): + calls.append(param) + return interval + callback = timer.SDL_TimerCallback(timerfunc) + timerid = timer.SDL_AddTimer(50, callback, "Test") + # Run a loop for 300 ms and make sure the callback runs 5 or 6 times + start = timer.SDL_GetTicks() + while (timer.SDL_GetTicks() - start) <= 300: + timer.SDL_Delay(10) + assert len(calls) in [5, 6] + # Try removing the timer and make sure the callback doesn't run anymore + timer.SDL_RemoveTimer(timerid) + timer.SDL_Delay(10) + orig_calls = len(calls) + start = timer.SDL_GetTicks() + while (timer.SDL_GetTicks() - start) <= 200: timer.SDL_Delay(10) + assert len(calls) == orig_calls + # Wait a bit, so the last executing handlers can finish + timer.SDL_Delay(10) diff --git a/sdl2/test/touch_test.py b/sdl2/test/touch_test.py index 6dd382ba..8871165d 100644 --- a/sdl2/test/touch_test.py +++ b/sdl2/test/touch_test.py @@ -5,65 +5,77 @@ from sdl2 import touch +# Check if we have any touch devices before running tests +devices = 0 +sdl2.SDL_SetHint(sdl2.SDL_HINT_MOUSE_TOUCH_EVENTS, b"1") +ret = sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) +if ret == 0: + devices = touch.SDL_GetNumTouchDevices() +SDL_Quit() + +# Override the global fixture to enable trackpads as touch devices @pytest.fixture(scope="module", autouse=True) -def sdl_setup(): - SDL_Init(0) +def with_sdl(): + sdl2.SDL_SetHint(sdl2.SDL_HINT_MOUSE_TOUCH_EVENTS, b"1") + sdl2.SDL_ClearError() + ret = sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 yield - SDL_Quit() + sdl2.SDL_Quit() def test_SDL_GetNumTouchDevices(): assert touch.SDL_GetNumTouchDevices() >= 0 +@pytest.mark.skipif(devices == 0, reason="No available touch devices") +def test_SDL_GetTouchDevice(): + count = touch.SDL_GetNumTouchDevices() + for i in range(count): + dev_id = touch.SDL_GetTouchDevice(i) + assert SDL_GetError() == b"" + assert dev_id != 0 -class TestSDLTouchDevice(object): - - # NOTE: these are currently untested due to lack of hardware - - @classmethod - def setup_class(cls): - num = touch.SDL_GetNumTouchDevices() - if num < 1: - pytest.skip("no available touch devices") - cls.num_devices = num - - def setup_method(self): - SDL_ClearError() - - def test_SDL_GetTouchDevice(self): - for i in range(0, self.num_devices): - dev_id = touch.SDL_GetTouchDevice(i) - assert dev_id > 0 - - @pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") - def test_SDL_GetTouchDeviceType(self): - types = [ - touch.SDL_TOUCH_DEVICE_INVALID, touch.SDL_TOUCH_DEVICE_DIRECT, - touch.SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, - touch.SDL_TOUCH_DEVICE_INDIRECT_RELATIVE - ] - for i in range(0, self.num_devices): - dev_id = touch.SDL_GetTouchDevice(i) - assert dev_id > 0 - dev_type = touch.SDL_GetTouchDeviceType(dev_id) - assert dev_type in types +@pytest.mark.skipif(sdl2.dll.version < 2010, reason="not available") +@pytest.mark.skipif(devices == 0, reason="No available touch devices") +def test_SDL_GetTouchDeviceType(): + types = [ + touch.SDL_TOUCH_DEVICE_INVALID, touch.SDL_TOUCH_DEVICE_DIRECT, + touch.SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, + touch.SDL_TOUCH_DEVICE_INDIRECT_RELATIVE + ] + count = touch.SDL_GetNumTouchDevices() + for i in range(count): + dev_id = touch.SDL_GetTouchDevice(i) + assert SDL_GetError() == b"" + assert dev_id != 0 + dev_type = touch.SDL_GetTouchDeviceType(dev_id) + assert dev_type in types - def test_SDL_GetNumTouchFingers(self): - for i in range(0, self.num_devices): - dev_id = touch.SDL_GetTouchDevice(i) - assert dev_id > 0 - fingers = touch.SDL_GetNumTouchFingers(dev_id) - err = SDL_GetError() - assert fingers > 0 - assert len(err) == 0 +@pytest.mark.skipif(devices == 0, reason="No available touch devices") +def test_SDL_GetNumTouchFingers(): + count = touch.SDL_GetNumTouchDevices() + for i in range(count): + dev_id = touch.SDL_GetTouchDevice(i) + assert SDL_GetError() == b"" + assert dev_id != 0 + fingers = touch.SDL_GetNumTouchFingers(dev_id) + assert SDL_GetError() == b"" + assert fingers >= 0 - def test_SDL_GetTouchFinger(self): - for i in range(0, self.num_devices): - dev_id = touch.SDL_GetTouchDevice(i) - assert dev_id > 0 - fingers = touch.SDL_GetNumTouchFingers(dev_id) - assert fingers > 0 - for f in range(0, fingers): - finger = touch.SDL_GetTouchFinger(dev_id, f) - assert isinstance(finger.contents, touch.SDL_Finger) +@pytest.mark.skipif(devices == 0, reason="No available touch devices") +def test_SDL_GetTouchFinger(): + count = touch.SDL_GetNumTouchDevices() + for i in range(count): + dev_id = touch.SDL_GetTouchDevice(i) + assert SDL_GetError() == b"" + assert dev_id != 0 + fingers = touch.SDL_GetNumTouchFingers(dev_id) + assert fingers >= 0 + for f in range(0, fingers): + finger = touch.SDL_GetTouchFinger(dev_id, f) + assert isinstance(finger.contents, touch.SDL_Finger) + assert finger.contents.id >= 0 + assert 0 <= finger.contents.x <= 1 + assert 0 <= finger.contents.y <= 1 \ No newline at end of file diff --git a/sdl2/test/version_test.py b/sdl2/test/version_test.py index 0a39a2e6..4bf4a072 100644 --- a/sdl2/test/version_test.py +++ b/sdl2/test/version_test.py @@ -4,47 +4,44 @@ from sdl2 import version, dll, __version__, version_info -class TestSDLVersion(object): - __tags__ = ["sdl"] - - def test_SDL_version(self): - v = version.SDL_version(0, 0, 0) - assert v.major == 0 - assert v.minor == 0 - assert v.patch == 0 - - def test_SDL_GetVersion(self): - v = version.SDL_version() - version.SDL_GetVersion(ctypes.byref(v)) - assert type(v) == version.SDL_version - assert v.major == 2 - assert v.minor == 0 - assert v.patch >= 5 - - def test_SDL_VERSIONNUM(self): - assert version.SDL_VERSIONNUM(1, 2, 3) == 1203 - assert version.SDL_VERSIONNUM(4, 5, 6) == 4506 - assert version.SDL_VERSIONNUM(2, 0, 0) == 2000 - assert version.SDL_VERSIONNUM(17, 42, 3) == 21203 - - def test_SDL_VERSION_ATLEAST(self): - assert version.SDL_VERSION_ATLEAST(1, 2, 3) - assert version.SDL_VERSION_ATLEAST(2, 0, 0) - assert version.SDL_VERSION_ATLEAST(2, 0, 1) - assert not version.SDL_VERSION_ATLEAST(2, 0, 100) - - def test_SDL_GetRevision(self): - rev = version.SDL_GetRevision() - # If revision not empty string (e.g. Conda), test the prefix - if len(rev): - if dll.version >= 2016: - assert rev[0:4] == b"http" - else: - assert rev[0:3] == b"hg-" - - def test_SDL_GetRevisionNumber(self): - if sys.platform in ("win32",) or dll.version >= 2016: - # HG tip on Win32 does not set any revision number - assert version.SDL_GetRevisionNumber() >= 0 +def test_SDL_version(): + v = version.SDL_version(0, 0, 0) + assert v.major == 0 + assert v.minor == 0 + assert v.patch == 0 + +def test_SDL_GetVersion(): + v = version.SDL_version() + version.SDL_GetVersion(ctypes.byref(v)) + assert type(v) == version.SDL_version + assert v.major == 2 + assert v.minor == 0 + assert v.patch >= 5 + +def test_SDL_VERSIONNUM(): + assert version.SDL_VERSIONNUM(1, 2, 3) == 1203 + assert version.SDL_VERSIONNUM(4, 5, 6) == 4506 + assert version.SDL_VERSIONNUM(2, 0, 0) == 2000 + assert version.SDL_VERSIONNUM(17, 42, 3) == 21203 + +def test_SDL_VERSION_ATLEAST(): + assert version.SDL_VERSION_ATLEAST(1, 2, 3) + assert version.SDL_VERSION_ATLEAST(2, 0, 0) + assert version.SDL_VERSION_ATLEAST(2, 0, 1) + assert not version.SDL_VERSION_ATLEAST(2, 0, 100) + +def test_SDL_GetRevision(): + rev = version.SDL_GetRevision() + # If revision not empty string (e.g. Conda), test the prefix + if len(rev): + if dll.version >= 2016: + assert rev[0:4] == b"http" else: - assert version.SDL_GetRevisionNumber() >= 7000 + assert rev[0:3] == b"hg-" + +def test_SDL_GetRevisionNumber(): + if sys.platform in ("win32",) or dll.version >= 2016: + # HG tip on Win32 does not set any revision number + assert version.SDL_GetRevisionNumber() >= 0 + else: + assert version.SDL_GetRevisionNumber() >= 7000 diff --git a/sdl2/test/video_test.py b/sdl2/test/video_test.py index d4b911ff..f7beaff2 100644 --- a/sdl2/test/video_test.py +++ b/sdl2/test/video_test.py @@ -5,110 +5,141 @@ from ctypes import c_int, c_ubyte, c_float, byref, cast, POINTER, py_object import pytest import sdl2 -from sdl2.stdinc import SDL_FALSE, SDL_TRUE -from sdl2 import video, rect, surface, SDL_GetError +from sdl2.stdinc import SDL_FALSE, SDL_TRUE, Uint16 +from sdl2 import video, rect, pixels, surface, SDL_GetError +from .conftest import SKIP_ANNOYING + +# Some tests don't work properly with some video drivers, so check the name +DRIVER_DUMMY = False +DRIVER_X11 = False +try: + sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO) + driver_name = video.SDL_GetCurrentVideoDriver() + sdl2.SDL_Quit() + DRIVER_DUMMY = driver_name == b"dummy" + DRIVER_X11 = driver_name == b"x11" +except: + pass + +# Some tests don't work right on PyPy +is_pypy = hasattr(sys, "pypy_version_info") if sys.version_info[0] >= 3: long = int to_ctypes = lambda seq, dtype: (dtype * len(seq))(*seq) - def has_opengl_lib(): for libname in("gl", "opengl", "opengl32"): path = find_library(libname) if path is not None: return True - def get_opengl_path(): for libname in("gl", "opengl", "opengl32"): path = find_library(libname) if path is not None: return path - -# TODO: mostly covers positive tests right now - fix this! -class TestSDLVideo(object): - __tags__ = ["sdl"] - - @classmethod - def setup_class(cls): - if video.SDL_VideoInit(None) != 0: - raise pytest.skip('Video subsystem not supported') - - @classmethod - def teardown_class(cls): - video.SDL_VideoQuit() - - def setup_method(self): - sdl2.SDL_ClearError() - - def test_SDL_WINDOWPOS_UNDEFINED_DISPLAY(self): - undef_mask = video.SDL_WINDOWPOS_UNDEFINED_MASK - for x in range(0xFFFF): - undef = video.SDL_WINDOWPOS_UNDEFINED_DISPLAY(x) - assert undef_mask | x == undef - assert (undef & undef_mask) == undef_mask - assert undef != video.SDL_WINDOWPOS_CENTERED_DISPLAY(x) - - def test_SDL_WINDOWPOS_ISUNDEFINED(self): - assert video.SDL_WINDOWPOS_ISUNDEFINED(video.SDL_WINDOWPOS_UNDEFINED) - assert not video.SDL_WINDOWPOS_ISUNDEFINED(video.SDL_WINDOWPOS_CENTERED) - for x in range(0xFFFF): - undef = video.SDL_WINDOWPOS_UNDEFINED_DISPLAY(x) - assert video.SDL_WINDOWPOS_ISUNDEFINED(undef) - - def test_SDL_WINDOWPOS_CENTERED_DISPLAY(self): - centered_mask = video.SDL_WINDOWPOS_CENTERED_MASK - for x in range(0xFFFF): - centered = video.SDL_WINDOWPOS_CENTERED_DISPLAY(x) - assert centered_mask | x == centered - assert (centered & centered_mask) == centered_mask - assert centered != video.SDL_WINDOWPOS_UNDEFINED_DISPLAY(x) - - def test_SDL_WINDOWPOS_ISCENTERED(self): - assert video.SDL_WINDOWPOS_ISCENTERED(video.SDL_WINDOWPOS_CENTERED) - assert not video.SDL_WINDOWPOS_ISCENTERED(video.SDL_WINDOWPOS_UNDEFINED) - for x in range(0xFFFF): - centered = video.SDL_WINDOWPOS_CENTERED_DISPLAY(x) - assert video.SDL_WINDOWPOS_ISCENTERED(centered) - - def test_SDL_DisplayMode(self): +@pytest.fixture +def with_sdl_gl(with_sdl): + ret = video.SDL_GL_LoadLibrary(None) + assert SDL_GetError() == b"" + assert ret == 0 + yield + video.SDL_GL_UnloadLibrary() + +@pytest.fixture +def window(with_sdl): + flag = video.SDL_WINDOW_BORDERLESS + w = video.SDL_CreateWindow(b"Test", 10, 40, 12, 13, flag) + assert SDL_GetError() == b"" + assert isinstance(w.contents, video.SDL_Window) + yield w + video.SDL_DestroyWindow(w) + +@pytest.fixture +def decorated_window(with_sdl): + flag = video.SDL_WINDOW_RESIZABLE + w = video.SDL_CreateWindow(b"Test", 10, 40, 12, 13, flag) + assert SDL_GetError() == b"" + assert isinstance(w.contents, video.SDL_Window) + yield w + video.SDL_DestroyWindow(w) + +@pytest.fixture +def gl_window(with_sdl_gl): + flag = video.SDL_WINDOW_OPENGL + w = video.SDL_CreateWindow(b"OpenGL", 10, 40, 12, 13, flag) + assert SDL_GetError() == b"" + ctx = video.SDL_GL_CreateContext(w) + assert SDL_GetError() == b"" + yield (w, ctx) + video.SDL_GL_DeleteContext(ctx) + video.SDL_DestroyWindow(w) + + +# Test custom macros + +def test_SDL_WINDOWPOS_UNDEFINED_DISPLAY(): + undef_mask = video.SDL_WINDOWPOS_UNDEFINED_MASK + for x in range(0xFFFF): + undef = video.SDL_WINDOWPOS_UNDEFINED_DISPLAY(x) + assert undef_mask | x == undef + assert (undef & undef_mask) == undef_mask + assert undef != video.SDL_WINDOWPOS_CENTERED_DISPLAY(x) + +def test_SDL_WINDOWPOS_ISUNDEFINED(): + assert video.SDL_WINDOWPOS_ISUNDEFINED(video.SDL_WINDOWPOS_UNDEFINED) + assert not video.SDL_WINDOWPOS_ISUNDEFINED(video.SDL_WINDOWPOS_CENTERED) + for x in range(0xFFFF): + undef = video.SDL_WINDOWPOS_UNDEFINED_DISPLAY(x) + assert video.SDL_WINDOWPOS_ISUNDEFINED(undef) + +def test_SDL_WINDOWPOS_CENTERED_DISPLAY(): + centered_mask = video.SDL_WINDOWPOS_CENTERED_MASK + for x in range(0xFFFF): + centered = video.SDL_WINDOWPOS_CENTERED_DISPLAY(x) + assert centered_mask | x == centered + assert (centered & centered_mask) == centered_mask + assert centered != video.SDL_WINDOWPOS_UNDEFINED_DISPLAY(x) + +def test_SDL_WINDOWPOS_ISCENTERED(): + assert video.SDL_WINDOWPOS_ISCENTERED(video.SDL_WINDOWPOS_CENTERED) + assert not video.SDL_WINDOWPOS_ISCENTERED(video.SDL_WINDOWPOS_UNDEFINED) + for x in range(0xFFFF): + centered = video.SDL_WINDOWPOS_CENTERED_DISPLAY(x) + assert video.SDL_WINDOWPOS_ISCENTERED(centered) + + +# Test structures and classes + +def test_SDL_Window(): + window = video.SDL_Window() + assert isinstance(window, video.SDL_Window) + + +class TestSDLDisplayMode(object): + + def test_init(self): mode = video.SDL_DisplayMode() assert isinstance(mode, video.SDL_DisplayMode) - for fmt in range(0, 10): - for w in range(0, 20): - for h in range(0, 30): - for r in range(0, 40): - mode = video.SDL_DisplayMode(fmt, w, h, r) - assert isinstance(mode, video.SDL_DisplayMode) - assert mode.format == fmt - assert mode.w == w - assert mode.h == h - assert mode.refresh_rate == r + fmt = sdl2.SDL_PIXELFORMAT_ARGB8888 + mode = video.SDL_DisplayMode(fmt, 800, 600, 60) + assert isinstance(mode, video.SDL_DisplayMode) + assert mode.format == fmt + assert mode.w == 800 + assert mode.h == 600 + assert mode.refresh_rate == 60 + # Test exceptions on bad input with pytest.raises(TypeError): video.SDL_DisplayMode("Test") with pytest.raises(TypeError): - video.SDL_DisplayMode("Test", 10, 10, 10) - with pytest.raises(TypeError): - video.SDL_DisplayMode(10, "Test", 10, 10) - with pytest.raises(TypeError): - video.SDL_DisplayMode(10, 10, "Test", 10) - with pytest.raises(TypeError): - video.SDL_DisplayMode(10, 10, 10, "Test") - with pytest.raises(TypeError): - video.SDL_DisplayMode(None) - with pytest.raises(TypeError): - video.SDL_DisplayMode(None, 10, 10, 10) - with pytest.raises(TypeError): - video.SDL_DisplayMode(10, None, 10, 10) - with pytest.raises(TypeError): - video.SDL_DisplayMode(10, 10, None, 10) + video.SDL_DisplayMode(10, 10.6, 10, 10) with pytest.raises(TypeError): video.SDL_DisplayMode(10, 10, 10, None) - def test_SDL_DisplayMode__eq__(self): + def test___eq__(self): DMode = video.SDL_DisplayMode assert DMode() == DMode() assert DMode(10, 0, 0, 0) == DMode(10, 0, 0, 0) @@ -125,7 +156,7 @@ def test_SDL_DisplayMode__eq__(self): assert not (DMode(10, 0, 0, 0) == DMode(0, 0, 10, 0)) assert not (DMode(10, 0, 0, 0) == DMode(0, 0, 0, 10)) - def test_SDL_DisplayMode__ne__(self): + def test___ne__(self): DMode = video.SDL_DisplayMode assert not (DMode() != DMode()) assert not (DMode(10, 0, 0, 0) != DMode(10, 0, 0, 0)) @@ -142,901 +173,736 @@ def test_SDL_DisplayMode__ne__(self): assert DMode(10, 0, 0, 0) != DMode(0, 0, 10, 0) assert DMode(10, 0, 0, 0) != DMode(0, 0, 0, 10) - def test_SDL_Window(self): - window = video.SDL_Window() - assert isinstance(window, video.SDL_Window) - - def test_SDL_GetNumVideoDrivers(self): - numdrivers = video.SDL_GetNumVideoDrivers() - assert numdrivers >= 1 - - def test_SDL_GetVideoDriver(self): - numdrivers = video.SDL_GetNumVideoDrivers() - for i in range(numdrivers): - name = video.SDL_GetVideoDriver(i) - assert type(name) in (str, bytes) - - def test_SDL_GetCurrentVideoDriver(self): - curdriver = video.SDL_GetCurrentVideoDriver() - found = False - numdrivers = video.SDL_GetNumVideoDrivers() - for i in range(numdrivers): - name = video.SDL_GetVideoDriver(i) - if name == curdriver: - found = True - break - assert found, "Current video driver not found" - - def test_SDL_GetNumVideoDisplays(self): - numdisplays = video.SDL_GetNumVideoDisplays() - assert numdisplays >= 1 - - def test_SDL_GetNumDisplayModes(self): - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - modes = video.SDL_GetNumDisplayModes(index) - assert modes >= 1 - - def test_SDL_GetDisplayMode(self): - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - modes = video.SDL_GetNumDisplayModes(index) - for mode in range(modes): - dmode = video.SDL_DisplayMode() - ret = video.SDL_GetDisplayMode(index, mode, byref(dmode)) - assert ret == 0 - - def test_SDL_GetCurrentDisplayMode(self): - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - dmode = video.SDL_DisplayMode() - ret = video.SDL_GetCurrentDisplayMode(index, byref(dmode)) - assert ret == 0 - - def test_SDL_GetDesktopDisplayMode(self): - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - dmode = video.SDL_DisplayMode() - ret = video.SDL_GetDesktopDisplayMode(index, byref(dmode)) - assert ret == 0 - def test_SDL_GetClosestDisplayMode(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support closest display modes") - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - modes = video.SDL_GetNumDisplayModes(index) - dmode = video.SDL_DisplayMode() - for mode in range(modes): - ret = video.SDL_GetDisplayMode(index, mode, byref(dmode)) - #self.assertIsInstance(dmode.contents, video.SDL_DisplayMode) - assert ret == 0 - cmode = video.SDL_DisplayMode(dmode.format, - dmode.w - 1, dmode.h - 1, - dmode.refresh_rate) - closest = video.SDL_DisplayMode() - video.SDL_GetClosestDisplayMode(index, cmode, byref(closest)) - assert closest == dmode, SDL_GetError() - - def test_SDL_VideoInit(self): - video.SDL_VideoInit(None) - video.SDL_VideoInit(None) - video.SDL_VideoInit(None) - video.SDL_VideoQuit(None) - video.SDL_VideoInit(None) - - def test_SDL_VideoQuit(self): - video.SDL_VideoQuit() - video.SDL_VideoQuit() - video.SDL_VideoQuit() - video.SDL_VideoInit(None) - - def test_SDL_GetDisplayName(self): - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - name = video.SDL_GetDisplayName(index) - assert name != None - - def test_SDL_GetDisplayBounds(self): - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - bounds = rect.SDL_Rect() - ret = video.SDL_GetDisplayBounds(index, byref(bounds)) - assert ret == 0 - assert not rect.SDL_RectEmpty(bounds) - - @pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") - def test_SDL_GetDisplayOrientation(self): - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - orientation = video.SDL_GetDisplayOrientation(index) - assert isinstance(orientation, int) - - def test_GetDisplayInfo(self): - current = video.SDL_GetCurrentVideoDriver().decode('utf-8') - print("Available Video Drivers:") - for i in range(video.SDL_GetNumVideoDrivers()): - name = video.SDL_GetVideoDriver(i).decode('utf-8') - if name == current: - name += " (*)" - print(" - " + name) - print("") - print("Detected Displays:") - for i in range(video.SDL_GetNumVideoDisplays()): - name = video.SDL_GetDisplayName(i).decode('utf-8') - info = " - " + name - dm = video.SDL_DisplayMode() - ret = video.SDL_GetDesktopDisplayMode(i, byref(dm)) - if ret == 0: - res = " ({0}x{1} @ {2}Hz)".format(dm.w, dm.h, dm.refresh_rate) - info += res - print(info) - - def test_screensaver(self): - initial = video.SDL_IsScreenSaverEnabled() - assert initial in (SDL_FALSE, SDL_TRUE) - - video.SDL_EnableScreenSaver() - assert video.SDL_IsScreenSaverEnabled() == SDL_TRUE - video.SDL_EnableScreenSaver() - assert video.SDL_IsScreenSaverEnabled() == SDL_TRUE - video.SDL_DisableScreenSaver() - assert video.SDL_IsScreenSaverEnabled() == SDL_FALSE - video.SDL_DisableScreenSaver() - assert video.SDL_IsScreenSaverEnabled() == SDL_FALSE - video.SDL_EnableScreenSaver() - assert video.SDL_IsScreenSaverEnabled() == SDL_TRUE - video.SDL_DisableScreenSaver() - assert video.SDL_IsScreenSaverEnabled() == SDL_FALSE - - if initial == SDL_TRUE: - video.SDL_EnableScreenSaver() - else: - video.SDL_DisableScreenSaver() - - def test_SDL_CreateWindow(self): - # Borderless to ensure that the size check works - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 40, 12, 13, flag) - assert isinstance(window.contents, video.SDL_Window) - px, py = c_int(), c_int() - video.SDL_GetWindowPosition(window, byref(px), byref(py)) - assert (px.value, py.value) == (10, 40) - video.SDL_GetWindowSize(window, byref(px), byref(py)) - assert (px.value, py.value) == (12, 13) - assert video.SDL_GetWindowFlags(window) & flag == flag - assert video.SDL_GetWindowTitle(window) == b"Test" - video.SDL_DestroyWindow(window) - # TODO - - def test_SDL_DestroyWindow(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flag) - # TODO: how to check for this in a meaningful way? - video.SDL_DestroyWindow(window) - - @pytest.mark.skip("not implemented") - def test_SDL_CreateWindowFrom(self): - pass - - def test_SDL_GetWindowDisplayIndex(self): - numdisplays = video.SDL_GetNumVideoDisplays() - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 40, 12, 13, flag) - assert isinstance(window.contents, video.SDL_Window) - px, py = c_int(), c_int() - video.SDL_GetWindowPosition(window, byref(px), byref(py)) - assert (px.value, py.value) == (10, 40) - video.SDL_GetWindowSize(window, byref(px), byref(py)) - assert (px.value, py.value) == (12, 13) - assert video.SDL_GetWindowFlags(window) & flag == flag - assert video.SDL_GetWindowTitle(window) == b"Test" - - dindex = video.SDL_GetWindowDisplayIndex(window) - assert 0 <= dindex <= numdisplays, "Invalid display index" - video.SDL_DestroyWindow(window) - # self.assertRaises(sdl.SDLError, video.SDL_GetWindowDisplay, - # window) - - def test_SDL_GetWindowDisplayMode(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flag) - dmode = video.SDL_DisplayMode() - ret = video.SDL_GetWindowDisplayMode(window, byref(dmode)) - assert ret == 0 - video.SDL_DestroyWindow(window) - # self.assertRaises(sdl.SDLError, video.SDL_GetWindowDisplayMode, - # window) - - def test_SDL_SetWindowDisplayMode(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flag) - dindex = video.SDL_GetWindowDisplayIndex(window) +# Test module SDL functions + +def test_SDL_VideoInitQuit(): + # Test with default driver + assert sdl2.SDL_WasInit(0) & sdl2.SDL_INIT_VIDEO != sdl2.SDL_INIT_VIDEO + ret = video.SDL_VideoInit(None) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + assert video.SDL_GetCurrentVideoDriver() # If initialized, should be string + video.SDL_VideoQuit() + assert not video.SDL_GetCurrentVideoDriver() + # TODO: Test with string input (fails with b"dummy" for some reason?) + +def test_SDL_GetNumVideoDrivers(with_sdl): + numdrivers = video.SDL_GetNumVideoDrivers() + assert numdrivers >= 1 + +def test_SDL_GetVideoDriver(with_sdl): + numdrivers = video.SDL_GetNumVideoDrivers() + for i in range(numdrivers): + name = video.SDL_GetVideoDriver(i) + assert type(name) in (str, bytes) + +def test_SDL_GetCurrentVideoDriver(with_sdl): + curdriver = video.SDL_GetCurrentVideoDriver() + numdrivers = video.SDL_GetNumVideoDrivers() + drivers = [] + for i in range(numdrivers): + drivers.append(video.SDL_GetVideoDriver(i)) + assert curdriver in drivers + +def test_SDL_GetNumVideoDisplays(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + assert numdisplays >= 1 + +def test_SDL_GetNumDisplayModes(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + modes = video.SDL_GetNumDisplayModes(index) + assert modes >= 1 + +def test_SDL_GetDisplayMode(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + modes = video.SDL_GetNumDisplayModes(index) + for mode in range(modes): dmode = video.SDL_DisplayMode() - - ret = video.SDL_GetCurrentDisplayMode(dindex, byref(dmode)) - assert ret == 0 - - video.SDL_SetWindowDisplayMode(window, dmode) - wmode = video.SDL_DisplayMode() - ret = video.SDL_GetWindowDisplayMode(window, byref(wmode)) + ret = video.SDL_GetDisplayMode(index, mode, byref(dmode)) + assert sdl2.SDL_GetError() == b"" assert ret == 0 - # TODO: refresh rates differ - #self.assertEqual(dmode, wmode) - - video.SDL_DestroyWindow(window) - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_GetWindowICCProfile(self): - flags = video.SDL_WINDOW_BORDERLESS - prof_size = ctypes.c_size_t(0) - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flags) - prof_ptr = video.SDL_GetWindowICCProfile(window, byref(prof_size)) - # This function returns a void pointer to the loaded ICC profile, which - # needs to be cast to bytes to be read. As per the ICC spec, bytes - # 36 to 39 of the header should always be 'acsp' in ASCII. - if prof_size.value > 0: - prof = ctypes.cast(prof_ptr, ctypes.POINTER(c_ubyte)) - assert bytes(prof[36:40]) == b"acsp" - video.SDL_DestroyWindow(window) - - def test_SDL_GetWindowPixelFormat(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flag) - fmt = video.SDL_GetWindowPixelFormat(window) - assert type(fmt) in(int, long) - video.SDL_DestroyWindow(window) - - def test_SDL_GetWindowID(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flag) - assert video.SDL_GetWindowID(window) >= 0 - - video.SDL_DestroyWindow(window) - #self.assertRaises(sdl.SDLError, video.SDL_GetWindowID, window) - - def test_SDL_GetWindowFromID(self): - get_id = video.SDL_GetWindowID - get_title = video.SDL_GetWindowTitle - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flag) - window2 = video.SDL_GetWindowFromID(video.SDL_GetWindowID(window)) - assert get_id(window) == get_id(window2) - assert get_title(window) == get_title(window2) - px1, py1, px2, py2 = c_int(0), c_int(0), c_int(0), c_int(0) - video.SDL_GetWindowPosition(window, byref(px1), byref(py1)) - video.SDL_GetWindowPosition(window2, byref(px2), byref(py2)) - assert (px1.value, py1.value) == (px2.value, py2.value) - video.SDL_GetWindowSize(window, byref(px1), byref(py1)) - video.SDL_GetWindowSize(window2, byref(px2), byref(py2)) - assert (px1.value, py1.value) == (px2.value, py2.value) - - def test_SDL_GetWindowFlags(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flag) - wflags = video.SDL_GetWindowFlags(window) - assert (wflags & flag) == flag - - def test_SDL_GetSetWindowTitle(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, 0) - assert video.SDL_GetWindowTitle(window) == b"Test" - video.SDL_SetWindowTitle(window, b"Hello there") - assert video.SDL_GetWindowTitle(window) == b"Hello there" - video.SDL_DestroyWindow(window) - #self.assertRaises(sdl.SDLError, video.SDL_GetWindowTitle, window) - - def test_SDL_SetWindowIcon(self): - sf = surface.SDL_CreateRGBSurface(0, 16, 16, 16, 0xF000, 0x0F00, - 0x00F0, 0x000F) - assert isinstance(sf.contents, surface.SDL_Surface) - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, 0) - video.SDL_SetWindowIcon(window, sf) - - # self.assertRaises((AttributeError, TypeError), - # video.SDL_SetWindowIcon, None, None) - # self.assertRaises((AttributeError, TypeError), - # video.SDL_SetWindowIcon, window, None) - # self.assertRaises((AttributeError, TypeError), - # video.SDL_SetWindowIcon, None, sf) - # self.assertRaises((AttributeError, TypeError), - # video.SDL_SetWindowIcon, window, "Test") - # self.assertRaises((AttributeError, TypeError), - # video.SDL_SetWindowIcon, window, 123456) - - @pytest.mark.skipif(hasattr(sys, "pypy_version_info"), - reason="PyPy can't create proper py_object() values") - def test_SDL_GetSetWindowData(self): - # TODO: fix this - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, 0) - assert isinstance(window.contents, video.SDL_Window) - values = {b"text": py_object("Teststring"), - b"object": py_object(self), - b"list": py_object([1, 2, 3, 4]), - b"tuple": py_object(("a", 1, self)) - } - - for k, v in values.items(): - retval = video.SDL_GetWindowData(window, k) - assert not retval - video.SDL_SetWindowData(window, k, v) - retval = video.SDL_GetWindowData(window, k) - assert retval.contents.value == v.value - video.SDL_DestroyWindow(window) - - def test_SDL_GetSetWindowPosition(self): - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, 0) - px, py = c_int(0), c_int(0) - video.SDL_GetWindowPosition(window, byref(px), byref(py)) - assert (px.value, py.value) == (10, 10) - video.SDL_SetWindowPosition(window, 0, 0) - video.SDL_GetWindowPosition(window, byref(px), byref(py)) - assert (px.value, py.value) == (0, 0) - video.SDL_SetWindowPosition(window, 600, 900) - video.SDL_GetWindowPosition(window, byref(px), byref(py)) - assert (px.value, py.value) == (600, 900) - video.SDL_DestroyWindow(window) - - def test_SDL_GetSetWindowSize(self): - flags = video.SDL_WINDOW_BORDERLESS - window = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flags) - sx, sy = c_int(), c_int() - video.SDL_GetWindowSize(window, byref(sx), byref(sy)) - assert (sx.value, sy.value) == (10, 10) - video.SDL_SetWindowSize(window, 1, 1) - video.SDL_GetWindowSize(window, byref(sx), byref(sy)) - assert (sx.value, sy.value) == (1, 1) - video.SDL_SetWindowSize(window, 600, 900) - video.SDL_GetWindowSize(window, byref(sx), byref(sy)) - assert (sx.value, sy.value) == (600, 900) - video.SDL_SetWindowSize(window, -200, -10) - video.SDL_GetWindowSize(window, byref(sx), byref(sy)) - assert (sx.value, sy.value) == (600, 900) - video.SDL_DestroyWindow(window) - -# @interactive("Was the window shown?") -# def test_SDL_ShowWindow(self): -# window = video.SDL_CreateWindow(b"test_SDL_ShowWindow", -# 200, 200, 200, 200, 0) -# video.SDL_ShowWindow(window) -# doprint("""Please check, if a window with the title -# 'test_SDL_ShowWindow' is shown""") -# video.SDL_DestroyWindow(window) - -# @interactive("Did the window vanish from your sight and pop up again?") -# def test_SDL_HideWindow(self): -# window = video.SDL_CreateWindow(b"test_SDL_HideWindow", -# 200, 200, 200, 200, 0) -# video.SDL_ShowWindow(window) -# doprint("""Please check, if a window with the title -# 'test_SDL_HideWindow' is shown""") -# video.SDL_HideWindow(window) -# doprint("Please check, that the window is not shown anymore") -# video.SDL_ShowWindow(window) -# doprint("Please check, if the window is shown again") -# video.SDL_DestroyWindow(window) - -# @interactive("Did the window raise properly?") -# def test_SDL_RaiseWindow(self): -# window = video.SDL_CreateWindow(b"test_SDL_RaiseWindow", -# 200, 200, 200, 200, 0) -# video.SDL_ShowWindow(window) -# doprint("""Please check, that a window with the title -# 'test_SDL_RaiseWindow' is shown""") -# doprint("Move another window on top of the window, so it is hidden") -# video.SDL_RaiseWindow(window) -# doprint("The window should be raised to the foreground now") -# video.SDL_DestroyWindow(window) - -# @interactive("Was the window maximized?") -# def test_SDL_MaximizeWindow(self): -# window = video.SDL_CreateWindow(b"test_SDL_MaximizeWindow", 200, 200, -# 200, 200, video.SDL_WINDOW_RESIZABLE) -# video.SDL_ShowWindow(window) -# doprint("""Please check, that a window with the title -# 'test_SDL_MaximizeWindow' is shown""") -# video.SDL_MaximizeWindow(window) -# doprint("Please check, if the window was maximized properly") -# video.SDL_DestroyWindow(window) - -# @interactive("Was the window minimized?") -# def test_SDL_MinimizeWindow(self): -# window = video.SDL_CreateWindow(b"test_SDL_MinimizeWindow", 200, 200, -# 200, 200, 0) -# video.SDL_ShowWindow(window) -# doprint("""Please check, that a window with the title -# 'test_SDL_MinimizeWindow' is shown""") -# video.SDL_MinimizeWindow(window) -# doprint("Please check, if the window was minimized properly") -# video.SDL_DestroyWindow(window) - -# @interactive("Was the window maximized and restored properly?") -# def test_SDL_RestoreWindow(self): -# window = video.SDL_CreateWindow(b"test_SDL_RestoreWindow", 200, 200, -# 200, 200, video.SDL_WINDOW_RESIZABLE) -# video.SDL_ShowWindow(window) -# doprint("""Please check, that a window with the title -# 'test_SDL_RestoreWindow' is shown""") -# video.SDL_MaximizeWindow(window) -# doprint("Please check, if the window was maximized properly") -# video.SDL_RestoreWindow(window) -# doprint("Please check, if the window was restored properly") -# video.SDL_DestroyWindow(window) - - def test_SDL_SetWindowFullscreen(self): - # TODO: HIDDEN avoids flickering, but is this really a sufficient test? - flags = (video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_MINIMIZED | - video.SDL_WINDOW_HIDDEN) - is_fullscreen = video.SDL_WINDOW_FULLSCREEN - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 0, 0, 1024, 768, flag) - video.SDL_SetWindowFullscreen(window, True) - flags = video.SDL_GetWindowFlags(window) - assert flags & is_fullscreen == is_fullscreen - video.SDL_SetWindowFullscreen(window, False) - flags = video.SDL_GetWindowFlags(window) - assert flags & is_fullscreen != is_fullscreen - video.SDL_DestroyWindow(window) - - def test_SDL_GetWindowSurface(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_MINIMIZED) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flag) - sf = video.SDL_GetWindowSurface(window) - assert isinstance(sf.contents, surface.SDL_Surface) - video.SDL_DestroyWindow(window) - # self.assertRaises(sdl.SDLError, video.SDL_GetWindowSurface, - # window) - - def test_SDL_UpdateWindowSurface(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_MINIMIZED) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flag) - video.SDL_UpdateWindowSurface(window) - video.SDL_DestroyWindow(window) - - def test_SDL_UpdateWindowSurfaceRects(self): - rectlist = (rect.SDL_Rect * 4)(rect.SDL_Rect(), - rect.SDL_Rect(10, 10, 10, 10), - rect.SDL_Rect(0, 0, 5, 4), - rect.SDL_Rect(-5, -5, 6, 2)) - rptr = cast(rectlist, POINTER(rect.SDL_Rect)) - - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_MINIMIZED) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flag) - # self.assertRaises(sdl.SDLError, - # video.SDL_UpdateWindowSurfaceRects, - # window, rectlist) - sf = surface.SDL_Surface() - video.SDL_GetWindowSurface(window, byref(sf)) - ret = video.SDL_UpdateWindowSurfaceRects(window, rptr, 4) - assert ret == 0 - video.SDL_DestroyWindow(window) - - @pytest.mark.skip("Test doesn't work, may need to be interactive") - def test_SDL_GetSetWindowGrab(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_MINIMIZED) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flag) - assert video.SDL_GetWindowGrab(window) == SDL_FALSE - video.SDL_SetWindowGrab(window, SDL_TRUE) - assert video.SDL_GetWindowGrab(window) == SDL_TRUE - video.SDL_SetWindowGrab(window, SDL_FALSE) - assert video.SDL_GetWindowGrab(window) == SDL_FALSE - video.SDL_DestroyWindow(window) - - @pytest.mark.skip("Test doesn't work, may need to be interactive") - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_GetSetWindowKeyboardGrab(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_MINIMIZED) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flag) - assert video.SDL_GetWindowKeyboardGrab(window) == SDL_FALSE - video.SDL_SetWindowKeyboardGrab(window, SDL_TRUE) - assert video.SDL_GetWindowKeyboardGrab(window) == SDL_TRUE - video.SDL_SetWindowKeyboardGrab(window, SDL_FALSE) - assert video.SDL_GetWindowKeyboardGrab(window) == SDL_FALSE - video.SDL_DestroyWindow(window) - - @pytest.mark.skip("Test doesn't work, may need to be interactive") - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_GetSetWindowMouseGrab(self): - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_MINIMIZED) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flag) - assert video.SDL_GetWindowMouseGrab(window) == SDL_FALSE - video.SDL_SetWindowMouseGrab(window, SDL_TRUE) - assert video.SDL_GetWindowMouseGrab(window) == SDL_TRUE - video.SDL_SetWindowMouseGrab(window, SDL_FALSE) - assert video.SDL_GetWindowMouseGrab(window) == SDL_FALSE - video.SDL_DestroyWindow(window) - - @pytest.mark.skip("not implemented") - def test_SDL_GetGrabbedWindow(self): - pass - - @pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") - def test_SDL_GetSetWindowMouseRect(self): - flags = video.SDL_WINDOW_BORDERLESS - bounds_in = rect.SDL_Rect(0, 0, 100, 50) - window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flags) - # Try setting a mouse boundary - ret = video.SDL_SetWindowMouseRect(window, byref(bounds_in)) - err = SDL_GetError() + if not DRIVER_DUMMY: + assert dmode.w > 0 + assert dmode.h > 0 + +def test_SDL_GetCurrentDisplayMode(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + dmode = video.SDL_DisplayMode() + ret = video.SDL_GetCurrentDisplayMode(index, byref(dmode)) + assert sdl2.SDL_GetError() == b"" assert ret == 0 - bounds_out = video.SDL_GetWindowMouseRect(window) - assert bounds_out != None - assert bounds_in == bounds_out.contents - # Try removing the boundary - ret = video.SDL_SetWindowMouseRect(window, None) - err = SDL_GetError() + assert dmode.w > 0 + assert dmode.h > 0 + +def test_SDL_GetDesktopDisplayMode(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + dmode = video.SDL_DisplayMode() + ret = video.SDL_GetDesktopDisplayMode(index, byref(dmode)) + assert sdl2.SDL_GetError() == b"" assert ret == 0 - bounds_out = video.SDL_GetWindowMouseRect(window) - assert not bounds_out # bounds_out should be null pointer - video.SDL_DestroyWindow(window) - - @pytest.mark.skipif(os.environ.get("APPVEYOR") == "True", - reason="Appveyor cannot set the brightness") - def test_SDL_GetSetWindowBrightness(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support brightness") - flags = (video.SDL_WINDOW_BORDERLESS, - video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, - video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_MINIMIZED) - for flag in flags: - window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flag) - orig = video.SDL_GetWindowBrightness(window) - assert isinstance(orig, float) - # Go from 0.0, 0.1 ... to 1.0 - gammas = (x * 0.1 for x in range(0, 10)) - count = 0 - for b in gammas: - ret = video.SDL_SetWindowBrightness(window, b) - if ret == 0: - val = video.SDL_GetWindowBrightness(window) - assert round(abs(val-b), 7) == 0 - count += 1 - assert count > 0 - video.SDL_DestroyWindow(window) - - @pytest.mark.skip("not implemented") - def test_SDL_SetWindowGammaRamp(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GetWindowGammaRamp(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_GetWindowGammaRamp(self): - pass - - @pytest.mark.skip("not implemented") - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_FlashWindow(self): - # Would need to be an interactive test - pass - - def test_SDL_GL_LoadUnloadLibrary(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - # Try the default library - assert video.SDL_GL_LoadLibrary(None) == 0, SDL_GetError() - video.SDL_GL_UnloadLibrary() - - if has_opengl_lib(): - fpath = get_opengl_path().encode("utf-8") - assert video.SDL_GL_LoadLibrary(fpath) == 0, SDL_GetError() - video.SDL_GL_UnloadLibrary() - - def test_SDL_GL_GetProcAddress(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - - if sys.platform != "darwin": - procaddr = video.SDL_GL_GetProcAddress(b"glGetString") - assert procaddr is None - - assert video.SDL_GL_LoadLibrary(None) == 0, SDL_GetError() - - # Behaviour is undefined as long as there is no window and context. - window = video.SDL_CreateWindow(b"OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_OPENGL) - - ctx = video.SDL_GL_CreateContext(window) - - procaddr = video.SDL_GL_GetProcAddress(b"glGetString") - assert procaddr is not None and int(procaddr) != 0 - - video.SDL_GL_DeleteContext(ctx) - video.SDL_DestroyWindow(window) - video.SDL_GL_UnloadLibrary() - - if sys.platform != "darwin": - procaddr = video.SDL_GL_GetProcAddress(b"glGetString") - assert procaddr is None - - def test_SDL_GL_ExtensionSupported(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - - assert not video.SDL_GL_ExtensionSupported(b"GL_EXT_bgra") - - assert video.SDL_GL_LoadLibrary(None) == 0, SDL_GetError() - window = video.SDL_CreateWindow(b"OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_OPENGL) - - ctx = video.SDL_GL_CreateContext(window) - - assert video.SDL_GL_ExtensionSupported(b"GL_EXT_bgra") - - video.SDL_GL_DeleteContext(ctx) - video.SDL_DestroyWindow(window) - video.SDL_GL_UnloadLibrary() - - assert not video.SDL_GL_ExtensionSupported(b"GL_EXT_bgra") - - def test_SDL_GL_GetSetAttribute(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - - assert video.SDL_GL_LoadLibrary(None) == 0, SDL_GetError() - - window = video.SDL_CreateWindow(b"OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_OPENGL) - - ctx = video.SDL_GL_CreateContext(window) - - depth = c_int() - video.SDL_GL_GetAttribute(video.SDL_GL_DEPTH_SIZE, byref(depth)) - - video.SDL_GL_DeleteContext(ctx) - video.SDL_DestroyWindow(window) - - newdepth = 24 - if depth == 8: - newdepth = 16 - elif depth == 16: - newdepth = 24 - elif depth == 24: - newdepth = 16 - video.SDL_GL_SetAttribute(video.SDL_GL_DEPTH_SIZE, newdepth) - - window = video.SDL_CreateWindow(b"OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_OPENGL) - ctx = video.SDL_GL_CreateContext(window) - - val = c_int() - video.SDL_GL_GetAttribute(video.SDL_GL_DEPTH_SIZE, byref(val)) - assert depth != val - assert val.value >= newdepth - # self.assertEqual(val.value, newdepth) - - video.SDL_GL_DeleteContext(ctx) - video.SDL_DestroyWindow(window) - video.SDL_GL_UnloadLibrary() - - def test_SDL_GL_CreateDeleteContext(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - - assert video.SDL_GL_LoadLibrary(None) == 0, SDL_GetError() - window = video.SDL_CreateWindow(b"OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_OPENGL) - - ctx = video.SDL_GL_CreateContext(window) - video.SDL_GL_DeleteContext(ctx) - video.SDL_DestroyWindow(window) - - window = video.SDL_CreateWindow(b"OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_OPENGL) - ctx = video.SDL_GL_CreateContext(window) - video.SDL_DestroyWindow(window) - video.SDL_GL_DeleteContext(ctx) - video.SDL_GL_UnloadLibrary() - - def test_SDL_GL_MakeCurrent(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - - assert video.SDL_GL_LoadLibrary(None) == 0, SDL_GetError() - window = video.SDL_CreateWindow(b"No OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_BORDERLESS) - ctx = video.SDL_GL_CreateContext(window) - video.SDL_GL_MakeCurrent(window, ctx) - video.SDL_GL_DeleteContext(ctx) - video.SDL_DestroyWindow(window) - video.SDL_GL_UnloadLibrary() - - def test_SDL_GL_GetSetSwapInterval(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - - - assert video.SDL_GL_LoadLibrary(None) == 0, SDL_GetError() - window = video.SDL_CreateWindow(b"OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_OPENGL) - ctx = video.SDL_GL_CreateContext(window) - video.SDL_GL_MakeCurrent(window, ctx) - - ret = video.SDL_GL_SetSwapInterval(0) - if ret == 0: - assert video.SDL_GL_GetSwapInterval() == 0 - ret = video.SDL_GL_SetSwapInterval(1) + assert dmode.w > 0 + assert dmode.h > 0 + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GetClosestDisplayMode(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + dmode = video.SDL_DisplayMode() + ret = video.SDL_GetCurrentDisplayMode(index, byref(dmode)) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + cmode = video.SDL_DisplayMode( + dmode.format, dmode.w - 1, dmode.h - 1, dmode.refresh_rate + ) + closest = video.SDL_DisplayMode() + video.SDL_GetClosestDisplayMode(index, cmode, byref(closest)) + assert closest == dmode + +def test_SDL_GetDisplayName(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + name = video.SDL_GetDisplayName(index) + assert type(name) in (str, bytes) + +def test_SDL_GetDisplayBounds(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + bounds = rect.SDL_Rect() + ret = video.SDL_GetDisplayBounds(index, byref(bounds)) + assert sdl2.SDL_GetError() == b"" + assert ret == 0 + assert bounds.w > 0 + assert bounds.h > 0 + assert not rect.SDL_RectEmpty(bounds) + +@pytest.mark.skipif(sdl2.dll.version < 2005, reason="not available") +def test_SDL_GetDisplayUsableBounds(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + bounds = rect.SDL_Rect() + ret = video.SDL_GetDisplayUsableBounds(index, byref(bounds)) + assert ret == 0 + assert not rect.SDL_RectEmpty(bounds) + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GetDisplayDPI(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + ddpi, hdpi, vdpi = c_float(0), c_float(0), c_float(0) + ret = video.SDL_GetDisplayDPI( + index, byref(ddpi), byref(hdpi), byref(vdpi) + ) + assert SDL_GetError() == b"" + assert ret == 0 + assert ddpi.value >= 96.0 + assert hdpi.value >= 96.0 + assert vdpi.value >= 96.0 + +@pytest.mark.skipif(sdl2.dll.version < 2009, reason="not available") +def test_SDL_GetDisplayOrientation(with_sdl): + numdisplays = video.SDL_GetNumVideoDisplays() + for index in range(numdisplays): + orientation = video.SDL_GetDisplayOrientation(index) + assert isinstance(orientation, int) + assert orientation >= 0 + +def test_GetDisplayInfo(with_sdl): + current = video.SDL_GetCurrentVideoDriver().decode('utf-8') + print("Available Video Drivers:") + for i in range(video.SDL_GetNumVideoDrivers()): + name = video.SDL_GetVideoDriver(i).decode('utf-8') + if name == current: + name += " (*)" + print(" - " + name) + print("") + print("Detected Displays:") + for i in range(video.SDL_GetNumVideoDisplays()): + name = video.SDL_GetDisplayName(i).decode('utf-8') + info = " - " + name + dm = video.SDL_DisplayMode() + ret = video.SDL_GetDesktopDisplayMode(i, byref(dm)) if ret == 0: - assert video.SDL_GL_GetSwapInterval() == 1 - - video.SDL_GL_DeleteContext(ctx) - video.SDL_DestroyWindow(window) - video.SDL_GL_UnloadLibrary() - - def test_SDL_GL_SwapWindow(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - - assert video.SDL_GL_LoadLibrary(None) == 0, SDL_GetError() - window = video.SDL_CreateWindow(b"OpenGL", 10, 10, 10, 10, - video.SDL_WINDOW_OPENGL) - ctx = video.SDL_GL_CreateContext(window) - video.SDL_GL_MakeCurrent(window, ctx) - video.SDL_GL_SwapWindow(window) - video.SDL_GL_SwapWindow(window) - video.SDL_GL_SwapWindow(window) - video.SDL_GL_SwapWindow(window) - video.SDL_GL_DeleteContext(ctx) - video.SDL_DestroyWindow(window) - video.SDL_GL_UnloadLibrary() - - @pytest.mark.skip("not implemented") - def test_SDL_GL_ResetAttributes(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support GL loading") - - pass - - def test_SDL_GetDisplayDPI(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support display DPI") - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - ddpi, hdpi, vdpi = c_float(), c_float(), c_float() - ret = video.SDL_GetDisplayDPI(index, byref(ddpi), byref(hdpi), - byref(vdpi)) - assert ret == 0, SDL_GetError() - assert ddpi.value >= 96.0 - assert hdpi.value >= 96.0 - assert vdpi.value >= 96.0 - - def test_SDL_SetWindowResizable(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support resizable flags") - window = video.SDL_CreateWindow(b"Resizable", 10, 10, 10, 10, - video.SDL_WINDOW_RESIZABLE) - flags = video.SDL_GetWindowFlags(window) - assert flags & video.SDL_WINDOW_RESIZABLE == video.SDL_WINDOW_RESIZABLE - video.SDL_SetWindowResizable(window, SDL_FALSE) - flags = video.SDL_GetWindowFlags(window) - assert flags & video.SDL_WINDOW_RESIZABLE != video.SDL_WINDOW_RESIZABLE - video.SDL_SetWindowResizable(window, SDL_TRUE) - flags = video.SDL_GetWindowFlags(window) - assert flags & video.SDL_WINDOW_RESIZABLE == video.SDL_WINDOW_RESIZABLE - video.SDL_DestroyWindow(window) + res = " ({0}x{1} @ {2}Hz)".format(dm.w, dm.h, dm.refresh_rate) + info += res + print(info) + +def test_SDL_CreateDestroyWindow(with_sdl): + flag = video.SDL_WINDOW_BORDERLESS + window = video.SDL_CreateWindow(b"Test", 10, 40, 12, 13, flag) + assert SDL_GetError() == b"" + assert isinstance(window.contents, video.SDL_Window) + video.SDL_DestroyWindow(window) + +@pytest.mark.skip("not implemented") +def test_SDL_CreateWindowFrom(with_sdl): + # No obvious cross-platform way to test this + pass + +def test_SDL_GetWindowDisplayIndex(window): + numdisplays = video.SDL_GetNumVideoDisplays() + dindex = video.SDL_GetWindowDisplayIndex(window) + # Make sure display index is valid + assert 0 <= dindex <= numdisplays + +def test_SDL_GetWindowDisplayMode(window): + # NOTE: Gets fullscreen mode of parent display, not size of window + dmode = video.SDL_DisplayMode() + ret = video.SDL_GetWindowDisplayMode(window, byref(dmode)) + assert SDL_GetError() == b"" + assert ret == 0 + assert dmode.w > 0 + assert dmode.h > 0 + +def test_SDL_SetWindowDisplayMode(window): + # NOTE: Sets the fullscreen mode of the window, so can't easily test + # NOTE: If set mode not supported, will change to closest supported res + dindex = video.SDL_GetWindowDisplayIndex(window) + dmode = video.SDL_DisplayMode() + ret = video.SDL_GetCurrentDisplayMode(dindex, byref(dmode)) + assert ret == 0 + video.SDL_SetWindowDisplayMode(window, dmode) + wmode = video.SDL_DisplayMode() + ret = video.SDL_GetWindowDisplayMode(window, byref(wmode)) + assert SDL_GetError() == b"" + assert ret == 0 + assert dmode == wmode + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_GetWindowICCProfile(window): + prof_size = ctypes.c_size_t(0) + prof_ptr = video.SDL_GetWindowICCProfile(window, byref(prof_size)) + # This function returns a void pointer to the loaded ICC profile, which + # needs to be cast to bytes to be read. As per the ICC spec, bytes + # 36 to 39 of the header should always be 'acsp' in ASCII. + if prof_size.value > 0: + prof = ctypes.cast(prof_ptr, ctypes.POINTER(c_ubyte)) + assert bytes(prof[36:40]) == b"acsp" + +def test_SDL_GetWindowPixelFormat(window): + fmt = video.SDL_GetWindowPixelFormat(window) + assert fmt in sdl2.ALL_PIXELFORMATS + +def test_SDL_GetWindowID(window): + assert video.SDL_GetWindowID(window) >= 0 + +def test_SDL_GetWindowFromID(window): + window2 = video.SDL_GetWindowFromID(video.SDL_GetWindowID(window)) + assert video.SDL_GetWindowID(window) == video.SDL_GetWindowID(window2) + assert video.SDL_GetWindowTitle(window) == video.SDL_GetWindowTitle(window2) + # Make sure sizes/positions are the same + px1, py1, px2, py2 = c_int(0), c_int(0), c_int(0), c_int(0) + video.SDL_GetWindowPosition(window, byref(px1), byref(py1)) + video.SDL_GetWindowPosition(window2, byref(px2), byref(py2)) + assert (px1.value, py1.value) == (px2.value, py2.value) + video.SDL_GetWindowSize(window, byref(px1), byref(py1)) + video.SDL_GetWindowSize(window2, byref(px2), byref(py2)) + assert (px1.value, py1.value) == (px2.value, py2.value) + +def test_SDL_GetWindowFlags(with_sdl): + flags = ( + video.SDL_WINDOW_BORDERLESS, + video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, + video.SDL_WINDOW_RESIZABLE + ) + for flag in flags: + win = video.SDL_CreateWindow(b"Test", 10, 10, 10, 10, flag) + wflags = video.SDL_GetWindowFlags(win) + assert (wflags & flag) == flag + video.SDL_DestroyWindow(win) + +def test_SDL_GetSetWindowTitle(window): + assert video.SDL_GetWindowTitle(window) == b"Test" + video.SDL_SetWindowTitle(window, b"Hello there") + assert video.SDL_GetWindowTitle(window) == b"Hello there" + +def test_SDL_SetWindowIcon(window): + sf = surface.SDL_CreateRGBSurface( + 0, 16, 16, 16, 0xF000, 0x0F00, 0x00F0, 0x000F + ) + assert isinstance(sf.contents, surface.SDL_Surface) + video.SDL_SetWindowIcon(window, sf) + assert SDL_GetError() == b"" + +@pytest.mark.xfail(is_pypy, reason="PyPy can't create proper py_object values") +def test_SDL_GetSetWindowData(window): + values = { + b"text": py_object("Teststring"), + b"list": py_object([1, 2, "a", "b"]), + b"tuple": py_object((1, 2, 3)), + } + for k, v in values.items(): + video.SDL_SetWindowData(window, k, v) + retval = video.SDL_GetWindowData(window, k) + assert retval.contents.value == v.value + +@pytest.mark.xfail(DRIVER_X11, reason="Wonky with some window managers") +def test_SDL_GetSetWindowPosition(with_sdl): + window = video.SDL_CreateWindow(b"Test", 10, 200, 10, 10, 0) + px, py = c_int(0), c_int(0) + video.SDL_GetWindowPosition(window, byref(px), byref(py)) + assert (px.value, py.value) == (10, 200) + video.SDL_SetWindowPosition(window, 0, 150) + video.SDL_GetWindowPosition(window, byref(px), byref(py)) + assert (px.value, py.value) == (0, 150) + video.SDL_SetWindowPosition(window, 480, 320) + video.SDL_GetWindowPosition(window, byref(px), byref(py)) + assert (px.value, py.value) == (480, 320) + video.SDL_DestroyWindow(window) + +def test_SDL_GetSetWindowSize(window): + sx, sy = c_int(0), c_int(0) + video.SDL_GetWindowSize(window, byref(sx), byref(sy)) + assert (sx.value, sy.value) == (12, 13) + video.SDL_SetWindowSize(window, 1, 1) + video.SDL_GetWindowSize(window, byref(sx), byref(sy)) + assert (sx.value, sy.value) == (1, 1) + video.SDL_SetWindowSize(window, 480, 320) + video.SDL_GetWindowSize(window, byref(sx), byref(sy)) + assert (sx.value, sy.value) == (480, 320) + # Test that negative sizes are ignored + video.SDL_SetWindowSize(window, -200, -10) + video.SDL_GetWindowSize(window, byref(sx), byref(sy)) + assert (sx.value, sy.value) == (480, 320) + +def test_SDL_GetWindowBordersSize(window, decorated_window): + # Currently, only X11 and Windows video drivers support border size + supports_borders = video.SDL_GetCurrentVideoDriver() in [b"x11", b"windows"] + # For a decorated window, make sure all borders are >= 0 + video.SDL_ShowWindow(decorated_window) + t, l, b, r = c_int(), c_int(), c_int(), c_int() + ret = video.SDL_GetWindowBordersSize( + decorated_window, byref(t), byref(l), byref(b), byref(r) + ) + values = [x.value for x in (t, l, b, r)] + assert all([v >= 0 for v in values]) + if supports_borders: + assert ret == 0 + # Test again with a borderless window & make sure borders are all 0 + video.SDL_ShowWindow(window) + ret = video.SDL_GetWindowBordersSize( + window, byref(t), byref(l), byref(b), byref(r) + ) + values = [x.value for x in (t, l, b, r)] + assert all([v == 0 for v in values]) + if supports_borders: + assert ret == 0 - @pytest.mark.skip("Test doesn't work, may need to be interactive") - @pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") - def test_SDL_SetWindowAlwaysOnTop(self): - ON_TOP_FLAG = video.SDL_WINDOW_ALWAYS_ON_TOP - window = video.SDL_CreateWindow(b"Always On Top", 10, 10, 10, 10, - video.SDL_WINDOW_ALWAYS_ON_TOP) - video.SDL_ShowWindow(window) +def test_SDL_GetSetWindowMinimumSize(window): + sx, sy = c_int(0), c_int(0) + minx, miny = c_int(0), c_int(0) + video.SDL_GetWindowSize(window, byref(sx), byref(sy)) + assert (sx.value, sy.value) == (12, 13) + # Set and verify the minimum window size + video.SDL_SetWindowMinimumSize(window, 10, 10) + assert SDL_GetError() == b"" + video.SDL_GetWindowMinimumSize(window, byref(minx), byref(miny)) + assert (minx.value, miny.value) == (10, 10) + # Make sure window can't be set below its minimum size + video.SDL_SetWindowSize(window, 1, 1) + video.SDL_GetWindowSize(window, byref(sx), byref(sy)) + assert (sx.value, sy.value) == (10, 10) + +def test_SDL_GetSetWindowMaximumSize(window): + sx, sy = c_int(0), c_int(0) + maxx, maxy = c_int(0), c_int(0) + video.SDL_GetWindowSize(window, byref(sx), byref(sy)) + assert (sx.value, sy.value) == (12, 13) + # Set and verify the maximum window size + video.SDL_SetWindowMaximumSize(window, 32, 32) + assert SDL_GetError() == b"" + video.SDL_GetWindowMaximumSize(window, byref(maxx), byref(maxy)) + assert (maxx.value, maxy.value) == (32, 32) + # Make sure window can't be set above its maximum size + video.SDL_SetWindowSize(window, 50, 50) + video.SDL_GetWindowSize(window, byref(sx), byref(sy)) + assert (sx.value, sy.value) == (32, 32) + +def test_SDL_SetWindowBordered(window): + border_flag = video.SDL_WINDOW_BORDERLESS + assert video.SDL_GetWindowFlags(window) & border_flag == border_flag + video.SDL_SetWindowBordered(window, SDL_TRUE) + if not DRIVER_DUMMY: + assert not video.SDL_GetWindowFlags(window) & border_flag == border_flag + video.SDL_SetWindowBordered(window, SDL_FALSE) + assert video.SDL_GetWindowFlags(window) & border_flag == border_flag + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_SetWindowResizable(window): + flags = video.SDL_GetWindowFlags(window) + assert flags & video.SDL_WINDOW_RESIZABLE != video.SDL_WINDOW_RESIZABLE + video.SDL_SetWindowResizable(window, SDL_TRUE) + flags = video.SDL_GetWindowFlags(window) + assert flags & video.SDL_WINDOW_RESIZABLE == video.SDL_WINDOW_RESIZABLE + video.SDL_SetWindowResizable(window, SDL_FALSE) + flags = video.SDL_GetWindowFlags(window) + assert flags & video.SDL_WINDOW_RESIZABLE != video.SDL_WINDOW_RESIZABLE + +@pytest.mark.skip("Test doesn't work, may need to be interactive") +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_SetWindowAlwaysOnTop(with_sdl): + ON_TOP_FLAG = video.SDL_WINDOW_ALWAYS_ON_TOP + window = video.SDL_CreateWindow( + b"Always On Top", 10, 100, 10, 10, ON_TOP_FLAG + ) + video.SDL_ShowWindow(window) + flags = video.SDL_GetWindowFlags(window) + assert flags & ON_TOP_FLAG == ON_TOP_FLAG + video.SDL_SetWindowAlwaysOnTop(window, SDL_FALSE) + flags = video.SDL_GetWindowFlags(window) + assert flags & ON_TOP_FLAG != ON_TOP_FLAG + video.SDL_SetWindowAlwaysOnTop(window, SDL_TRUE) + flags = video.SDL_GetWindowFlags(window) + assert flags & ON_TOP_FLAG == ON_TOP_FLAG + video.SDL_DestroyWindow(window) + +def test_SDL_ShowHideWindow(window): + shown_flag = video.SDL_WINDOW_SHOWN + video.SDL_ShowWindow(window) + assert video.SDL_GetWindowFlags(window) & shown_flag == shown_flag + video.SDL_HideWindow(window) + assert not video.SDL_GetWindowFlags(window) & shown_flag == shown_flag + +def test_SDL_RaiseWindow(window): + # NOTE: Doesn't set any flags, so can't test this super well + video.SDL_RaiseWindow(window) + +@pytest.mark.skipif(SKIP_ANNOYING, reason="Skip unless requested") +def test_SDL_MaximizeWindow(decorated_window): + shown_flag = video.SDL_WINDOW_SHOWN + max_flag = video.SDL_WINDOW_MAXIMIZED + window = decorated_window + video.SDL_ShowWindow(window) + assert video.SDL_GetWindowFlags(window) & shown_flag == shown_flag + assert not video.SDL_GetWindowFlags(window) & max_flag == max_flag + video.SDL_MaximizeWindow(window) + if not DRIVER_DUMMY: + assert video.SDL_GetWindowFlags(window) & max_flag == max_flag + +@pytest.mark.skipif(SKIP_ANNOYING, reason="Skip unless requested") +def test_SDL_MinimizeRestoreWindow(decorated_window): + shown_flag = video.SDL_WINDOW_SHOWN + min_flag = video.SDL_WINDOW_MINIMIZED + window = decorated_window + video.SDL_ShowWindow(window) + assert video.SDL_GetWindowFlags(window) & shown_flag == shown_flag + assert not video.SDL_GetWindowFlags(window) & min_flag == min_flag + video.SDL_MinimizeWindow(window) + if not (DRIVER_DUMMY or DRIVER_X11): + assert video.SDL_GetWindowFlags(window) & min_flag == min_flag + video.SDL_RestoreWindow(window) + if not (DRIVER_DUMMY or DRIVER_X11): + assert not video.SDL_GetWindowFlags(window) & min_flag == min_flag + +def test_SDL_SetWindowFullscreen(with_sdl): + # TODO: Add non-hidden test once annoying test toggle implemented + flags = ( + video.SDL_WINDOW_BORDERLESS | video.SDL_WINDOW_HIDDEN, + video.SDL_WINDOW_RESIZABLE | video.SDL_WINDOW_HIDDEN, + ) + is_fullscreen = video.SDL_WINDOW_FULLSCREEN + for flag in flags: + window = video.SDL_CreateWindow(b"Test", 0, 0, 1024, 768, flag) + video.SDL_SetWindowFullscreen(window, True) flags = video.SDL_GetWindowFlags(window) - assert flags & ON_TOP_FLAG == ON_TOP_FLAG - video.SDL_SetWindowAlwaysOnTop(window, SDL_FALSE) + assert flags & is_fullscreen == is_fullscreen + video.SDL_SetWindowFullscreen(window, False) flags = video.SDL_GetWindowFlags(window) - assert flags & ON_TOP_FLAG != ON_TOP_FLAG - video.SDL_SetWindowAlwaysOnTop(window, SDL_TRUE) - flags = video.SDL_GetWindowFlags(window) - assert flags & ON_TOP_FLAG == ON_TOP_FLAG + assert flags & is_fullscreen != is_fullscreen video.SDL_DestroyWindow(window) - def test_SDL_GetSetWindowOpacity(self): - window = video.SDL_CreateWindow(b"Opacity", 10, 10, 10, 10, 0) - opacity = c_float() +def test_SDL_GetWindowSurface(window): + sf = video.SDL_GetWindowSurface(window) + assert SDL_GetError() == b"" + assert isinstance(sf.contents, surface.SDL_Surface) + +def test_SDL_UpdateWindowSurface(window): + sf = video.SDL_GetWindowSurface(window) + assert isinstance(sf.contents, surface.SDL_Surface) + ret = video.SDL_UpdateWindowSurface(window) + assert SDL_GetError() == b"" + assert ret == 0 + +def test_SDL_UpdateWindowSurfaceRects(window): + sf = video.SDL_GetWindowSurface(window) + assert isinstance(sf.contents, surface.SDL_Surface) + rectlist = (rect.SDL_Rect * 4)( + rect.SDL_Rect(0, 0, 0, 0), + rect.SDL_Rect(10, 10, 10, 10), + rect.SDL_Rect(0, 0, 5, 4), + rect.SDL_Rect(-5, -5, 6, 2) + ) + rect_ptr = cast(rectlist, POINTER(rect.SDL_Rect)) + ret = video.SDL_UpdateWindowSurfaceRects(window, rect_ptr, 4) + assert SDL_GetError() == b"" + assert ret == 0 + +@pytest.mark.skip("Can't set window grab for some reason") +def test_SDL_GetSetWindowGrab(decorated_window): + window = decorated_window + video.SDL_ShowWindow(window) + assert video.SDL_GetWindowGrab(window) == SDL_FALSE + video.SDL_SetWindowGrab(window, SDL_TRUE) + assert video.SDL_GetWindowGrab(window) == SDL_TRUE + video.SDL_SetWindowGrab(window, SDL_FALSE) + assert video.SDL_GetWindowGrab(window) == SDL_FALSE + +@pytest.mark.skip("Can't set window grab for some reason") +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_GetSetWindowKeyboardGrab(decorated_window): + window = decorated_window + video.SDL_ShowWindow(window) + assert video.SDL_GetWindowKeyboardGrab(window) == SDL_FALSE + video.SDL_SetWindowKeyboardGrab(window, SDL_TRUE) + assert video.SDL_GetWindowKeyboardGrab(window) == SDL_TRUE + video.SDL_SetWindowKeyboardGrab(window, SDL_FALSE) + assert video.SDL_GetWindowKeyboardGrab(window) == SDL_FALSE + +@pytest.mark.skip("Can't set window grab for some reason") +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_GetSetWindowMouseGrab(decorated_window): + window = decorated_window + video.SDL_ShowWindow(window) + assert video.SDL_GetWindowMouseGrab(window) == SDL_FALSE + video.SDL_SetWindowMouseGrab(window, SDL_TRUE) + assert video.SDL_GetWindowMouseGrab(window) == SDL_TRUE + video.SDL_SetWindowMouseGrab(window, SDL_FALSE) + assert video.SDL_GetWindowMouseGrab(window) == SDL_FALSE + +@pytest.mark.skip("not implemented") +def test_SDL_GetGrabbedWindow(window): + # NOTE: Should implement this once the above tests are fixed + pass + +@pytest.mark.skipif(sdl2.dll.version < 2018, reason="not available") +def test_SDL_GetSetWindowMouseRect(with_sdl): + flags = video.SDL_WINDOW_BORDERLESS + bounds_in = rect.SDL_Rect(0, 0, 100, 50) + window = video.SDL_CreateWindow(b"Test", 200, 200, 200, 200, flags) + # Try setting a mouse boundary + ret = video.SDL_SetWindowMouseRect(window, byref(bounds_in)) + assert SDL_GetError() == b"" + assert ret == 0 + bounds_out = video.SDL_GetWindowMouseRect(window) + assert bounds_out != None + assert bounds_in == bounds_out.contents + # Try removing the boundary + ret = video.SDL_SetWindowMouseRect(window, None) + assert SDL_GetError() == b"" + assert ret == 0 + bounds_out = video.SDL_GetWindowMouseRect(window) + assert not bounds_out # bounds_out should be null pointer + video.SDL_DestroyWindow(window) + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GetSetWindowBrightness(window): + orig = video.SDL_GetWindowBrightness(window) + assert isinstance(orig, float) + assert orig >= 0 + # Go from 0.0, 0.1 ... to 1.0 + gammas = (x * 0.1 for x in range(0, 10)) + count = 0 + for b in gammas: + ret = video.SDL_SetWindowBrightness(window, b) + if ret == 0: + val = video.SDL_GetWindowBrightness(window) + assert round(abs(val-b), 7) == 0 + count += 1 + assert count > 0 + +def test_SDL_GetSetWindowOpacity(window): + opacity = c_float(0) + ret = video.SDL_GetWindowOpacity(window, byref(opacity)) + assert ret == 0 + assert opacity.value == 1.0 + if not DRIVER_DUMMY: + ret = video.SDL_SetWindowOpacity(window, 0.5) + assert SDL_GetError() == b"" + assert ret == 0 ret = video.SDL_GetWindowOpacity(window, byref(opacity)) + assert SDL_GetError() == b"" + assert ret == 0 + assert opacity.value == 0.5 + +@pytest.mark.skipif(sdl2.dll.version < 2005, reason="not available") +def test_SDL_SetWindowModalFor(window, decorated_window): + # NOTE: Only supported on X11 + ret = video.SDL_SetWindowModalFor(window, decorated_window) + if video.SDL_GetCurrentVideoDriver() == b"x11": + assert SDL_GetError() == b"" assert ret == 0 - assert opacity.value == 1.0 - if video.SDL_GetCurrentVideoDriver() != b"dummy": - ret = video.SDL_SetWindowOpacity(window, 0.0) - assert ret == 0, SDL_GetError() - ret = video.SDL_GetWindowOpacity(window, byref(opacity)) - assert ret == 0 - assert opacity.value == 0.0 - ret = video.SDL_SetWindowOpacity(window, 0.653) - assert ret == 0 - ret = video.SDL_GetWindowOpacity(window, byref(opacity)) - assert ret == 0 - assert round(abs(opacity.value-0.653), 2) == 0 - video.SDL_DestroyWindow(window) - def test_SDL_GetDisplayUsableBounds(self): - numdisplays = video.SDL_GetNumVideoDisplays() - for index in range(numdisplays): - bounds = rect.SDL_Rect() - ret = video.SDL_GetDisplayUsableBounds(index, byref(bounds)) - assert ret == 0 - assert not rect.SDL_RectEmpty(bounds) - - def test_SDL_GetWindowsBordersSize(self): - if video.SDL_GetCurrentVideoDriver() == b"dummy": - pytest.skip("dummy video driver does not support the window border size") - window = video.SDL_CreateWindow(b"Borders", 10, 10, 10, 10, 0) - video.SDL_ShowWindow(window) - l, r, t, b = c_int(), c_int(), c_int(), c_int() - ret = video.SDL_GetWindowBordersSize(window, byref(t), byref(l), - byref(b), byref(r)) - if sys.platform in ("cygwin", "darwin"): - assert ret == -1 - assert t.value == 0 - assert l.value == 0 - assert b.value == 0 - assert r.value == 0 - else: - assert ret == 0 - assert t.value != 0 - assert l.value != 0 - assert b.value != 0 - assert r.value != 0 - video.SDL_DestroyWindow(window) - window = video.SDL_CreateWindow(b"No Borders", 10, 10, 10, 10, - video.SDL_WINDOW_BORDERLESS) - video.SDL_ShowWindow(window) - ret = video.SDL_GetWindowBordersSize(window, byref(t), byref(l), - byref(b), byref(r)) - if sys.platform not in ("cygwin", "darwin"): - assert ret == 0 - assert t.value == 0 - assert l.value == 0 - assert b.value == 0 - assert r.value == 0 - video.SDL_DestroyWindow(window) +@pytest.mark.skipif(sdl2.dll.version < 2005, reason="not available") +def test_SDL_SetWindowInputFocus(window): + # NOTE: Only supported on X11 and Wayland + ret = video.SDL_SetWindowInputFocus(window) + if video.SDL_GetCurrentVideoDriver() in [b"x11", b"wayland"]: + assert SDL_GetError() == b"" + assert ret == 0 - @pytest.mark.skip("not implemented") - def test_SDL_SetWindowModalFor(self): - pass +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GetSetWindowGammaRamp(window): + vals = (Uint16 * 256)() + pixels.SDL_CalculateGammaRamp(0.5, vals) + ret = video.SDL_SetWindowGammaRamp(window, vals, vals, vals) + assert SDL_GetError() == b"" + assert ret == 0 + r = (Uint16 * 256)() + g = (Uint16 * 256)() + b = (Uint16 * 256)() + ret = video.SDL_GetWindowGammaRamp(window, r, g, b) + assert SDL_GetError() == b"" + assert ret == 0 + for i in range(len(vals)): + assert r[i] == vals[i] + assert g[i] == vals[i] + assert b[i] == vals[i] + +@pytest.mark.skip("not implemented") +@pytest.mark.skipif(sdl2.dll.version < 2004, reason="not available") +def test_SDL_SetWindowHitTest(self): + # NOTE: This sets a callback that's triggered when you mouse over certain + # regions of a window. Pretty sure this can't be tested non-interactively. + pass + +@pytest.mark.skipif(sdl2.dll.version < 2016, reason="not available") +def test_SDL_FlashWindow(window): + # NOTE: Not the most comprehensive test, but it does test the basic bindings + ret = video.SDL_FlashWindow(window, video.SDL_FLASH_BRIEFLY) + if not DRIVER_DUMMY: + assert SDL_GetError() == b"" + assert ret == 0 - @pytest.mark.skip("not implemented") - def test_SDL_SetWindowInputFocus(self): - pass +def test_screensaver(with_sdl): + video.SDL_EnableScreenSaver() + assert video.SDL_IsScreenSaverEnabled() == SDL_TRUE + video.SDL_EnableScreenSaver() + assert video.SDL_IsScreenSaverEnabled() == SDL_TRUE + video.SDL_DisableScreenSaver() + assert video.SDL_IsScreenSaverEnabled() == SDL_FALSE + video.SDL_DisableScreenSaver() + assert video.SDL_IsScreenSaverEnabled() == SDL_FALSE + video.SDL_EnableScreenSaver() + assert video.SDL_IsScreenSaverEnabled() == SDL_TRUE + video.SDL_DisableScreenSaver() + assert video.SDL_IsScreenSaverEnabled() == SDL_FALSE + + +# Test SDL OpenGL functions + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GL_LoadUnloadLibrary(with_sdl): + # TODO: Test whether other GL functions work after GL is unloaded + # (unloading doesn't always work right on macOS for some reason) + ret = video.SDL_GL_LoadLibrary(None) + assert SDL_GetError() == b"" + assert ret == 0 + video.SDL_GL_UnloadLibrary() + # Try loading a library from a path + if has_opengl_lib(): + fpath = get_opengl_path().encode("utf-8") + ret = video.SDL_GL_LoadLibrary(fpath) + assert SDL_GetError() == b"" + assert ret == 0 + video.SDL_GL_UnloadLibrary() + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GL_CreateDeleteContext(with_sdl_gl): + window = video.SDL_CreateWindow( + b"OpenGL", 10, 40, 32, 24, video.SDL_WINDOW_OPENGL + ) + ctx = video.SDL_GL_CreateContext(window) + assert SDL_GetError() == b"" + video.SDL_GL_DeleteContext(ctx) + ctx = video.SDL_GL_CreateContext(window) + assert SDL_GetError() == b"" + video.SDL_GL_DeleteContext(ctx) + video.SDL_DestroyWindow(window) + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GL_GetProcAddress(gl_window): + procaddr = video.SDL_GL_GetProcAddress(b"glGetString") + assert SDL_GetError() == b"" + assert procaddr is not None and int(procaddr) != 0 + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GL_ExtensionSupported(gl_window): + assert video.SDL_GL_ExtensionSupported(b"GL_EXT_bgra") + assert SDL_GetError() == b"" + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GL_GetSetResetAttribute(with_sdl_gl): + # Create a context and get its bit depth + window = video.SDL_CreateWindow( + b"OpenGL", 10, 40, 12, 13, video.SDL_WINDOW_OPENGL + ) + ctx = video.SDL_GL_CreateContext(window) + bufstate = c_int(0) + ret = video.SDL_GL_GetAttribute(video.SDL_GL_DOUBLEBUFFER, byref(bufstate)) + video.SDL_GL_DeleteContext(ctx) + video.SDL_DestroyWindow(window) + assert SDL_GetError() == b"" + assert ret == 0 + # Try setting a different GL bit depth + new_bufstate = 0 if bufstate.value == 1 else 1 + video.SDL_GL_SetAttribute(video.SDL_GL_DOUBLEBUFFER, new_bufstate) + assert SDL_GetError() == b"" + assert ret == 0 + # Create a new context to see if it's using the new bit depth + window = video.SDL_CreateWindow( + b"OpenGL", 10, 40, 12, 13, video.SDL_WINDOW_OPENGL + ) + ctx = video.SDL_GL_CreateContext(window) + val = c_int(0) + ret = video.SDL_GL_GetAttribute(video.SDL_GL_DOUBLEBUFFER, byref(val)) + video.SDL_GL_DeleteContext(ctx) + video.SDL_DestroyWindow(window) + assert SDL_GetError() == b"" + assert ret == 0 + assert bufstate.value != val.value + assert val.value == new_bufstate + # Try resetting the context and see if it goes back to the original depth + video.SDL_GL_ResetAttributes() + window = video.SDL_CreateWindow( + b"OpenGL", 10, 40, 12, 13, video.SDL_WINDOW_OPENGL + ) + ctx = video.SDL_GL_CreateContext(window) + val = c_int(0) + ret = video.SDL_GL_GetAttribute(video.SDL_GL_DOUBLEBUFFER, byref(val)) + video.SDL_GL_DeleteContext(ctx) + video.SDL_DestroyWindow(window) + assert bufstate.value == val.value + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GL_MakeCurrent(gl_window): + window, ctx = gl_window + ret = video.SDL_GL_MakeCurrent(window, ctx) + assert SDL_GetError() == b"" + assert ret == 0 + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GL_GetSetSwapInterval(gl_window): + window, ctx = gl_window + ret = video.SDL_GL_MakeCurrent(window, ctx) + assert SDL_GetError() == b"" + assert ret == 0 + # Try enabling/disabling OpenGL vsync + for value in [0, 1]: + ret = video.SDL_GL_SetSwapInterval(value) + if ret == 0: + assert video.SDL_GL_GetSwapInterval() == value + +@pytest.mark.skipif(DRIVER_DUMMY, reason="Doesn't work with dummy driver") +def test_SDL_GL_SwapWindow(gl_window): + window, ctx = gl_window + ret = video.SDL_GL_MakeCurrent(window, ctx) + assert SDL_GetError() == b"" + assert ret == 0 + video.SDL_GL_SwapWindow(window) + video.SDL_GL_SwapWindow(window) + video.SDL_GL_SwapWindow(window) + assert SDL_GetError() == b"" diff --git a/sdl2/test/vulkan_test.py b/sdl2/test/vulkan_test.py index f3aa808c..24a2b1ed 100644 --- a/sdl2/test/vulkan_test.py +++ b/sdl2/test/vulkan_test.py @@ -2,38 +2,27 @@ from sdl2 import SDL_Init, SDL_Quit, SDL_INIT_VIDEO from sdl2 import vulkan -class TestSDLVulkan(object): - __tags__ = ["sdl"] - @classmethod - def setup_class(cls): - if SDL_Init(SDL_INIT_VIDEO) != 0: - raise pytest.skip('Video subsystem not supported') +@pytest.mark.skip("not implemented") +def test_SDL_Vulkan_LoadLibrary(with_sdl): + pass - @classmethod - def teardown_class(cls): - SDL_Quit() +@pytest.mark.skip("not implemented") +def test_SDL_Vulkan_GetVkGetInstanceProcAddr(with_sdl): + pass - @pytest.mark.skip("not implemented") - def test_SDL_Vulkan_LoadLibrary(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_Vulkan_UnloadLibrary(with_sdl): + pass - @pytest.mark.skip("not implemented") - def test_SDL_Vulkan_GetVkGetInstanceProcAddr(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_Vulkan_GetInstanceExtensions(with_sdl): + pass - @pytest.mark.skip("not implemented") - def test_SDL_Vulkan_UnloadLibrary(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_Vulkan_CreateSurface(with_sdl): + pass - @pytest.mark.skip("not implemented") - def test_SDL_Vulkan_GetInstanceExtensions(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_Vulkan_CreateSurface(self): - pass - - @pytest.mark.skip("not implemented") - def test_SDL_Vulkan_GetDrawableSize(self): - pass +@pytest.mark.skip("not implemented") +def test_SDL_Vulkan_GetDrawableSize(with_sdl): + pass