daily_automated

This commit is contained in:
topicchi
2023-03-17 11:59:21 +00:00
parent 252ecca9cf
commit e2f276193e
4496 changed files with 1178007 additions and 0 deletions

View File

@@ -0,0 +1,991 @@
#include "unit-tests.h"
#include "unit-tests_Settings.h"
#include <src/MIDI.h>
#include <test/mocks/test-mocks_SerialMock.h>
BEGIN_MIDI_NAMESPACE
END_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
BEGIN_UNNAMED_NAMESPACE
using namespace testing;
USING_NAMESPACE_UNIT_TESTS
typedef test_mocks::SerialMock<32> SerialMock;
typedef midi::SerialMIDI<SerialMock> Transport;
typedef midi::MidiInterface<Transport> MidiInterface;
template<unsigned Size>
struct VariableSysExSettings : midi::DefaultSettings
{
static const unsigned SysExMaxSize = Size;
};
TEST(MidiInput, getTypeFromStatusByte)
{
// Channel Messages
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0x81), midi::NoteOff);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0x92), midi::NoteOn);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xa3), midi::AfterTouchPoly);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xb4), midi::ControlChange);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xc5), midi::ProgramChange);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xd6), midi::AfterTouchChannel);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xe7), midi::PitchBend);
// System Messages
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xf0), midi::SystemExclusive);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xf1), midi::TimeCodeQuarterFrame);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xf2), midi::SongPosition);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xf3), midi::SongSelect);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xf6), midi::TuneRequest);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xf8), midi::Clock);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xfa), midi::Start);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xfb), midi::Continue);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xfc), midi::Stop);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xfe), midi::ActiveSensing);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xff), midi::SystemReset);
// Invalid Messages
for (int i = 0; i < 0x80; ++i)
{
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(i), midi::InvalidType);
}
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xf4), midi::InvalidType);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xf5), midi::InvalidType);
EXPECT_EQ(MidiInterface::getTypeFromStatusByte(0xfd), midi::InvalidType);
}
TEST(MidiInput, getChannelFromStatusByte)
{
EXPECT_EQ(MidiInterface::getChannelFromStatusByte(0x00), 1);
EXPECT_EQ(MidiInterface::getChannelFromStatusByte(0x80), 1);
EXPECT_EQ(MidiInterface::getChannelFromStatusByte(0x94), 5);
EXPECT_EQ(MidiInterface::getChannelFromStatusByte(0xaf), 16);
}
TEST(MidiInput, isChannelMessage)
{
EXPECT_EQ(MidiInterface::isChannelMessage(midi::InvalidType), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::NoteOff), true);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::NoteOn), true);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::AfterTouchPoly), true);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::ControlChange), true);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::ProgramChange), true);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::AfterTouchChannel), true);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::PitchBend), true);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::SystemExclusive), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::TimeCodeQuarterFrame), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::SongPosition), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::SongSelect), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::TuneRequest), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::Clock), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::Start), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::Continue), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::Stop), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::ActiveSensing), false);
EXPECT_EQ(MidiInterface::isChannelMessage(midi::SystemReset), false);
}
// --
TEST(MidiInput, begin)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
// Default channel
midi.begin();
EXPECT_EQ(serial.mBaudrate, 31250);
EXPECT_EQ(midi.getInputChannel(), 1);
// Specific channel
midi.begin(12);
EXPECT_EQ(serial.mBaudrate, 31250);
EXPECT_EQ(midi.getInputChannel(), 12);
}
TEST(MidiInput, initInputChannel)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
EXPECT_EQ(midi.getInputChannel(), 0);
midi.setInputChannel(12);
EXPECT_EQ(midi.getInputChannel(), 12);
}
TEST(MidiInput, initMessage)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
EXPECT_EQ(midi.getType(), midi::InvalidType);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.getSysExArrayLength(), unsigned(0));
EXPECT_EQ(midi.check(), false);
}
TEST(MidiInput, channelFiltering)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0x9b, 12, 34 };
midi.begin(4); // Mistmatching channel
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
}
TEST(MidiInput, noRxData)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
midi.begin();
EXPECT_EQ(midi.read(), false);
}
TEST(MidiInput, inputDisabled)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0x9b, 12, 34 };
midi.begin(MIDI_CHANNEL_OFF); // Invalid channel
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
}
TEST(MidiInput, multiByteParsing)
{
typedef VariableSettings<false, false> Settings;
typedef midi::MidiInterface<Transport, Settings> MultiByteMidiInterface;
SerialMock serial;
Transport transport(serial);
MultiByteMidiInterface midi(transport);
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0x9b, 12, 34 };
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), true);
}
TEST(MidiInput, noteOn)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 10;
static const byte rxData[rxSize] = {
0x9b, 12, 34,
0x9b, 56, 78,
12, 34, // Running status
56, 0 // NoteOn with null velocity interpreted as NoteOff
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
// First NoteOn
EXPECT_EQ(midi.getType(), midi::NoteOn);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOn);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 78);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOn);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOff);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 0);
}
TEST(MidiInput, noteOff)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 8;
static const byte rxData[rxSize] = {
0x8b, 12, 34,
0x8b, 56, 78,
12, 34, // Running status
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
// First NoteOn
EXPECT_EQ(midi.getType(), midi::NoteOff);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOff);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 78);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOff);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
}
TEST(MidiInput, programChange)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = {
0xc3, 12, 34,
0xc4, 56, 78
};
midi.begin(MIDI_CHANNEL_OMNI);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ProgramChange);
EXPECT_EQ(midi.getChannel(), 4);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ProgramChange);
EXPECT_EQ(midi.getChannel(), 4);
EXPECT_EQ(midi.getData1(), 34);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ProgramChange);
EXPECT_EQ(midi.getChannel(), 5);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ProgramChange);
EXPECT_EQ(midi.getChannel(), 5);
EXPECT_EQ(midi.getData1(), 78);
EXPECT_EQ(midi.getData2(), 0);
}
TEST(MidiInput, controlChange)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 8;
static const byte rxData[rxSize] = {
0xbb, 12, 34,
0xbb, 56, 78,
12, 34
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
// First NoteOn
EXPECT_EQ(midi.getType(), midi::ControlChange);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ControlChange);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 78);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ControlChange);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
}
TEST(MidiInput, pitchBend)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 8;
static const byte rxData[rxSize] = {
0xeb, 12, 34,
0xeb, 56, 78,
12, 34
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
// First NoteOn
EXPECT_EQ(midi.getType(), midi::PitchBend);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::PitchBend);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 78);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::PitchBend);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
}
TEST(MidiInput, afterTouchPoly)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 8;
static const byte rxData[rxSize] = {
0xab, 12, 34,
0xab, 56, 78,
12, 34
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
// First NoteOn
EXPECT_EQ(midi.getType(), midi::AfterTouchPoly);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::AfterTouchPoly);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 78);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::AfterTouchPoly);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
}
TEST(MidiInput, afterTouchChannel)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = {
0xd3, 12, 34,
0xd4, 56, 78
};
midi.begin(MIDI_CHANNEL_OMNI);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::AfterTouchChannel);
EXPECT_EQ(midi.getChannel(), 4);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::AfterTouchChannel);
EXPECT_EQ(midi.getChannel(), 4);
EXPECT_EQ(midi.getData1(), 34);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::AfterTouchChannel);
EXPECT_EQ(midi.getChannel(), 5);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::AfterTouchChannel);
EXPECT_EQ(midi.getChannel(), 5);
EXPECT_EQ(midi.getData1(), 78);
EXPECT_EQ(midi.getData2(), 0);
}
TEST(MidiInput, sysExWithinBufferSize)
{
typedef VariableSysExSettings<1024> Settings;
typedef test_mocks::SerialMock<2048> LargerSerialMock;
typedef midi::SerialMIDI<LargerSerialMock> LargerTransport;
typedef midi::MidiInterface<LargerTransport, Settings> LargerMidiInterface;
LargerSerialMock serial;
LargerTransport transport(serial);
LargerMidiInterface midi(transport);
// Short Frame < 256
{
static const unsigned frameLength = 15;
static const byte frame[frameLength] = {
0xf0, 'H','e','l','l','o',',',' ','W','o','r','l','d','!', 0xf7
};
midi.begin();
serial.mRxBuffer.write(frame, frameLength);
for (unsigned i = 0; i < frameLength - 1; ++i)
{
EXPECT_EQ(midi.read(), false);
}
EXPECT_EQ(midi.read(), true); // 0xf7
EXPECT_EQ(midi.getSysExArrayLength(), frameLength);
const std::vector<byte> sysExData(midi.getSysExArray(),
midi.getSysExArray() + frameLength);
EXPECT_THAT(sysExData, ElementsAreArray(frame));
}
// Long Frame
{
static const unsigned frameLength = 957;
static const byte frame[frameLength] = {
0xf0,
'L','o','r','e','m',' ','i','p','s','u','m',' ','d','o','l','o','r',' ','s','i','t',' ','a','m','e','t',',',' ',
'c','o','n','s','e','c','t','e','t','u','r',' ','a','d','i','p','i','s','c','i','n','g',' ','e','l','i','t','.',' ','P','r','o','i','n',' ','m','a','x','i','m','u','s',' ','d','u','i',' ','a',' ','m','a','s','s','a',' ','m','a','x','i','m','u','s',',',' ',
'a',' ','v','e','s','t','i','b','u','l','u','m',' ','m','i',' ','v','e','n','e','n','a','t','i','s','.',' ','C','r','a','s',' ','s','i','t',' ','a','m','e','t',' ','e','x',' ','i','d',' ','v','e','l','i','t',' ','s','u','s','c','i','p','i','t',' ','p','h','a','r','e','t','r','a',' ','e','g','e','t', ' ','a',' ','t','u','r','p','i','s','.',' ','P','h','a','s','e','l','l','u','s',' ','i','n','t','e','r','d','u','m',' ','m','e','t','u','s',' ','a','c',' ','s','a','g','i','t','t','i','s',' ','c','u','r','s','u','s','.',' ','N','a','m',' ','q','u','i','s',' ','e','s','t',' ','a','t',' ','n','i','s', 'l',' ','u','l','l','a','m','c','o','r','p','e','r',' ','e','g','e','s','t','a','s',' ','p','u','l','v','i','n','a','r',' ','e','u',' ','e','r','a','t','.',' ','D','u','i','s',' ','a',' ','e','l','i','t',' ','d','i','g','n','i','s','s','i','m',',',' ',
'v','e','s','t','i','b','u','l','u','m',' ','e','r','o','s',' ','v','e','l',',',' ',
't','e','m','p','u','s',' ','n','i','s','l','.',' ','A','e','n','e','a','n',' ','t','u','r','p','i','s',' ','n','u','n','c',',',' ',
'c','u','r','s','u','s',' ','v','e','l',' ','l','a','c','i','n','i','a',' ','n','o','n',',',' ',
'p','h','a','r','e','t','r','a',' ','e','g','e','t',' ','s','a','p','i','e','n','.',' ','D','u','i','s',' ','c','o','n','d','i','m','e','n','t','u','m',',',' ',
'l','a','c','u','s',' ','a','t',' ','p','u','l','v','i','n','a','r',' ','t','e','m','p','o','r',',',' ',
'l','e','o',' ','l','i','b','e','r','o',' ','v','o','l','u','t','p','a','t',' ','n','i','s','l',',',' ',
'e','g','e','t',' ','p','o','r','t','t','i','t','o','r',' ','l','o','r','e','m',' ','m','i',' ','s','e','d',' ','m','a','g','n','a','.',' ','D','u','i','s',' ','d','i','c','t','u','m',',',' ',
'm','a','s','s','a',' ','v','e','l',' ','e','u','i','s','m','o','d',' ','i','n','t','e','r','d','u','m',',',' ',
'l','o','r','e','m',' ','m','i',' ','e','g','e','s','t','a','s',' ','e','l','i','t',',',' ',
'h','e','n','d','r','e','r','i','t',' ','t','i','n','c','i','d','u','n','t',' ','e','s','t',' ','a','r','c','u',' ','a',' ','l','i','b','e','r','o','.',' ','I','n','t','e','r','d','u','m',' ','e','t',' ','m','a','l','e','s','u','a','d','a',' ','f','a','m','e','s',' ','a','c',' ','a','n','t','e',' ', 'i','p','s','u','m',' ','p','r','i','m','i','s',' ','i','n',' ','f','a','u','c','i','b','u','s','.',' ','C','u','r','a','b','i','t','u','r',' ','v','e','h','i','c','u','l','a',' ','m','a','g','n','a',' ','l','i','b','e','r','o',',',' ',
'a','t',' ','r','h','o','n','c','u','s',' ','s','e','m',' ','o','r','n','a','r','e',' ','a','.',' ','I','n',' ','e','l','e','m','e','n','t','u','m',',',' ',
'e','l','i','t',' ','e','t',' ','c','o','n','g','u','e',' ','p','u','l','v','i','n','a','r',',',' ',
'm','a','s','s','a',' ','v','e','l','i','t',' ','c','o','m','m','o','d','o',' ','v','e','l','i','t',',',' ',
'n','o','n',' ','e','l','e','m','e','n','t','u','m',' ','p','u','r','u','s',' ','l','i','g','u','l','a',' ','e','g','e','t',' ','l','a','c','u','s','.',' ','D','o','n','e','c',' ','e','f','f','i','c','i','t','u','r',' ','n','i','s','i',' ','e','u',' ','u','l','t','r','i','c','e','s',' ','e','f','f', 'i','c','i','t','u','r','.',' ','D','o','n','e','c',' ','n','e','q','u','e',' ','d','u','i',',',' ',
'u','l','l','a','m','c','o','r','p','e','r',' ','i','d',' ','m','o','l','e','s','t','i','e',' ','q','u','i','s',',',' ',
'c','o','n','s','e','q','u','a','t',' ','s','i','t',' ','a','m','e','t',' ','l','i','g','u','l','a','.',
0xf7,
};
midi.begin();
serial.mRxBuffer.write(frame, frameLength);
for (unsigned i = 0; i < frameLength - 1; ++i)
{
EXPECT_EQ(midi.read(), false);
}
EXPECT_EQ(serial.mRxBuffer.getLength(), 1);
EXPECT_EQ(serial.mRxBuffer.peek(), 0xf7);
EXPECT_EQ(midi.read(), true);
}
}
TEST(MidiInput, sysExOverBufferSize)
{
typedef VariableSysExSettings<8> Settings;
typedef midi::MidiInterface<Transport, Settings> SmallMidiInterface;
SerialMock serial;
Transport transport(serial);
SmallMidiInterface midi(transport);
static const unsigned frameLength = 15;
static const byte frame[frameLength] = {
0xf0, 'H','e','l','l','o',',',' ','W','o','r','l','d','!', 0xf7
};
midi.begin();
serial.mRxBuffer.write(frame, frameLength);
EXPECT_EQ(midi.read(), false); // start sysex f0
EXPECT_EQ(midi.read(), false); // H
EXPECT_EQ(midi.read(), false); // e
EXPECT_EQ(midi.read(), false); // l
EXPECT_EQ(midi.read(), false); // l
EXPECT_EQ(midi.read(), false); // o
EXPECT_EQ(midi.read(), false); // , message send and buffer cleared.
EXPECT_EQ(midi.read(), false); // start sysex
EXPECT_EQ(midi.read(), false); // (space)
EXPECT_EQ(midi.read(), false); // W
EXPECT_EQ(midi.read(), false); // o
EXPECT_EQ(midi.read(), false); // r
EXPECT_EQ(midi.read(), false); // l
EXPECT_EQ(midi.read(), false); // d
EXPECT_EQ(midi.read(), true); // end sysex
}
TEST(MidiInput, mtcQuarterFrame)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 4;
static const byte rxData[rxSize] = {
0xf1, 12,
0xf1, 42
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::TimeCodeQuarterFrame);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::TimeCodeQuarterFrame);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 42);
EXPECT_EQ(midi.getData2(), 0);
}
TEST(MidiInput, songPosition)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = {
0xf2, 12, 34,
0xf2, 56, 78
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::SongPosition);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::SongPosition);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 56);
EXPECT_EQ(midi.getData2(), 78);
}
TEST(MidiInput, songSelect)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 4;
static const byte rxData[rxSize] = {
0xf3, 12,
0xf3, 42
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
// 1 byte parsing
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::SongSelect);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::SongSelect);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 42);
EXPECT_EQ(midi.getData2(), 0);
}
TEST(MidiInput, tuneRequest)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 1;
static const byte rxData[rxSize] = {
0xf6
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::TuneRequest);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
}
TEST(MidiInput, realTime)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 8;
static const byte rxData[rxSize] = {
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Clock);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Tick);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Start);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Continue);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Stop);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false); // 0xfd = undefined
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ActiveSensing);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::SystemReset);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
}
// --
TEST(MidiInput, interleavedRealTime)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
// Interleaved Clocks between NoteOn / Off messages (with running status)
{
static const unsigned rxSize = 13;
static const byte rxData[rxSize] = {
0x9b, 12, 0xf8, 34,
12, 0,
42, 0xf8, 127,
0xf8,
42, 0xf8, 0
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Clock);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOn);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOff);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Clock);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOn);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 42);
EXPECT_EQ(midi.getData2(), 127);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Clock);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::Clock);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::NoteOff);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 42);
EXPECT_EQ(midi.getData2(), 0);
}
// Interleaved ActiveSensing between SysEx
{
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = {
0xf0, 12, 34, 0xfe, 56, 0xf7
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ActiveSensing);
EXPECT_EQ(midi.getChannel(), 0);
EXPECT_EQ(midi.getData1(), 0);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getSysExArrayLength(), rxSize - 1);
const std::vector<byte> sysExData(midi.getSysExArray(),
midi.getSysExArray() + rxSize - 1);
EXPECT_THAT(sysExData, ElementsAreArray({
0xf0, 12, 34, 56, 0xf7
}));
}
}
TEST(MidiInput, strayEox)
{
// A stray End of Exclusive will reset the parser, but should it ?
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 4;
static const byte rxData[rxSize] = {
0x8b, 42, 0xf7, 12
};
midi.begin(MIDI_CHANNEL_OMNI);
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
}
TEST(MidiInput, strayUndefinedOneByteParsing)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
static const unsigned rxSize = 13;
static const byte rxData[rxSize] = {
0xbb, 12, 0xfd, 34,
12, 0,
42, 0xfd, 127,
0xfd,
42, 0xfd, 0
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false); // Invalid, should not reset parser
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ControlChange);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ControlChange);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ControlChange);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 42);
EXPECT_EQ(midi.getData2(), 127);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ControlChange);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 42);
EXPECT_EQ(midi.getData2(), 0);
}
TEST(MidiInput, strayUndefinedMultiByteParsing)
{
typedef VariableSettings<false, false> Settings;
typedef midi::MidiInterface<Transport, Settings> MultiByteMidiInterface;
SerialMock serial;
Transport transport(serial);
MultiByteMidiInterface midi(transport);
static const unsigned rxSize = 4;
static const byte rxData[rxSize] = {
0xbb, 12, 0xfd, 34,
};
midi.begin(12);
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.getType(), midi::ControlChange);
EXPECT_EQ(midi.getChannel(), 12);
EXPECT_EQ(midi.getData1(), 12);
EXPECT_EQ(midi.getData2(), 34);
}
END_UNNAMED_NAMESPACE

View File

@@ -0,0 +1,594 @@
#include "unit-tests.h"
#include "unit-tests_Settings.h"
#include <src/MIDI.h>
#include <test/mocks/test-mocks_SerialMock.h>
BEGIN_MIDI_NAMESPACE
END_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
BEGIN_UNNAMED_NAMESPACE
using namespace testing;
USING_NAMESPACE_UNIT_TESTS
template<unsigned Size>
struct VariableSysExSettings : midi::DefaultSettings
{
static const unsigned SysExMaxSize = Size;
};
typedef test_mocks::SerialMock<256> SerialMock;
typedef midi::SerialMIDI<SerialMock> Transport;
typedef VariableSysExSettings<256> Settings;
typedef midi::MidiInterface<Transport, Settings> MidiInterface;
MidiInterface* midi;
class MidiInputCallbacks : public Test
{
public:
MidiInputCallbacks()
: mTransport(mSerial)
, mMidi(mTransport)
{
}
virtual ~MidiInputCallbacks()
{
}
protected:
virtual void SetUp()
{
midi = &mMidi;
}
virtual void TearDown()
{
midi = nullptr;
}
protected:
SerialMock mSerial;
Transport mTransport;
MidiInterface mMidi;
};
// --
void handleNoteOn(byte inChannel, byte inPitch, byte inVelocity)
{
EXPECT_NE(midi, nullptr);
midi->sendNoteOn(inPitch, inVelocity, inChannel);
}
TEST_F(MidiInputCallbacks, noteOn)
{
mMidi.setHandleNoteOn(handleNoteOn);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0x9b, 12, 34 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::NoteOn);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 34);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 3);
byte buffer[3] = { 0 };
mSerial.mTxBuffer.read(buffer, 3);
EXPECT_THAT(buffer, ContainerEq(rxData));
// Test null velocity note on
EXPECT_EQ(MidiInterface::Settings::HandleNullVelocityNoteOnAsNoteOff, true);
mSerial.mRxBuffer.write(0x9b);
mSerial.mRxBuffer.write(12);
mSerial.mRxBuffer.write(0);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::NoteOff);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 0);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 0);
}
// --
void handleNoteOff(byte inChannel, byte inPitch, byte inVelocity)
{
EXPECT_NE(midi, nullptr);
midi->sendNoteOff(inPitch, inVelocity, inChannel);
}
TEST_F(MidiInputCallbacks, noteOff)
{
mMidi.setHandleNoteOff(handleNoteOff);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0x8b, 12, 34 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::NoteOff);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 34);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 3);
byte buffer[3] = { 0 };
mSerial.mTxBuffer.read(buffer, 3);
EXPECT_THAT(buffer, ContainerEq(rxData));
// Test null velocity note on
EXPECT_EQ(MidiInterface::Settings::HandleNullVelocityNoteOnAsNoteOff, true);
mSerial.mRxBuffer.write(0x9b);
mSerial.mRxBuffer.write(12);
mSerial.mRxBuffer.write(0);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::NoteOff);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 0);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 3);
mSerial.mTxBuffer.read(buffer, 3);
EXPECT_THAT(buffer, ElementsAreArray({
0x8b, 12, 0
}));
}
// --
void handleAfterTouchPoly(byte inChannel, byte inNote, byte inValue)
{
EXPECT_NE(midi, nullptr);
midi->sendAfterTouch(inNote, inValue, inChannel);
}
TEST_F(MidiInputCallbacks, afterTouchPoly)
{
mMidi.setHandleAfterTouchPoly(handleAfterTouchPoly);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0xab, 12, 34 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::AfterTouchPoly);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 34);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 3);
byte buffer[3] = { 0 };
mSerial.mTxBuffer.read(buffer, 3);
EXPECT_THAT(buffer, ContainerEq(rxData));
}
// --
void handleControlChange(byte inChannel, byte inNumber, byte inValue)
{
EXPECT_NE(midi, nullptr);
midi->sendControlChange(inNumber, inValue, inChannel);
}
TEST_F(MidiInputCallbacks, controlChange)
{
mMidi.setHandleControlChange(handleControlChange);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0xbb, 12, 34 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::ControlChange);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 34);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 3);
byte buffer[3] = { 0 };
mSerial.mTxBuffer.read(buffer, 3);
EXPECT_THAT(buffer, ContainerEq(rxData));
}
// --
void handleProgramChange(byte inChannel, byte inNumber)
{
EXPECT_NE(midi, nullptr);
midi->sendProgramChange(inNumber, inChannel);
}
TEST_F(MidiInputCallbacks, programChange)
{
mMidi.setHandleProgramChange(handleProgramChange);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 2;
static const byte rxData[rxSize] = { 0xcb, 12 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::ProgramChange);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 0);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 2);
byte buffer[2] = { 0 };
mSerial.mTxBuffer.read(buffer, 2);
EXPECT_THAT(buffer, ContainerEq(rxData));
}
// --
void handleAfterTouchChannel(byte inChannel, byte inPressure)
{
EXPECT_NE(midi, nullptr);
midi->sendAfterTouch(inPressure, inChannel);
}
TEST_F(MidiInputCallbacks, afterTouchChannel)
{
mMidi.setHandleAfterTouchChannel(handleAfterTouchChannel);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 2;
static const byte rxData[rxSize] = { 0xdb, 12 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::AfterTouchChannel);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 0);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 2);
byte buffer[2] = { 0 };
mSerial.mTxBuffer.read(buffer, 2);
EXPECT_THAT(buffer, ContainerEq(rxData));
}
// --
void handlePitchBend(byte inChannel, int inValue)
{
EXPECT_NE(midi, nullptr);
midi->sendPitchBend(inValue, inChannel);
}
TEST_F(MidiInputCallbacks, pitchBend)
{
mMidi.setHandlePitchBend(handlePitchBend);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0xeb, 12, 34 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::PitchBend);
EXPECT_EQ(mMidi.getChannel(), 12);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 34);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 3);
byte buffer[3] = { 0 };
mSerial.mTxBuffer.read(buffer, 3);
EXPECT_THAT(buffer, ContainerEq(rxData));
}
// --
void handleSysEx(byte* inData, unsigned inSize)
{
EXPECT_NE(midi, nullptr);
midi->sendSysEx(inSize, inData, true);
}
TEST_F(MidiInputCallbacks, sysEx)
{
mMidi.setHandleSystemExclusive(handleSysEx);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 15;
static const byte rxData[rxSize] = {
0xf0, 'H','e','l','l','o',',',' ','W','o','r','l','d','!', 0xf7
};
mSerial.mRxBuffer.write(rxData, rxSize);
for (unsigned i = 0; i < rxSize - 1; ++i)
{
EXPECT_EQ(mMidi.read(), false);
}
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::SystemExclusive);
EXPECT_EQ(mMidi.getChannel(), 0);
EXPECT_EQ(mMidi.getSysExArrayLength(), rxSize);
EXPECT_EQ(unsigned(mSerial.mTxBuffer.getLength()), rxSize);
const std::vector<byte> sysExData(mMidi.getSysExArray(),
mMidi.getSysExArray() + rxSize);
EXPECT_THAT(sysExData, ElementsAreArray(rxData));
}
TEST_F(MidiInputCallbacks, sysExLong)
{
mMidi.setHandleSystemExclusive(handleSysEx);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 210;
static const byte rxData[rxSize] = {
0xf0,
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
'H','e','l','l','o',',',' ','W','o','r','l','d','!',
0xf7
};
mSerial.mRxBuffer.write(rxData, rxSize);
for (unsigned i = 0; i < rxSize - 1; ++i)
{
EXPECT_EQ(mMidi.read(), false);
}
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::SystemExclusive);
EXPECT_EQ(mMidi.getChannel(), 0);
EXPECT_EQ(mMidi.getSysExArrayLength(), rxSize);
EXPECT_EQ(unsigned(mSerial.mTxBuffer.getLength()), rxSize);
const std::vector<byte> sysExData(mMidi.getSysExArray(),
mMidi.getSysExArray() + rxSize);
EXPECT_THAT(sysExData, ElementsAreArray(rxData));
}
// --
void handleMtcQuarterFrame(byte inData)
{
EXPECT_NE(midi, nullptr);
midi->sendTimeCodeQuarterFrame(inData);
}
TEST_F(MidiInputCallbacks, mtcQuarterFrame)
{
mMidi.setHandleTimeCodeQuarterFrame(handleMtcQuarterFrame);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 2;
static const byte rxData[rxSize] = { 0xf1, 12 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::TimeCodeQuarterFrame);
EXPECT_EQ(mMidi.getChannel(), 0);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 0);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 2);
byte buffer[2] = { 0 };
mSerial.mTxBuffer.read(buffer, 2);
EXPECT_THAT(buffer, ContainerEq(rxData));
}
// --
void handleSongPosition(unsigned inBeats)
{
EXPECT_NE(midi, nullptr);
midi->sendSongPosition(inBeats);
}
TEST_F(MidiInputCallbacks, songPosition)
{
mMidi.setHandleSongPosition(handleSongPosition);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 3;
static const byte rxData[rxSize] = { 0xf2, 12, 34 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::SongPosition);
EXPECT_EQ(mMidi.getChannel(), 0);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 34);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 3);
byte buffer[3] = { 0 };
mSerial.mTxBuffer.read(buffer, 3);
EXPECT_THAT(buffer, ContainerEq(rxData));
}
// --
void handleSongSelect(byte inSongNumber)
{
EXPECT_NE(midi, nullptr);
midi->sendSongSelect(inSongNumber);
}
TEST_F(MidiInputCallbacks, songSelect)
{
mMidi.setHandleSongSelect(handleSongSelect);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 2;
static const byte rxData[rxSize] = { 0xf3, 12 };
mSerial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(mMidi.read(), false);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::SongSelect);
EXPECT_EQ(mMidi.getChannel(), 0);
EXPECT_EQ(mMidi.getData1(), 12);
EXPECT_EQ(mMidi.getData2(), 0);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 2);
byte buffer[2] = { 0 };
mSerial.mTxBuffer.read(buffer, 2);
EXPECT_THAT(buffer, ContainerEq(rxData));
}
// --
void handleTuneRequest()
{
EXPECT_NE(midi, nullptr);
midi->sendTuneRequest();
}
TEST_F(MidiInputCallbacks, tuneRequest)
{
mMidi.setHandleTuneRequest(handleTuneRequest);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
mSerial.mRxBuffer.write(0xf6);
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), midi::TuneRequest);
EXPECT_EQ(mMidi.getChannel(), 0);
EXPECT_EQ(mMidi.getData1(), 0);
EXPECT_EQ(mMidi.getData2(), 0);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 1);
EXPECT_EQ(mSerial.mTxBuffer.read(), 0xf6);
}
// --
void handleClock()
{
EXPECT_NE(midi, nullptr);
midi->sendRealTime(midi::Clock);
}
void handleStart()
{
EXPECT_NE(midi, nullptr);
midi->sendRealTime(midi::Start);
}
void handleContinue()
{
EXPECT_NE(midi, nullptr);
midi->sendRealTime(midi::Continue);
}
void handleStop()
{
EXPECT_NE(midi, nullptr);
midi->sendRealTime(midi::Stop);
}
void handleActiveSensing()
{
EXPECT_NE(midi, nullptr);
midi->sendRealTime(midi::ActiveSensing);
}
void handleSystemReset()
{
EXPECT_NE(midi, nullptr);
midi->sendRealTime(midi::SystemReset);
}
TEST_F(MidiInputCallbacks, realTime)
{
mMidi.setHandleClock(handleClock);
mMidi.setHandleStart(handleStart);
mMidi.setHandleContinue(handleContinue);
mMidi.setHandleStop(handleStop);
mMidi.setHandleActiveSensing(handleActiveSensing);
mMidi.setHandleSystemReset(handleSystemReset);
mMidi.begin(MIDI_CHANNEL_OMNI);
mMidi.turnThruOff();
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = {
0xf8, 0xfa, 0xfb, 0xfc, 0xfe, 0xff
};
mSerial.mRxBuffer.write(rxData, rxSize);
static const midi::MidiType types[rxSize] = {
midi::Clock,
midi::Start,
midi::Continue,
midi::Stop,
midi::ActiveSensing,
midi::SystemReset,
};
for (unsigned i = 0; i < rxSize; ++i)
{
EXPECT_EQ(mMidi.read(), true);
EXPECT_EQ(mMidi.getType(), types[i]);
EXPECT_EQ(mMidi.getChannel(), 0);
EXPECT_EQ(mMidi.getData1(), 0);
EXPECT_EQ(mMidi.getData2(), 0);
EXPECT_EQ(mSerial.mTxBuffer.getLength(), 1);
const byte read = mSerial.mTxBuffer.read();
EXPECT_EQ(read, rxData[i]);
EXPECT_EQ(read, types[i]);
}
}
END_UNNAMED_NAMESPACE

View File

@@ -0,0 +1,83 @@
#include "unit-tests.h"
#include <src/midi_Message.h>
BEGIN_MIDI_NAMESPACE
// Declare references:
// http://stackoverflow.com/questions/4891067/weird-undefined-symbols-of-static-constants-inside-a-struct-class
template<unsigned Size>
const unsigned Message<Size>::sSysExMaxSize;
END_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
BEGIN_UNNAMED_NAMESPACE
TEST(MidiMessage, hasTheRightProperties)
{
typedef midi::Message<42> Message;
const Message message = Message();
EXPECT_EQ(message.channel, 0);
EXPECT_EQ(message.type, 0);
EXPECT_EQ(message.data1, 0);
EXPECT_EQ(message.data2, 0);
EXPECT_EQ(message.valid, false);
EXPECT_EQ(message.getSysExSize(), unsigned(0));
}
template<typename Message>
inline void setSysExSize(Message& ioMessage, unsigned inSize)
{
ioMessage.data2 = inSize >> 8; // MSB
ioMessage.data1 = inSize & 0xff; // LSB
}
TEST(MidiMessage, getSysExSize)
{
// Small message
{
typedef midi::Message<32> Message;
ASSERT_EQ(Message::sSysExMaxSize, unsigned(32));
Message message = Message();
const unsigned sizeUnder = 20;
setSysExSize(message, sizeUnder);
ASSERT_EQ(message.getSysExSize(), sizeUnder);
const unsigned sizeOver = 64;
setSysExSize(message, sizeOver);
ASSERT_EQ(message.getSysExSize(), unsigned(32));
}
// Medium message
{
typedef midi::Message<256> Message;
ASSERT_EQ(Message::sSysExMaxSize, unsigned(256));
Message message = Message();
const unsigned sizeUnder = 200;
setSysExSize(message, sizeUnder);
ASSERT_EQ(message.getSysExSize(), sizeUnder);
const unsigned sizeOver = 300;
setSysExSize(message, sizeOver);
ASSERT_EQ(message.getSysExSize(), unsigned(256));
}
// Large message
{
typedef midi::Message<1024> Message;
ASSERT_EQ(Message::sSysExMaxSize, unsigned(1024));
Message message = Message();
const unsigned sizeUnder = 1000;
setSysExSize(message, sizeUnder);
ASSERT_EQ(message.getSysExSize(), sizeUnder);
const unsigned sizeOver = 2000;
setSysExSize(message, sizeOver);
ASSERT_EQ(message.getSysExSize(), unsigned(1024));
}
}
END_UNNAMED_NAMESPACE

View File

@@ -0,0 +1,884 @@
#include "unit-tests.h"
#include "unit-tests_Settings.h"
#include <src/MIDI.h>
#include <test/mocks/test-mocks_SerialMock.h>
BEGIN_MIDI_NAMESPACE
END_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
BEGIN_UNNAMED_NAMESPACE
using namespace testing;
USING_NAMESPACE_UNIT_TESTS;
typedef test_mocks::SerialMock<32> SerialMock;
typedef midi::SerialMIDI<SerialMock> Transport;
typedef midi::MidiInterface<Transport> MidiInterface;
typedef std::vector<uint8_t> Buffer;
// --
TEST(MidiOutput, sendInvalid)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
midi.begin();
midi.send(midi::NoteOn, 42, 42, 42); // Invalid channel > OFF
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
midi.send(midi::InvalidType, 0, 0, 12); // Invalid type
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
midi.send(midi::NoteOn, 12, 42, MIDI_CHANNEL_OMNI); // OMNI not allowed
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
}
TEST(MidiOutput, sendGenericSingle)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(3);
midi.begin();
midi.send(midi::NoteOn, 47, 42, 12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({0x9b, 47, 42}));
}
TEST(MidiOutput, sendGenericWithRunningStatus)
{
typedef VariableSettings<true, false> Settings;
typedef midi::MidiInterface<Transport, Settings> RsMidiInterface;
SerialMock serial;
Transport transport(serial);
RsMidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(5);
midi.begin();
EXPECT_EQ(RsMidiInterface::Settings::UseRunningStatus, true);
EXPECT_EQ(serial.mTxBuffer.isEmpty(), true);
midi.send(midi::NoteOn, 47, 42, 12);
midi.send(midi::NoteOn, 42, 47, 12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 5);
serial.mTxBuffer.read(&buffer[0], 5);
EXPECT_THAT(buffer, ElementsAreArray({0x9b, 47, 42, 42, 47}));
}
TEST(MidiOutput, sendGenericWithoutRunningStatus)
{
typedef VariableSettings<false, true> Settings; // No running status
typedef midi::MidiInterface<Transport, Settings> NoRsMidiInterface;
SerialMock serial;
Transport transport(serial);
NoRsMidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
// Same status byte
midi.begin();
EXPECT_EQ(MidiInterface::Settings::UseRunningStatus, false);
EXPECT_EQ(serial.mTxBuffer.isEmpty(), true);
midi.send(midi::NoteOn, 47, 42, 12);
midi.send(midi::NoteOn, 42, 47, 12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0x9b, 47, 42, 0x9b, 42, 47}));
// Different status byte
midi.begin();
midi.send(midi::NoteOn, 47, 42, 12);
midi.send(midi::NoteOff, 47, 42, 12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0x9b, 47, 42, 0x8b, 47, 42}));
}
TEST(MidiOutput, sendGenericBreakingRunningStatus)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
midi.begin();
midi.send(midi::NoteOn, 47, 42, 12);
midi.send(midi::NoteOff, 47, 42, 12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0x9b, 47, 42, 0x8b, 47, 42}));
}
TEST(MidiOutput, sendGenericRealTimeShortcut)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
midi.begin();
midi.send(midi::Clock, 47, 42, 12);
midi.send(midi::Start, 47, 42, 12);
midi.send(midi::Continue, 47, 42, 12);
midi.send(midi::Stop, 47, 42, 12);
midi.send(midi::ActiveSensing, 47, 42, 12);
midi.send(midi::SystemReset, 47, 42, 12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0xf8, 0xfa, 0xfb, 0xfc, 0xfe, 0xff}));
}
// --
TEST(MidiOutput, sendNoteOn)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
midi.begin();
midi.sendNoteOn(10, 11, 12);
midi.sendNoteOn(12, 13, 4);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0x9b, 10, 11, 0x93, 12, 13}));
}
TEST(MidiOutput, sendNoteOff)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
midi.begin();
midi.sendNoteOff(10, 11, 12);
midi.sendNoteOff(12, 13, 4);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0x8b, 10, 11, 0x83, 12, 13}));
}
TEST(MidiOutput, sendProgramChange)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(4);
midi.begin();
midi.sendProgramChange(42, 12);
midi.sendProgramChange(47, 4);
EXPECT_EQ(serial.mTxBuffer.getLength(), 4);
serial.mTxBuffer.read(&buffer[0], 4);
EXPECT_THAT(buffer, ElementsAreArray({0xcb, 42, 0xc3, 47}));
}
TEST(MidiOutput, sendControlChange)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
midi.begin();
midi.sendControlChange(42, 12, 12);
midi.sendControlChange(47, 12, 4);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0xbb, 42, 12, 0xb3, 47, 12}));
}
TEST(MidiOutput, sendPitchBend)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
// Int signature - arbitrary values
{
buffer.clear();
buffer.resize(9);
midi.begin();
midi.sendPitchBend(0, 12);
midi.sendPitchBend(100, 4);
midi.sendPitchBend(-100, 7);
EXPECT_EQ(serial.mTxBuffer.getLength(), 9);
serial.mTxBuffer.read(&buffer[0], 9);
EXPECT_THAT(buffer, ElementsAreArray({0xeb, 0x00, 0x40,
0xe3, 0x64, 0x40,
0xe6, 0x1c, 0x3f}));
}
// Int signature - min/max
{
buffer.clear();
buffer.resize(9);
midi.begin();
midi.sendPitchBend(0, 12);
midi.sendPitchBend(MIDI_PITCHBEND_MAX, 4);
midi.sendPitchBend(MIDI_PITCHBEND_MIN, 7);
EXPECT_EQ(serial.mTxBuffer.getLength(), 9);
serial.mTxBuffer.read(&buffer[0], 9);
EXPECT_THAT(buffer, ElementsAreArray({0xeb, 0x00, 0x40,
0xe3, 0x7f, 0x7f,
0xe6, 0x00, 0x00}));
}
// Float signature
{
buffer.clear();
buffer.resize(9);
midi.begin();
midi.sendPitchBend(0.0, 12);
midi.sendPitchBend(1.0, 4);
midi.sendPitchBend(-1.0, 7);
EXPECT_EQ(serial.mTxBuffer.getLength(), 9);
serial.mTxBuffer.read(&buffer[0], 9);
EXPECT_THAT(buffer, ElementsAreArray({0xeb, 0x00, 0x40,
0xe3, 0x7f, 0x7f,
0xe6, 0x00, 0x00}));
}
}
TEST(MidiOutput, sendPolyPressure)
{
// Note: sendPolyPressure is deprecated in favor of sendAfterTouch, which
// now supports both mono and poly AfterTouch messages.
// This test is kept for coverage until removal of sendPolyPressure.
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
midi.begin();
midi.sendPolyPressure(42, 12, 12);
midi.sendPolyPressure(47, 12, 4);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0xab, 42, 12, 0xa3, 47, 12}));
}
TEST(MidiOutput, sendAfterTouchMono)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(4);
midi.begin();
midi.sendAfterTouch(42, 12);
midi.sendAfterTouch(47, 4);
EXPECT_EQ(serial.mTxBuffer.getLength(), 4);
serial.mTxBuffer.read(&buffer[0], 4);
EXPECT_THAT(buffer, ElementsAreArray({0xdb, 42, 0xd3, 47}));
}
TEST(MidiOutput, sendAfterTouchPoly)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
midi.begin();
midi.sendAfterTouch(42, 12, 12);
midi.sendAfterTouch(47, 12, 4);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0xab, 42, 12, 0xa3, 47, 12}));
}
TEST(MidiOutput, sendSysEx)
{
typedef test_mocks::SerialMock<1024> LargeSerialMock;
typedef midi::SerialMIDI<LargeSerialMock> LargeTransport;
typedef midi::MidiInterface<LargeTransport> LargeMidiInterface;
LargeSerialMock serial;
LargeTransport transport(serial);
LargeMidiInterface midi((LargeTransport&)transport);
Buffer buffer;
// Short frame
{
static const char* frame = "Hello, World!";
static const int frameLength = strlen(frame);
static const byte expected[] = {
0xf0,
'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!',
0xf7,
};
buffer.clear();
buffer.resize(frameLength + 2);
midi.begin();
midi.sendSysEx(frameLength, reinterpret_cast<const byte*>(frame), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), frameLength + 2);
serial.mTxBuffer.read(&buffer[0], frameLength + 2);
EXPECT_THAT(buffer, ElementsAreArray(expected));
}
// Long frame
{
static const char* frame = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin maximus dui a massa maximus, a vestibulum mi venenatis. Cras sit amet ex id velit suscipit pharetra eget a turpis. Phasellus interdum metus ac sagittis cursus. Nam quis est at nisl ullamcorper egestas pulvinar eu erat. Duis a elit dignissim, vestibulum eros vel, tempus nisl. Aenean turpis nunc, cursus vel lacinia non, pharetra eget sapien. Duis condimentum, lacus at pulvinar tempor, leo libero volutpat nisl, eget porttitor lorem mi sed magna. Duis dictum, massa vel euismod interdum, lorem mi egestas elit, hendrerit tincidunt est arcu a libero. Interdum et malesuada fames ac ante ipsum primis in faucibus. Curabitur vehicula magna libero, at rhoncus sem ornare a. In elementum, elit et congue pulvinar, massa velit commodo velit, non elementum purus ligula eget lacus. Donec efficitur nisi eu ultrices efficitur. Donec neque dui, ullamcorper id molestie quis, consequat sit amet ligula.";
static const int frameLength = strlen(frame);
static const byte expected[] = {
0xf0,
'L','o','r','e','m',' ','i','p','s','u','m',' ','d','o','l','o','r',' ','s','i','t',' ','a','m','e','t',',',' ',
'c','o','n','s','e','c','t','e','t','u','r',' ','a','d','i','p','i','s','c','i','n','g',' ','e','l','i','t','.',' ','P','r','o','i','n',' ','m','a','x','i','m','u','s',' ','d','u','i',' ','a',' ','m','a','s','s','a',' ','m','a','x','i','m','u','s',',',' ',
'a',' ','v','e','s','t','i','b','u','l','u','m',' ','m','i',' ','v','e','n','e','n','a','t','i','s','.',' ','C','r','a','s',' ','s','i','t',' ','a','m','e','t',' ','e','x',' ','i','d',' ','v','e','l','i','t',' ','s','u','s','c','i','p','i','t',' ','p','h','a','r','e','t','r','a',' ','e','g','e','t', ' ','a',' ','t','u','r','p','i','s','.',' ','P','h','a','s','e','l','l','u','s',' ','i','n','t','e','r','d','u','m',' ','m','e','t','u','s',' ','a','c',' ','s','a','g','i','t','t','i','s',' ','c','u','r','s','u','s','.',' ','N','a','m',' ','q','u','i','s',' ','e','s','t',' ','a','t',' ','n','i','s', 'l',' ','u','l','l','a','m','c','o','r','p','e','r',' ','e','g','e','s','t','a','s',' ','p','u','l','v','i','n','a','r',' ','e','u',' ','e','r','a','t','.',' ','D','u','i','s',' ','a',' ','e','l','i','t',' ','d','i','g','n','i','s','s','i','m',',',' ',
'v','e','s','t','i','b','u','l','u','m',' ','e','r','o','s',' ','v','e','l',',',' ',
't','e','m','p','u','s',' ','n','i','s','l','.',' ','A','e','n','e','a','n',' ','t','u','r','p','i','s',' ','n','u','n','c',',',' ',
'c','u','r','s','u','s',' ','v','e','l',' ','l','a','c','i','n','i','a',' ','n','o','n',',',' ',
'p','h','a','r','e','t','r','a',' ','e','g','e','t',' ','s','a','p','i','e','n','.',' ','D','u','i','s',' ','c','o','n','d','i','m','e','n','t','u','m',',',' ',
'l','a','c','u','s',' ','a','t',' ','p','u','l','v','i','n','a','r',' ','t','e','m','p','o','r',',',' ',
'l','e','o',' ','l','i','b','e','r','o',' ','v','o','l','u','t','p','a','t',' ','n','i','s','l',',',' ',
'e','g','e','t',' ','p','o','r','t','t','i','t','o','r',' ','l','o','r','e','m',' ','m','i',' ','s','e','d',' ','m','a','g','n','a','.',' ','D','u','i','s',' ','d','i','c','t','u','m',',',' ',
'm','a','s','s','a',' ','v','e','l',' ','e','u','i','s','m','o','d',' ','i','n','t','e','r','d','u','m',',',' ',
'l','o','r','e','m',' ','m','i',' ','e','g','e','s','t','a','s',' ','e','l','i','t',',',' ',
'h','e','n','d','r','e','r','i','t',' ','t','i','n','c','i','d','u','n','t',' ','e','s','t',' ','a','r','c','u',' ','a',' ','l','i','b','e','r','o','.',' ','I','n','t','e','r','d','u','m',' ','e','t',' ','m','a','l','e','s','u','a','d','a',' ','f','a','m','e','s',' ','a','c',' ','a','n','t','e',' ', 'i','p','s','u','m',' ','p','r','i','m','i','s',' ','i','n',' ','f','a','u','c','i','b','u','s','.',' ','C','u','r','a','b','i','t','u','r',' ','v','e','h','i','c','u','l','a',' ','m','a','g','n','a',' ','l','i','b','e','r','o',',',' ',
'a','t',' ','r','h','o','n','c','u','s',' ','s','e','m',' ','o','r','n','a','r','e',' ','a','.',' ','I','n',' ','e','l','e','m','e','n','t','u','m',',',' ',
'e','l','i','t',' ','e','t',' ','c','o','n','g','u','e',' ','p','u','l','v','i','n','a','r',',',' ',
'm','a','s','s','a',' ','v','e','l','i','t',' ','c','o','m','m','o','d','o',' ','v','e','l','i','t',',',' ',
'n','o','n',' ','e','l','e','m','e','n','t','u','m',' ','p','u','r','u','s',' ','l','i','g','u','l','a',' ','e','g','e','t',' ','l','a','c','u','s','.',' ','D','o','n','e','c',' ','e','f','f','i','c','i','t','u','r',' ','n','i','s','i',' ','e','u',' ','u','l','t','r','i','c','e','s',' ','e','f','f', 'i','c','i','t','u','r','.',' ','D','o','n','e','c',' ','n','e','q','u','e',' ','d','u','i',',',' ',
'u','l','l','a','m','c','o','r','p','e','r',' ','i','d',' ','m','o','l','e','s','t','i','e',' ','q','u','i','s',',',' ',
'c','o','n','s','e','q','u','a','t',' ','s','i','t',' ','a','m','e','t',' ','l','i','g','u','l','a','.',
0xf7,
};
buffer.clear();
buffer.resize(frameLength + 2);
midi.begin();
midi.sendSysEx(frameLength, reinterpret_cast<const byte*>(frame), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), frameLength + 2);
serial.mTxBuffer.read(&buffer[0], frameLength + 2);
EXPECT_THAT(buffer, ElementsAreArray(expected));
}
// With boundaries included
{
static const byte frame[] = {
0xf0, 12, 17, 42, 47, 0xf7
};
buffer.clear();
buffer.resize(6);
midi.begin();
midi.sendSysEx(6, frame, true);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray(frame));
}
}
TEST(MidiOutput, sendTimeCodeQuarterFrame)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
// Separate Nibbles
{
buffer.clear();
buffer.resize(4);
midi.begin();
midi.sendTimeCodeQuarterFrame(0x05, 0x0a);
midi.sendTimeCodeQuarterFrame(0xff, 0xff);
EXPECT_EQ(serial.mTxBuffer.getLength(), 4);
serial.mTxBuffer.read(&buffer[0], 4);
EXPECT_THAT(buffer, ElementsAreArray({0xf1, 0x5a,
0xf1, 0x7f}));
}
// Pre-encoded nibbles
{
buffer.clear();
buffer.resize(4);
midi.begin();
midi.sendTimeCodeQuarterFrame(12);
midi.sendTimeCodeQuarterFrame(42);
EXPECT_EQ(serial.mTxBuffer.getLength(), 4);
serial.mTxBuffer.read(&buffer[0], 4);
EXPECT_THAT(buffer, ElementsAreArray({0xf1, 0x0c,
0xf1, 0x2a}));
}
}
TEST(MidiOutput, sendSongPosition)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(6);
midi.begin();
midi.sendSongPosition(1234);
midi.sendSongPosition(4321);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({0xf2, 0x52, 0x09,
0xf2, 0x61, 0x21}));
}
TEST(MidiOutput, sendSongSelect)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(4);
midi.begin();
midi.sendSongSelect(12);
midi.sendSongSelect(42);
EXPECT_EQ(serial.mTxBuffer.getLength(), 4);
serial.mTxBuffer.read(&buffer[0], 4);
EXPECT_THAT(buffer, ElementsAreArray({0xf3, 12, 0xf3, 42}));
}
TEST(MidiOutput, sendTuneRequest)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
buffer.resize(1);
midi.begin();
midi.sendTuneRequest();
EXPECT_EQ(serial.mTxBuffer.getLength(), 1);
serial.mTxBuffer.read(&buffer[0], 1);
EXPECT_THAT(buffer, ElementsAreArray({0xf6}));
}
TEST(MidiOutput, sendRealTime)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
// Test valid RealTime messages
{
buffer.clear();
buffer.resize(6);
midi.begin();
midi.sendRealTime(midi::Clock);
midi.sendRealTime(midi::Start);
midi.sendRealTime(midi::Continue);
midi.sendRealTime(midi::Stop);
midi.sendRealTime(midi::ActiveSensing);
midi.sendRealTime(midi::SystemReset);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({
0xf8, 0xfa, 0xfb, 0xfc, 0xfe, 0xff
}));
}
// Test invalid messages
{
midi.begin();
midi.sendRealTime(midi::InvalidType);
midi.sendRealTime(midi::NoteOff);
midi.sendRealTime(midi::NoteOn);
midi.sendRealTime(midi::AfterTouchPoly);
midi.sendRealTime(midi::ControlChange);
midi.sendRealTime(midi::ProgramChange);
midi.sendRealTime(midi::AfterTouchChannel);
midi.sendRealTime(midi::PitchBend);
midi.sendRealTime(midi::SystemExclusive);
midi.sendRealTime(midi::TimeCodeQuarterFrame);
midi.sendRealTime(midi::SongPosition);
midi.sendRealTime(midi::SongSelect);
midi.sendRealTime(midi::TuneRequest);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
}
}
TEST(MidiOutput, RPN)
{
typedef VariableSettings<true, true> Settings;
typedef midi::MidiInterface<Transport, Settings> RsMidiInterface;
SerialMock serial;
Transport transport(serial);
RsMidiInterface midi((Transport&)transport);
Buffer buffer;
// 14-bit Value Single Frame
{
buffer.clear();
buffer.resize(13);
midi.begin();
midi.beginRpn(1242, 12);
midi.sendRpnValue(12345, 12);
midi.endRpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 13);
serial.mTxBuffer.read(&buffer[0], 13);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x64, 0x5a,
0x65, 0x09,
0x06, 0x60,
0x26, 0x39,
0x64, 0x7f,
0x65, 0x7f}));
}
// MSB/LSB Single Frame
{
buffer.clear();
buffer.resize(13);
midi.begin();
midi.beginRpn(1242, 12);
midi.sendRpnValue(12, 42, 12);
midi.endRpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 13);
serial.mTxBuffer.read(&buffer[0], 13);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x64, 0x5a,
0x65, 0x09,
0x06, 0x0c,
0x26, 0x2a,
0x64, 0x7f,
0x65, 0x7f}));
}
// Increment Single Frame
{
buffer.clear();
buffer.resize(11);
midi.begin();
midi.beginRpn(1242, 12);
midi.sendRpnIncrement(42, 12);
midi.endRpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 11);
serial.mTxBuffer.read(&buffer[0], 11);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x64, 0x5a,
0x65, 0x09,
0x60, 0x2a,
0x64, 0x7f,
0x65, 0x7f}));
}
// Decrement Single Frame
{
buffer.clear();
buffer.resize(11);
midi.begin();
midi.beginRpn(1242, 12);
midi.sendRpnDecrement(42, 12);
midi.endRpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 11);
serial.mTxBuffer.read(&buffer[0], 11);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x64, 0x5a,
0x65, 0x09,
0x61, 0x2a,
0x64, 0x7f,
0x65, 0x7f}));
}
// Multi Frame
{
buffer.clear();
buffer.resize(21);
midi.begin();
midi.beginRpn(1242, 12);
midi.sendRpnValue(12345, 12);
midi.sendRpnValue(12, 42, 12);
midi.sendRpnIncrement(42, 12);
midi.sendRpnDecrement(42, 12);
midi.endRpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 21);
serial.mTxBuffer.read(&buffer[0], 21);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x64, 0x5a,
0x65, 0x09,
0x06, 0x60,
0x26, 0x39,
0x06, 0x0c,
0x26, 0x2a,
0x60, 0x2a,
0x61, 0x2a,
0x64, 0x7f,
0x65, 0x7f}));
}
}
TEST(MidiOutput, NRPN)
{
typedef VariableSettings<true, true> Settings;
typedef midi::MidiInterface<Transport, Settings> RsMidiInterface;
SerialMock serial;
Transport transport(serial);
RsMidiInterface midi((Transport&)transport);
Buffer buffer;
// 14-bit Value Single Frame
{
buffer.clear();
buffer.resize(13);
midi.begin();
midi.beginNrpn(1242, 12);
midi.sendNrpnValue(12345, 12);
midi.endNrpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 13);
serial.mTxBuffer.read(&buffer[0], 13);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x62, 0x5a,
0x63, 0x09,
0x06, 0x60,
0x26, 0x39,
0x62, 0x7f,
0x63, 0x7f}));
}
// MSB/LSB Single Frame
{
buffer.clear();
buffer.resize(13);
midi.begin();
midi.beginNrpn(1242, 12);
midi.sendNrpnValue(12, 42, 12);
midi.endNrpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 13);
serial.mTxBuffer.read(&buffer[0], 13);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x62, 0x5a,
0x63, 0x09,
0x06, 0x0c,
0x26, 0x2a,
0x62, 0x7f,
0x63, 0x7f}));
}
// Increment Single Frame
{
buffer.clear();
buffer.resize(11);
midi.begin();
midi.beginNrpn(1242, 12);
midi.sendNrpnIncrement(42, 12);
midi.endNrpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 11);
serial.mTxBuffer.read(&buffer[0], 11);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x62, 0x5a,
0x63, 0x09,
0x60, 0x2a,
0x62, 0x7f,
0x63, 0x7f}));
}
// Decrement Single Frame
{
buffer.clear();
buffer.resize(11);
midi.begin();
midi.beginNrpn(1242, 12);
midi.sendNrpnDecrement(42, 12);
midi.endNrpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 11);
serial.mTxBuffer.read(&buffer[0], 11);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x62, 0x5a,
0x63, 0x09,
0x61, 0x2a,
0x62, 0x7f,
0x63, 0x7f}));
}
// Multi Frame
{
buffer.clear();
buffer.resize(21);
midi.begin();
midi.beginNrpn(1242, 12);
midi.sendNrpnValue(12345, 12);
midi.sendNrpnValue(12, 42, 12);
midi.sendNrpnIncrement(42, 12);
midi.sendNrpnDecrement(42, 12);
midi.endNrpn(12);
EXPECT_EQ(serial.mTxBuffer.getLength(), 21);
serial.mTxBuffer.read(&buffer[0], 21);
EXPECT_THAT(buffer, ElementsAreArray({0xbb,
0x62, 0x5a,
0x63, 0x09,
0x06, 0x60,
0x26, 0x39,
0x06, 0x0c,
0x26, 0x2a,
0x60, 0x2a,
0x61, 0x2a,
0x62, 0x7f,
0x63, 0x7f}));
}
}
TEST(MidiOutput, runningStatusCancellation)
{
typedef VariableSettings<true, false> Settings;
typedef midi::MidiInterface<Transport, Settings> RsMidiInterface;
SerialMock serial;
Transport transport(serial);
RsMidiInterface midi((Transport&)transport);
Buffer buffer;
static const unsigned sysExLength = 13;
static const byte sysEx[sysExLength] = {
'H','e','l','l','o',',',' ','W','o','r','l','d','!'
};
midi.begin();
midi.sendNoteOn(12, 34, 1);
midi.sendNoteOn(56, 78, 1);
EXPECT_EQ(serial.mTxBuffer.getLength(), 5);
buffer.clear();
buffer.resize(5);
serial.mTxBuffer.read(&buffer[0], 5);
EXPECT_THAT(buffer, ElementsAreArray({
0x90, 12, 34, 56, 78
}));
midi.sendRealTime(midi::Clock); // Should not reset running status.
midi.sendNoteOn(12, 34, 1);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
buffer.clear();
buffer.resize(3);
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({
0xf8, 12, 34
}));
midi.sendSysEx(sysExLength, sysEx); // Should reset running status.
midi.sendNoteOn(12, 34, 1);
EXPECT_EQ(serial.mTxBuffer.getLength(), 18);
buffer.clear();
buffer.resize(18);
serial.mTxBuffer.read(&buffer[0], 18);
{
static const byte expected[] = {
0xf0, 'H','e','l','l','o',',',' ','W','o','r','l','d','!', 0xf7,
0x90, 12, 34
};
EXPECT_THAT(buffer, ElementsAreArray(expected));
}
midi.sendTimeCodeQuarterFrame(42); // Should reset running status.
midi.sendNoteOn(12, 34, 1);
EXPECT_EQ(serial.mTxBuffer.getLength(), 5);
buffer.clear();
buffer.resize(5);
serial.mTxBuffer.read(&buffer[0], 5);
EXPECT_THAT(buffer, ElementsAreArray({
0xf1, 42,
0x90, 12, 34
}));
midi.sendSongPosition(42); // Should reset running status.
midi.sendNoteOn(12, 34, 1);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
buffer.clear();
buffer.resize(6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({
0xf2, 42, 0,
0x90, 12, 34
}));
midi.sendSongSelect(42); // Should reset running status.
midi.sendNoteOn(12, 34, 1);
EXPECT_EQ(serial.mTxBuffer.getLength(), 5);
buffer.clear();
buffer.resize(5);
serial.mTxBuffer.read(&buffer[0], 5);
EXPECT_THAT(buffer, ElementsAreArray({
0xf3, 42,
0x90, 12, 34
}));
midi.sendTuneRequest(); // Should reset running status.
midi.sendNoteOn(12, 34, 1);
EXPECT_EQ(serial.mTxBuffer.getLength(), 4);
buffer.clear();
buffer.resize(4);
serial.mTxBuffer.read(&buffer[0], 4);
EXPECT_THAT(buffer, ElementsAreArray({
0xf6,
0x90, 12, 34
}));
}
END_UNNAMED_NAMESPACE

View File

@@ -0,0 +1,389 @@
#include "unit-tests.h"
#include "unit-tests_Settings.h"
#include <src/MIDI.h>
#include <test/mocks/test-mocks_SerialMock.h>
BEGIN_MIDI_NAMESPACE
END_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
BEGIN_UNNAMED_NAMESPACE
using namespace testing;
USING_NAMESPACE_UNIT_TESTS
typedef test_mocks::SerialMock<32> SerialMock;
typedef midi::SerialMIDI<SerialMock> Transport;
typedef midi::MidiInterface<Transport> MidiInterface;
typedef std::vector<byte> Buffer;
template<unsigned Size>
struct VariableSysExSettings : midi::DefaultSettings
{
static const unsigned SysExMaxSize = Size;
};
// -----------------------------------------------------------------------------
TEST(MidiThru, defaultValues)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::Full);
midi.begin(); // Should not change the state
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::Full);
}
TEST(MidiThru, beginEnablesThru)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
midi.turnThruOff();
EXPECT_EQ(midi.getThruState(), false);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::Off);
midi.begin();
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::Full);
}
TEST(MidiThru, setGet)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
midi.turnThruOff();
EXPECT_EQ(midi.getThruState(), false);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::Off);
midi.turnThruOn();
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::Full);
midi.turnThruOn(midi::Thru::SameChannel);
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::SameChannel);
midi.turnThruOn(midi::Thru::DifferentChannel);
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::DifferentChannel);
midi.setThruFilterMode(midi::Thru::Full);
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::Full);
midi.setThruFilterMode(midi::Thru::SameChannel);
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::SameChannel);
midi.setThruFilterMode(midi::Thru::DifferentChannel);
EXPECT_EQ(midi.getThruState(), true);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::DifferentChannel);
midi.setThruFilterMode(midi::Thru::Off);
EXPECT_EQ(midi.getThruState(), false);
EXPECT_EQ(midi.getFilterMode(), midi::Thru::Off);
}
TEST(MidiThru, off)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
midi.begin(MIDI_CHANNEL_OMNI);
midi.turnThruOff();
static const unsigned rxSize = 5;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
}
TEST(MidiThru, full)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
midi.begin(MIDI_CHANNEL_OMNI);
midi.setThruFilterMode(midi::Thru::Full);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 0x9c, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), true);
buffer.clear();
buffer.resize(3);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({
0x9b, 12, 34
}));
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), true);
buffer.clear();
buffer.resize(3);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({
0x9c, 56, 78
}));
}
TEST(MidiThru, sameChannel)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
midi.begin(12);
midi.setThruFilterMode(midi::Thru::SameChannel);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 0x9c, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
buffer.clear();
buffer.resize(3);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({
0x9b, 12, 34
}));
}
TEST(MidiThru, sameChannelOmni) // Acts like full
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
midi.begin(MIDI_CHANNEL_OMNI);
midi.setThruFilterMode(midi::Thru::SameChannel);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 0x9c, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), true);
buffer.clear();
buffer.resize(3);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({
0x9b, 12, 34
}));
buffer.clear();
buffer.resize(3);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3); // Not using TX running status
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({
0x9c, 56, 78
}));
}
TEST(MidiThru, differentChannel)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
midi.begin(12);
midi.setThruFilterMode(midi::Thru::DifferentChannel);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 0x9c, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
buffer.clear();
buffer.resize(3);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({
0x9c, 56, 78
}));
}
TEST(MidiThru, differentChannelOmni) // Acts like off
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
Buffer buffer;
midi.begin(MIDI_CHANNEL_OMNI);
midi.setThruFilterMode(midi::Thru::DifferentChannel);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 0x9c, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
}
TEST(MidiThru, multiByteThru)
{
typedef VariableSettings<false, false> MultiByteParsing;
typedef midi::MidiInterface<Transport, MultiByteParsing> MultiByteMidiInterface;
SerialMock serial;
Transport transport(serial);
MultiByteMidiInterface midi((Transport&)transport);
Buffer buffer;
midi.begin(MIDI_CHANNEL_OMNI);
midi.setThruFilterMode(midi::Thru::Full);
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(serial.mTxBuffer.getLength(), 6);
buffer.clear();
buffer.resize(6);
serial.mTxBuffer.read(&buffer[0], 6);
EXPECT_THAT(buffer, ElementsAreArray({
0x9b, 12, 34, 0x9b, 56, 78
}));
}
TEST(MidiThru, withTxRunningStatus)
{
typedef VariableSettings<true, true> Settings;
typedef midi::MidiInterface<Transport, Settings> RsMidiInterface;
SerialMock serial;
Transport transport(serial);
RsMidiInterface midi((Transport&)transport);
Buffer buffer;
midi.begin(MIDI_CHANNEL_OMNI);
midi.setThruFilterMode(midi::Thru::Full);
static const unsigned rxSize = 5;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), true);
buffer.clear();
buffer.resize(3);
EXPECT_EQ(serial.mTxBuffer.getLength(), 3);
serial.mTxBuffer.read(&buffer[0], 3);
EXPECT_THAT(buffer, ElementsAreArray({
0x9b, 12, 34
}));
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
EXPECT_EQ(midi.read(), true);
buffer.clear();
buffer.resize(2);
EXPECT_EQ(serial.mTxBuffer.getLength(), 2);
serial.mTxBuffer.read(&buffer[0], 2);
EXPECT_THAT(buffer, ElementsAreArray({
56, 78
}));
}
TEST(MidiThru, invalidMode)
{
SerialMock serial;
Transport transport(serial);
MidiInterface midi((Transport&)transport);
midi.begin(MIDI_CHANNEL_OMNI);
midi.setThruFilterMode(midi::Thru::Mode(42));
static const unsigned rxSize = 6;
static const byte rxData[rxSize] = { 0x9b, 12, 34, 0x9c, 56, 78 };
serial.mRxBuffer.write(rxData, rxSize);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), false);
EXPECT_EQ(midi.read(), true);
EXPECT_EQ(serial.mTxBuffer.getLength(), 0);
}
END_UNNAMED_NAMESPACE

View File

@@ -0,0 +1,75 @@
#include "unit-tests.h"
#include <src/midi_UsbDefs.h>
BEGIN_MIDI_NAMESPACE
END_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
BEGIN_UNNAMED_NAMESPACE
TEST(MidiUsb, codeIndexNumberSizes)
{
typedef midi::CodeIndexNumbers CIN;
EXPECT_EQ(CIN::getSize(CIN::reserved), 0);
EXPECT_EQ(CIN::getSize(CIN::misc), 0);
EXPECT_EQ(CIN::getSize(CIN::cableEvent), 0);
EXPECT_EQ(CIN::getSize(CIN::systemCommon2Bytes), 2);
EXPECT_EQ(CIN::getSize(CIN::systemCommon3Bytes), 3);
EXPECT_EQ(CIN::getSize(CIN::sysExStart), 3);
EXPECT_EQ(CIN::getSize(CIN::sysExContinue), 3);
EXPECT_EQ(CIN::getSize(CIN::systemCommon1Byte), 1);
EXPECT_EQ(CIN::getSize(CIN::sysExEnds1Byte), 1);
EXPECT_EQ(CIN::getSize(CIN::sysExEnds2Bytes), 2);
EXPECT_EQ(CIN::getSize(CIN::sysExEnds3Bytes), 3);
EXPECT_EQ(CIN::getSize(CIN::noteOff), 3);
EXPECT_EQ(CIN::getSize(CIN::noteOn), 3);
EXPECT_EQ(CIN::getSize(CIN::polyPressure), 3);
EXPECT_EQ(CIN::getSize(CIN::controlChange), 3);
EXPECT_EQ(CIN::getSize(CIN::programChange), 2);
EXPECT_EQ(CIN::getSize(CIN::channelPressure), 2);
EXPECT_EQ(CIN::getSize(CIN::pitchBend), 3);
EXPECT_EQ(CIN::getSize(CIN::singleByte), 1);
}
TEST(MidiUsb, UsbMidiEventPacket)
{
midi::UsbMidiEventPacket packet;
EXPECT_EQ(packet.mData[0], 0);
EXPECT_EQ(packet.mData[1], 0);
EXPECT_EQ(packet.mData[2], 0);
EXPECT_EQ(packet.mData[3], 0);
EXPECT_EQ(packet.getCableNumber(), 0);
EXPECT_EQ(packet.getCodeIndexNumber(), 0);
packet.setHeader(12, 7);
EXPECT_EQ(packet.mData[0], 0xc7);
EXPECT_EQ(packet.getCableNumber(), 12);
EXPECT_EQ(packet.getCodeIndexNumber(), 7);
const byte midiData[3] = { 12, 42, 47 };
packet.setMidiData(midiData);
EXPECT_EQ(packet.mData[0], 0xc7);
EXPECT_EQ(packet.mData[1], 12);
EXPECT_EQ(packet.mData[2], 42);
EXPECT_EQ(packet.mData[3], 47);
const byte fullData[4] = { 12, 34, 56, 78 };
packet = fullData;
EXPECT_EQ(packet.mData[0], 12);
EXPECT_EQ(packet.mData[1], 34);
EXPECT_EQ(packet.mData[2], 56);
EXPECT_EQ(packet.mData[3], 78);
const byte* midiDataConst = packet.getMidiData();
EXPECT_EQ(midiDataConst[0], 34);
EXPECT_EQ(midiDataConst[1], 56);
EXPECT_EQ(midiDataConst[2], 78);
byte* midiDataMutable = packet.getMidiData();
EXPECT_EQ(midiDataMutable[0], 34);
EXPECT_EQ(midiDataMutable[1], 56);
EXPECT_EQ(midiDataMutable[2], 78);
}
END_UNNAMED_NAMESPACE

View File

@@ -0,0 +1,64 @@
#include "unit-tests.h"
#include <test/mocks/test-mocks_SerialMock.h>
BEGIN_UNNAMED_NAMESPACE
USING_NAMESPACE_TEST_MOCKS
using namespace testing;
TEST(RingBuffer, initialState)
{
typedef RingBuffer<uint8, 32> Buffer;
Buffer buffer;
EXPECT_EQ(buffer.getLength(), 0);
EXPECT_EQ(buffer.isEmpty(), true);
buffer.clear();
EXPECT_EQ(buffer.getLength(), 0);
EXPECT_EQ(buffer.isEmpty(), true);
}
TEST(RingBuffer, uint8)
{
typedef RingBuffer<uint8, 8> Buffer;
Buffer buffer;
buffer.write(42);
EXPECT_EQ(buffer.getLength(), 1);
EXPECT_EQ(buffer.isEmpty(), false);
const uint8 read = buffer.read();
EXPECT_EQ(read, 42);
EXPECT_EQ(buffer.getLength(), 0);
EXPECT_EQ(buffer.isEmpty(), true);
const uint8 data[] = "Hello, World!";
buffer.write(data, 13);
EXPECT_EQ(buffer.getLength(), 5); // 13 % 8
EXPECT_EQ(buffer.isEmpty(), false);
uint8 output[8] = { 0 };
buffer.read(output, 8);
const uint8 expected[8] = {
'o', 'r', 'l', 'd', '!', ',', ' ', 'W',
};
EXPECT_THAT(output, ContainerEq(expected));
buffer.clear();
EXPECT_EQ(buffer.getLength(), 0);
EXPECT_EQ(buffer.isEmpty(), true);
}
TEST(RingBuffer, uint32)
{
typedef RingBuffer<uint32_t, 32> Buffer;
Buffer buffer;
buffer.write(42);
EXPECT_EQ(buffer.getLength(), 1);
EXPECT_EQ(buffer.isEmpty(), false);
const uint8 read = buffer.read();
EXPECT_EQ(read, 42);
EXPECT_EQ(buffer.getLength(), 0);
EXPECT_EQ(buffer.isEmpty(), true);
}
END_UNNAMED_NAMESPACE

View File

@@ -0,0 +1,24 @@
#include "unit-tests_Settings.h"
BEGIN_MIDI_NAMESPACE
const bool DefaultSettings::UseRunningStatus;
const bool DefaultSettings::HandleNullVelocityNoteOnAsNoteOff;
const bool DefaultSettings::Use1ByteParsing;
const unsigned DefaultSettings::SysExMaxSize;
END_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
BEGIN_UNNAMED_NAMESPACE
TEST(Settings, hasTheRightDefaultValues)
{
EXPECT_EQ(midi::DefaultSettings::UseRunningStatus, false);
EXPECT_EQ(midi::DefaultSettings::HandleNullVelocityNoteOnAsNoteOff, true);
EXPECT_EQ(midi::DefaultSettings::Use1ByteParsing, true);
EXPECT_EQ(midi::DefaultSettings::SysExMaxSize, unsigned(128));
}
END_UNNAMED_NAMESPACE

View File

@@ -0,0 +1,20 @@
#pragma once
#include "unit-tests.h"
#include <src/midi_Settings.h>
BEGIN_UNIT_TESTS_NAMESPACE
template<bool RunningStatus, bool OneByteParsing>
struct VariableSettings : public midi::DefaultSettings
{
static const bool UseRunningStatus = RunningStatus;
static const bool Use1ByteParsing = OneByteParsing;
};
template<bool A, bool B>
const bool VariableSettings<A, B>::UseRunningStatus;
template<bool A, bool B>
const bool VariableSettings<A, B>::Use1ByteParsing;
END_UNIT_TESTS_NAMESPACE

View File

@@ -0,0 +1,181 @@
#include "unit-tests.h"
#include <src/MIDI.h>
BEGIN_MIDI_NAMESPACE
END_MIDI_NAMESPACE
// -----------------------------------------------------------------------------
BEGIN_UNNAMED_NAMESPACE
using namespace testing;
TEST(SysExCodec, EncoderAscii)
{
const byte input[] = "Hello, World!";
byte buffer[16];
memset(buffer, 0, 16 * sizeof(byte));
const unsigned encodedSize = midi::encodeSysEx(input, buffer, 13);
EXPECT_EQ(encodedSize, unsigned(15));
const byte expected[16] = {
0, 'H', 'e', 'l', 'l', 'o', ',', ' ',
0, 'W', 'o', 'r', 'l', 'd', '!', 0,
};
EXPECT_THAT(buffer, Each(Le(0x7f))); // All elements are <= 127
EXPECT_THAT(buffer, ContainerEq(expected));
}
TEST(SysExCodec, EncoderNonAscii)
{
const byte input[] = {
182, 236, 167, 177, 61, 91, 120, // 01111000 -> 120
107, 94, 209, 87, 94 // 000100xx -> 16
};
byte buffer[16];
memset(buffer, 0, 16 * sizeof(byte));
const unsigned encodedSize = midi::encodeSysEx(input, buffer, 12);
EXPECT_EQ(encodedSize, unsigned(14));
const byte expected[16] = {
// MSB Data
120, 54, 108, 39, 49, 61, 91, 120,
16, 107, 94, 81, 87, 94, 0, 0,
};
EXPECT_THAT(buffer, Each(Le(0x7f))); // All elements are <= 127
EXPECT_THAT(buffer, ContainerEq(expected));
}
TEST(SysExCodec, EncoderNonAsciiFlipHeader)
{
const byte input[] = {
182, 236, 167, 177, 61, 91, 120, // 00011111 -> 15
107, 94, 209, 87, 94 // 0xx00100 -> 4
};
byte buffer[16];
memset(buffer, 0, 16 * sizeof(byte));
const unsigned encodedSize = midi::encodeSysEx(input, buffer, 12, true);
EXPECT_EQ(encodedSize, unsigned(14));
const byte expected[16] = {
// MSB Data
15, 54, 108, 39, 49, 61, 91, 120,
4, 107, 94, 81, 87, 94, 0, 0,
};
EXPECT_THAT(buffer, Each(Le(0x7f))); // All elements are <= 127
EXPECT_THAT(buffer, ContainerEq(expected));
}
// -----------------------------------------------------------------------------
TEST(SysExCodec, DecoderAscii)
{
const byte input[] = {
0, 'H', 'e', 'l', 'l', 'o', ',', ' ',
0, 'W', 'o', 'r', 'l', 'd', '!',
};
byte buffer[16];
memset(buffer, 0, 16 * sizeof(byte));
const unsigned decodedSize = midi::decodeSysEx(input, buffer, 15);
EXPECT_EQ(decodedSize, unsigned(13));
const byte expected[16] = {
'H', 'e', 'l', 'l', 'o', ',', ' ', 'W',
'o', 'r', 'l', 'd', '!', 0, 0, 0,
};
EXPECT_THAT(buffer, Each(Le(0x7f))); // All elements are <= 127
EXPECT_THAT(buffer, ContainerEq(expected));
}
// Non-ASCII content
TEST(SysExCodec, DecoderNonAscii)
{
const byte input[] = {
// MSB Data
120, 54, 108, 39, 49, 61, 91, 120,
16, 107, 94, 81, 87, 94,
};
byte buffer[16];
memset(buffer, 0, 16 * sizeof(byte));
const unsigned encodedSize = midi::decodeSysEx(input, buffer, 14);
EXPECT_EQ(encodedSize, unsigned(12));
const byte expected[16] = {
182, 236, 167, 177, 61, 91, 120,
107, 94, 209, 87, 94, 0, 0,
0, 0,
};
EXPECT_THAT(input, Each(Le(0x7f))); // All elements are <= 127
EXPECT_THAT(buffer, ContainerEq(expected));
}
TEST(SysExCodec, DecoderNonAsciiFlipHeader)
{
const byte input[] = {
// MSB Data
15, 54, 108, 39, 49, 61, 91, 120,
4, 107, 94, 81, 87, 94,
};
byte buffer[16];
memset(buffer, 0, 16 * sizeof(byte));
const unsigned encodedSize = midi::decodeSysEx(input, buffer, 14, true);
EXPECT_EQ(encodedSize, unsigned(12));
const byte expected[16] = {
182, 236, 167, 177, 61, 91, 120,
107, 94, 209, 87, 94, 0, 0,
0, 0,
};
EXPECT_THAT(input, Each(Le(0x7f))); // All elements are <= 127
EXPECT_THAT(buffer, ContainerEq(expected));
}
// -----------------------------------------------------------------------------
TEST(SysExCodec, CodecAscii)
{
const byte input[] = "Hello, World!";
byte buffer1[16];
byte buffer2[16];
memset(buffer1, 0, 16 * sizeof(byte));
memset(buffer2, 0, 16 * sizeof(byte));
const unsigned encodedSize = midi::encodeSysEx(input, buffer1, 13);
EXPECT_EQ(encodedSize, unsigned(15));
const unsigned decodedSize = midi::decodeSysEx(buffer1, buffer2, encodedSize);
EXPECT_EQ(decodedSize, unsigned(13));
EXPECT_STREQ(reinterpret_cast<const char*>(buffer2),
reinterpret_cast<const char*>(input));
}
TEST(SysExCodec, CodecNonAscii)
{
const byte input[] = {
// MSB Data
182, 236, 167, 177, 61, 91, 120,
107, 94, 209, 87, 94
};
byte buffer1[14];
byte buffer2[12];
memset(buffer1, 0, 14 * sizeof(byte));
memset(buffer2, 0, 12 * sizeof(byte));
const unsigned encodedSize = midi::encodeSysEx(input, buffer1, 12);
EXPECT_EQ(encodedSize, unsigned(14));
const unsigned decodedSize = midi::decodeSysEx(buffer1, buffer2, encodedSize);
EXPECT_EQ(decodedSize, unsigned(12));
EXPECT_THAT(buffer2, ContainerEq(input));
}
TEST(SysExCodec, CodecNonAsciiFlipHeader)
{
const byte input[] = {
// MSB Data
182, 236, 167, 177, 61, 91, 120,
107, 94, 209, 87, 94
};
byte buffer1[14];
byte buffer2[12];
memset(buffer1, 0, 14 * sizeof(byte));
memset(buffer2, 0, 12 * sizeof(byte));
const unsigned encodedSize = midi::encodeSysEx(input, buffer1, 12, true);
EXPECT_EQ(encodedSize, unsigned(14));
const unsigned decodedSize = midi::decodeSysEx(buffer1, buffer2, encodedSize, true);
EXPECT_EQ(decodedSize, unsigned(12));
EXPECT_THAT(buffer2, ContainerEq(input));
}
END_UNNAMED_NAMESPACE