|
|
|
#include "module.h"
|
|
|
|
#include "engine.h"
|
|
|
|
#include "sampler.h"
|
|
|
|
#include "sfzloader.h"
|
|
|
|
#include "tests.h"
|
|
|
|
|
|
|
|
static struct sampler_module *create_sampler_instance(struct test_env *env, const char *cfg_section, const char *instance_name)
|
|
|
|
{
|
|
|
|
extern struct cbox_module_manifest sampler_module;
|
|
|
|
|
|
|
|
GError *error = NULL;
|
|
|
|
struct cbox_module *module = cbox_module_manifest_create_module(&sampler_module, cfg_section, env->doc, NULL, env->engine, instance_name, &error);
|
|
|
|
if (!module)
|
|
|
|
{
|
|
|
|
if (error)
|
|
|
|
fprintf(stderr, "Error: %s\n", error->message);
|
|
|
|
test_assert(module);
|
|
|
|
}
|
|
|
|
test_assert_equal_str(module->engine_name, "sampler");
|
|
|
|
test_assert_equal_str(module->instance_name, instance_name);
|
|
|
|
return (struct sampler_module *)module;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int count_free_voices(struct test_env *env, struct sampler_module *m)
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
for (struct sampler_voice *v = m->voices_free; v; count++, v = v->next)
|
|
|
|
test_assert(count < MAX_SAMPLER_VOICES);
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int count_channel_voices_if(struct test_env *env, struct sampler_module *m, int channel, gboolean (*cond_func)(struct sampler_voice *v, void *user_data), void *user_data)
|
|
|
|
{
|
|
|
|
struct sampler_channel *c = &m->channels[channel];
|
|
|
|
int count = 0;
|
|
|
|
for (struct sampler_voice *v = c->voices_running; v; v = v->next)
|
|
|
|
{
|
|
|
|
test_assert(count < MAX_SAMPLER_VOICES);
|
|
|
|
count += cond_func ? (cond_func(v, user_data) ? 1 : 0) : 1;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void verify_sampler_voices_if(struct test_env *env, struct sampler_module *m, int voices[16], gboolean (*cond_func)(struct sampler_voice *v, void *user_data), void *user_data)
|
|
|
|
{
|
|
|
|
int total = 0;
|
|
|
|
for (int i = 0; i < 16; ++i)
|
|
|
|
{
|
|
|
|
int count = count_channel_voices_if(env, m, i, cond_func, user_data);
|
|
|
|
test_assert_equal(int, count, voices[i]);
|
|
|
|
total += count;
|
|
|
|
}
|
|
|
|
if (!cond_func)
|
|
|
|
test_assert_equal(int, count_free_voices(env, m), MAX_SAMPLER_VOICES - total);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void verify_sampler_voices(struct test_env *env, struct sampler_module *m, int voices[16])
|
|
|
|
{
|
|
|
|
verify_sampler_voices_if(env, m, voices, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean is_voice_released(struct sampler_voice *v, void *ignore)
|
|
|
|
{
|
|
|
|
return v->released;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct sampler_program *load_sfz_into_sampler(struct test_env *env, struct sampler_module *m, const char *sfz_data)
|
|
|
|
{
|
|
|
|
GError *error = NULL;
|
|
|
|
|
|
|
|
struct sampler_program *prg = sampler_program_new(m, 0, "note_test", NULL, NULL, &error);
|
|
|
|
test_assert(prg);
|
|
|
|
test_assert_no_error(error);
|
|
|
|
|
|
|
|
test_assert(sampler_module_load_program_sfz(m, prg, sfz_data, 1, &error));
|
|
|
|
test_assert_no_error(error);
|
|
|
|
|
|
|
|
sampler_register_program(m, prg);
|
|
|
|
test_assert(sampler_select_program(m, 0, prg->name, &error));
|
|
|
|
test_assert_no_error(error);
|
|
|
|
|
|
|
|
return prg;
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void test_sampler_setup(struct test_env *env)
|
|
|
|
{
|
|
|
|
struct sampler_module *m = create_sampler_instance(env, "test_setup", "smp1");
|
|
|
|
|
|
|
|
int expected_voices[16] = {};
|
|
|
|
verify_sampler_voices(env, m, expected_voices);
|
|
|
|
|
|
|
|
CBOX_DELETE(&m->module);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void test_sampler_midicurve(struct test_env *env)
|
|
|
|
{
|
|
|
|
struct sampler_midi_curve curve;
|
|
|
|
float values[128];
|
|
|
|
for (int i = 0; i < 128; ++i)
|
|
|
|
{
|
|
|
|
curve.values[i] = SAMPLER_CURVE_GAP;
|
|
|
|
values[i] = -100;
|
|
|
|
}
|
|
|
|
curve.values[0] = 0;
|
|
|
|
curve.values[64] = 0;
|
|
|
|
curve.values[127] = 1;
|
|
|
|
// Linear
|
|
|
|
sampler_midi_curve_interpolate(&curve, values, 0, 1, FALSE);
|
|
|
|
for (int i = 0; i < 128; ++i)
|
|
|
|
{
|
|
|
|
float expected = i < 64 ? 0 : (i - 64) / 63.0;
|
|
|
|
test_assert(fabs(values[i] - expected) < 0.001);
|
|
|
|
}
|
|
|
|
// Quadratic
|
|
|
|
sampler_midi_curve_interpolate(&curve, values, 0, 1, TRUE);
|
|
|
|
for (int i = 0; i < 128; ++i)
|
|
|
|
{
|
|
|
|
float expected = i < 64 ? 0 : (i - 64) / 63.0;
|
|
|
|
expected = expected * expected;
|
|
|
|
test_assert(fabs(values[i] - expected) < 0.001);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void test_sampler_midicurve2(struct test_env *env)
|
|
|
|
{
|
|
|
|
struct sampler_module *m = create_sampler_instance(env, "test_setup", "smp1");
|
|
|
|
struct sampler_program *prg = load_sfz_into_sampler(env, m,
|
|
|
|
"<curve> curve_index=8 v0=-1 v32=0 v96=0 v127=1\n"
|
|
|
|
"<curve> curve_index=9 v32=0\n"
|
|
|
|
);
|
|
|
|
for (int i = 0; i < 128; ++i)
|
|
|
|
{
|
|
|
|
float expected, actual;
|
|
|
|
if (i < 32)
|
|
|
|
expected = (-1 + (i / 32.0));
|
|
|
|
else if (i <= 96)
|
|
|
|
expected = 0;
|
|
|
|
else
|
|
|
|
expected = (i - 96) * 1.f / (127 - 96);
|
|
|
|
actual = sampler_program_get_curve_value(prg, 8, i / 127.0);
|
|
|
|
test_assert(fabs(actual - expected) < 0.001);
|
|
|
|
|
|
|
|
// Test interpolation
|
|
|
|
expected = 0.25f * actual + 0.75f * sampler_program_get_curve_value(prg, 8, (i + 1) / 127.0);
|
|
|
|
actual = sampler_program_get_curve_value(prg, 8, (i + 0.75) / 127.0);
|
|
|
|
test_assert(fabs(actual - expected) < 0.001);
|
|
|
|
|
|
|
|
// Another curve
|
|
|
|
expected = i < 32 ? 0 : (i - 32) * 1.f / (127 - 32);
|
|
|
|
actual = sampler_program_get_curve_value(prg, 9, i / 127.0);
|
|
|
|
test_assert(fabs(actual - expected) < 0.001);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define VERIFY_BUILTIN_CURVE(curve, point, expected) \
|
|
|
|
test_assert(fabs(sampler_program_get_curve_value(prg, curve, point) - expected) < 0.001)
|
|
|
|
|
|
|
|
VERIFY_BUILTIN_CURVE(0, 0.f, 0.f);
|
|
|
|
VERIFY_BUILTIN_CURVE(0, 0.5f, 0.5f);
|
|
|
|
VERIFY_BUILTIN_CURVE(0, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
VERIFY_BUILTIN_CURVE(1, 0.0f, -1.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(1, 63.f/127.f, 0.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(1, 0.5f, 0.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(1, 64.f/127.f, 0.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(1, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
VERIFY_BUILTIN_CURVE(2, 0.f, 1.f);
|
|
|
|
VERIFY_BUILTIN_CURVE(2, 0.5f, 0.5f);
|
|
|
|
VERIFY_BUILTIN_CURVE(2, 1.0f, 0.f);
|
|
|
|
|
|
|
|
VERIFY_BUILTIN_CURVE(3, 0.0f, 1.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(3, 63.f/127.f, 0.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(3, 0.5f, 0.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(3, 64.f/127.f, 0.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(3, 1.0f, -1.0f);
|
|
|
|
|
|
|
|
VERIFY_BUILTIN_CURVE(4, 0.0f, 0.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(4, 0.5f, 0.25f);
|
|
|
|
VERIFY_BUILTIN_CURVE(4, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
VERIFY_BUILTIN_CURVE(5, 0.0f, 0.0f);
|
|
|
|
VERIFY_BUILTIN_CURVE(5, 0.25f, 0.5f);
|
|
|
|
VERIFY_BUILTIN_CURVE(5, 1.0f, 1.0f);
|
|
|
|
|
|
|
|
sampler_unselect_program(m, prg);
|
|
|
|
CBOX_DELETE(prg);
|
|
|
|
CBOX_DELETE(&m->module);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void test_sampler_note_basic(struct test_env *env)
|
|
|
|
{
|
|
|
|
struct sampler_module *m = create_sampler_instance(env, "test_setup", "smp1");
|
|
|
|
struct sampler_program *prg = load_sfz_into_sampler(env, m,
|
|
|
|
"<region> sample=*saw loop_mode=loop_continuous\n");
|
|
|
|
|
|
|
|
for (int i = 0; i < 5; ++i)
|
|
|
|
{
|
|
|
|
uint8_t midi_data[3] = { 0x90, 48 + i, 127 };
|
|
|
|
m->module.process_event(&m->module, midi_data, sizeof(midi_data));
|
|
|
|
int expected_voices[16] = {[0] = 1 + i};
|
|
|
|
verify_sampler_voices(env, m, expected_voices);
|
|
|
|
}
|
|
|
|
for (int i = 0; i < 5; ++i)
|
|
|
|
{
|
|
|
|
uint8_t midi_data[3] = { 0x91, 48 + i, 127 };
|
|
|
|
m->module.process_event(&m->module, midi_data, sizeof(midi_data));
|
|
|
|
int expected_voices[16] = {[0] = 5, [1] = 1 + i};
|
|
|
|
verify_sampler_voices(env, m, expected_voices);
|
|
|
|
int expected_released_voices[16] = {};
|
|
|
|
verify_sampler_voices_if(env, m, expected_released_voices, is_voice_released, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send some MIDI off to the first channel
|
|
|
|
for (int i = 0; i < 5; ++i)
|
|
|
|
{
|
|
|
|
uint8_t midi_data[3] = { (i & 1) ? 0x90 : 0x80, 48 + i, (i & 1) ? 0 : 127 };
|
|
|
|
m->module.process_event(&m->module, midi_data, sizeof(midi_data));
|
|
|
|
int expected_voices[16] = {[0] = 5, [1] = 5};
|
|
|
|
verify_sampler_voices(env, m, expected_voices);
|
|
|
|
int expected_released_voices[16] = {[0] = 1 + i};
|
|
|
|
verify_sampler_voices_if(env, m, expected_released_voices, is_voice_released, NULL);
|
|
|
|
}
|
|
|
|
sampler_unselect_program(m, prg);
|
|
|
|
CBOX_DELETE(prg);
|
|
|
|
CBOX_DELETE(&m->module);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step
|
|
|
|
{
|
|
|
|
const uint8_t *midi_data;
|
|
|
|
uint32_t midi_data_len;
|
|
|
|
uint32_t voices[16];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct region_logic_test_setup
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
const char *sfz_data;
|
|
|
|
const struct region_logic_test_setup_step *steps;
|
|
|
|
};
|
|
|
|
|
|
|
|
void test_sampler_note_region_logic(struct test_env *env)
|
|
|
|
{
|
|
|
|
struct region_logic_test_setup *setup = env->arg;
|
|
|
|
struct sampler_module *m = create_sampler_instance(env, "test_setup", "smp1");
|
|
|
|
struct sampler_program *prg = load_sfz_into_sampler(env, m, setup->sfz_data);
|
|
|
|
|
|
|
|
int expected_voices[16] = {};
|
|
|
|
for (int i = 0; setup->steps[i].midi_data; ++i)
|
|
|
|
{
|
|
|
|
env->context = g_strdup_printf("%s[%d]", setup->name, i);
|
|
|
|
const struct region_logic_test_setup_step *step = &setup->steps[i];
|
|
|
|
m->module.process_event(&m->module, step->midi_data, step->midi_data_len);
|
|
|
|
for (int c = 0; c < 16; ++c)
|
|
|
|
expected_voices[c] += step->voices[c];
|
|
|
|
verify_sampler_voices(env, m, expected_voices);
|
|
|
|
|
|
|
|
g_free(env->context);
|
|
|
|
env->context = NULL;
|
|
|
|
}
|
|
|
|
sampler_unselect_program(m, prg);
|
|
|
|
CBOX_DELETE(prg);
|
|
|
|
CBOX_DELETE(&m->module);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#define MIDI_DATA_STEP(data, voices) { (const uint8_t *)data, sizeof(data) - 1, {voices} }
|
|
|
|
#define MIDI_DATA_END { NULL, 0, {} }
|
|
|
|
#define MIDI_DATA_STEP_MT(data, ...) { (const uint8_t *)data, sizeof(data) - 1, {__VA_ARGS__} }
|
|
|
|
#define REGION_LOGIC_TEST_SETUP(_name, sfz) \
|
|
|
|
struct region_logic_test_setup setup_##_name = { \
|
|
|
|
.name = #_name, \
|
|
|
|
.sfz_data = sfz, \
|
|
|
|
.steps = steps_##_name \
|
|
|
|
}
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_lokeyhikey[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x24\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x1F\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x21\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x22\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x23\x7F", 1),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(lokeyhikey,
|
|
|
|
"<region>lokey=32 hikey=35 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_lokeyhikey2[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x0E\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x0F\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x11\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x1F\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x24\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x21\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x22\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x23\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x47\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x48\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x49\x7F", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(lokeyhikey2,
|
|
|
|
"<region>lokey=15 hikey=16 sample=*saw\n"
|
|
|
|
"<region>lokey=32 hikey=35 sample=*saw\n"
|
|
|
|
"<region>lokey=33 hikey=34 sample=*saw\n"
|
|
|
|
"<region>key=72 sample=*saw\n"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_lovelhivel[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x24", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x21", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x22", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x23", 1),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(lovelhivel,
|
|
|
|
"<region>lovel=32 hivel=35 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_lochanhichan[] = {
|
|
|
|
MIDI_DATA_STEP_MT("\x90\x20\x7F", 0, 0, 0, 0, 0, 0, 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x91\x20\x7F", 0, 1, 0, 0, 0, 0, 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x92\x20\x7F", 0, 0, 1, 0, 0, 0, 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x93\x20\x7F", 0, 0, 0, 0, 0, 0, 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x94\x20\x7F", 0, 0, 0, 0, 2, 0, 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x95\x20\x7F", 0, 0, 0, 0, 0, 2, 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x96\x20\x7F", 0, 0, 0, 0, 0, 0, 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(lochanhichan,
|
|
|
|
"<region>lochan=2 hichan=3 sample=*saw "
|
|
|
|
"<region>lochan=5 hichan=6 sample=*saw "
|
|
|
|
"<region>lochan=5 hichan=6 sample=*saw "
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_chanaft[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xD0\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xD0\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xD0\x21", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xD0\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(chanaft,
|
|
|
|
"<region>lochanaft=32 hichanaft=33 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_polyaft[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xA0\x10\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xA0\x10\x20", 0), // note that this does not care about which key - it uses the last poly aft value
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xA0\x10\x21", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xA0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(polyaft,
|
|
|
|
"<region>lopolyaft=32 hipolyaft=33 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_cc[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x7F", 0), // try a different CC, just in case (positive test)
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x21", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x21", 0), // try a different CC, just in case (negative test)
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(cc,
|
|
|
|
"<region>locc16=32 hicc16=33 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_cc2[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x41", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x21", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x21", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x42", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x41", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x3F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(cc2,
|
|
|
|
"<region>locc16=32 hicc16=33 locc17=64 hicc17=65 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_cc3[] = { // CC16 <= 33, CC17 >= 64
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x41", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x71", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x21", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x21", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x42", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x41", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x11\x3F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x20", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(cc3,
|
|
|
|
"<region>hicc16=33 locc17=64 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_oncc[] = {
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x1F", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x20", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x21", 1), // should probably be 1 according to test file 16, but that's madness
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x22", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x21", 1),
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x20", 1), // same
|
|
|
|
MIDI_DATA_STEP("\xB0\x10\x1F", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(oncc,
|
|
|
|
"<region>on_locc16=32 on_hicc16=33 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_release[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x80\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x80\x20\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x00", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x00", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(release,
|
|
|
|
"<region>trigger=release sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_firstlegato[] = {
|
|
|
|
MIDI_DATA_STEP_MT("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP_MT("\x90\x21\x7F", 2),
|
|
|
|
MIDI_DATA_STEP_MT("\x90\x22\x7F", 2),
|
|
|
|
MIDI_DATA_STEP_MT("\x91\x20\x7F", 0, 1), // a different channel has its own counter
|
|
|
|
MIDI_DATA_STEP_MT("\x91\x21\x7F", 0, 2),
|
|
|
|
MIDI_DATA_STEP_MT("\x91\x22\x7F", 0, 2),
|
|
|
|
MIDI_DATA_STEP_MT("\x80\x20\x7F", 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x80\x21\x7F", 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x80\x22\x7F", 0),
|
|
|
|
MIDI_DATA_STEP_MT("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP_MT("\x90\x21\x7F", 2),
|
|
|
|
MIDI_DATA_STEP_MT("\x90\x22\x7F", 2),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(firstlegato,
|
|
|
|
"<region>trigger=first sample=*saw"
|
|
|
|
"<region>trigger=legato sample=*saw"
|
|
|
|
"<region>trigger=legato sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_switches[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x12\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x11\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x0F\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x14\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x12\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(switches,
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_last=16 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_last=17 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_last=17 lokey=32 hikey=35 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_switches2[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x80\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x11\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x80\x11\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x11\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 3),
|
|
|
|
MIDI_DATA_STEP("\x80\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x80\x11\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 0),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(switches2,
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_down=16 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_down=17 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_down=17 lokey=32 hikey=35 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_switches3[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2), // [0]
|
|
|
|
MIDI_DATA_STEP("\x90\x12\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x11\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 3),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x0F\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2), // [10]
|
|
|
|
MIDI_DATA_STEP("\x90\x14\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x12\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
|
|
|
|
MIDI_DATA_STEP("\x90\x09\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x12\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 3),
|
|
|
|
MIDI_DATA_STEP("\x90\x11\x7F", 0), // [20]
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 4),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 3),
|
|
|
|
MIDI_DATA_STEP("\x90\x0F\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 3),
|
|
|
|
MIDI_DATA_STEP("\x90\x14\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 3),
|
|
|
|
MIDI_DATA_STEP("\x90\x12\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
|
|
|
|
MIDI_DATA_STEP("\xB0\x79\x7F", 0), // [30] reset all controllers
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(switches3,
|
|
|
|
"<region>lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=8 sw_hikey=9 sw_last=9 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_last=16 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_last=17 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_last=17 lokey=32 hikey=35 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
struct region_logic_test_setup_step steps_switches4[] = {
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 1),
|
|
|
|
MIDI_DATA_STEP("\x90\x11\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x10\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\xB0\x79\x7F", 0), // reset all controllers
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_STEP("\x90\x08\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 3),
|
|
|
|
MIDI_DATA_STEP("\x90\x09\x7F", 0),
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 4),
|
|
|
|
MIDI_DATA_STEP("\xB0\x79\x7F", 0), // reset all controllers
|
|
|
|
MIDI_DATA_STEP("\x90\x20\x7F", 2),
|
|
|
|
MIDI_DATA_END,
|
|
|
|
};
|
|
|
|
|
|
|
|
REGION_LOGIC_TEST_SETUP(switches4,
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_default=17 sw_last=16 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_last=17 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=16 sw_hikey=19 sw_last=17 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=8 sw_hikey=10 sw_last=8 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=8 sw_hikey=10 sw_last=9 lokey=32 hikey=35 sample=*saw"
|
|
|
|
"<region>sw_lokey=8 sw_hikey=10 sw_default=10 sw_last=9 lokey=32 hikey=35 sample=*saw"
|
|
|
|
);
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
void test_assert_failed(struct test_env *env, const char *file, int line, const char *check)
|
|
|
|
{
|
|
|
|
if (env->context)
|
|
|
|
fprintf(stderr, "FAIL @%s:%d Assertion '%s' failed, context: %s.\n", file, line, check, env->context);
|
|
|
|
else
|
|
|
|
fprintf(stderr, "FAIL @%s:%d Assertion '%s' failed.\n", file, line, check);
|
|
|
|
longjmp(env->on_fail, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_assert_failed_free(struct test_env *env, const char *file, int line, gchar *check)
|
|
|
|
{
|
|
|
|
if (env->context)
|
|
|
|
fprintf(stderr, "FAIL @%s:%d %s, context: %s\n", file, line, check, env->context);
|
|
|
|
else
|
|
|
|
fprintf(stderr, "FAIL @%s:%d %s.\n", file, line, check);
|
|
|
|
g_free(check);
|
|
|
|
longjmp(env->on_fail, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct test_info {
|
|
|
|
const char *name;
|
|
|
|
void (*func)(struct test_env *env);
|
|
|
|
void *arg;
|
|
|
|
} tests[] = {
|
|
|
|
{ "test_sampler_setup", test_sampler_setup },
|
|
|
|
{ "test_sampler_midicurve", test_sampler_midicurve },
|
|
|
|
{ "test_sampler_midicurve2", test_sampler_midicurve2 },
|
|
|
|
{ "test_sampler_note_basic", test_sampler_note_basic },
|
|
|
|
{ "test_sampler_note_region_logic/key", test_sampler_note_region_logic, &setup_lokeyhikey },
|
|
|
|
{ "test_sampler_note_region_logic/key2", test_sampler_note_region_logic, &setup_lokeyhikey2 },
|
|
|
|
{ "test_sampler_note_region_logic/vel", test_sampler_note_region_logic, &setup_lovelhivel },
|
|
|
|
{ "test_sampler_note_region_logic/ch", test_sampler_note_region_logic, &setup_lochanhichan },
|
|
|
|
{ "test_sampler_note_region_logic/chanaft", test_sampler_note_region_logic, &setup_chanaft },
|
|
|
|
{ "test_sampler_note_region_logic/polyaft", test_sampler_note_region_logic, &setup_polyaft },
|
|
|
|
{ "test_sampler_note_region_logic/cc", test_sampler_note_region_logic, &setup_cc },
|
|
|
|
{ "test_sampler_note_region_logic/cc2", test_sampler_note_region_logic, &setup_cc2 },
|
|
|
|
{ "test_sampler_note_region_logic/cc3", test_sampler_note_region_logic, &setup_cc3 },
|
|
|
|
{ "test_sampler_note_region_logic/oncc", test_sampler_note_region_logic, &setup_oncc },
|
|
|
|
{ "test_sampler_note_region_logic/release", test_sampler_note_region_logic, &setup_release },
|
|
|
|
{ "test_sampler_note_region_logic/firstlegato", test_sampler_note_region_logic, &setup_firstlegato },
|
|
|
|
{ "test_sampler_note_region_logic/switches", test_sampler_note_region_logic, &setup_switches },
|
|
|
|
{ "test_sampler_note_region_logic/switches2", test_sampler_note_region_logic, &setup_switches2 },
|
|
|
|
{ "test_sampler_note_region_logic/switches3", test_sampler_note_region_logic, &setup_switches3 },
|
|
|
|
{ "test_sampler_note_region_logic/switches4", test_sampler_note_region_logic, &setup_switches4 },
|
|
|
|
};
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
uint32_t tests_run = 0, tests_failed = 0;
|
|
|
|
for (unsigned int i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
|
|
|
|
{
|
|
|
|
struct test_env env;
|
|
|
|
env.doc = cbox_document_new();
|
|
|
|
env.engine = cbox_engine_new(env.doc, NULL);
|
|
|
|
env.arg = tests[i].arg;
|
|
|
|
env.context = NULL;
|
|
|
|
cbox_config_init("");
|
|
|
|
cbox_wavebank_init();
|
|
|
|
tests_run++;
|
|
|
|
if (0 == setjmp(env.on_fail))
|
|
|
|
{
|
|
|
|
printf("Running %s... ", tests[i].name);
|
|
|
|
fflush(stdout);
|
|
|
|
tests[i].func(&env);
|
|
|
|
printf("PASS\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
tests_failed++;
|
|
|
|
|
|
|
|
CBOX_DELETE(env.engine);
|
|
|
|
env.engine = NULL;
|
|
|
|
cbox_document_destroy(env.doc);
|
|
|
|
env.doc = NULL;
|
|
|
|
cbox_wavebank_close();
|
|
|
|
cbox_config_close();
|
|
|
|
if (env.context)
|
|
|
|
{
|
|
|
|
g_free(env.context);
|
|
|
|
env.context = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("%d tests ran, %d tests failed.\n", tests_run, tests_failed);
|
|
|
|
return tests_failed != 0;
|
|
|
|
}
|
|
|
|
|