196 lines
6.8 KiB
C++
196 lines
6.8 KiB
C++
//------------------------------------------------------------------------
|
|
// Flags : clang-format SMTGSequencer
|
|
// Project : VST SDK
|
|
//
|
|
// Category : Examples
|
|
// Filename : public.sdk/source/vst/utility/testing.h
|
|
// Created by : Steinberg, 04/2021
|
|
// Description : Utility classes for custom testing in the vst validator
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
// This file is part of a Steinberg SDK. It is subject to the license terms
|
|
// in the LICENSE file found in the top-level directory of this distribution
|
|
// and at www.steinberg.net/sdklicenses.
|
|
// No part of the SDK, including this file, may be copied, modified, propagated,
|
|
// or distributed except according to the terms contained in the LICENSE file.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#include "pluginterfaces/test/itest.h"
|
|
#include <cmath>
|
|
#include <functional>
|
|
#include <limits>
|
|
|
|
//------------------------------------------------------------------------
|
|
namespace Steinberg {
|
|
namespace Vst {
|
|
|
|
//------------------------------------------------------------------------
|
|
/** How to use the validator to run your own tests?
|
|
\ingroup TestClass
|
|
|
|
It is possible to run your own tests when the validator checks your plug-in.
|
|
|
|
First you have to register a test factory in your plugin factory:
|
|
|
|
\code{.cpp}
|
|
|
|
#include "public.sdk/source/vst/utility/testing.h"
|
|
|
|
BEGIN_FACTORY_DEF(...
|
|
|
|
DEF_CLASS2 (Your Plugin Processor)
|
|
DEF_CLASS2 (Your Plugin Controller)
|
|
|
|
DEF_CLASS2 (INLINE_UID_FROM_FUID (getTestFactoryUID ()), PClassInfo::kManyInstances, kTestClass,
|
|
"Test Factory", 0, "", "", "", createTestFactoryInstance)
|
|
|
|
END_FACTORY
|
|
|
|
\endcode
|
|
|
|
Second: write your tests:
|
|
|
|
\code{.cpp}
|
|
|
|
#include "public.sdk/source/main/moduleinit.h"
|
|
#include "public.sdk/source/vst/utility/testing.h"
|
|
|
|
static ModuleInitializer InitMyTests ([] () {
|
|
registerTest ("MyTests", STR ("two plus two is four"), [] (ITestResult* testResult) {
|
|
auto result = 2 + 2;
|
|
if (result == 4)
|
|
return true;
|
|
testResult->addErrorMessage (STR ("Unexpected universe change where 2+2 != 4."));
|
|
return false;
|
|
});
|
|
});
|
|
|
|
\endcode
|
|
|
|
If you need access to your audio effect or edit controller you can write your tests as done in the
|
|
adelay example:
|
|
|
|
\code{.cpp}
|
|
|
|
#include "public.sdk/source/main/moduleinit.h"
|
|
#include "public.sdk/source/vst/testsuite/vsttestsuite.h"
|
|
#include "public.sdk/source/vst/utility/testing.h"
|
|
|
|
static ModuleInitializer InitMyTests ([] () {
|
|
registerTest ("MyTests", STR ("check one two three"), [] (FUnknown* context, ITestResult*
|
|
testResult)
|
|
{
|
|
if (auto plugProvider = U::cast<ITestPlugProvider> (context))
|
|
{
|
|
auto controller = plugProvider->getController ();
|
|
auto testController = U::cast<IDelayTestController> (controller);
|
|
if (!controller)
|
|
{
|
|
testResult->addErrorMessage (String ("Unknown IEditController"));
|
|
return false;
|
|
}
|
|
bool result = testController->doTest ();
|
|
plugProvider->releasePlugIn (nullptr, controller);
|
|
|
|
return (result);
|
|
}
|
|
return false;
|
|
});
|
|
});
|
|
|
|
\endcode
|
|
|
|
After that recompile and if the validator does not run automatically after every build, start the
|
|
validator manually and let it check your plug-in.
|
|
|
|
*/
|
|
|
|
//------------------------------------------------------------------------
|
|
/** create a Test Factory instance */
|
|
FUnknown* createTestFactoryInstance (void*);
|
|
|
|
/** the test factory class ID */
|
|
static const DECLARE_UID (TestFactoryUID, 0x70AA33A3, 0x1AE74B24, 0xB726F784, 0xB706C080);
|
|
|
|
/** get the test factory class ID */
|
|
const FUID& getTestFactoryUID ();
|
|
|
|
/** simple test function */
|
|
using TestFunc = std::function<bool (ITestResult*)>;
|
|
/** register a simple test function */
|
|
void registerTest (FIDString name, const tchar* desc, const TestFunc& func);
|
|
/** register a simple test function */
|
|
void registerTest (FIDString name, const tchar* desc, TestFunc&& func);
|
|
|
|
/** test function with context pointer */
|
|
using TestFuncWithContext = std::function<bool (FUnknown*, ITestResult*)>;
|
|
/** register a test function with context pointer */
|
|
void registerTest (FIDString name, const tchar* desc, const TestFuncWithContext& func);
|
|
/** register a test function with context pointer */
|
|
void registerTest (FIDString name, const tchar* desc, TestFuncWithContext&& func);
|
|
|
|
/** register a custom test, the test object will be owned by the implementation */
|
|
void registerTest (FIDString name, ITest* test);
|
|
|
|
//------------------------------------------------------------------------
|
|
namespace Test {
|
|
|
|
//------------------------------------------------------------------------
|
|
template <typename T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
|
|
inline constexpr bool equal (const T& lhs, const T& rhs) noexcept
|
|
{
|
|
return std::abs (lhs - rhs) <= std::numeric_limits<T>::epsilon ();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
|
|
inline constexpr bool equal (const T& lhs, const T& rhs) noexcept
|
|
{
|
|
return lhs == rhs;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template <typename T>
|
|
inline constexpr bool notEqual (const T& lhs, const T& rhs) noexcept
|
|
{
|
|
return equal (lhs, rhs) == false;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
template <typename T>
|
|
inline constexpr bool maxDiff (const T& lhs, const T& rhs, const T& maxDiff) noexcept
|
|
{
|
|
return std::abs (lhs - rhs) <= maxDiff;
|
|
}
|
|
|
|
#ifndef SMTG_DISABLE_VST_TEST_MACROS
|
|
|
|
#ifndef SMTG_MAKE_STRING_PRIVATE_DONT_USE
|
|
#define SMTG_MAKE_STRING_PRIVATE_DONT_USE(x) #x
|
|
#define SMTG_MAKE_STRING(x) SMTG_MAKE_STRING_PRIVATE_DONT_USE (x)
|
|
#endif // SMTG_MAKE_STRING_PRIVATE_DONT_USE
|
|
|
|
#define EXPECT(condition) \
|
|
{ \
|
|
if (!(condition)) \
|
|
{ \
|
|
testResult->addErrorMessage (STR (__FILE__ ":" SMTG_MAKE_STRING ( \
|
|
__LINE__) ": error: " SMTG_MAKE_STRING (condition))); \
|
|
return false; \
|
|
} \
|
|
}
|
|
|
|
#define EXPECT_TRUE(condition) EXPECT (condition)
|
|
#define EXPECT_FALSE(condition) EXPECT (!condition)
|
|
#define EXPECT_EQ(var1, var2) EXPECT ((var1 == var2))
|
|
#define EXPECT_NE(var1, var2) EXPECT ((var1 != var2))
|
|
|
|
#endif // SMTG_DISABLE_VST_TEST_MACROS
|
|
|
|
//------------------------------------------------------------------------
|
|
} // Test
|
|
} // Vst
|
|
} // Steinberg
|