Skip to content

Commit

Permalink
Add tests for Audio module types
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisThrasher committed May 16, 2024
1 parent a61eb6a commit 84e9db1
Show file tree
Hide file tree
Showing 9 changed files with 641 additions and 38 deletions.
28 changes: 14 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ jobs:
- { name: Windows VS2022 OpenGL ES, os: windows-2022, flags: -DSFML_USE_MESA3D=TRUE -DSFML_OPENGL_ES=ON -GNinja }
- { name: Windows VS2022 Unity, os: windows-2022, flags: -DSFML_USE_MESA3D=TRUE -DCMAKE_UNITY_BUILD=ON -GNinja }
- { name: Windows LLVM/Clang, os: windows-2022, flags: -DSFML_USE_MESA3D=TRUE -DCMAKE_CXX_COMPILER=clang++ -GNinja }
- { name: Windows MinGW, os: windows-2022, flags: -DSFML_USE_MESA3D=TRUE -DCMAKE_CXX_COMPILER=g++ -GNinja }
- { name: Linux GCC, os: ubuntu-22.04, flags: -GNinja }
- { name: Linux Clang, os: ubuntu-22.04, flags: -DCMAKE_CXX_COMPILER=clang++ -GNinja , gcovr_options: '--gcov-executable="llvm-cov-$CLANG_VERSION gcov"' }
- { name: Linux GCC DRM, os: ubuntu-22.04, flags: -DSFML_USE_DRM=ON -DSFML_RUN_DISPLAY_TESTS=OFF -GNinja }
- { name: Linux GCC OpenGL ES, os: ubuntu-22.04, flags: -DSFML_OPENGL_ES=ON -DSFML_RUN_DISPLAY_TESTS=OFF -GNinja }
- { name: Windows MinGW, os: windows-2022, flags: -DSFML_USE_MESA3D=TRUE -DCMAKE_CXX_COMPILER=g++ -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF -GNinja }
- { name: Linux GCC, os: ubuntu-22.04, flags: -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF -GNinja }
- { name: Linux Clang, os: ubuntu-22.04, flags: -DCMAKE_CXX_COMPILER=clang++ -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF -GNinja , gcovr_options: '--gcov-executable="llvm-cov-$CLANG_VERSION gcov"' }
- { name: Linux GCC DRM, os: ubuntu-22.04, flags: -DSFML_USE_DRM=ON -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF -GNinja }
- { name: Linux GCC OpenGL ES, os: ubuntu-22.04, flags: -DSFML_OPENGL_ES=ON -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF -GNinja }
- { name: macOS x64, os: macos-12, flags: -GNinja }
- { name: macOS x64 Xcode, os: macos-12, flags: -GXcode }
- { name: macOS arm64, os: macos-14, flags: -GNinja }
- { name: macOS arm64, os: macos-14, flags: -GNinja -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF }
- { name: iOS, os: macos-12, flags: -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64 }
- { name: iOS Xcode, os: macos-12, flags: -DCMAKE_SYSTEM_NAME=iOS -GXcode -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=NO }
config:
Expand All @@ -56,9 +56,9 @@ jobs:
- platform: { name: Windows VS2022 x64, os: windows-2022 }
config: { name: Static with PCH (MSVC), flags: -DSFML_USE_MESA3D=TRUE -GNinja -DBUILD_SHARED_LIBS=FALSE -DSFML_ENABLE_PCH=1 }
- platform: { name: Linux GCC, os: ubuntu-22.04 }
config: { name: Static with PCH (GCC), flags: -GNinja -DCMAKE_CXX_COMPILER=g++ -DBUILD_SHARED_LIBS=FALSE -DSFML_ENABLE_PCH=1 }
config: { name: Static with PCH (GCC), flags: -GNinja -DCMAKE_CXX_COMPILER=g++ -DBUILD_SHARED_LIBS=FALSE -DSFML_ENABLE_PCH=1 -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF }
- platform: { name: Linux Clang, os: ubuntu-22.04 }
config: { name: Static with PCH (Clang), flags: -GNinja -DCMAKE_CXX_COMPILER=clang++ -DBUILD_SHARED_LIBS=FALSE -DSFML_ENABLE_PCH=1 }
config: { name: Static with PCH (Clang), flags: -GNinja -DCMAKE_CXX_COMPILER=clang++ -DBUILD_SHARED_LIBS=FALSE -DSFML_ENABLE_PCH=1 -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF }
- platform: { name: Windows MinGW, os: windows-2022 }
config: { name: Static Standard Libraries, flags: -GNinja -DSFML_USE_MESA3D=TRUE -DCMAKE_CXX_COMPILER=g++ -DSFML_USE_STATIC_STD_LIBS=TRUE }
- platform: { name: Windows MinGW, os: windows-2022 }
Expand All @@ -70,7 +70,7 @@ jobs:
- platform: { name: Android, os: ubuntu-latest }
config:
name: x86 (API 21)
flags: -GNinja -DCMAKE_ANDROID_ARCH_ABI=x86 -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=21 -DCMAKE_ANDROID_NDK=$ANDROID_NDK_ROOT -DBUILD_SHARED_LIBS=TRUE -DCMAKE_ANDROID_STL_TYPE=c++_shared -DSFML_RUN_DISPLAY_TESTS=OFF
flags: -GNinja -DCMAKE_ANDROID_ARCH_ABI=x86 -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=21 -DCMAKE_ANDROID_NDK=$ANDROID_NDK_ROOT -DBUILD_SHARED_LIBS=TRUE -DCMAKE_ANDROID_STL_TYPE=c++_shared -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF
arch: x86
api: 21
libcxx: i686-linux-android/libc++_shared.so
Expand All @@ -80,7 +80,7 @@ jobs:
- platform: { name: Android, os: ubuntu-latest }
config:
name: x86_64 (API 24)
flags: -GNinja -DCMAKE_ANDROID_ARCH_ABI=x86_64 -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=24 -DCMAKE_ANDROID_NDK=$ANDROID_NDK_ROOT -DBUILD_SHARED_LIBS=TRUE -DCMAKE_ANDROID_STL_TYPE=c++_shared -DSFML_RUN_DISPLAY_TESTS=OFF
flags: -GNinja -DCMAKE_ANDROID_ARCH_ABI=x86_64 -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=24 -DCMAKE_ANDROID_NDK=$ANDROID_NDK_ROOT -DBUILD_SHARED_LIBS=TRUE -DCMAKE_ANDROID_STL_TYPE=c++_shared -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF
arch: x86_64
api: 24
libcxx: x86_64-linux-android/libc++_shared.so
Expand All @@ -98,7 +98,7 @@ jobs:
- platform: { name: Android, os: ubuntu-latest }
config:
name: arm64-v8a (API 33)
flags: -GNinja -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=33 -DCMAKE_ANDROID_NDK=$ANDROID_NDK_ROOT -DBUILD_SHARED_LIBS=TRUE -DCMAKE_ANDROID_STL_TYPE=c++_shared -DSFML_RUN_DISPLAY_TESTS=OFF
flags: -GNinja -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=33 -DCMAKE_ANDROID_NDK=$ANDROID_NDK_ROOT -DBUILD_SHARED_LIBS=TRUE -DCMAKE_ANDROID_STL_TYPE=c++_shared -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF
arch: arm64-v8a
api: 33
libcxx: aarch64-linux-android/libc++_shared.so
Expand Down Expand Up @@ -386,9 +386,9 @@ jobs:
fail-fast: false
matrix:
platform:
- { name: Linux, os: ubuntu-22.04 }
- { name: Linux DRM, os: ubuntu-22.04, flags: -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_USE_DRM=ON }
- { name: Linux GCC OpenGL ES, os: ubuntu-22.04, flags: -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_OPENGL_ES=ON }
- { name: Linux, os: ubuntu-22.04, flags: -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF }
- { name: Linux DRM, os: ubuntu-22.04, flags: -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_USE_DRM=ON }
- { name: Linux GCC OpenGL ES, os: ubuntu-22.04, flags: -DSFML_RUN_AUDIO_DEVICE_TESTS=OFF -DSFML_RUN_DISPLAY_TESTS=OFF -DSFML_OPENGL_ES=ON }

steps:
- name: Checkout Code
Expand Down
209 changes: 205 additions & 4 deletions test/Audio/Music.test.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,209 @@
#include <SFML/Audio/Music.hpp>

// Other 1st party headers
#include <SFML/System/FileInputStream.hpp>

#include <catch2/catch_test_macros.hpp>

#include <AudioUtil.hpp>
#include <SystemUtil.hpp>
#include <array>
#include <fstream>
#include <thread>
#include <type_traits>

static_assert(!std::is_copy_constructible_v<sf::Music>);
static_assert(!std::is_copy_assignable_v<sf::Music>);
static_assert(!std::is_nothrow_move_constructible_v<sf::Music>);
static_assert(!std::is_nothrow_move_assignable_v<sf::Music>);
TEST_CASE("[Audio] sf::Music", runAudioDeviceTests())
{
SECTION("Type traits")
{
STATIC_CHECK(!std::is_copy_constructible_v<sf::Music>);
STATIC_CHECK(!std::is_copy_assignable_v<sf::Music>);
STATIC_CHECK(!std::is_nothrow_move_constructible_v<sf::Music>);
STATIC_CHECK(!std::is_nothrow_move_assignable_v<sf::Music>);
STATIC_CHECK(std::has_virtual_destructor_v<sf::Music>);
}

SECTION("Span")
{
const sf::Music::Span<float> span;
CHECK(span.offset == 0);
CHECK(span.length == 0);

const sf::Music::TimeSpan timeSpan;
CHECK(timeSpan.offset == sf::Time::Zero);
CHECK(timeSpan.length == sf::Time::Zero);
}

SECTION("Construction")
{
const sf::Music music;
CHECK(music.getDuration() == sf::Time::Zero);
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::Time::Zero);
CHECK(music.getChannelCount() == 0);
CHECK(music.getSampleRate() == 0);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}

SECTION("openFromFile()")
{
sf::Music music;

SECTION("Invalid file")
{
REQUIRE(!music.openFromFile("does/not/exist.wav"));
CHECK(music.getDuration() == sf::Time::Zero);
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::Time::Zero);
CHECK(music.getChannelCount() == 0);
CHECK(music.getSampleRate() == 0);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}

SECTION("Valid file")
{
REQUIRE(music.openFromFile("Audio/ding.mp3"));
CHECK(music.getDuration() == sf::microseconds(1990884));
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::microseconds(1990884));
CHECK(music.getChannelCount() == 1);
CHECK(music.getSampleRate() == 44100);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}
}

SECTION("openFromMemory()")
{
std::vector<std::byte> memory;
sf::Music music;

SECTION("Invalid buffer")
{
REQUIRE(!music.openFromMemory(memory.data(), memory.size()));
CHECK(music.getDuration() == sf::Time::Zero);
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::Time::Zero);
CHECK(music.getChannelCount() == 0);
CHECK(music.getSampleRate() == 0);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}

SECTION("Valid buffer")
{
memory = loadIntoMemory("Audio/ding.flac");
REQUIRE(music.openFromMemory(memory.data(), memory.size()));
CHECK(music.getDuration() == sf::microseconds(1990884));
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::microseconds(1990884));
CHECK(music.getChannelCount() == 1);
CHECK(music.getSampleRate() == 44100);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}
}

SECTION("openFromStream()")
{
sf::FileInputStream stream;
sf::Music music;

SECTION("Invalid stream")
{
CHECK(!music.openFromStream(stream));
CHECK(music.getDuration() == sf::Time::Zero);
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::Time::Zero);
CHECK(music.getChannelCount() == 0);
CHECK(music.getSampleRate() == 0);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}

SECTION("Valid stream")
{
REQUIRE(stream.open("Audio/doodle_pop.ogg"));
REQUIRE(music.openFromStream(stream));
CHECK(music.getDuration() == sf::microseconds(24002176));
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::microseconds(24002176));
CHECK(music.getChannelCount() == 2);
CHECK(music.getSampleRate() == 44100);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}
}

SECTION("play/pause/stop")
{
sf::Music music;
REQUIRE(music.openFromFile("Audio/ding.mp3"));

// Wait for background thread to start
music.play();
while (music.getStatus() == sf::SoundSource::Status::Stopped)
std::this_thread::sleep_for(std::chrono::milliseconds(10));
CHECK(music.getStatus() == sf::SoundSource::Status::Playing);

// Wait for background thread to pause
music.pause();
while (music.getStatus() == sf::SoundSource::Status::Playing)
std::this_thread::sleep_for(std::chrono::milliseconds(10));
CHECK(music.getStatus() == sf::SoundSource::Status::Paused);

// Wait for background thread to stop
music.stop();
while (music.getStatus() == sf::SoundSource::Status::Paused)
std::this_thread::sleep_for(std::chrono::milliseconds(10));
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
}

SECTION("setLoopPoints()")
{
sf::Music music;

SECTION("No file")
{
music.setLoopPoints({sf::Time::Zero, sf::Time::Zero});
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::Time::Zero);
CHECK(music.getChannelCount() == 0);
CHECK(music.getSampleRate() == 0);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}

SECTION("Loaded file")
{
REQUIRE(music.openFromFile("Audio/killdeer.wav"));
music.setLoopPoints({sf::seconds(1), sf::seconds(2)});
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::seconds(1));
CHECK(length == sf::seconds(2));
CHECK(music.getChannelCount() == 1);
CHECK(music.getSampleRate() == 22050);
CHECK(music.getStatus() == sf::SoundSource::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}
}
}
89 changes: 82 additions & 7 deletions test/Audio/Sound.test.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,86 @@
#include <SFML/Audio/Sound.hpp>

// Other 1st party headers
#include <SFML/Audio/SoundBuffer.hpp>

#include <SFML/System/Time.hpp>

#include <catch2/catch_test_macros.hpp>

#include <AudioUtil.hpp>
#include <SystemUtil.hpp>
#include <type_traits>

static_assert(!std::is_constructible_v<sf::Sound, sf::SoundBuffer&&>);
static_assert(std::is_copy_constructible_v<sf::Sound>);
static_assert(std::is_copy_assignable_v<sf::Sound>);
static_assert(std::is_move_constructible_v<sf::Sound>);
static_assert(!std::is_nothrow_move_constructible_v<sf::Sound>);
static_assert(std::is_move_assignable_v<sf::Sound>);
static_assert(!std::is_nothrow_move_assignable_v<sf::Sound>);
TEST_CASE("[Audio] sf::Sound", runAudioDeviceTests())
{
SECTION("Type traits")
{
STATIC_CHECK(!std::is_constructible_v<sf::Sound, sf::SoundBuffer&&>);
STATIC_CHECK(std::is_copy_constructible_v<sf::Sound>);
STATIC_CHECK(std::is_copy_assignable_v<sf::Sound>);
STATIC_CHECK(std::is_move_constructible_v<sf::Sound>);
STATIC_CHECK(!std::is_nothrow_move_constructible_v<sf::Sound>);
STATIC_CHECK(std::is_move_assignable_v<sf::Sound>);
STATIC_CHECK(!std::is_nothrow_move_assignable_v<sf::Sound>);
STATIC_CHECK(std::has_virtual_destructor_v<sf::Sound>);
}

sf::SoundBuffer soundBuffer;
REQUIRE(soundBuffer.loadFromFile("Audio/ding.flac"));

SECTION("Construction")
{
const sf::Sound sound(soundBuffer);
CHECK(&sound.getBuffer() == &soundBuffer);
CHECK(!sound.getLoop());
CHECK(sound.getPlayingOffset() == sf::Time::Zero);
CHECK(sound.getStatus() == sf::SoundSource::Status::Stopped);
}

SECTION("Copy semantics")
{
const sf::Sound sound(soundBuffer);

SECTION("Construction")
{
const sf::Sound soundCopy(sound); // NOLINT(performance-unnecessary-copy-initialization)
CHECK(&soundCopy.getBuffer() == &soundBuffer);
CHECK(!soundCopy.getLoop());
CHECK(soundCopy.getPlayingOffset() == sf::Time::Zero);
CHECK(soundCopy.getStatus() == sf::SoundSource::Status::Stopped);
}

SECTION("Assignment")
{
const sf::SoundBuffer emptySoundBuffer;
sf::Sound soundCopy(emptySoundBuffer);
soundCopy = sound;
CHECK(&soundCopy.getBuffer() == &soundBuffer);
CHECK(!soundCopy.getLoop());
CHECK(soundCopy.getPlayingOffset() == sf::Time::Zero);
CHECK(soundCopy.getStatus() == sf::SoundSource::Status::Stopped);
}
}

SECTION("Set/get buffer")
{
const sf::SoundBuffer otherSoundBuffer;
sf::Sound sound(soundBuffer);
sound.setBuffer(otherSoundBuffer);
CHECK(&sound.getBuffer() == &otherSoundBuffer);
}

SECTION("Set/get loop")
{
sf::Sound sound(soundBuffer);
sound.setLoop(true);
CHECK(sound.getLoop());
}

SECTION("Set/get playing offset")
{
sf::Sound sound(soundBuffer);
sound.setPlayingOffset(sf::seconds(10));
CHECK(sound.getPlayingOffset() == sf::seconds(10));
}
}

0 comments on commit 84e9db1

Please sign in to comment.