mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Graph: Add unit tests
This commit is contained in:
parent
5746bc99da
commit
44a7987322
1 changed files with 162 additions and 0 deletions
|
|
@ -1777,4 +1777,166 @@ void AudioProcessorGraph::AudioGraphIOProcessor::setParentGraph (AudioProcessorG
|
|||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
class AudioProcessorGraphTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
AudioProcessorGraphTests()
|
||||
: UnitTest ("AudioProcessorGraph", UnitTestCategories::audioProcessors) {}
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
const auto midiChannel = AudioProcessorGraph::midiChannelIndex;
|
||||
|
||||
beginTest ("isConnected returns true when two nodes are connected");
|
||||
{
|
||||
AudioProcessorGraph graph;
|
||||
const auto nodeA = graph.addNode (BasicProcessor::make ({}, MidiIn::no, MidiOut::yes))->nodeID;
|
||||
const auto nodeB = graph.addNode (BasicProcessor::make ({}, MidiIn::yes, MidiOut::no))->nodeID;
|
||||
|
||||
expect (graph.canConnect ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));
|
||||
expect (! graph.canConnect ({ { nodeB, midiChannel }, { nodeA, midiChannel } }));
|
||||
expect (! graph.canConnect ({ { nodeA, midiChannel }, { nodeA, midiChannel } }));
|
||||
expect (! graph.canConnect ({ { nodeB, midiChannel }, { nodeB, midiChannel } }));
|
||||
|
||||
expect (graph.getConnections().empty());
|
||||
expect (! graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));
|
||||
expect (! graph.isConnected (nodeA, nodeB));
|
||||
|
||||
expect (graph.addConnection ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));
|
||||
|
||||
expect (graph.getConnections().size() == 1);
|
||||
expect (graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));
|
||||
expect (graph.isConnected (nodeA, nodeB));
|
||||
|
||||
expect (graph.disconnectNode (nodeA));
|
||||
|
||||
expect (graph.getConnections().empty());
|
||||
expect (! graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));
|
||||
expect (! graph.isConnected (nodeA, nodeB));
|
||||
}
|
||||
|
||||
beginTest ("graph lookups work with a large number of connections");
|
||||
{
|
||||
AudioProcessorGraph graph;
|
||||
|
||||
std::vector<AudioProcessorGraph::NodeID> nodeIDs;
|
||||
|
||||
constexpr auto numNodes = 100;
|
||||
|
||||
for (auto i = 0; i < numNodes; ++i)
|
||||
{
|
||||
nodeIDs.push_back (graph.addNode (BasicProcessor::make (BasicProcessor::getStereoProperties(),
|
||||
MidiIn::yes,
|
||||
MidiOut::yes))->nodeID);
|
||||
}
|
||||
|
||||
for (auto it = nodeIDs.begin(); it != std::prev (nodeIDs.end()); ++it)
|
||||
{
|
||||
expect (graph.addConnection ({ { it[0], 0 }, { it[1], 0 } }));
|
||||
expect (graph.addConnection ({ { it[0], 1 }, { it[1], 1 } }));
|
||||
}
|
||||
|
||||
// Check whether isConnected reports correct results when called
|
||||
// with both connections and nodes
|
||||
for (auto it = nodeIDs.begin(); it != std::prev (nodeIDs.end()); ++it)
|
||||
{
|
||||
expect (graph.isConnected ({ { it[0], 0 }, { it[1], 0 } }));
|
||||
expect (graph.isConnected ({ { it[0], 1 }, { it[1], 1 } }));
|
||||
expect (graph.isConnected (it[0], it[1]));
|
||||
}
|
||||
|
||||
const auto& nodes = graph.getNodes();
|
||||
|
||||
expect (! graph.isAnInputTo (*nodes[0], *nodes[0]));
|
||||
|
||||
// Check whether isAnInputTo behaves correctly for a non-cyclic graph
|
||||
for (auto it = std::next (nodes.begin()); it != std::prev (nodes.end()); ++it)
|
||||
{
|
||||
expect (! graph.isAnInputTo (**it, **it));
|
||||
|
||||
expect (graph.isAnInputTo (*nodes[0], **it));
|
||||
expect (! graph.isAnInputTo (**it, *nodes[0]));
|
||||
|
||||
expect (graph.isAnInputTo (**it, *nodes[nodes.size() - 1]));
|
||||
expect (! graph.isAnInputTo (*nodes[nodes.size() - 1], **it));
|
||||
}
|
||||
|
||||
// Make the graph cyclic
|
||||
graph.addConnection ({ { nodeIDs.back(), 0 }, { nodeIDs.front(), 0 } });
|
||||
graph.addConnection ({ { nodeIDs.back(), 1 }, { nodeIDs.front(), 1 } });
|
||||
|
||||
// Check whether isAnInputTo behaves correctly for a cyclic graph
|
||||
for (const auto* node : graph.getNodes())
|
||||
{
|
||||
expect (graph.isAnInputTo (*node, *node));
|
||||
|
||||
expect (graph.isAnInputTo (*nodes[0], *node));
|
||||
expect (graph.isAnInputTo (*node, *nodes[0]));
|
||||
|
||||
expect (graph.isAnInputTo (*node, *nodes[nodes.size() - 1]));
|
||||
expect (graph.isAnInputTo (*nodes[nodes.size() - 1], *node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
enum class MidiIn { no, yes };
|
||||
enum class MidiOut { no, yes };
|
||||
|
||||
class BasicProcessor : public AudioProcessor
|
||||
{
|
||||
public:
|
||||
explicit BasicProcessor (const AudioProcessor::BusesProperties& layout, MidiIn mIn, MidiOut mOut)
|
||||
: AudioProcessor (layout), midiIn (mIn), midiOut (mOut) {}
|
||||
|
||||
const String getName() const override { return "Basic Processor"; }
|
||||
double getTailLengthSeconds() const override { return {}; }
|
||||
bool acceptsMidi() const override { return midiIn == MidiIn ::yes; }
|
||||
bool producesMidi() const override { return midiOut == MidiOut::yes; }
|
||||
AudioProcessorEditor* createEditor() override { return {}; }
|
||||
bool hasEditor() const override { return {}; }
|
||||
int getNumPrograms() override { return 1; }
|
||||
int getCurrentProgram() override { return {}; }
|
||||
void setCurrentProgram (int) override {}
|
||||
const String getProgramName (int) override { return {}; }
|
||||
void changeProgramName (int, const String&) override {}
|
||||
void getStateInformation (juce::MemoryBlock&) override {}
|
||||
void setStateInformation (const void*, int) override {}
|
||||
void prepareToPlay (double, int) override {}
|
||||
void releaseResources() override {}
|
||||
void processBlock (AudioBuffer<float>&, MidiBuffer&) override {}
|
||||
bool supportsDoublePrecisionProcessing() const override { return true; }
|
||||
bool isMidiEffect() const override { return {}; }
|
||||
void reset() override {}
|
||||
void setNonRealtime (bool) noexcept override {}
|
||||
|
||||
using AudioProcessor::processBlock;
|
||||
|
||||
static std::unique_ptr<AudioProcessor> make (const BusesProperties& layout,
|
||||
MidiIn midiIn,
|
||||
MidiOut midiOut)
|
||||
{
|
||||
return std::make_unique<BasicProcessor> (layout, midiIn, midiOut);
|
||||
}
|
||||
|
||||
static BusesProperties getStereoProperties()
|
||||
{
|
||||
return BusesProperties().withInput ("in", AudioChannelSet::stereo())
|
||||
.withOutput ("out", AudioChannelSet::stereo());
|
||||
}
|
||||
|
||||
private:
|
||||
MidiIn midiIn;
|
||||
MidiOut midiOut;
|
||||
};
|
||||
};
|
||||
|
||||
static AudioProcessorGraphTests audioProcessorGraphTests;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue