lumiera_/tests/core/steam/engine/node-meta-test.cpp
Ichthyostega ead494e465 Invocation: Argument-spec evaluation sufficiently complete for now
Some additional tests to challenge the parser, which seems to work well.
Without extended analysis into the usage of those node specifications,
it is pointless to expand further on its capabilities. For now, it is
sufficient to have a foundation for hash-computation in place.

__Note__: found a nifty way to give lib::Several an easy toString rendering,
without cranking up the header inclusion load.
2025-02-02 17:22:16 +01:00

187 lines
7.2 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
NodeMeta(Test) - verify render node data feeds
Copyright (C)
2024, Hermann Vosseler <Ichthyostega@web.de>
  **Lumiera** is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the
  Free Software Foundation; either version 2 of the License, or (at your
  option) any later version. See the file COPYING for further details.
* *****************************************************************/
/** @file node-meta-test.cpp
** Naming and hash-key identification of render nodes is covered by \ref NodeMeta_test.
*/
#include "lib/test/run.hpp"
#include "steam/engine/proc-node.hpp"
#include "steam/engine/node-builder.hpp"
#include "lib/format-util.hpp"
//#include "steam/engine/test-rand-ontology.hpp" ///////////TODO
#include "lib/test/diagnostic-output.hpp"/////////////////TODO
//#include "lib/util.hpp"
#include <cmath>
//using std::string;
namespace steam {
namespace engine{
namespace test {
using std::abs;
// using util::join;
/***************************************************************//**
* @test Render node metadata and hash identity keys.
*/
class NodeMeta_test : public Test
{
virtual void
run (Arg)
{
verify_ID_specification();
verify_ID_properties();
}
/** @test evaluation of processing-spec for a ProcID
* @todo 1/25 ✔ define ⟶ ✔ implement
*/
void
verify_ID_specification()
{
auto& p1 = ProcID::describe("N1","(arg)");
auto& p2 = ProcID::describe("U:N2","+(a1,a2)");
auto& p3 = ProcID::describe("O:N3","(in/3)(o1,o2/2)");
CHECK (p1.genNodeName() == "N1"_expect );
CHECK (p1.genNodeSymbol() == "N1"_expect );
CHECK (p1.genNodeDomain() == ""_expect );
CHECK (p2.genNodeName() == "U:N2"_expect );
CHECK (p2.genNodeSymbol() == "N2"_expect );
CHECK (p2.genNodeDomain() == "U"_expect );
CHECK (p3.genNodeName() == "O:N3"_expect );
CHECK (p3.genNodeSymbol() == "N3"_expect );
CHECK (p3.genNodeDomain() == "O"_expect );
CHECK (p1.genProcName() == "N1"_expect );
CHECK (p1.genQualifier() == ""_expect );
CHECK (p2.genProcName() == "N2.+"_expect ); // domain omitted, qualifier joined with '.'
CHECK (p2.genQualifier() == ".+"_expect ); // qualifier includes leading '.'
CHECK (p3.genProcName() == "N3"_expect );
CHECK (p2.genProcSpec() == "U:N2.+(a1,a2)"_expect );
CHECK (p3.genProcSpec() == "O:N3(in/3)(o1,o2/2)"_expect );
ProcID::ArgModel arg1 = p1.genArgModel();
ProcID::ArgModel arg2 = p2.genArgModel();
ProcID::ArgModel arg3 = p3.genArgModel();
CHECK (not arg1.hasInArgs());
CHECK (not arg2.hasInArgs());
CHECK (arg1.outArity() == 1);
CHECK (arg2.outArity() == 2);
CHECK (arg3.outArity() == 3);
CHECK (arg3.inArity() == 3);
CHECK (arg1.iArg == "[]"_expect );
CHECK (arg1.oArg == "[arg]"_expect ); // only one argument list -> used for output
CHECK (arg2.iArg == "[]"_expect );
CHECK (arg2.oArg == "[a1, a2]"_expect );
CHECK (arg3.iArg == "[in, in, in]"_expect ); // repetition-abbreviation of arguments unfolded
CHECK (arg3.oArg == "[o1, o2, o2]"_expect );
// give the spec-parser a rough time....
string nastySpec = "(\":-)\"/2,std::tuple<short,long>/3,{oh,RLY?}/2,\\\")";
auto hairyModel = ProcID::describe("", nastySpec).genArgModel();
CHECK (hairyModel.outArity() == 8);
CHECK (hairyModel.inArity() == 0);
CHECK (hairyModel.oArg == "[\":-)\", \":-)\", "
"std::tuple<short,long>, "
"std::tuple<short,long>, "
"std::tuple<short,long>, "
"{oh,RLY?}, {oh,RLY?}, \\\"]"_expect);
}
/** @test TODO aspects of node definition relevant for the ProcID
* @todo WIP 2/25 🔁 define ⟶ implement
*/
void
verify_ID_properties()
{
// This operation emulates a data source
auto src_opA = [](int param, int* res) { *res = param; };
auto src_opB = [](ulong param, ulong* res){ *res = param; };
// A Node with two (source) ports
ProcNode nA{prepareNode("srcA")
.preparePort()
.invoke("a(int)", src_opA)
.setParam(5)
.completePort()
.preparePort()
.invoke("b(int)", src_opA)
.setParam(23)
.completePort()
.build()};
// A different Node with three ports
ProcNode nB{prepareNode("srcB")
.preparePort()
.invoke("a(ulong)", src_opB)
.setParam(7)
.completePort()
.preparePort()
.invoke("b(ulong)", src_opB)
.setParam(13)
.completePort()
.preparePort()
.invoke("c(ulong)", src_opB)
.setParam(17)
.completePort()
.build()};
// This operation emulates fading of two source chains
auto fade_op = [](double mix, tuple<int*,ulong*> src, uint64_t* res)
{
auto [srcA,srcB] = src;
*res = uint64_t(abs(*srcA * mix + (1-mix) * int64_t(*srcB)));
};
// Wiring for the Mix, building up three ports
// Since the first source-chain has only two ports,
// for the third result port we'll re-use the second source
ProcNode nM{prepareNode("fade")
.preparePort()
.invoke("A_mix(int,ulong)(uint64_t)", fade_op)
.connectLead(nA)
.connectLead(nB)
.completePort()
.preparePort()
.invoke("B_mix(int,ulong)(uint64_t)", fade_op)
.connectLead(nA)
.connectLead(nB)
.completePort()
.preparePort()
.invoke("C_mix(int,ulong)(uint64_t)", fade_op)
.connectLeadPort(nA,1)
.connectLead(nB)
.setParam(0.5)
.completePort()
.build()};
UNIMPLEMENTED ("verify connectivity");
}
};
/** Register this test class... */
LAUNCHER (NodeMeta_test, "unit node");
}}} // namespace steam::engine::test