Files
reasampler/tests/test_note_entry.cpp
T

75 lines
2.7 KiB
C++

// Standalone tests for reasampler::instrument::map::note_entry — no VST3, no REAPER, no framework.
// Assert the S12 direct-numeric-entry parse for a zone's low/high/root MIDI note.
//
// Covers: plain decimal integers (with +/- sign + surrounding whitespace); note names under the
// C4==60 convention (C-1==0, sharps + flats, negative octaves); out-of-range values CLAMPING to
// [0,127] rather than rejecting; empty / whitespace-only / unparseable input returning nullopt;
// the integer path taking precedence over the note-name path for a leading digit.
#include "../src/core/instrument/map/note_entry.h"
#include <cstdio>
using namespace reasampler;
using namespace reasampler::instrument::map;
static int g_fail = 0;
#define CHECK(cond) do { if(!(cond)) { \
std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0)
static void testPlainIntegers() {
CHECK(parseNoteEntry("60") == 60);
CHECK(parseNoteEntry("0") == 0);
CHECK(parseNoteEntry("127") == 127);
CHECK(parseNoteEntry(" 64 ") == 64); // surrounding whitespace ignored
CHECK(parseNoteEntry("+5") == 5);
}
static void testIntegerClamps() {
CHECK(parseNoteEntry("200") == 127); // over-range clamps to the ceiling
CHECK(parseNoteEntry("-10") == 0); // under-range clamps to the floor
CHECK(parseNoteEntry("99999") == 127);
}
static void testNoteNames() {
// C4 == 60 (MIDI 0 == C-1).
CHECK(parseNoteEntry("C4") == 60);
CHECK(parseNoteEntry("c4") == 60); // case-insensitive
CHECK(parseNoteEntry("A4") == 69); // A4 = 69 (concert A)
CHECK(parseNoteEntry("C-1") == 0); // lowest MIDI note
CHECK(parseNoteEntry("G9") == 127); // G9 = 127
}
static void testAccidentals() {
CHECK(parseNoteEntry("C#4") == 61);
CHECK(parseNoteEntry("Db4") == 61); // enharmonic of C#4
CHECK(parseNoteEntry("F#3") == 54);
CHECK(parseNoteEntry("Bb3") == 58); // Bb3 = 58
}
static void testNoteNameClamps() {
CHECK(parseNoteEntry("C10") == 127); // above the range clamps
CHECK(parseNoteEntry("C-5") == 0); // below the range clamps
}
static void testRejects() {
CHECK(parseNoteEntry("") == std::nullopt);
CHECK(parseNoteEntry(" ") == std::nullopt);
CHECK(parseNoteEntry("hello") == std::nullopt);
CHECK(parseNoteEntry("C") == std::nullopt); // a bare letter with no octave is ambiguous
CHECK(parseNoteEntry("H4") == std::nullopt); // H is not a note letter
CHECK(parseNoteEntry("+") == std::nullopt);
}
int main() {
testPlainIntegers();
testIntegerClamps();
testNoteNames();
testAccidentals();
testNoteNameClamps();
testRejects();
if (g_fail == 0) std::printf("note_entry: all tests passed\n");
return g_fail != 0;
}