Skip to content
Merged
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
83 changes: 67 additions & 16 deletions NAM/get_dsp.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include <fstream>
#include <iostream>
#include <mutex>
#include <regex>
#include <sstream>
#include <stdexcept>

Expand All @@ -11,6 +13,47 @@

namespace nam
{
namespace
{

class CoreVersionSupportChecker : public IVersionSupportChecker
{
public:
Supported support(const std::string& version) const override
{
static const std::regex semver_regex(R"(^\d+\.\d+\.\d+$)");
if (!std::regex_match(version, semver_regex))
return Supported::NO;

const Version parsed = ParseVersion(version);
const Version latest = ParseVersion(LATEST_FULLY_SUPPORTED_NAM_FILE_VERSION);
const Version earliest = ParseVersion(EARLIEST_SUPPORTED_NAM_FILE_VERSION);

if (parsed < earliest)
return Supported::NO;
if (parsed.major > latest.major || parsed.minor > latest.minor)
return Supported::NO;
if (latest < parsed)
return Supported::PARTIAL;
return Supported::YES;
}
};

std::vector<std::shared_ptr<const IVersionSupportChecker>>& version_support_registry()
{
static std::vector<std::shared_ptr<const IVersionSupportChecker>> registry{
std::make_shared<CoreVersionSupportChecker>()};
return registry;
}

std::mutex& version_support_registry_mutex()
{
static std::mutex registry_mutex;
return registry_mutex;
}

} // namespace

Version ParseVersion(const std::string& versionStr)
{
// Split the version string into major, minor, and patch components
Expand Down Expand Up @@ -47,32 +90,40 @@ Version ParseVersion(const std::string& versionStr)
return Version(major, minor, patch);
}

void verify_config_version(const std::string versionStr)
void register_version_support_checker(std::shared_ptr<const IVersionSupportChecker> checker)
{
Version version = ParseVersion(versionStr);
Version currentVersion = ParseVersion(LATEST_FULLY_SUPPORTED_NAM_FILE_VERSION);
Version earliestSupportedVersion = ParseVersion(EARLIEST_SUPPORTED_NAM_FILE_VERSION);
if (!checker)
throw std::invalid_argument("version support checker cannot be null");
std::lock_guard<std::mutex> lock(version_support_registry_mutex());
version_support_registry().push_back(std::move(checker));
}

if (version < earliestSupportedVersion)
Supported is_version_supported(const std::string version)
{
std::lock_guard<std::mutex> lock(version_support_registry_mutex());
Supported best_support = Supported::NO;
for (const auto& checker : version_support_registry())
{
std::stringstream ss;
ss << "Model config is an unsupported version " << versionStr << ". The earliest supported version is "
<< earliestSupportedVersion.toString()
<< ". Try either converting the model to a more recent version, or "
"update your version of the NAM plugin.";
throw std::runtime_error(ss.str());
const auto candidate_support = checker->support(version);
if (static_cast<int>(candidate_support) > static_cast<int>(best_support))
best_support = candidate_support;
}
if (version.major > currentVersion.major || version.minor > currentVersion.minor)
return best_support;
}

void verify_config_version(const std::string versionStr)
{
const Supported support = is_version_supported(versionStr);
if (support == Supported::NO)
{
std::stringstream ss;
ss << "Model config is an unsupported version " << versionStr << ". The latest fully-supported version is "
<< currentVersion.toString();
ss << "Model config is an unsupported version " << versionStr << ".";
throw std::runtime_error(ss.str());
}
else if (currentVersion < version)
if (support == Supported::PARTIAL)
{
std::stringstream ss;
std::cerr << "Model config is a partially-supported version " << versionStr
<< ". The latest fully-supported version is " << currentVersion.toString()
<< ". Continuing with partial support." << std::endl;
}
}
Expand Down
20 changes: 20 additions & 0 deletions NAM/get_dsp.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
#pragma once

#include <fstream>
#include <memory>
#include <vector>

#include "dsp.h"

namespace nam
{
enum class Supported
{
NO = 0,
PARTIAL = 1,
YES = 2
};

class IVersionSupportChecker
{
public:
virtual ~IVersionSupportChecker() = default;
virtual Supported support(const std::string& version) const = 0;
};

class Version
{
public:
Expand Down Expand Up @@ -40,6 +56,10 @@ class Version

Version ParseVersion(const std::string& versionStr);

void register_version_support_checker(std::shared_ptr<const IVersionSupportChecker> checker);

Supported is_version_supported(const std::string version);

void verify_config_version(const std::string versionStr);

const std::string LATEST_FULLY_SUPPORTED_NAM_FILE_VERSION = "0.7.0";
Expand Down
2 changes: 2 additions & 0 deletions tools/run_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ int main()
test_get_dsp::test_version_patch_one_beyond_supported();
test_get_dsp::test_version_minor_one_beyond_supported();
test_get_dsp::test_version_too_early();
test_get_dsp::test_is_version_supported_core_behavior();
test_get_dsp::test_register_custom_version_support_checker();

// Finally, some end-to-end tests.
test_get_dsp::test_load_and_process_nam_files();
Expand Down
44 changes: 44 additions & 0 deletions tools/test/test_get_dsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,24 @@ std::string createConfigWithVersion(const std::string& version)
return j.dump();
}

class DemoVersionSupportChecker : public nam::IVersionSupportChecker
{
public:
nam::Supported support(const std::string& version) const override
{
const std::string prefix = "DEMO::";
if (version.rfind(prefix, 0) != 0)
return nam::Supported::NO;

const std::string scopedVersion = version.substr(prefix.size());
if (scopedVersion == "1.0.0")
return nam::Supported::YES;
if (scopedVersion.rfind("1.0.", 0) == 0)
return nam::Supported::PARTIAL;
return nam::Supported::NO;
}
};

void test_version_patch_one_beyond_supported()
{
// Test that a .nam file with version one patch beyond the latest fully supported
Expand Down Expand Up @@ -232,4 +250,30 @@ void test_version_too_early()
}
assert(threw);
}

void test_is_version_supported_core_behavior()
{
assert(nam::is_version_supported(nam::LATEST_FULLY_SUPPORTED_NAM_FILE_VERSION)
== nam::Supported::YES);

nam::Version patchBeyondLatest = nam::ParseVersion(nam::LATEST_FULLY_SUPPORTED_NAM_FILE_VERSION);
patchBeyondLatest.patch++;
assert(nam::is_version_supported(patchBeyondLatest.toString())
== nam::Supported::PARTIAL);

nam::Version minorBeyondLatest = nam::ParseVersion(nam::LATEST_FULLY_SUPPORTED_NAM_FILE_VERSION);
minorBeyondLatest.minor++;
minorBeyondLatest.patch = 0;
assert(nam::is_version_supported(minorBeyondLatest.toString())
== nam::Supported::NO);
}

void test_register_custom_version_support_checker()
{
nam::register_version_support_checker(std::make_shared<DemoVersionSupportChecker>());

assert(nam::is_version_supported("DEMO::1.0.0") == nam::Supported::YES);
assert(nam::is_version_supported("DEMO::1.0.3") == nam::Supported::PARTIAL);
assert(nam::is_version_supported("DEMO::2.0.0") == nam::Supported::NO);
}
}; // namespace test_get_dsp
Loading