Initial release
This commit is contained in:
+159
@@ -0,0 +1,159 @@
|
||||
|
||||
set(validator_sources
|
||||
${SDK_ROOT}/public.sdk/source/common/memorystream.cpp
|
||||
${SDK_ROOT}/public.sdk/source/main/moduleinit.cpp
|
||||
${SDK_ROOT}/public.sdk/source/main/moduleinit.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/moduleinfo/moduleinfoparser.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/moduleinfo/moduleinfoparser.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/test/connectionproxytest.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/test/eventlisttest.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/test/hostclassestest.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/test/parameterchangestest.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/test/pluginterfacesupporttest.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/test/processdatatest.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/plugprovider.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/plugprovider.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/busactivation.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/busactivation.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/busconsistency.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/busconsistency.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/businvalidindex.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/businvalidindex.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/checkaudiobusarrangement.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/checkaudiobusarrangement.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/scanbusses.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/scanbusses.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/sidechainarrangement.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/bus/sidechainarrangement.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/editorclasses.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/editorclasses.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/midilearn.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/midilearn.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/midimapping.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/midimapping.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/plugcompat.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/plugcompat.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/scanparameters.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/scanparameters.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/suspendresume.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/suspendresume.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/terminit.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/general/terminit.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/noteexpression/keyswitch.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/noteexpression/keyswitch.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/noteexpression/noteexpression.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/noteexpression/noteexpression.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/automation.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/automation.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/process.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/process.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processcontextrequirements.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processcontextrequirements.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processformat.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processformat.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processinputoverwriting.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processinputoverwriting.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processtail.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processtail.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processthreaded.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/processthreaded.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/silenceflags.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/silenceflags.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/silenceprocessing.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/silenceprocessing.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/speakerarrangement.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/speakerarrangement.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/variableblocksize.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/processing/variableblocksize.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/bypasspersistence.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/bypasspersistence.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/invalidstatetransition.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/invalidstatetransition.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/repeatidenticalstatetransition.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/repeatidenticalstatetransition.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/validstatetransition.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/state/validstatetransition.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/testbase.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/testbase.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/checkunitstructure.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/checkunitstructure.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/scanprograms.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/scanprograms.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/scanunits.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/unit/scanunits.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/vststructsizecheck.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/vsttestsuite.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/testsuite/vsttestsuite.h
|
||||
${SDK_ROOT}/public.sdk/source/vst/utility/testing.cpp
|
||||
${SDK_ROOT}/public.sdk/source/vst/utility/testing.h
|
||||
source/main.cpp
|
||||
source/usediids.cpp
|
||||
source/validator.cpp
|
||||
source/validator.h
|
||||
source/testsuite.h
|
||||
)
|
||||
|
||||
if(SMTG_MAC)
|
||||
set(validator_sources
|
||||
${validator_sources}
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm
|
||||
)
|
||||
set_source_files_properties(
|
||||
"${SDK_ROOT}/public.sdk/source/vst/hosting/module_mac.mm" PROPERTIES
|
||||
COMPILE_FLAGS "-fobjc-arc"
|
||||
)
|
||||
elseif(SMTG_LINUX)
|
||||
set(validator_sources
|
||||
${validator_sources}
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/module_linux.cpp
|
||||
)
|
||||
elseif(SMTG_WIN)
|
||||
set(validator_sources
|
||||
${validator_sources}
|
||||
${SDK_ROOT}/public.sdk/source/vst/hosting/module_win32.cpp
|
||||
)
|
||||
endif(SMTG_MAC)
|
||||
|
||||
set(target validator)
|
||||
add_executable(${target} ${validator_sources})
|
||||
if(SDK_IDE_HOSTING_EXAMPLES_FOLDER)
|
||||
set_target_properties(${target}
|
||||
PROPERTIES
|
||||
${SDK_IDE_HOSTING_EXAMPLES_FOLDER}
|
||||
)
|
||||
endif(SDK_IDE_HOSTING_EXAMPLES_FOLDER)
|
||||
target_compile_features(${target}
|
||||
PUBLIC
|
||||
cxx_std_17
|
||||
)
|
||||
target_link_libraries(${target}
|
||||
PRIVATE
|
||||
sdk_hosting
|
||||
)
|
||||
smtg_target_codesign(${target})
|
||||
smtg_target_setup_universal_binary(${target})
|
||||
if(APPLE AND NOT XCODE)
|
||||
find_library(COCOA_FRAMEWORK Cocoa)
|
||||
target_link_libraries(${target}
|
||||
PRIVATE
|
||||
${COCOA_FRAMEWORK}
|
||||
)
|
||||
endif(APPLE AND NOT XCODE)
|
||||
|
||||
#####################################################
|
||||
if(SMTG_RUN_VST_VALIDATOR)
|
||||
####################
|
||||
# Workaround for Xcode 15 not allowing to add adhoc_codesign linker setting
|
||||
####################
|
||||
if(SMTG_MAC AND XCODE_VERSION VERSION_GREATER_EQUAL 15)
|
||||
add_custom_command(
|
||||
TARGET ${target} POST_BUILD
|
||||
COMMENT "[SMTG] Adhoc codesign workaround for Xcode 15"
|
||||
COMMAND codesign --force --verbose --sign -
|
||||
"$<TARGET_FILE:${target}>"
|
||||
)
|
||||
endif()
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND $<TARGET_FILE:${target}> "-selftest"
|
||||
)
|
||||
endif(SMTG_RUN_VST_VALIDATOR)
|
||||
@@ -0,0 +1,18 @@
|
||||
# Validator
|
||||
|
||||
## Introduction
|
||||
|
||||
Validator is a small command line host application which can be used to check your plug-in for **VST 3** conformity.
|
||||
|
||||
> See also: [Online Documentation](https://steinbergmedia.github.io/vst3_dev_portal/pages/What+is+the+VST+3+SDK/Validator.html).
|
||||
|
||||
## Getting Started
|
||||
|
||||
This application is part of the VST 3 SDK package. It is created with the VST 3 SDK root project.
|
||||
|
||||
> See the top-level README of the VST 3 SDK: https://github.com/steinbergmedia/vst3sdk.git
|
||||
|
||||
## Getting Help
|
||||
|
||||
* Read through the SDK documentation on the **[VST 3 Developer Portal](https://steinbergmedia.github.io/vst3_dev_portal/pages/index.html)**
|
||||
* Ask some real people in the official **[VST 3 Developer Forum](https://forums.steinberg.net/c/developer/103)**
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : Validator
|
||||
// Filename : public.sdk/samples/vst-hosting/validator/source/main.cpp
|
||||
// Created by : Steinberg, 04/2005
|
||||
// Description : main entry point
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "validator.h"
|
||||
#include "public.sdk/source/vst/utility/stringconvert.h"
|
||||
|
||||
void* moduleHandle = nullptr;
|
||||
extern bool InitModule ();
|
||||
extern bool DeinitModule ();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int run (int argc, char* argv[])
|
||||
{
|
||||
InitModule ();
|
||||
|
||||
auto result = Steinberg::Vst::Validator (argc, argv).run ();
|
||||
|
||||
DeinitModule ();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
#if SMTG_OS_WINDOWS
|
||||
//------------------------------------------------------------------------
|
||||
using Utf8String = std::string;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
using Utf8Args = std::vector<Utf8String>;
|
||||
Utf8Args toUtf8Args (int argc, wchar_t* wargv[])
|
||||
{
|
||||
Utf8Args utf8Args;
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
auto str = reinterpret_cast<const Steinberg::Vst::TChar*> (wargv[i]);
|
||||
utf8Args.push_back (Steinberg::Vst::StringConvert::convert (str));
|
||||
}
|
||||
|
||||
return utf8Args;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
using Utf8ArgPtrs = std::vector<char*>;
|
||||
Utf8ArgPtrs toUtf8ArgPtrs (Utf8Args& utf8Args)
|
||||
{
|
||||
Utf8ArgPtrs utf8ArgPtrs;
|
||||
for (auto& el : utf8Args)
|
||||
{
|
||||
utf8ArgPtrs.push_back (el.data ());
|
||||
}
|
||||
|
||||
return utf8ArgPtrs;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int wmain (int argc, wchar_t* wargv[])
|
||||
{
|
||||
Utf8Args utf8Args = toUtf8Args (argc, wargv);
|
||||
Utf8ArgPtrs utf8ArgPtrs = toUtf8ArgPtrs (utf8Args);
|
||||
|
||||
char** argv = &(utf8ArgPtrs.at (0));
|
||||
return run (argc, argv);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int main (int argc, char* argv[])
|
||||
{
|
||||
return run (argc, argv);
|
||||
}
|
||||
|
||||
#endif // SMTG_OS_WINDOWS
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags : clang-format SMTGSequencer
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : Validator
|
||||
// Filename : public.sdk/samples/vst-hosting/validator/source/testsuite.h
|
||||
// Created by : Steinberg, 05/2019
|
||||
// Description : VST 3 Plug-in Validator test suite class
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "base/source/fobject.h"
|
||||
#include "pluginterfaces/test/itest.h"
|
||||
#include <vector>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace Steinberg {
|
||||
namespace Vst {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// TestSuite
|
||||
//------------------------------------------------------------------------
|
||||
class TestSuite : public ITestSuite, public FObject
|
||||
{
|
||||
public:
|
||||
TestSuite (FIDString _name) : name (_name) {}
|
||||
|
||||
tresult PLUGIN_API addTest (FIDString _name, ITest* test) SMTG_OVERRIDE
|
||||
{
|
||||
tests.push_back (IPtr<Test> (NEW Test (_name, test), false));
|
||||
return kResultTrue;
|
||||
}
|
||||
|
||||
tresult PLUGIN_API addTestSuite (FIDString _name, ITestSuite* testSuite) SMTG_OVERRIDE
|
||||
{
|
||||
testSuites.push_back (std::make_pair (_name, testSuite));
|
||||
return kResultTrue;
|
||||
}
|
||||
|
||||
tresult PLUGIN_API setEnvironment (ITest* /*environment*/) SMTG_OVERRIDE
|
||||
{
|
||||
return kNotImplemented;
|
||||
}
|
||||
|
||||
int32 getTestCount () const { return static_cast<int32> (tests.size ()); }
|
||||
|
||||
tresult getTest (int32 index, ITest*& _test, std::string& _name) const
|
||||
{
|
||||
if (auto test = tests.at (index))
|
||||
{
|
||||
_test = test->test;
|
||||
_name = test->name;
|
||||
return kResultTrue;
|
||||
}
|
||||
return kResultFalse;
|
||||
}
|
||||
|
||||
tresult getTestSuite (int32 index, ITestSuite*& testSuite, std::string& _name) const
|
||||
{
|
||||
if (index < 0 || index >= int32 (testSuites.size ()))
|
||||
return kInvalidArgument;
|
||||
const auto& ts = testSuites[index];
|
||||
_name = ts.first;
|
||||
testSuite = ts.second;
|
||||
return kResultTrue;
|
||||
}
|
||||
|
||||
ITestSuite* getTestSuite (FIDString _name) const
|
||||
{
|
||||
for (const auto& testSuite : testSuites)
|
||||
{
|
||||
if (testSuite.first == _name)
|
||||
return testSuite.second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string& getName () const { return name; }
|
||||
OBJ_METHODS (TestSuite, FObject)
|
||||
REFCOUNT_METHODS (FObject)
|
||||
DEF_INTERFACES_1 (ITestSuite, FObject)
|
||||
protected:
|
||||
class Test : public FObject
|
||||
{
|
||||
public:
|
||||
Test (FIDString _name, ITest* _test) : name (_name), test (_test) {}
|
||||
|
||||
std::string name;
|
||||
IPtr<ITest> test;
|
||||
};
|
||||
std::string name;
|
||||
std::vector<IPtr<Test>> tests;
|
||||
|
||||
using TestSuitePair = std::pair<std::string, IPtr<ITestSuite>>;
|
||||
using TestSuiteVector = std::vector<TestSuitePair>;
|
||||
TestSuiteVector testSuites;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // Vst
|
||||
} // Steinberg
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : Validator
|
||||
// Filename : public.sdk/samples/vst-hosting/validator/source/usediids.cpp
|
||||
// Created by : Steinberg 09.2008
|
||||
// Description : Interface symbols file
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
//#define INIT_CLASS_IID
|
||||
// This macro definition modifies the behavior of DECLARE_CLASS_IID (funknown.h)
|
||||
// and produces the actual symbols for all interface identifiers.
|
||||
// It must be defined before including the interface headers and
|
||||
// in only one source file!
|
||||
//------------------------------------------------------------------------
|
||||
//#define INIT_CLASS_IID
|
||||
|
||||
#include "pluginterfaces/base/ipluginbase.h"
|
||||
#include "pluginterfaces/test/itest.h"
|
||||
|
||||
namespace Steinberg {
|
||||
DEF_CLASS_IID (ITestResult)
|
||||
}
|
||||
+837
@@ -0,0 +1,837 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags : clang-format SMTGSequencer
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : Validator
|
||||
// Filename : public.sdk/samples/vst-hosting/validator/source/validator.cpp
|
||||
// Created by : Steinberg, 04/2005
|
||||
// Description : VST 3 Plug-in Validator class
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "validator.h"
|
||||
#include "testsuite.h"
|
||||
#include "public.sdk/source/vst/hosting/plugprovider.h"
|
||||
#include "public.sdk/source/vst/testsuite/general/plugcompat.h"
|
||||
#include "public.sdk/source/vst/testsuite/vststructsizecheck.h"
|
||||
#include "public.sdk/source/vst/utility/stringconvert.h"
|
||||
#include "public.sdk/source/vst/utility/testing.h"
|
||||
#include "base/source/fcommandline.h"
|
||||
#include "pluginterfaces/base/iplugincompatibility.h"
|
||||
#include "pluginterfaces/vst/ivstaudioprocessor.h"
|
||||
#include "pluginterfaces/vst/ivstcomponent.h"
|
||||
#include "pluginterfaces/vst/ivsteditcontroller.h"
|
||||
#include "pluginterfaces/vst/ivsthostapplication.h"
|
||||
#include "pluginterfaces/vst/ivstunits.h"
|
||||
|
||||
#include "pluginterfaces/base/funknownimpl.h"
|
||||
#include "pluginterfaces/gui/iplugview.h"
|
||||
|
||||
#if SMTG_OS_WINDOWS
|
||||
#include <conio.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace Steinberg {
|
||||
namespace Vst {
|
||||
namespace {
|
||||
|
||||
constexpr auto SEPARATOR = "-------------------------------------------------------------\n";
|
||||
constexpr auto VALIDATOR_INFO = kVstVersionString
|
||||
" Plug-in Validator\n"
|
||||
"Program by Steinberg (Built on " __DATE__ ")\n";
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool filterClassCategory (FIDString category, FIDString classCategory)
|
||||
{
|
||||
return strcmp (category, classCategory) == 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void printAllInstalledPlugins (std::ostream* os)
|
||||
{
|
||||
if (!os)
|
||||
return;
|
||||
|
||||
*os << "Searching installed Plug-ins...\n";
|
||||
os->flush ();
|
||||
|
||||
auto paths = VST3::Hosting::Module::getModulePaths ();
|
||||
if (paths.empty ())
|
||||
{
|
||||
*os << "No Plug-ins found.\n";
|
||||
return;
|
||||
}
|
||||
for (const auto& path : paths)
|
||||
{
|
||||
*os << path << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void printAllSnapshots (std::ostream* os)
|
||||
{
|
||||
if (!os)
|
||||
return;
|
||||
*os << "Searching installed Plug-ins...\n";
|
||||
auto paths = VST3::Hosting::Module::getModulePaths ();
|
||||
if (paths.empty ())
|
||||
{
|
||||
*os << "No Plug-ins found.\n";
|
||||
return;
|
||||
}
|
||||
for (const auto& path : paths)
|
||||
{
|
||||
auto snapshots = VST3::Hosting::Module::getSnapshots (path);
|
||||
if (snapshots.empty ())
|
||||
{
|
||||
*os << "No snapshots in " << path << "\n";
|
||||
continue;
|
||||
}
|
||||
for (auto& snapshot : snapshots)
|
||||
{
|
||||
for (auto& desc : snapshot.images)
|
||||
{
|
||||
*os << "Snapshot : " << desc.path << "[" << desc.scaleFactor << "x]\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void printFactoryInfo (const VST3::Hosting::PluginFactory& factory, std::ostream* os)
|
||||
{
|
||||
if (os)
|
||||
{
|
||||
*os << "* Scanning classes...\n\n";
|
||||
|
||||
auto factoryInfo = factory.info ();
|
||||
|
||||
*os << " Factory Info:\n\tvendor = " << factoryInfo.vendor ()
|
||||
<< "\n\turl = " << factoryInfo.url () << "\n\temail = " << factoryInfo.email ()
|
||||
<< "\n\n";
|
||||
|
||||
//---print all included plug-ins---------------
|
||||
uint32 i = 0;
|
||||
for (auto& classInfo : factory.classInfos ())
|
||||
{
|
||||
*os << " Class Info " << i << ":\n\tname = " << classInfo.name ()
|
||||
<< "\n\tcategory = " << classInfo.category ()
|
||||
<< "\n\tsubCategories = " << classInfo.subCategoriesString ()
|
||||
<< "\n\tversion = " << classInfo.version ()
|
||||
<< "\n\tsdkVersion = " << classInfo.sdkVersion ()
|
||||
<< "\n\tcid = " << classInfo.ID ().toString () << "\n\n";
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void checkModuleSnapshots (const VST3::Hosting::Module::Ptr& module, std::ostream* infoStream)
|
||||
{
|
||||
if (infoStream)
|
||||
*infoStream << "* Checking snapshots...\n\n";
|
||||
|
||||
auto snapshots = VST3::Hosting::Module::getSnapshots (module->getPath ());
|
||||
if (snapshots.empty ())
|
||||
{
|
||||
if (infoStream)
|
||||
*infoStream << "Info: No snapshots in Bundle.\n\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& classInfo : module->getFactory ().classInfos ())
|
||||
{
|
||||
if (!filterClassCategory (kVstAudioEffectClass, classInfo.category ().data ()))
|
||||
continue;
|
||||
bool found = false;
|
||||
for (auto& snapshot : snapshots)
|
||||
{
|
||||
if (snapshot.uid == classInfo.ID ())
|
||||
{
|
||||
found = true;
|
||||
if (infoStream)
|
||||
{
|
||||
*infoStream << "Found snapshots for '" << classInfo.name () << "'\n";
|
||||
for (auto& image : snapshot.images)
|
||||
*infoStream << " - " << image.path << " [" << image.scaleFactor
|
||||
<< "x]\n";
|
||||
*infoStream << "\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
if (infoStream)
|
||||
{
|
||||
*infoStream << "Info: No snapshot for '" << classInfo.name ()
|
||||
<< "' in Bundle.\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SMTG_OS_LINUX
|
||||
//------------------------------------------------------------------------
|
||||
struct DummyRunLoop : U::ImplementsNonDestroyable<U::Directly<Steinberg::Linux::IRunLoop>>
|
||||
{
|
||||
using IEventHandler = Steinberg::Linux::IEventHandler;
|
||||
using ITimerHandler = Steinberg::Linux::ITimerHandler;
|
||||
using FileDescriptor = Steinberg::Linux::FileDescriptor;
|
||||
using TimerInterval = Steinberg::Linux::TimerInterval;
|
||||
|
||||
static Steinberg::Linux::IRunLoop& instance ()
|
||||
{
|
||||
static DummyRunLoop drl;
|
||||
return drl;
|
||||
}
|
||||
tresult PLUGIN_API registerEventHandler (IEventHandler* handler, FileDescriptor fd) override
|
||||
{
|
||||
return kNotImplemented;
|
||||
}
|
||||
tresult PLUGIN_API unregisterEventHandler (IEventHandler* handler) override
|
||||
{
|
||||
return kNotImplemented;
|
||||
}
|
||||
tresult PLUGIN_API registerTimer (ITimerHandler* handler, TimerInterval milliseconds) override
|
||||
{
|
||||
return kNotImplemented;
|
||||
}
|
||||
tresult PLUGIN_API unregisterTimer (ITimerHandler* handler) override { return kNotImplemented; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//-- Options
|
||||
constexpr auto optHelp = "help";
|
||||
constexpr auto optVersion = "version";
|
||||
constexpr auto optLocalInstance = "l";
|
||||
constexpr auto optSuiteName = "suite";
|
||||
constexpr auto optExtensiveTests = "e";
|
||||
constexpr auto optQuiet = "q";
|
||||
constexpr auto optTestComponentPath = "test-component";
|
||||
constexpr auto optListInstalledPlugIns = "list";
|
||||
constexpr auto optListPlugInSnapshots = "snapshots";
|
||||
constexpr auto optCID = "cid";
|
||||
constexpr auto optSelftest = "selftest";
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // anonymous
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Validator
|
||||
//------------------------------------------------------------------------
|
||||
Validator::Validator (int argc, char* argv[]) : argc (argc), argv (argv)
|
||||
{
|
||||
infoStream = &std::cout;
|
||||
errorStream = &std::cout;
|
||||
errorStream->setf (std::ios::unitbuf);
|
||||
|
||||
mPlugInterfaceSupport = owned (NEW PlugInterfaceSupport);
|
||||
|
||||
PluginContextFactory::instance ().setPluginContext (this->unknownCast ());
|
||||
TestingPluginContext::set (this->unknownCast ());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
Validator::~Validator ()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
tresult PLUGIN_API Validator::queryInterface (const char* _iid, void** obj)
|
||||
{
|
||||
QUERY_INTERFACE (_iid, obj, IHostApplication::iid, IHostApplication)
|
||||
QUERY_INTERFACE (_iid, obj, ITestResult::iid, ITestResult)
|
||||
|
||||
if (mPlugInterfaceSupport && mPlugInterfaceSupport->queryInterface (_iid, obj) == kResultTrue)
|
||||
return ::Steinberg::kResultOk;
|
||||
|
||||
return FObject::queryInterface (_iid, obj);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void PLUGIN_API Validator::addErrorMessage (const tchar* msg)
|
||||
{
|
||||
if (errorStream)
|
||||
{
|
||||
auto str = StringConvert::convert (msg);
|
||||
if (addErrorWarningTextToOutput)
|
||||
*errorStream << "ERROR: " << str << "\n";
|
||||
else
|
||||
*errorStream << str << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void PLUGIN_API Validator::addMessage (const tchar* msg)
|
||||
{
|
||||
if (infoStream)
|
||||
{
|
||||
auto str = StringConvert::convert (msg);
|
||||
if (addErrorWarningTextToOutput)
|
||||
*infoStream << "Info: " << str << "\n";
|
||||
else
|
||||
*infoStream << str << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API Validator::getName (String128 name)
|
||||
{
|
||||
StringConvert::convert ("vstvalidator", name, 127);
|
||||
return kResultTrue;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
tresult PLUGIN_API Validator::createInstance (TUID cid, TUID iid, void** obj)
|
||||
{
|
||||
FUID classID = FUID::fromTUID (cid);
|
||||
FUID interfaceID = FUID::fromTUID (iid);
|
||||
if (classID == IMessage::iid && interfaceID == IMessage::iid)
|
||||
{
|
||||
*obj = new HostMessage;
|
||||
return kResultTrue;
|
||||
}
|
||||
else if (classID == IAttributeList::iid && interfaceID == IAttributeList::iid)
|
||||
{
|
||||
if (auto al = HostAttributeList::make ())
|
||||
{
|
||||
*obj = al.take ();
|
||||
return kResultTrue;
|
||||
}
|
||||
return kOutOfMemory;
|
||||
}
|
||||
*obj = nullptr;
|
||||
return kResultFalse;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int Validator::run ()
|
||||
{
|
||||
// defaults
|
||||
bool useGlobalInstance = true;
|
||||
bool useExtensiveTests = false;
|
||||
std::string testSuiteName;
|
||||
|
||||
// parse command line
|
||||
CommandLine::Descriptions desc;
|
||||
CommandLine::VariablesMap valueMap;
|
||||
CommandLine::FilesVector files;
|
||||
|
||||
using Description = CommandLine::Description;
|
||||
desc.addOptions (
|
||||
kVstVersionString " Plug-in Validator",
|
||||
{{optHelp, "Print help", Description::kBool},
|
||||
{optVersion, "Print version", Description::kBool},
|
||||
{optLocalInstance, "Use local instance per test", Description::kBool},
|
||||
{optSuiteName, "[name] Only run a special test suite", Description::kString},
|
||||
{optExtensiveTests, "Run extensive tests [may take a long time]", Description::kBool},
|
||||
{optQuiet, "Only print errors", Description::kBool},
|
||||
{optCID, "Only test processor with specified class ID", Description::kString},
|
||||
{optTestComponentPath,
|
||||
"[path] Path to an additional component which includes custom tests",
|
||||
Description::kString},
|
||||
{optListInstalledPlugIns, "Show all installed Plug-Ins", Description::kBool},
|
||||
{optSelftest, "Run a selftest", Description::kBool},
|
||||
{optListPlugInSnapshots, "List snapshots from all installed Plug-Ins",
|
||||
Description::kBool}});
|
||||
|
||||
CommandLine::parse (argc, argv, desc, valueMap, &files);
|
||||
if (valueMap.count (optVersion))
|
||||
{
|
||||
std::cout << VALIDATOR_INFO;
|
||||
return 0;
|
||||
}
|
||||
else if (valueMap.count (optListInstalledPlugIns))
|
||||
{
|
||||
printAllInstalledPlugins (infoStream);
|
||||
return 0;
|
||||
}
|
||||
else if (valueMap.count (optListPlugInSnapshots))
|
||||
{
|
||||
printAllSnapshots (infoStream);
|
||||
return 0;
|
||||
}
|
||||
else if (valueMap.count (optSelftest))
|
||||
{
|
||||
addErrorWarningTextToOutput = false;
|
||||
auto testFactoryInstance = owned (createTestFactoryInstance (nullptr));
|
||||
if (auto testFactory = U::cast<ITestFactory> (testFactoryInstance))
|
||||
{
|
||||
std::cout << "Running validator selftest:\n\n";
|
||||
IPtr<TestSuite> testSuite = owned (new TestSuite (""));
|
||||
if (testFactory->createTests (nullptr, testSuite) == kResultTrue)
|
||||
runTestSuite (testSuite, nullptr);
|
||||
std::cout << "Executed " << (numTestsFailed + numTestsPassed) << " Tests.\n";
|
||||
std::cout << numTestsFailed << " failed test(s).\n";
|
||||
return numTestsFailed == 0 ? 0 : 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else if (valueMap.hasError () || valueMap.count (optHelp) || files.empty ())
|
||||
{
|
||||
std::cout << "\n" << desc << "\n";
|
||||
std::cout << "Usage: vstvalidator [options] vst3module\n\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (valueMap.count (optLocalInstance))
|
||||
useGlobalInstance = false;
|
||||
if (valueMap.count (optExtensiveTests))
|
||||
useExtensiveTests = true;
|
||||
if (valueMap.count (optQuiet))
|
||||
infoStream = nullptr;
|
||||
if (valueMap.count (optSuiteName))
|
||||
testSuiteName = valueMap[optSuiteName];
|
||||
VST3::Optional<VST3::UID> testProcessor;
|
||||
if (valueMap.count (optCID))
|
||||
testProcessor = VST3::UID::fromString (valueMap[optCID]);
|
||||
std::string customTestComponentPath;
|
||||
if (valueMap.count (optTestComponentPath))
|
||||
customTestComponentPath = valueMap[optTestComponentPath];
|
||||
|
||||
auto globalFailure = false;
|
||||
for (auto& path : files)
|
||||
{
|
||||
|
||||
#if SMTG_OS_WINDOWS
|
||||
// TODO: Impl
|
||||
#else
|
||||
// if path is not absolute, create one
|
||||
if (path[0] != '/')
|
||||
{
|
||||
auto realPath = realpath (path.data (), NULL);
|
||||
if (realPath)
|
||||
{
|
||||
path.assign (realPath);
|
||||
free (realPath);
|
||||
}
|
||||
}
|
||||
if (customTestComponentPath.empty () == false && customTestComponentPath[0] != '/')
|
||||
{
|
||||
auto realPath = realpath (customTestComponentPath.data (), NULL);
|
||||
if (realPath)
|
||||
{
|
||||
customTestComponentPath.assign (realPath);
|
||||
free (realPath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//---load VST module-----------------
|
||||
if (infoStream)
|
||||
*infoStream << "* Loading module...\n\n\t" << path << "\n\n";
|
||||
|
||||
std::string error;
|
||||
auto module = Module::create (path, error);
|
||||
if (!module)
|
||||
{
|
||||
*errorStream << "Invalid Module!\n";
|
||||
if (!error.empty ())
|
||||
*errorStream << error << "\n";
|
||||
return -1;
|
||||
}
|
||||
#if SMTG_OS_LINUX
|
||||
module->getFactory ().setHostContext (&DummyRunLoop::instance ());
|
||||
#endif
|
||||
testModule (module, {useGlobalInstance, useExtensiveTests, customTestComponentPath,
|
||||
testSuiteName, std::move (testProcessor)});
|
||||
|
||||
if (numTestsFailed > 0)
|
||||
globalFailure = true;
|
||||
}
|
||||
|
||||
return globalFailure ? -1 : 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void Validator::testModule (Module::Ptr module, const ModuleTestConfig& config)
|
||||
{
|
||||
using TestFactoryMap = std::map<std::string, IPtr<ITestFactory>>;
|
||||
using PlugProviderVector = std::vector<IPtr<PlugProvider>>;
|
||||
|
||||
numTestsFailed = numTestsPassed = 0;
|
||||
|
||||
//---check bundle structure--------------
|
||||
std::string errorStr;
|
||||
if (infoStream)
|
||||
*infoStream << "* Check valid bundle structure...\n";
|
||||
if (Module::validateBundleStructure (module->getPath (), errorStr) == false)
|
||||
{
|
||||
++numTestsFailed;
|
||||
if (errorStream)
|
||||
*errorStream << "Invalid bundle structure: " << errorStr << "\n";
|
||||
}
|
||||
if (infoStream)
|
||||
*infoStream << "\n";
|
||||
|
||||
auto factory = module->getFactory ();
|
||||
printFactoryInfo (module->getFactory (), infoStream);
|
||||
|
||||
//---check for snapshots-----------------
|
||||
checkModuleSnapshots (module, infoStream);
|
||||
|
||||
Module::Ptr testModule;
|
||||
PlugProviderVector plugProviders;
|
||||
TestFactoryMap testFactories;
|
||||
IPtr<IPluginCompatibility> plugCompatibility;
|
||||
auto testSuite = owned (new TestSuite ("Tests"));
|
||||
|
||||
//---create tests---------------
|
||||
if (infoStream)
|
||||
*infoStream << "* Creating tests...\n\n";
|
||||
for (auto& classInfo : factory.classInfos ())
|
||||
{
|
||||
if (filterClassCategory (kVstAudioEffectClass, classInfo.category ().data ()))
|
||||
{
|
||||
if (!config.testProcessor || *config.testProcessor == classInfo.ID ())
|
||||
{
|
||||
auto plugProvider =
|
||||
owned (new PlugProvider (factory, classInfo, config.useGlobalInstance));
|
||||
if (plugProvider)
|
||||
{
|
||||
auto tests = createTests (plugProvider, classInfo.name ().data (),
|
||||
config.useExtensiveTests);
|
||||
testSuite->addTestSuite (classInfo.name ().data (), tests);
|
||||
plugProviders.emplace_back (plugProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (filterClassCategory (kTestClass, classInfo.category ().data ()))
|
||||
{ // gather test factories supplied by the plug-in
|
||||
if (auto testFactory = factory.createInstance<ITestFactory> (classInfo.ID ()))
|
||||
{
|
||||
testFactories.insert (std::make_pair (classInfo.name ().data (), testFactory));
|
||||
}
|
||||
}
|
||||
else if (filterClassCategory (kPluginCompatibilityClass, classInfo.category ().data ()))
|
||||
{
|
||||
if (plugCompatibility)
|
||||
{
|
||||
if (errorStream)
|
||||
{
|
||||
*errorStream
|
||||
<< "Error: Factory contains multiple Plugin Compatibility classes.\n";
|
||||
}
|
||||
++numTestsFailed;
|
||||
}
|
||||
plugCompatibility = factory.createInstance<IPluginCompatibility> (classInfo.ID ());
|
||||
if (!plugCompatibility)
|
||||
{
|
||||
if (errorStream)
|
||||
{
|
||||
*errorStream << "Error: Failed creating IPluginCompatibility instance.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now check testModule if supplied
|
||||
if (config.customTestComponentPath.empty () == false)
|
||||
{
|
||||
std::string error;
|
||||
testModule = Module::create (config.customTestComponentPath, error);
|
||||
if (testModule)
|
||||
{
|
||||
const auto& _factory = testModule->getFactory ();
|
||||
for (const auto& classInfo : _factory.classInfos ())
|
||||
{
|
||||
if (filterClassCategory (kTestClass, classInfo.category ().data ()))
|
||||
{ // gather test factories supplied by the plug-in
|
||||
if (auto testFactory = _factory.createInstance<ITestFactory> (classInfo.ID ()))
|
||||
{
|
||||
testFactories.insert (
|
||||
std::make_pair (classInfo.name ().data (), testFactory));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (errorStream)
|
||||
{
|
||||
*errorStream << "Could not create custom test component ["
|
||||
<< config.customTestComponentPath << "]\n";
|
||||
}
|
||||
}
|
||||
if (infoStream && !testFactories.empty ())
|
||||
*infoStream << "* Creating Plug-in supplied tests...\n\n";
|
||||
// create plug-in supplied tests
|
||||
for (const auto& item : testFactories)
|
||||
{
|
||||
for (const auto& plugProvider : plugProviders)
|
||||
{
|
||||
IPtr<TestSuite> plugTestSuite = owned (new TestSuite (item.first.data ()));
|
||||
if (item.second->createTests (plugProvider->unknownCast (), plugTestSuite) ==
|
||||
kResultTrue)
|
||||
{
|
||||
testSuite->addTestSuite (plugTestSuite->getName ().data (), plugTestSuite);
|
||||
}
|
||||
}
|
||||
}
|
||||
testFactories.clear ();
|
||||
|
||||
//---run tests---------------------------
|
||||
if (infoStream)
|
||||
*infoStream << "* Running tests...\n\n";
|
||||
|
||||
runTestSuite (testSuite,
|
||||
config.testSuiteName.empty () ? nullptr : config.testSuiteName.data ());
|
||||
|
||||
if (plugCompatibility)
|
||||
{
|
||||
if (!checkPluginCompatibility (module, plugCompatibility, errorStream))
|
||||
++numTestsFailed;
|
||||
}
|
||||
|
||||
if (infoStream)
|
||||
{
|
||||
*infoStream << SEPARATOR;
|
||||
*infoStream << "Result: " << numTestsPassed << " tests passed, " << numTestsFailed
|
||||
<< " tests failed\n";
|
||||
*infoStream << SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
namespace { // anonymous
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
template <typename T, typename... Args>
|
||||
void createTest (ITestSuite* parent, ITestPlugProvider* plugProvider, Args&&... arguments)
|
||||
{
|
||||
auto test = owned (new T (plugProvider, std::forward<Args> (arguments)...));
|
||||
parent->addTest (test->getName (), test);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void createSpeakerArrangementTest (ITestSuite* parent, ITestPlugProvider* plugProvider,
|
||||
SymbolicSampleSizes sampleSize, SpeakerArrangement inSpArr,
|
||||
SpeakerArrangement outSpArr)
|
||||
{
|
||||
createTest<SpeakerArrangementTest> (parent, plugProvider, sampleSize, inSpArr, outSpArr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void createPrecisionTests (ITestSuite* parent, ITestPlugProvider* plugProvider,
|
||||
SymbolicSampleSizes sampleSize, bool extensive)
|
||||
{
|
||||
createTest<ProcessTest> (parent, plugProvider, sampleSize);
|
||||
createTest<ProcessThreadTest> (parent, plugProvider, sampleSize);
|
||||
createTest<SilenceFlagsTest> (parent, plugProvider, sampleSize);
|
||||
createTest<SilenceProcessingTest> (parent, plugProvider, sampleSize);
|
||||
createTest<FlushParamTest> (parent, plugProvider, sampleSize);
|
||||
createTest<FlushParamTest2> (parent, plugProvider, sampleSize);
|
||||
createTest<FlushParamTest3> (parent, plugProvider, sampleSize);
|
||||
createTest<VariableBlockSizeTest> (parent, plugProvider, sampleSize);
|
||||
createTest<ProcessFormatTest> (parent, plugProvider, sampleSize);
|
||||
createTest<BypassPersistenceTest> (parent, plugProvider, sampleSize);
|
||||
|
||||
if (extensive)
|
||||
{
|
||||
constexpr std::array<SpeakerArrangement, 15> saArray = {
|
||||
{SpeakerArr::kMono, SpeakerArr::kStereo, SpeakerArr::kStereoSurround,
|
||||
SpeakerArr::kStereoCenter, SpeakerArr::kStereoSide, SpeakerArr::kStereoCLfe,
|
||||
SpeakerArr::k30Cine, SpeakerArr::k30Music, SpeakerArr::k31Cine, SpeakerArr::k31Music,
|
||||
SpeakerArr::k40Cine, SpeakerArr::k40Music, SpeakerArr::k41Cine, SpeakerArr::k41Music,
|
||||
SpeakerArr::k50}};
|
||||
|
||||
for (auto inArr : saArray)
|
||||
{
|
||||
for (auto outArr : saArray)
|
||||
{
|
||||
createSpeakerArrangementTest (parent, plugProvider, sampleSize, inArr, outArr);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr std::array<int32, 3> autoRates = {{100, 50, 1}};
|
||||
constexpr std::array<int32, 4> numParams = {{1, 2, 10, -1}};
|
||||
for (auto inp : numParams)
|
||||
{
|
||||
for (auto iar : autoRates)
|
||||
{
|
||||
createTest<AutomationTest> (parent, plugProvider, sampleSize, iar, inp, false);
|
||||
createTest<AutomationTest> (parent, plugProvider, sampleSize, iar, inp, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
createSpeakerArrangementTest (parent, plugProvider, sampleSize, SpeakerArr::kStereo,
|
||||
SpeakerArr::kStereo);
|
||||
createSpeakerArrangementTest (parent, plugProvider, sampleSize, SpeakerArr::kMono,
|
||||
SpeakerArr::kMono);
|
||||
|
||||
createTest<AutomationTest> (parent, plugProvider, sampleSize, 100, 1, false);
|
||||
createTest<AutomationTest> (parent, plugProvider, sampleSize, 100, 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // anonymous
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
IPtr<TestSuite> Validator::createTests (ITestPlugProvider* plugProvider,
|
||||
const ConstString& plugName, bool extensive)
|
||||
{
|
||||
IPtr<TestSuite> plugTestSuite = owned (new TestSuite (plugName));
|
||||
|
||||
IPtr<TestSuite> generalTests = owned (new TestSuite ("General Tests"));
|
||||
// todo: add tests here!
|
||||
createTest<EditorClassesTest> (generalTests, plugProvider);
|
||||
createTest<ScanBussesTest> (generalTests, plugProvider);
|
||||
createTest<ScanParametersTest> (generalTests, plugProvider);
|
||||
createTest<MidiMappingTest> (generalTests, plugProvider);
|
||||
createTest<MidiLearnTest> (generalTests, plugProvider);
|
||||
createTest<UnitInfoTest> (generalTests, plugProvider);
|
||||
createTest<ProgramInfoTest> (generalTests, plugProvider);
|
||||
createTest<TerminateInitializeTest> (generalTests, plugProvider);
|
||||
createTest<UnitStructureTest> (generalTests, plugProvider);
|
||||
createTest<ValidStateTransitionTest> (generalTests, plugProvider, kSample32);
|
||||
createTest<ValidStateTransitionTest> (generalTests, plugProvider, kSample64);
|
||||
// createTest<InvalidStateTransitionTest> (generalTests, plugProvider);
|
||||
// createTest<RepeatIdenticalStateTransitionTest> (generalTests, plugProvider);
|
||||
|
||||
createTest<BusConsistencyTest> (generalTests, plugProvider);
|
||||
// createTest<BusInvalidIndexTest> (generalTests, plugProvider);
|
||||
createTest<BusActivationTest> (generalTests, plugProvider);
|
||||
|
||||
createTest<CheckAudioBusArrangementTest> (generalTests, plugProvider);
|
||||
createTest<SideChainArrangementTest> (generalTests, plugProvider);
|
||||
|
||||
createTest<SuspendResumeTest> (generalTests, plugProvider, kSample32);
|
||||
|
||||
createTest<NoteExpressionTest> (generalTests, plugProvider);
|
||||
createTest<KeyswitchTest> (generalTests, plugProvider);
|
||||
createTest<ProcessContextRequirementsTest> (generalTests, plugProvider);
|
||||
|
||||
plugTestSuite->addTestSuite (generalTests->getName ().data (), generalTests);
|
||||
|
||||
IPtr<TestSuite> singlePrecisionTests =
|
||||
owned (new TestSuite ("Single Precision (32 bit) Tests"));
|
||||
createPrecisionTests (singlePrecisionTests, plugProvider, kSample32, extensive);
|
||||
plugTestSuite->addTestSuite (singlePrecisionTests->getName ().data (), singlePrecisionTests);
|
||||
|
||||
IPtr<TestSuite> doublePrecisionTests =
|
||||
owned (new TestSuite ("Double Precision (64 bit) Tests"));
|
||||
createPrecisionTests (doublePrecisionTests, plugProvider, kSample64, extensive);
|
||||
plugTestSuite->addTestSuite (doublePrecisionTests->getName ().data (), doublePrecisionTests);
|
||||
|
||||
return plugTestSuite;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void Validator::addTest (ITestSuite* _testSuite, TestBase* testItem)
|
||||
{
|
||||
_testSuite->addTest (testItem->getName (), testItem);
|
||||
testItem->release ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void Validator::runTestSuite (TestSuite* suite, FIDString nameFilter)
|
||||
{
|
||||
std::string name;
|
||||
if (nameFilter == nullptr || suite->getName () == nameFilter)
|
||||
{
|
||||
nameFilter = nullptr; // make sure if suiteName is the namefilter that sub suite will run
|
||||
ITest* testItem = nullptr;
|
||||
// first run all tests in the suite
|
||||
for (int32 i = 0; i < suite->getTestCount (); i++)
|
||||
{
|
||||
if (suite->getTest (i, testItem, name) == kResultTrue)
|
||||
{
|
||||
if (infoStream)
|
||||
{
|
||||
*infoStream << "[" << name;
|
||||
if (auto desc = testItem->getDescription ())
|
||||
{
|
||||
auto descStr = StringConvert::convert (desc);
|
||||
if (!descStr.empty ())
|
||||
*infoStream << ": " << descStr;
|
||||
}
|
||||
*infoStream << "]\n";
|
||||
}
|
||||
|
||||
if (testItem->setup ())
|
||||
{
|
||||
bool success = testItem->run (this);
|
||||
if (success)
|
||||
{
|
||||
if (infoStream)
|
||||
*infoStream << "[Succeeded]\n";
|
||||
numTestsPassed++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (infoStream)
|
||||
*infoStream << "[XXXXXXX Failed]\n";
|
||||
if (errorStream && errorStream != infoStream)
|
||||
{
|
||||
*errorStream << "Test [" << name << "] ";
|
||||
*errorStream << "Failed\n";
|
||||
}
|
||||
numTestsFailed++;
|
||||
}
|
||||
|
||||
if (!testItem->teardown ())
|
||||
{
|
||||
if (infoStream)
|
||||
*infoStream << "Failed to teardown test!\n";
|
||||
if (errorStream && errorStream != infoStream)
|
||||
{
|
||||
*errorStream << "[" << name << "] ";
|
||||
*errorStream << "Failed to teardown test!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
testItem->teardown ();
|
||||
if (infoStream)
|
||||
*infoStream << "Failed to setup test!\n";
|
||||
if (errorStream && errorStream != infoStream)
|
||||
{
|
||||
*errorStream << "[" << name << "] ";
|
||||
*errorStream << "Failed to setup test!\n";
|
||||
}
|
||||
}
|
||||
if (infoStream)
|
||||
*infoStream << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// next run sub suites
|
||||
int32 subTestSuiteIndex = 0;
|
||||
ITestSuite* subSuite = nullptr;
|
||||
while (suite->getTestSuite (subTestSuiteIndex++, subSuite, name) == kResultTrue)
|
||||
{
|
||||
auto* ts = FCast<TestSuite> (subSuite);
|
||||
if (ts)
|
||||
{
|
||||
if (infoStream)
|
||||
{
|
||||
*infoStream << SEPARATOR;
|
||||
*infoStream << "TestSuite : " << ts->getName ().data () << "\n";
|
||||
*infoStream << SEPARATOR << "\n";
|
||||
}
|
||||
runTestSuite (ts, nameFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // namespace Vst
|
||||
} // namespace Steinberg
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flags : clang-format SMTGSequencer
|
||||
// Project : VST SDK
|
||||
//
|
||||
// Category : Validator
|
||||
// Filename : public.sdk/samples/vst-hosting/validator/source/validator.h
|
||||
// Created by : Steinberg, 04/2005
|
||||
// Description : VST 3 Plug-in Validator class
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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 "public.sdk/source/vst/hosting/hostclasses.h"
|
||||
#include "public.sdk/source/vst/hosting/module.h"
|
||||
#include "public.sdk/source/vst/hosting/pluginterfacesupport.h"
|
||||
#include "public.sdk/source/vst/testsuite/vsttestsuite.h"
|
||||
#include "base/source/fstring.h"
|
||||
#include "pluginterfaces/base/ipluginbase.h"
|
||||
#include "pluginterfaces/test/itest.h"
|
||||
#include <iosfwd>
|
||||
|
||||
namespace Steinberg {
|
||||
namespace Vst {
|
||||
|
||||
class IComponent;
|
||||
class IEditController;
|
||||
|
||||
class VstModule;
|
||||
class TestBase;
|
||||
class TestSuite;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/** Main Class of Validator.
|
||||
* \defgroup Validator VST3 Validator
|
||||
*/
|
||||
class Validator : public FObject, public ITestResult, public IHostApplication
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------------
|
||||
Validator (int argc, char* argv[]);
|
||||
~Validator () override;
|
||||
|
||||
int run ();
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
OBJ_METHODS (Validator, FObject)
|
||||
REFCOUNT_METHODS (FObject)
|
||||
|
||||
tresult PLUGIN_API queryInterface (const char* _iid, void** obj) override;
|
||||
//------------------------------------------------------------------------
|
||||
protected:
|
||||
using Module = VST3::Hosting::Module;
|
||||
|
||||
// ITestResult
|
||||
void PLUGIN_API addErrorMessage (const tchar* msg) override;
|
||||
void PLUGIN_API addMessage (const tchar* msg) override;
|
||||
|
||||
// IHostApplication
|
||||
tresult PLUGIN_API getName (String128 name) override;
|
||||
tresult PLUGIN_API createInstance (TUID cid, TUID iid, void** obj) override;
|
||||
|
||||
IPtr<TestSuite> createTests (ITestPlugProvider* plugProvider, const ConstString& plugName,
|
||||
bool extensive);
|
||||
void addTest (ITestSuite* testSuite, TestBase* test);
|
||||
void runTestSuite (TestSuite* suite, FIDString nameFilter = nullptr);
|
||||
|
||||
struct ModuleTestConfig
|
||||
{
|
||||
ModuleTestConfig (bool useGlobalInstance, bool useExtensiveTests,
|
||||
std::string& customTestComponentPath, std::string& testSuiteName,
|
||||
VST3::Optional<VST3::UID>&& testProcessor)
|
||||
: useGlobalInstance (useGlobalInstance)
|
||||
, useExtensiveTests (useExtensiveTests)
|
||||
, customTestComponentPath (customTestComponentPath)
|
||||
, testSuiteName (testSuiteName)
|
||||
, testProcessor (std::move (testProcessor))
|
||||
{
|
||||
}
|
||||
|
||||
bool useGlobalInstance {true};
|
||||
bool useExtensiveTests {false};
|
||||
std::string customTestComponentPath;
|
||||
std::string testSuiteName;
|
||||
VST3::Optional<VST3::UID> testProcessor;
|
||||
};
|
||||
|
||||
void testModule (Module::Ptr module, const ModuleTestConfig& config);
|
||||
|
||||
int argc;
|
||||
char** argv;
|
||||
|
||||
IPtr<PlugInterfaceSupport> mPlugInterfaceSupport;
|
||||
|
||||
int32 numTestsFailed {0};
|
||||
int32 numTestsPassed {0};
|
||||
bool addErrorWarningTextToOutput {true};
|
||||
|
||||
std::ostream* infoStream {nullptr};
|
||||
std::ostream* errorStream {nullptr};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
} // namespace Vst
|
||||
} // namespace Steinberg
|
||||
Reference in New Issue
Block a user