Merge pull request #361 from FluidSynth/unit-test

Introduce unit tests
This commit is contained in:
Tom M 2018-04-08 13:45:43 +02:00 committed by GitHub
commit dcb54f8438
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 227 additions and 6 deletions

View file

@ -56,7 +56,9 @@ build_script:
- mkdir build
- cd build
- cmake -G "%generator%" %CMAKE_FLAGS% -Denable-pkgconfig=0 -DCMAKE_TOOLCHAIN_FILE=c:/Tools/vcpkg/scripts/buildsystems/vcpkg.cmake ..
- cmake --build . --config Release
- cmake --build . --config Release # build libfluidsynth and fluidsynth exec
- cmake -Denable-tests=1 ..
- cmake --build . --config Release --target check # build unittests
after_build:
- 7z a fluidsynth.zip %APPVEYOR_BUILD_FOLDER%\build\src\Release\*

View file

@ -58,7 +58,10 @@ build_script:
- mkdir build
- cd build
- cmake -G "%generator%" ..
- cmake --build . --config Release
- cmake --build . --config Release # build libfluidsynth and fluidsynth exec
# FIXME the linker doesnt find gthread-2.0.lib in the second run, why???
# - cmake -Denable-tests=1 ..
# - cmake --build . --config Release --target check # build unittests
after_build:
- 7z a fluidsynth.zip %APPVEYOR_BUILD_FOLDER%\build\src\Release\* c:\deps\bin\libglib*.dll c:\deps\bin\libgthread*.dll c:\deps\bin\*intl*.dll

View file

@ -178,17 +178,17 @@ matrix:
- os: osx
osx_image: xcode8
env:
- MATRIX_EVAL="brew install gcc5 glib && CC=gcc-5 && CXX=g++-5"
- MATRIX_EVAL="brew install gcc5 glib gettext && brew link gettext && CC=gcc-5 && CXX=g++-5" # gettext should provide libintl, but doesnt work
- os: osx
osx_image: xcode8
env:
- MATRIX_EVAL="brew install gcc6 glib && CC=gcc-6 && CXX=g++-6"
- MATRIX_EVAL="brew install gcc6 glib gettext && brew link gettext && CC=gcc-6 && CXX=g++-6"
- os: osx
osx_image: xcode8
env:
- MATRIX_EVAL="brew install gcc glib libsndfile jack dbus-glib pulseaudio portaudio && CC=gcc-7 && CXX=g++-7"
- MATRIX_EVAL="brew install gcc glib gettext libsndfile jack dbus-glib pulseaudio portaudio && brew link gettext && CC=gcc-7 && CXX=g++-7"
before_install:
- if [ $TRAVIS_OS_NAME = linux ]; then sudo apt-get update; else brew update; fi
@ -201,4 +201,4 @@ before_script:
script:
- cmake -DCMAKE_INSTALL_PREFIX=$HOME/fluidsynth_install ${CMAKE_FLAGS} "-Denable-portaudio=1" "-Denable-ladspa=1" "-DCMAKE_BUILD_TYPE=RelWithDebInfo" ..
- make -j4
- if [ $TRAVIS_OS_NAME = linux ]; then make install; fi # install only on linux, as CMAKE_INSTALL_PREFIX is ignored for frameworks on macosx and I cant tell whether that's correct or a bug
- if [ $TRAVIS_OS_NAME = linux ]; then make install; cmake -Denable-tests=1 ..; make check; fi # install only on linux, as CMAKE_INSTALL_PREFIX is ignored for frameworks on macosx and I cant tell whether that's correct or a bug. also build unit test only on linux, as libintl is not found on macosx

View file

@ -55,6 +55,7 @@ option ( enable-fpe-check "enable Floating Point Exception checks and debug mess
option ( enable-portaudio "compile PortAudio support" off )
option ( enable-profiling "profile the dsp code" off )
option ( enable-trap-on-fpe "enable SIGFPE trap on Floating Point Exceptions" off )
option ( enable-tests "build unit tests (implicitly disables BUILD_SHARED_LIBS and overrides DEFAULT_SOUNDFONT)" off )
# Options enabled by default
option ( enable-aufile "compile support for sound file output" on )
@ -500,10 +501,23 @@ else ( enable-readline )
endif ( enable-readline )
if(enable-tests)
# manipulate some variables to setup a proper test env
set(DEFAULT_SOUNDFONT "${CMAKE_SOURCE_DIR}/sf2/VintageDreamsWaves-v2.sf2")
# force to build a static lib, in order to bypass the visibility control, allowing us
# to test fluidsynths private/internal functions
set(BUILD_SHARED_LIBS OFF)
add_subdirectory ( test )
endif(enable-tests)
# General configuration file
configure_file ( ${CMAKE_SOURCE_DIR}/src/config.cmake
${CMAKE_BINARY_DIR}/config.h )
# Process subdirectories
add_subdirectory ( src )
add_subdirectory ( doc )

View file

@ -0,0 +1,15 @@
macro ( ADD_FLUID_TEST _test )
ADD_EXECUTABLE(${_test} ${_test}.c)
TARGET_LINK_LIBRARIES(${_test} libfluidsynth)
# use the local include path to look for fluidsynth.h, as we cannot be sure fluidsynth is already installed
target_include_directories(${_test}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include> # include auto generated headers
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include> # include "normal" public (sub-)headers
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/src> # include private headers
$<TARGET_PROPERTY:libfluidsynth,INCLUDE_DIRECTORIES> # include all other header search paths needed by libfluidsynth (esp. glib)
)
ADD_TEST(NAME ${_test} COMMAND ${_test})
endmacro ( ADD_FLUID_TEST )

20
sf2/COPYRIGHT.txt Normal file
View file

@ -0,0 +1,20 @@
Vintage Dreams Waves v 2.0. for Creative Labs' AWE Soundcards
(EMU Soundfont 2 Format)
Copyright (c) Ian Wilson, 1996 (Updated January 1998)
This soundfont is freeware. You may freely use and/or redistribute it subject
to the following terms:
1. It is not altered, edited, modified, ripped, or converted to other formats,
except for private use only.
2. It is distributed with this copyright notice.
This soundfont is distributed WITHOUT WARRANTY, and without the implied
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. No liability
or damages can be inferred upon the said copyright owner, Ian Wilson.
Any feedback, contact Ian Wilson.
vintagedreamworks@hotmail.com
http://www.geocities.com/SiliconValley/Campus/8645/index.html
http://members.nbci.com/silicon39/
http://www.mp3.com/silicon39

Binary file not shown.

View file

@ -362,6 +362,7 @@ if ( MACOSX_FRAMEWORK )
install ( TARGETS fluidsynth libfluidsynth
RUNTIME DESTINATION ${BIN_INSTALL_DIR}
FRAMEWORK DESTINATION ${FRAMEWORK_INSTALL_DIR}
ARCHIVE DESTINATION ${FRAMEWORK_INSTALL_DIR}
)
else ( MACOSX_FRAMEWORK )
install ( TARGETS fluidsynth libfluidsynth

17
test/CMakeLists.txt Normal file
View file

@ -0,0 +1,17 @@
project(fluidsynth-test)
ENABLE_TESTING()
include ( FluidUnitTest )
## add unit tests here ##
ADD_FLUID_TEST(test_sample_cache)
ADD_FLUID_TEST(test_sfont_loading)
add_custom_target(check
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG> --output-on-failure
DEPENDS
test_sample_cache
test_sfont_loading
)

19
test/README.md Normal file
View file

@ -0,0 +1,19 @@
This directory contains small executables to verify fluidsynths correct behaviour, i.e. unit tests.
#### Do *not* blindly use the tests as template for your application!
Although some tests might serve as educational demonstration of how to use certain parts of fluidsynth,
they are **not** intended to do so! It is most likely that those tests will consist of many hacky parts
that are necessary to test fluidsynth (e.g. including fluidsynth's private headers to access internal
data types and functions). For user applications this programming style is strongly discouraged!
Keep referring to the documentation and code examples listed in the [API documentation](http://www.fluidsynth.org/api/).
#### Developers
To add a unit test just duplicate an existing one, give it a unique name and update the CMakeLists.txt by
* adding a call to `ADD_FLUID_TEST()` and
* a dependency to the custom `check` target.
Make sure you call cmake with `-Denable-tests=1` to build and execute the tests via `make check`.

11
test/test.h Normal file
View file

@ -0,0 +1,11 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#define TEST_ASSERT(COND) if (!(COND)) { fprintf(stderr, __FILE__ ":%d assertion ("#COND") failed\n", __LINE__); exit(-1); }
#define TEST_ASSERT_EQ(LHS, RHS) TEST_ASSERT((LHS) == (RHS))
#define TEST_ASSERT_NEQ(LHS, RHS) TEST_ASSERT((LHS) != (RHS))
#define TEST_SUCCESS(FLUID_FUNCT) TEST_ASSERT_NEQ((FLUID_FUNCT), FLUID_FAILED)

48
test/test_sample_cache.c Normal file
View file

@ -0,0 +1,48 @@
#include "test.h"
#include "fluidsynth.h" // use local fluidsynth header
// this test aims to make sure that sample data used by multiple synths is not freed
// once unloaded by its parent synth
int main(void)
{
enum { FRAMES = 1024 };
float buf[FRAMES * 2];
char *s;
fluid_settings_t *settings = new_fluid_settings();
fluid_synth_t *synth1 = new_fluid_synth(settings),
*synth2 = new_fluid_synth(settings);
TEST_ASSERT_NEQ(settings, NULL);
TEST_ASSERT_NEQ(synth1, NULL);
TEST_ASSERT_NEQ(synth2, NULL);
TEST_SUCCESS(fluid_settings_dupstr(settings, "synth.default-soundfont", &s))
TEST_ASSERT_NEQ(s[0], '\0');
printf("Attempt to open %s\n", s);
// load a sfont to synth1
TEST_SUCCESS(fluid_synth_sfload(synth1, s, 1));
// load the same font to synth2 and start a note
TEST_SUCCESS(fluid_synth_sfload(synth2, s, 1));
TEST_SUCCESS(fluid_synth_noteon(synth2, 0, 60, 127));
// render some audio
TEST_SUCCESS(fluid_synth_write_float(synth2, FRAMES, buf, 0, 2, buf, 1, 2));
// delete the synth that owns the soundfont
delete_fluid_synth(synth1);
// render again with the unloaded sfont and hope no segfault happens
TEST_SUCCESS(fluid_synth_write_float(synth2, FRAMES, buf, 0, 2, buf, 1, 2));
delete_fluid_synth(synth2);
delete_fluid_settings(settings);
return EXIT_SUCCESS;
}

71
test/test_sfont_loading.c Normal file
View file

@ -0,0 +1,71 @@
#include "test.h"
#include "fluidsynth.h"
#include "sfloader/fluid_sfont.h"
#include "utils/fluidsynth_priv.h"
// this test aims to make sure that sample data used by multiple synths is not freed
// once unloaded by its parent synth
int main(void)
{
char *s;
int id;
fluid_sfont_t *sfont;
fluid_settings_t *settings = new_fluid_settings();
fluid_synth_t *synth = new_fluid_synth(settings);
TEST_ASSERT_NEQ(settings, NULL);
TEST_ASSERT_NEQ(synth, NULL);
// no sfont loaded
TEST_ASSERT_EQ(fluid_synth_sfcount(synth), 0);
TEST_SUCCESS(fluid_settings_dupstr(settings, "synth.default-soundfont", &s))
TEST_ASSERT_NEQ(s[0], '\0');
FLUID_LOG(FLUID_INFO, "Attempt to open %s", s);
// load a sfont to synth
TEST_SUCCESS(id = fluid_synth_sfload(synth, s, 1));
// one sfont loaded
TEST_ASSERT_EQ(fluid_synth_sfcount(synth), 1);
TEST_ASSERT_NEQ(sfont = fluid_synth_get_sfont_by_id(synth, id), NULL);
// this is still the same filename as we've put in
TEST_ASSERT_EQ(FLUID_STRCMP(s, fluid_sfont_get_name(sfont)), 0);
TEST_ASSERT_EQ(fluid_sfont_get_id(sfont), id);
// still the same id?
TEST_ASSERT_EQ(fluid_synth_sfreload(synth, id), id);
// one sfont loaded
TEST_ASSERT_EQ(fluid_synth_sfcount(synth), 1);
TEST_ASSERT_NEQ(sfont = fluid_synth_get_sfont_by_id(synth, id), NULL);
// still the same filename?
TEST_ASSERT_EQ(FLUID_STRCMP(s, fluid_sfont_get_name(sfont)), 0);
// correct id stored?
TEST_ASSERT_EQ(fluid_sfont_get_id(sfont), id);
// remove the sfont without deleting
TEST_SUCCESS(fluid_synth_remove_sfont(synth, sfont));
// no sfont loaded
TEST_ASSERT_EQ(fluid_synth_sfcount(synth), 0);
// re-add the sfont without deleting
TEST_SUCCESS(id = fluid_synth_add_sfont(synth, sfont));
// one sfont loaded
TEST_ASSERT_EQ(fluid_synth_sfcount(synth), 1);
// destroy the sfont
TEST_SUCCESS(fluid_synth_sfunload(synth, id, 0));
// no sfont loaded
TEST_ASSERT_EQ(fluid_synth_sfcount(synth), 0);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
return EXIT_SUCCESS;
}