From 523c5a08010e8882e9bf2f601f1e85092a5c61b3 Mon Sep 17 00:00:00 2001 From: Evgeny Voropaev Date: Mon, 13 Apr 2026 23:18:07 +0800 Subject: [PATCH v11 4/5] Tests for Delta Frame of Reference unit. The unit test is implemented as a C program (ELF executable). The test can be run with the 'make check-unit'. Tests support the TAP protocol and are executed using the Prove utility. Author: Evgeny Voropaev Reviewed by: Andrey Borodin --- src/test/dfor/.gitignore | 1 + src/test/dfor/Makefile | 3 +- src/test/dfor/meson.build | 2 + src/test/dfor/test_dfor_u16.c | 371 ++++++++++++++++++++++++++++++++++ 4 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 src/test/dfor/test_dfor_u16.c diff --git a/src/test/dfor/.gitignore b/src/test/dfor/.gitignore index 0d77a51216b..447e95c0c09 100644 --- a/src/test/dfor/.gitignore +++ b/src/test/dfor/.gitignore @@ -1,3 +1,4 @@ test_bitpack_u16 +test_dfor_u16 test_uniqsortvect_u16 test_vect_u16 diff --git a/src/test/dfor/Makefile b/src/test/dfor/Makefile index 4fc9f4bc1ba..2ca98f76a0f 100644 --- a/src/test/dfor/Makefile +++ b/src/test/dfor/Makefile @@ -33,7 +33,8 @@ LIBTAP_OBJS = $(top_builddir)/src/test/libtap/tap.o TESTS= test_vect_u16 \ test_uniqsortvect_u16 \ - test_bitpack_u16 + test_bitpack_u16 \ + test_dfor_u16 $(TESTS:%=%.o): CPPFLAGS += -I$(top_builddir)/src/test -DFRONTEND diff --git a/src/test/dfor/meson.build b/src/test/dfor/meson.build index ce762c52430..4a760ab68fa 100644 --- a/src/test/dfor/meson.build +++ b/src/test/dfor/meson.build @@ -8,6 +8,7 @@ dfor_dir = join_paths(meson.project_source_root(), 'src/backend/lib') dfor_sources = files( join_paths(dfor_dir, 'vect_u16.c'), join_paths(dfor_dir, 'bitpack_u16.c'), + join_paths(dfor_dir, 'dfor_u16.c'), ) dfor_test_lib = static_library( @@ -36,6 +37,7 @@ test_names = [ 'test_vect_u16', 'test_uniqsortvect_u16', 'test_bitpack_u16', + 'test_dfor_u16', ] foreach t : test_names diff --git a/src/test/dfor/test_dfor_u16.c b/src/test/dfor/test_dfor_u16.c new file mode 100644 index 00000000000..322b714ba38 --- /dev/null +++ b/src/test/dfor/test_dfor_u16.c @@ -0,0 +1,371 @@ +/* + * test_dfor.c + */ + +#include "lib/bitpack_u16.h" +#include "lib/dfor_u16.h" +#include "lib/vect_u16.h" +#include "libtap/tap.h" +#include "test.h" + +void test_delta_calculation(size_t cnt, uint16_t inArr[], size_t cntDelta, + uint16_t marDeltasExpected[], size_t cntWidth, + uint16_t marWidthsExpected[], size_t cntStat, + uint16_t marWidthsStatExpected[]); + +void test_calc_exceptions(size_t numDeltas, size_t numWidths, + uint16_t marWidths[], size_t numCounts, + uint16_t marCounts[], size_t szAwaitedWidth, + size_t cntAwaitedExcCount); + +void test_dfor(size_t cnt, uint16_t arr[], excalg_t isExcUsage, + size_t widDeltaAwaited, size_t cntExcCntAwaited, + size_t widExcWidAwaited, size_t widExcPosWidAwaited, + size_t cntBitsCountAwaited, size_t cntByteCountAwaited, + float flMinRatioAwaited, uint8_t u8arPackAwaited[]); + +void +test_delta_calculation(size_t cnt, uint16_t inArr[], size_t cntDelta, + uint16_t marDeltasExpected[], size_t cntWidth, + uint16_t marWidthsExpected[], size_t cntStat, + uint16_t marWidthsStatExpected[]) +{ + vect_u16_t vDeltas; + vect_u16_t vWidthCounters; + uniqsortvect_u16_t usvDeltaWidths; + vect_u16_t awaited; + int res; + + printf("------------------------------------------------\n"); + printf("Test\n"); + printf("------------------------------------------------\n"); + + printf(" inArr:"); + for (size_t i = 0; i < cnt; i++) + printf(" %u", (uint32_t)inArr[i]); + printf("\n"); + + vect_u16_init(&vDeltas, 0, NULL); + vect_u16_init(&usvDeltaWidths, 0, NULL); + vect_u16_init(&vWidthCounters, 0, NULL); + + /* Tested function */ + res = dfor_u16_calc_deltas(cnt, inArr, &vDeltas, &usvDeltaWidths, + &vWidthCounters); + cmp_ok(res, "==", 0); + + printf(" Delta expected:"); + for (size_t i = 0; i < cntDelta; i++) + printf(" %u", (uint32_t)marDeltasExpected[i]); + printf("\n"); + + printf(" Delta fact: "); + vect_u16_print(&vDeltas); + + cmp_ok(vDeltas.cnt, "==", cnt, "The Delta count is OK."); + vect_u16_init(&awaited, 0, NULL); + vect_u16_fill(&awaited, cnt, marDeltasExpected); + cmp_ok(vect_u16_compare(&vDeltas, &awaited), "==", 0, + "All deltas are calculated properly"); + vect_u16_clear(&awaited); + + printf(" Width expected:"); + for (size_t i = 0; i < cntWidth; i++) + printf(" %u", (uint32_t)marWidthsExpected[i]); + printf("\n"); + + printf(" Width fact: "); + vect_u16_print(&usvDeltaWidths); + + cmp_ok(usvDeltaWidths.cnt, "==", cntWidth, "The Width count is OK."); + + /* don't really need initialisation after vect_clean having been done + * above*/ + /* vect_u16_init(&awaited, 0, NULL); */ + + vect_u16_fill(&awaited, cntWidth, marWidthsExpected); + cmp_ok(vect_u16_compare(&usvDeltaWidths, &awaited), "==", 0, + "All delta widths is OK."); + vect_u16_clear(&awaited); + + printf(" Statistics expected:"); + for (size_t i = 0; i < cntStat; i++) + printf(" %u", (uint32_t)marWidthsStatExpected[i]); + printf("\n"); + + printf(" Statistics fact: "); + vect_u16_print(&vWidthCounters); + + cmp_ok( + usvDeltaWidths.cnt, "==", vWidthCounters.cnt, + "The count of statistics of widths is equal to the count of widths."); + + /* don't really need initialisation after vect_clean having been done + * above*/ + vect_u16_fill(&awaited, cntStat, marWidthsStatExpected); + cmp_ok(vect_u16_compare(&vWidthCounters, &awaited), "==", 0, + "Width statistics is OK."); + vect_u16_clear(&awaited); + + vect_u16_clear(&vDeltas); + vect_u16_clear(&usvDeltaWidths); + vect_u16_clear(&vWidthCounters); +} + +void +test_calc_exceptions(size_t numDeltas, size_t numWidths, uint16_t marWidths[], + size_t numCounts, uint16_t marCounts[], + size_t szAwaitedWidth, size_t cntAwaitedExcCount) +{ + int res; + vect_u16_t vWidthCounters; + uniqsortvect_u16_t usvDeltaWidths; + size_t width, cntExceptions; + + vect_u16_init(&usvDeltaWidths, 0, NULL); + vect_u16_fill(&usvDeltaWidths, numWidths, marWidths); + + vect_u16_init(&vWidthCounters, 0, NULL); + vect_u16_fill(&vWidthCounters, numCounts, marCounts); + + res = dfor_u16_calc_width(numDeltas, &usvDeltaWidths, &vWidthCounters, + &width, &cntExceptions); + cmp_ok(res, "==", 0); + cmp_ok(width, "==", szAwaitedWidth, "Width is OK."); + cmp_ok(cntExceptions, "==", cntAwaitedExcCount, "Exceptions num is OK"); + + vect_u16_clear(&usvDeltaWidths); + vect_u16_clear(&vWidthCounters); +} + +void +test_dfor(size_t cnt, uint16_t arr[], excalg_t isExcUsage, + size_t widDeltaWidthAwaited, size_t cntExcCntAwaited, + size_t widExcWidAwaited, size_t widExcPosWidAwaited, + size_t cntBitsCountAwaited, size_t cntByteCountAwaited, + float flMinRatioAwaited, uint8_t u8arPackAwaited[]) +{ + int res; + dfor_meta_t dfor; + dfor_stats_t stats; + uniqsortvect_u16_t extracted; + + res = dfor_u16_pack(cnt, arr, isExcUsage, &dfor, 0, NULL); + cmp_ok(res, "==", 0, "dfor_pack func has processed OK."); + cmp_ok(dfor.item_cnt, "==", cnt, "Count of deltas is OK."); + cmp_ok(dfor.delta_wid, "==", widDeltaWidthAwaited, "Delta width is OK."); + cmp_ok(dfor.exc_cnt, "==", cntExcCntAwaited, "Exception count is OK."); + cmp_ok(dfor.exc_wid, "==", widExcWidAwaited, "Exception width is OK."); + cmp_ok(dfor.exc_pos_wid, "==", widExcPosWidAwaited, + "Exception position width is OK."); + ok(dfor.pack != NULL, "Pack is created (not NULL)."); + + stats = dfor_u16_calc_stats(dfor); + cmp_ok(stats.nbits, "==", cntBitsCountAwaited, "Bits count is OK."); + cmp_ok(dfor.nbytes, "==", cntByteCountAwaited, "Bytes count is OK."); + ok(stats.ratio > flMinRatioAwaited, "Compression ratio is OK."); + + if (u8arPackAwaited != NULL) + ok(0 == memcmp(dfor.pack, u8arPackAwaited, cntByteCountAwaited), + "Pack content is OK."); + else + ok(0 == 0, "Pack content check is skipped."); + + test_print_u16_array(cnt, (uint16_t *)arr, "\n\nOriginal integer array"); + test_print_u8_array(dfor.nbytes, dfor.pack, "Compressed integer array"); + printf("Compression ratio:%f\n\n", stats.ratio); + + vect_u16_init(&extracted, 0, NULL); + + dfor_u16_unpack(&dfor, &extracted, 0, NULL); + cmp_ok(extracted.cnt, "==", cnt, "Extracted count is OK"); + cmp_ok(0, "==", memcmp(arr, extracted.m, cnt), + "Extracted array is equal to original"); + + free(dfor.pack); + vect_u16_clear(&extracted); +} + +int +main(void) +{ + plan(130); + printf("========================================\n"); + printf("Test DELTA CALCULATION\n"); + { + test_delta_calculation( + 10, (uint16_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, /* inArr */ + 10, + (uint16_t[]) { 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1 }, /* marDeltasExpected*/ + 1, (uint16_t[]) { 1 }, /* marWidthsExpected */ + 1, (uint16_t[]) { 10 } /* marWidthsStatExpected */); + + test_delta_calculation( + 10, (uint16_t[]) { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 }, /* inArr */ + 10, + (uint16_t[]) { 1, 2, 2, 2, 2, 2, 2, 2, 2, + 2 }, /* marDeltasExpected*/ + 2, (uint16_t[]) { 1, 2 }, /* marWidthsExpected */ + 2, (uint16_t[]) { 1, 9 } /* marWidthsStatExpected */); + + test_delta_calculation( + 14, + (uint16_t[]) { 100, 200, 300, 400, 401, 402, 403, 404, 406, 408, + 410, 412, 414, 416 }, /* inArr */ + 14, + (uint16_t[]) { 100, 100, 100, 100, 1, 1, 1, 1, 2, 2, 2, 2, 2, + 2 }, /* marDeltasExpected*/ + 3, (uint16_t[]) { 1, 2, 7 }, /* marWidthsExpected */ + 3, (uint16_t[]) { 4, 6, 4 } /* marWidthsStatExpected */); + + test_delta_calculation(1, (uint16_t[]) { 123 }, /* inArr */ + 1, (uint16_t[]) { 123 }, /* marDeltasExpected*/ + 1, (uint16_t[]) { 7 }, /* marWidthsExpected */ + 1, + (uint16_t[]) { 1 } /* marWidthsStatExpected */); + + test_delta_calculation(0, NULL, /* inArr */ + 0, NULL, /* marDeltasExpected*/ + 0, NULL, /* marWidthsExpected */ + 0, NULL /* marWidthsStatExpected */); + } + printf("Test DELTA CALCULATION PASSED\n"); + printf("========================================\n\n"); + + printf("========================================\n"); + printf("Test EXCEPTIONS CALCULATION\n"); + { + int res; + vect_u16_t vWidthCounters; + uniqsortvect_u16_t usvDeltaWidths; + size_t width, cntExceptions; + + vect_u16_init(&usvDeltaWidths, 0, NULL); + vect_u16_fill(&usvDeltaWidths, 3, (uint16_t[]) { 1, 2, 7 }); + + vect_u16_init(&vWidthCounters, 0, NULL); + vect_u16_fill(&vWidthCounters, 3, (uint16_t[]) { 4, 6, 4 }); // 4+6+4=14 + + res = dfor_u16_calc_width(14, &usvDeltaWidths, &vWidthCounters, &width, + &cntExceptions); + cmp_ok(res, "==", 0); + cmp_ok(width, "==", 7, "Widths={1,2,7}, Counters={4,6,4} => width=7"); + cmp_ok(cntExceptions, "==", 0, + "Widths={1,2,7}, Counters={4,6,4} => excptions_num=0"); + } + + test_calc_exceptions(14, 3, (uint16_t[]) { 1, 2, 7 }, /* widths of deltas*/ + 3, (uint16_t[]) { 4, 6, 4 }, /* statistics */ + 7, /* width of short deltas */ + 0); /* number of exceptions*/ + + test_calc_exceptions(14, 3, (uint16_t[]) { 1, 2, 7 }, /* widths */ + 3, (uint16_t[]) { 6, 7, 1 }, /* stat */ + 2, 1); /* short deltas width, exceptions count*/ + + test_calc_exceptions(40, 3, (uint16_t[]) { 5, 6, 12 }, /* widths */ + 3, (uint16_t[]) { 36, 2, 2 }, /* stat */ + 5, 4); /* short deltas width, exceptions count*/ + + test_calc_exceptions(40, 4, (uint16_t[]) { 5, 6, 7, 12 }, 4, + (uint16_t[]) { 36, 1, 1, 2 }, 5, 4); + + test_calc_exceptions(40, 4, (uint16_t[]) { 5, 6, 7, 12 }, 4, + (uint16_t[]) { 35, 1, 2, 2 }, 6, 4); + + test_calc_exceptions(40, 4, (uint16_t[]) { 5, 6, 7, 12 }, 4, + (uint16_t[]) { 34, 1, 2, 3 }, 7, 3); + + test_calc_exceptions(40, 4, (uint16_t[]) { 5, 6, 7, 12 }, 4, + (uint16_t[]) { 1, 34, 2, 3 }, 7, 3); + + test_calc_exceptions(40, 4, (uint16_t[]) { 5, 6, 7, 12 }, 4, + (uint16_t[]) { 1, 33, 2, 4 }, 7, 4); + + test_calc_exceptions(40, 4, (uint16_t[]) { 5, 6, 7, 12 }, 4, + (uint16_t[]) { 1, 32, 2, 5 }, 12, 0); + + printf("Test EXCEPTIONS CALCULATION PASSED\n"); + printf("========================================\n\n"); + + printf("========================================\n"); + printf("Test DELTA FRAME OF REFERENCES PACKING\n"); + + test_dfor(16, + (uint16_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15 }, /* cnt, array */ + DFOR_EXC_DONT_USE, /* flag on use of exceptions */ + 1, /* awaited width of short deltas */ + 0, /* awaited count of exceptions */ + 0, /* awaited exception width*/ + 0, /* awaited exception position width*/ + 16, /* awaited bits count */ + 2, /* cntByteCountAwaited */ + 15.99, /* awaited ratio min value (ratio >= 15.99) */ + (uint8_t[]) { 0xFE, 0xFF }); + + test_dfor(16, + (uint16_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15 }, /* cnt, array */ + DFOR_EXC_USE, /* flag on use of exceptions */ + 1, /* awaited width of short deltas */ + 0, /* awaited count of exceptions */ + 0, /* awaited exception width*/ + 0, /* awaited exception position width*/ + 16, /* awaited bits count */ + 2, /* cntByteCountAwaited */ + 15.99, /* awaited ratio min value (ratio >= 15.99) */ + (uint8_t[]) { 0xFE, 0xFF }); + + test_dfor(16, + (uint16_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 1023 }, /* cnt, array */ + DFOR_EXC_DONT_USE, /* flag on use of exceptions */ + 10, /* awaited width of short deltas */ + 0, /* awaited count of exceptions */ + 0, /* awaited exception width*/ + 0, /* awaited exception position width*/ + 10 * 16, /* awaited bits count */ + 20, /* awaited bytes count */ + 1.5, /* awaited ratio min value */ + (uint8_t[]) { 0x00, 0x04, 0x10, 0x40, 0x00, 0x01, 0x04, + 0x10, 0x40, 0x00, 0x01, 0x04, 0x10, 0x40, + 0x00, 0x01, 0x04, 0x10, 0x40, 0xFC }); + + test_dfor(16, + (uint16_t[]) { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 1023 }, /* cnt, array */ + DFOR_EXC_USE, /* flag on use of exceptions */ + 1, /* awaited width of short deltas */ + 1, /* awaited count of exceptions */ + 9, /* awaited exception width*/ + 4, /* awaited exception position width*/ + 16 * 1 + 9 + 4, /* awaited bits count */ + 4, /* awaited bytes count */ + 7.99, /* awaited ratio min value */ + (uint8_t[]) { 0xFE, 0xFF, 0xF8, 0x1F }); + + test_dfor(30, /* cnt */ + (uint16_t[]) { 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, + /* delta=2, pos=10, deltapos=10 */ 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, + /* delta=3, pos=25, deltapos=15 */ 28, 29, 30, 31, + /* delta=3, pos=29, deltapos=4 */ 34 }, /* array */ + DFOR_EXC_USE, /* flag on use of exceptions */ + 1, /* awaited width of short deltas */ + 3, /* awaited count of exceptions */ + 1, /* awaited exception width*/ + 4, /* awaited exception position width*/ + 30 * 1 + 3 * 1 + 3 * 4, /* awaited bits count */ + 6, /* awaited bytes count */ + 9.99, /* awaited ratio min value */ + (uint8_t[]) { 0xFE, 0xFB, 0xFF, 0xFF, 0xF5, 0x09 }); + + printf("Test DELTA FRAME OF REFERENCES PACKING PASSED\n"); + printf("========================================\n\n"); + + done_testing(); +} -- 2.53.0