Skip to content

Commit

Permalink
WIP: Enable Plugin tests for clang and use ut
Browse files Browse the repository at this point in the history
  • Loading branch information
frankosterfeld committed Nov 14, 2023
1 parent 9f24bac commit a024356
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 132 deletions.
7 changes: 3 additions & 4 deletions core/include/gnuradio-4.0/plugin_loader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,18 +178,17 @@ class plugin_loader {
}

std::unique_ptr<gr::BlockModel>
instantiate(std::string name, std::string_view type, const property_map &params = {}) {
instantiate(std::string_view name, std::string_view type, const property_map &params = {}) {
// Try to create a node from the global registry
if (auto result = _global_registry->createBlock(name, type, params)) {
return result;
}

auto it = _handler_for_name.find(name);
auto it = _handler_for_name.find(std::string(name)); // TODO avoid std::string here
if (it == _handler_for_name.end()) return {};

auto &handler = it->second;

return handler->createBlock(std::move(name), type, params);
return handler->createBlock(name, type, params);
}

template<typename Graph, typename... InstantiateArgs>
Expand Down
6 changes: 4 additions & 2 deletions core/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ add_ut_test(qa_port_array)
add_ut_test(qa_thread_affinity)
add_ut_test(qa_thread_pool)

if (NOT (EMSCRIPTEN OR (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")))
if (NOT EMSCRIPTEN)
add_subdirectory(plugins)

add_executable(qa_plugins_test qa_plugins_test.cpp)
Expand All @@ -52,6 +52,8 @@ if (NOT (EMSCRIPTEN OR (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")))

add_app_test(app_plugins_test app_plugins_test.cpp)

add_app_test(app_grc)
add_executable(app_grc app_grc.cpp)
setup_test_no_asan(app_grc)

target_link_libraries(app_grc PRIVATE yaml-cpp::yaml-cpp gr-basic gr-testing)
endif ()
141 changes: 69 additions & 72 deletions core/test/app_grc.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
// TODO: This is a test application that doesn't use ut framework.
// Once all problems with ut and plugins have been resolved,
// implement a unit testing suite

#include <fstream>
#include <sstream>

Expand All @@ -11,6 +7,8 @@
#include <build_configure.hpp>
#include <gnuradio-4.0/basic/common_blocks.hpp>

#include <boost/ut.hpp>

template<typename T>
struct ArraySource : public gr::Block<ArraySource<T>> {
std::array<gr::PortOut<T>, 2> outA;
Expand All @@ -34,7 +32,7 @@ struct ArraySink : public gr::Block<ArraySink<T>> {
ENABLE_REFLECTION_FOR_TEMPLATE(ArraySink, inA, inB, bool_setting, string_setting, bool_vector, string_vector, double_vector, int16_vector);

struct TestContext {
TestContext(std::vector<std::filesystem::path> paths) : registry(), loader(&registry, std::move(paths)) {}
explicit TestContext(std::vector<std::filesystem::path> paths = {}) : registry(), loader(&registry, std::move(paths)) {}

gr::BlockRegistry registry;
gr::plugin_loader loader;
Expand All @@ -57,69 +55,65 @@ collectEdges(const gr::Graph &graph) {
});
return result;
};

auto
readFile(const auto &path) {
std::ifstream input(path);
std::stringstream buffer;
buffer << input.rdbuf();
return buffer.str();
};

} // namespace

int
main(int argc, char *argv[]) {
std::vector<std::filesystem::path> paths;
if (argc < 2) {
paths.push_back(TESTS_BINARY_PATH "/plugins");
} else {
for (int i = 1; i < argc; ++i) {
paths.push_back(argv[i]);
}
}
using namespace boost::ut;

auto read_file = [](const auto &path) {
std::ifstream input(path);
std::stringstream buffer;
buffer << input.rdbuf();
return buffer.str();
};
namespace gr::app_grc_test {

TestContext context(std::move(paths));
const boost::ut::suite AppGrcTests = [] {
static TestContext context = [] {
TestContext ctx({ TESTS_BINARY_PATH "/plugins" });
registerBuiltinBlocks(&ctx.registry);
GP_REGISTER_NODE_RUNTIME(&ctx.registry, ArraySource, double);
GP_REGISTER_NODE_RUNTIME(&ctx.registry, ArraySink, double);
return ctx;
}();

// Test the basic graph loading and storing
{
"Basic graph loading and storing"_test = [] {
using namespace gr;
registerBuiltinBlocks(&context.registry);

auto graph_source = read_file(TESTS_SOURCE_PATH "/grc/test.grc");
auto graph_source = readFile(TESTS_SOURCE_PATH "/grc/test.grc");

auto graph = gr::load_grc(context.loader, graph_source);
auto graph_saved_source = gr::save_grc(graph);
auto graph = gr::load_grc(context.loader, graph_source);
auto graph_saved_source = gr::save_grc(graph);

auto graph_expected_source = read_file(TESTS_SOURCE_PATH "/grc/test.grc.expected");
assert(graph_saved_source + "\n"
auto graph_expected_source = readFile(TESTS_SOURCE_PATH "/grc/test.grc.expected");
expect(graph_saved_source + "\n"
== graph_expected_source); // TODO: this is not a good assert since we will add new parameters regularly... should not be identity but checking critical parameter/aspects

gr::scheduler::Simple scheduler(std::move(graph));
scheduler.runAndWait();
}
};

// Test if we get the same graph when saving it and loading the saved
// data into another graph
{
"Save and load"_test = [] {
// Test if we get the same graph when saving it and loading the saved
// data into another graph
using namespace gr;
registerBuiltinBlocks(&context.registry);

auto graph_source = read_file(TESTS_SOURCE_PATH "/grc/test.grc");

auto graph_1 = gr::load_grc(context.loader, graph_source);
auto graph_saved_source = gr::save_grc(graph_1);

auto graph_2 = gr::load_grc(context.loader, graph_saved_source);

assert(collectBlocks(graph_1) == collectBlocks(graph_2));
assert(collectEdges(graph_1) == collectEdges(graph_2));
}
auto graph_source = readFile(TESTS_SOURCE_PATH "/grc/test.grc");

try {
auto graph_1 = gr::load_grc(context.loader, graph_source);
auto graph_saved_source = gr::save_grc(graph_1);
auto graph_2 = gr::load_grc(context.loader, graph_saved_source);
expect(collectBlocks(graph_1) == collectBlocks(graph_2));
expect(collectEdges(graph_1) == collectEdges(graph_2));
} catch (const std::string &e) {
fmt::println(std::cerr, "Unexpected exception: {}", e);
expect(false);
}
};

// Test that connections involving port collections are handled correctly
{
"Port collections"_test = [] {
using namespace gr;
registerBuiltinBlocks(&context.registry);
GP_REGISTER_NODE_RUNTIME(&context.registry, ArraySource, double);
GP_REGISTER_NODE_RUNTIME(&context.registry, ArraySink, double);

gr::Graph graph_1;
auto &arraySink = graph_1.emplaceBlock<ArraySink<double>>();
Expand All @@ -131,20 +125,17 @@ main(int argc, char *argv[]) {
graph_1.connect<"outB", 0>(arraySource0).to<"inA", 0>(arraySink);
graph_1.connect<"outB", 1>(arraySource1).to<"inA", 1>(arraySink);

assert(graph_1.performConnections());
expect(graph_1.performConnections());

const auto graph_1_saved = gr::save_grc(graph_1);
const auto graph_2 = gr::load_grc(context.loader, graph_1_saved);

assert(collectBlocks(graph_1) == collectBlocks(graph_2));
assert(collectEdges(graph_1) == collectEdges(graph_2));
}
expect(collectBlocks(graph_1) == collectBlocks(graph_2));
expect(collectEdges(graph_1) == collectEdges(graph_2));
};

// Test settings serialization
{
"Settings serialization"_test = [] {
using namespace gr;
registerBuiltinBlocks(&context.registry);
GP_REGISTER_NODE_RUNTIME(&context.registry, ArraySink, double);

gr::Graph graph_1;
const auto expectedString = std::string("abc");
Expand All @@ -160,19 +151,25 @@ main(int argc, char *argv[]) {
{ "double_vector", expectedDoubleVector },
{ "int16_vector", expectedInt16Vector } });

const auto graph_1_saved = gr::save_grc(graph_1);
const auto graph_2 = gr::load_grc(context.loader, graph_1_saved);
const auto graph_1_saved = gr::save_grc(graph_1);
const auto graph_2 = gr::load_grc(context.loader, graph_1_saved);
graph_2.forEachBlock([&](const auto &node) {
const auto settings = node.settings().get();
assert(std::get<bool>(settings.at("bool_setting")) == expectedBool);
assert(std::get<std::string>(settings.at("string_setting")) == expectedString);
assert(std::get<std::vector<bool>>(settings.at("bool_vector")) == expectedBoolVector);
assert(std::get<std::vector<std::string>>(settings.at("string_vector")) == expectedStringVector);
assert(std::get<std::vector<double>>(settings.at("double_vector")) == expectedDoubleVector);
assert(std::get<std::vector<int16_t>>(settings.at("int16_vector")) == expectedInt16Vector);
expect(std::get<bool>(settings.at("bool_setting")) == expectedBool);
expect(std::get<std::string>(settings.at("string_setting")) == expectedString);
expect(std::get<std::vector<bool>>(settings.at("bool_vector")) == expectedBoolVector);
expect(std::get<std::vector<std::string>>(settings.at("string_vector")) == expectedStringVector);
expect(std::get<std::vector<double>>(settings.at("double_vector")) == expectedDoubleVector);
expect(std::get<std::vector<int16_t>>(settings.at("int16_vector")) == expectedInt16Vector);
});

assert(collectBlocks(graph_1) == collectBlocks(graph_2));
assert(collectEdges(graph_1) == collectEdges(graph_2));
}
}
expect(collectBlocks(graph_1) == collectBlocks(graph_2));
expect(collectEdges(graph_1) == collectEdges(graph_2));
};
};

} // namespace gr::app_grc_test

int
main() { /* tests are statically executed */
}
10 changes: 5 additions & 5 deletions core/test/app_plugins_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ main(int argc, char *argv[]) {
auto block_sink_load = context.loader.instantiate(names::cout_sink, "double", block_sink_params);

assert(block_sink_load);
auto &block_sink = testGraph.addBlock(std::move(block_sink_load));
auto &block_sink = testGraph.addBlock(std::move(block_sink_load));

auto connection_1 [[maybe_unused]] = testGraph.connect(block_source, 0, block_multiply_1, 0);
auto connection_2 [[maybe_unused]] = testGraph.connect(block_multiply_1, 0, block_multiply_2, 0);
auto connection_3 [[maybe_unused]] = testGraph.connect(block_multiply_2, 0, block_counter, 0);
auto connection_4 [[maybe_unused]] = testGraph.connect(block_counter, 0, block_sink, 0);
auto connection_1 [[maybe_unused]] = testGraph.connect(block_source, 0, block_multiply_1, 0);
auto connection_2 [[maybe_unused]] = testGraph.connect(block_multiply_1, 0, block_multiply_2, 0);
auto connection_3 [[maybe_unused]] = testGraph.connect(block_multiply_2, 0, block_counter, 0);
auto connection_4 [[maybe_unused]] = testGraph.connect(block_counter, 0, block_sink, 0);

assert(connection_1 == grg::ConnectionResult::SUCCESS);
assert(connection_2 == grg::ConnectionResult::SUCCESS);
Expand Down
Loading

0 comments on commit a024356

Please sign in to comment.