Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@
*.exe
*.out
*.app

# IDE Based files
*.idea

# Build folder
build/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "Dependencies/eigen"]
path = Dependencies/eigen
url = https://gitlab.com/libeigen/eigen
[submodule "Dependencies/Catch2"]
path = Dependencies/Catch2
url = https://github.com/catchorg/Catch2.git
1 change: 1 addition & 0 deletions Dependencies/Catch2
Submodule Catch2 added at a1faad
24 changes: 19 additions & 5 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
file(GLOB_RECURSE NAM_SOURCES ../NAM/*.cpp ../NAM/*.c ../NAM*.h)
file(GLOB TEST_SOURCES test/*.cpp)

set(CATCH_INSTALL_DOCS OFF CACHE BOOL "" FORCE)
set(CATCH_INSTALL_EXTRAS OFF CACHE BOOL "" FORCE)
add_subdirectory(${NAM_DEPS_PATH}/Catch2 Catch2 EXCLUDE_FROM_ALL)

# TODO: add loadmodel and run_tests to TOOLS?
set(TOOLS benchmodel)

add_custom_target(tools ALL
Expand All @@ -12,11 +16,14 @@ include_directories(tools ${NAM_DEPS_PATH}/nlohmann)

add_executable(loadmodel loadmodel.cpp ${NAM_SOURCES})
add_executable(benchmodel benchmodel.cpp ${NAM_SOURCES})
add_executable(run_tests run_tests.cpp ${NAM_SOURCES})
add_executable(run_tests run_tests.cpp ${TEST_SOURCES} ${NAM_SOURCES})

target_link_libraries(run_tests PRIVATE Catch2::Catch2WithMain)

source_group(NAM ${CMAKE_CURRENT_SOURCE_DIR} FILES ${NAM_SOURCES})

target_compile_features(${TOOLS} PUBLIC cxx_std_20)
target_compile_features(run_tests PUBLIC cxx_std_20)

set_target_properties(${TOOLS}
PROPERTIES
Expand All @@ -27,22 +34,29 @@ set_target_properties(${TOOLS}

if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
target_compile_definitions(${TOOLS} PRIVATE NOMINMAX WIN32_LEAN_AND_MEAN)
target_compile_definitions(run_tests PRIVATE NOMINMAX WIN32_LEAN_AND_MEAN)
endif()

if (MSVC)
target_compile_options(${TOOLS} PRIVATE
"$<$<CONFIG:DEBUG>:/W4>"
"$<$<CONFIG:RELEASE>:/O2>"
)
target_compile_options(run_tests PRIVATE
"$<$<CONFIG:DEBUG>:/W4>"
"$<$<CONFIG:RELEASE>:/O2>"
)
else()
target_compile_options(${TOOLS} PRIVATE
-Wall -Wextra -Wpedantic -Wstrict-aliasing -Wunreachable-code -Weffc++ -Wno-unused-parameter
"$<$<CONFIG:DEBUG>:-Og;-ggdb;-Werror>"
"$<$<CONFIG:RELEASE>:-Ofast>"
)
target_compile_options(run_tests PRIVATE
-Wall -Wextra -Wpedantic -Wstrict-aliasing -Wunreachable-code -Weffc++ -Wno-unused-parameter
"$<$<CONFIG:DEBUG>:-Og;-ggdb;-Werror>"
"$<$<CONFIG:RELEASE>:-Ofast>"
)
endif()

# There's an error in eigen's
# /Users/steve/src/NeuralAmpModelerCore/Dependencies/eigen/Eigen/src/Core/products/GeneralBlockPanelKernel.h
# Don't let this break my build on debug:
set_source_files_properties(../NAM/dsp.cpp PROPERTIES COMPILE_FLAGS "-Wno-error")
42 changes: 2 additions & 40 deletions tools/run_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,40 +1,2 @@
// Entry point for tests
// See the GitHub Action for a demo how to build and run tests.

#include <iostream>
#include "test/test_activations.cpp"
#include "test/test_dsp.cpp"
#include "test/test_get_dsp.cpp"
#include "test/test_wavenet.cpp"

int main()
{
std::cout << "Running tests..." << std::endl;
// TODO Automatically loop, catch exceptions, log results

test_activations::TestFastTanh::test_core_function();
test_activations::TestFastTanh::test_get_by_init();
test_activations::TestFastTanh::test_get_by_str();

test_activations::TestLeakyReLU::test_core_function();
test_activations::TestLeakyReLU::test_get_by_init();
test_activations::TestLeakyReLU::test_get_by_str();

test_dsp::test_construct();
test_dsp::test_get_input_level();
test_dsp::test_get_output_level();
test_dsp::test_has_input_level();
test_dsp::test_has_output_level();
test_dsp::test_set_input_level();
test_dsp::test_set_output_level();

test_get_dsp::test_gets_input_level();
test_get_dsp::test_gets_output_level();
test_get_dsp::test_null_input_level();
test_get_dsp::test_null_output_level();

test_wavenet::test_gated();

std::cout << "Success!" << std::endl;
return 0;
}
#define CATCH_CONFIG_MAIN
#include <catch2/catch_test_macros.hpp>
160 changes: 42 additions & 118 deletions tools/test/test_activations.cpp
Original file line number Diff line number Diff line change
@@ -1,122 +1,46 @@
// Tests for activation functions
//
// Things you want ot test for:
// 1. That the core elementwise funciton is snapshot-correct.
// 2. The class that wraps the core function for an array of data
// 3. .cpp: that you have the singleton defined, and that it's in the unordered map to get by string

#include <cassert>
#include <string>
#include <vector>

#include <catch2/catch_test_macros.hpp>
#include "NAM/activations.h"

namespace test_activations
{
// TODO get nonzero cases
class TestFastTanh
{
public:
static void test_core_function()
{
auto TestCase = [](float input, float expectedOutput) {
float actualOutput = nam::activations::fast_tanh(input);
assert(actualOutput == expectedOutput);
};
// A few snapshot tests
TestCase(0.0f, 0.0f);
// TestCase(1.0f, 1.0f);
// TestCase(-1.0f, -0.01f);
};

static void test_get_by_init()
{
auto a = nam::activations::ActivationLeakyReLU();
_test_class(&a);
TEST_CASE("FastTanh core function", "[activations]") {
REQUIRE(nam::activations::fast_tanh(0.0f) == 0.0f);
}

TEST_CASE("FastTanh get by init", "[activations]") {
auto a = nam::activations::ActivationLeakyReLU();
std::vector<float> inputs{0.0f};
a.apply(inputs.data(), inputs.size());
REQUIRE(inputs[0] == 0.0f);
}

TEST_CASE("FastTanh get by string", "[activations]") {
auto a = nam::activations::Activation::get_activation("Fasttanh");
std::vector<float> inputs{0.0f};
a->apply(inputs.data(), inputs.size());
REQUIRE(inputs[0] == 0.0f);
}

TEST_CASE("LeakyReLU core function", "[activations]") {
REQUIRE(nam::activations::leaky_relu(0.0f) == 0.0f);
REQUIRE(nam::activations::leaky_relu(1.0f) == 1.0f);
REQUIRE(nam::activations::leaky_relu(-1.0f) == -0.01f);
}

TEST_CASE("LeakyReLU get by init", "[activations]") {
auto a = nam::activations::ActivationLeakyReLU();
std::vector<float> inputs{0.0f, 1.0f, -1.0f};
std::vector<float> expected{0.0f, 1.0f, -0.01f};
a.apply(inputs.data(), inputs.size());
for (size_t i = 0; i < inputs.size(); ++i) {
REQUIRE(inputs[i] == expected[i]);
}

// Get the singleton and test it
static void test_get_by_str()
{
const std::string name = "Fasttanh";
auto a = nam::activations::Activation::get_activation(name);
_test_class(a);
}

TEST_CASE("LeakyReLU get by string", "[activations]") {
auto a = nam::activations::Activation::get_activation("LeakyReLU");
std::vector<float> inputs{0.0f, 1.0f, -1.0f};
std::vector<float> expected{0.0f, 1.0f, -0.01f};
a->apply(inputs.data(), inputs.size());
for (size_t i = 0; i < inputs.size(); ++i) {
REQUIRE(inputs[i] == expected[i]);
}

private:
// Put the class through its paces
static void _test_class(nam::activations::Activation* a)
{
std::vector<float> inputs, expectedOutputs;

inputs.push_back(0.0f);
expectedOutputs.push_back(0.0f);

// inputs.push_back(1.0f);
// expectedOutputs.push_back(1.0f);

// inputs.push_back(-1.0f);
// expectedOutputs.push_back(-0.01f);

a->apply(inputs.data(), (long)inputs.size());
for (auto itActual = inputs.begin(), itExpected = expectedOutputs.begin(); itActual != inputs.end();
++itActual, ++itExpected)
{
assert(*itActual == *itExpected);
}
};
};

class TestLeakyReLU
{
public:
static void test_core_function()
{
auto TestCase = [](float input, float expectedOutput) {
float actualOutput = nam::activations::leaky_relu(input);
assert(actualOutput == expectedOutput);
};
// A few snapshot tests
TestCase(0.0f, 0.0f);
TestCase(1.0f, 1.0f);
TestCase(-1.0f, -0.01f);
};

static void test_get_by_init()
{
auto a = nam::activations::ActivationLeakyReLU();
_test_class(&a);
}

// Get the singleton and test it
static void test_get_by_str()
{
const std::string name = "LeakyReLU";
auto a = nam::activations::Activation::get_activation(name);
_test_class(a);
}

private:
// Put the class through its paces
static void _test_class(nam::activations::Activation* a)
{
std::vector<float> inputs, expectedOutputs;

inputs.push_back(0.0f);
expectedOutputs.push_back(0.0f);

inputs.push_back(1.0f);
expectedOutputs.push_back(1.0f);

inputs.push_back(-1.0f);
expectedOutputs.push_back(-0.01f);

a->apply(inputs.data(), (long)inputs.size());
for (auto itActual = inputs.begin(), itExpected = expectedOutputs.begin(); itActual != inputs.end();
++itActual, ++itExpected)
{
assert(*itActual == *itExpected);
}
};
};
}; // namespace test_activations
}
52 changes: 16 additions & 36 deletions tools/test/test_dsp.cpp
Original file line number Diff line number Diff line change
@@ -1,66 +1,46 @@
// Tests for dsp

#include <catch2/catch_test_macros.hpp>
#include "NAM/dsp.h"

namespace test_dsp
{
// Simplest test: can I construct something!
void test_construct()
{
TEST_CASE("DSP construct", "[dsp]") {
nam::DSP myDsp(48000.0);
}

void test_get_input_level()
{
TEST_CASE("DSP get input level", "[dsp]") {
nam::DSP myDsp(48000.0);
const double expected = 19.0;
myDsp.SetInputLevel(expected);
assert(myDsp.HasInputLevel());
const double actual = myDsp.GetInputLevel();

assert(actual == expected);
REQUIRE(myDsp.HasInputLevel());
REQUIRE(myDsp.GetInputLevel() == expected);
}

void test_get_output_level()
{
TEST_CASE("DSP get output level", "[dsp]") {
nam::DSP myDsp(48000.0);
const double expected = 12.0;
myDsp.SetOutputLevel(expected);
assert(myDsp.HasOutputLevel());
const double actual = myDsp.GetOutputLevel();

assert(actual == expected);
REQUIRE(myDsp.HasOutputLevel());
REQUIRE(myDsp.GetOutputLevel() == expected);
}

// Test correct function of DSP::HasInputLevel()
void test_has_input_level()
{
TEST_CASE("DSP has input level", "[dsp]") {
nam::DSP myDsp(48000.0);
assert(!myDsp.HasInputLevel());

REQUIRE(!myDsp.HasInputLevel());
myDsp.SetInputLevel(19.0);
assert(myDsp.HasInputLevel());
REQUIRE(myDsp.HasInputLevel());
}

void test_has_output_level()
{
TEST_CASE("DSP has output level", "[dsp]") {
nam::DSP myDsp(48000.0);
assert(!myDsp.HasOutputLevel());

REQUIRE(!myDsp.HasOutputLevel());
myDsp.SetOutputLevel(12.0);
assert(myDsp.HasOutputLevel());
REQUIRE(myDsp.HasOutputLevel());
}

// Test correct function of DSP::HasInputLevel()
void test_set_input_level()
{
TEST_CASE("DSP set input level", "[dsp]") {
nam::DSP myDsp(48000.0);
myDsp.SetInputLevel(19.0);
}

void test_set_output_level()
{
TEST_CASE("DSP set output level", "[dsp]") {
nam::DSP myDsp(48000.0);
myDsp.SetOutputLevel(19.0);
}
}; // namespace test_dsp
Loading