better testing
continuous-integration/drone/push Build is failing
continuous-integration/drone/pr Build is passing

This commit is contained in:
2026-03-03 21:37:20 +00:00
parent 699aa4cbe5
commit cf37c62650
12 changed files with 792 additions and 674 deletions
+1 -1
View File
@@ -4,4 +4,4 @@ echo "======================="
echo " " echo " "
echo "Compiling FPC Sources..." echo "Compiling FPC Sources..."
echo " " echo " "
fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/include/data_structures/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas fpc -Aelf -gw -g -gl -n -v0ew -O3 -OpPENTIUM3 -Si -Sc -Sg -Xd -CX -XXs -CfSSE -CfSSE2 -Rintel -Pi386 -Tlinux -FElib/ -Fusrc/* -Fusrc/include/* -Fusrc/driver/* -Fusrc/driver/net/* -Fusrc/driver/bus/* -Fusrc/driver/bus/usb/* -Fusrc/driver/hid/* src/kernel.pas
+3 -3
View File
@@ -24,9 +24,9 @@ unit bheap;
interface interface
uses uses
lmemorymanager, dstypes,
dstypes, lmemorymanager,
util; util;
{** Creates a new BinaryHeap. {** Creates a new BinaryHeap.
@param ElementSize Size (in bytes) of each data element. @param ElementSize Size (in bytes) of each data element.
+103
View File
@@ -87,8 +87,14 @@ uses
**} **}
procedure CFIFO_Free(Queue : PCFIFOQueue); procedure CFIFO_Free(Queue : PCFIFOQueue);
{** Runs unit tests for the contiguous FIFO queue. **}
procedure UnitTest;
implementation implementation
uses
syslog, strings;
{ ---------------------------------------------------------------------------- } { ---------------------------------------------------------------------------- }
{ Internal helpers } { Internal helpers }
{ ---------------------------------------------------------------------------- } { ---------------------------------------------------------------------------- }
@@ -222,4 +228,101 @@ begin
kfree(void(Queue)); kfree(void(Queue));
end; end;
procedure UnitTest;
var
q : PCFIFOQueue;
v, r : uint32;
ok : boolean;
p : void;
i : uint32;
passed, failed : uint32;
procedure Assert(condition : boolean; testName : pchar);
var
msg : pchar;
begin
if condition then begin
inc(passed);
end else begin
inc(failed);
msg := stringConcat('FAIL: ', testName);
syslog.logln('CFIFO', msg);
kfree(void(msg));
end;
end;
procedure PrintSummary;
var
pStr, fStr, msg, tmp : pchar;
begin
pStr := intToString(passed);
fStr := intToString(failed);
msg := stringConcat(pStr, ' passed, ');
tmp := stringConcat(msg, fStr);
kfree(void(msg));
msg := stringConcat(tmp, ' failed.');
kfree(void(tmp));
syslog.logln('CFIFO', msg);
kfree(void(msg));
kfree(void(pStr));
kfree(void(fStr));
end;
begin
passed := 0;
failed := 0;
syslog.logln('CFIFO', 'Unit tests starting...');
{ === New / Empty / Size / Capacity === }
q := CFIFO_New(sizeof(uint32), 4);
Assert(q <> nil, 'New returns non-nil');
Assert(CFIFO_IsEmpty(q), 'Initially empty');
Assert(CFIFO_Size(q) = 0, 'Initial size is 0');
Assert(CFIFO_Capacity(q) = 4, 'Initial capacity is 4');
{ === Fill initial capacity === }
for i := 1 to 4 do
begin
v := i * 10;
CFIFO_Enqueue(q, @v);
end;
Assert(CFIFO_Size(q) = 4, 'Size after 4 enqueues');
{ === Dequeue first two to advance Head === }
ok := CFIFO_Dequeue(q, @r);
Assert(ok, 'Dequeue 1 succeeds');
Assert(r = 10, 'Dequeue 1 value');
ok := CFIFO_Dequeue(q, @r);
Assert(ok, 'Dequeue 2 succeeds');
Assert(r = 20, 'Dequeue 2 value');
Assert(CFIFO_Size(q) = 2, 'Size after 2 dequeues');
{ === Enqueue more to trigger compaction/growth === }
for i := 5 to 8 do
begin
v := i * 10;
CFIFO_Enqueue(q, @v);
end;
Assert(CFIFO_Size(q) = 6, 'Size after grow');
{ === Verify FIFO order: 30,40,50,60,70,80 === }
ok := CFIFO_Dequeue(q, @r); Assert(r = 30, 'Order 30');
ok := CFIFO_Dequeue(q, @r); Assert(r = 40, 'Order 40');
ok := CFIFO_Dequeue(q, @r); Assert(r = 50, 'Order 50');
ok := CFIFO_Dequeue(q, @r); Assert(r = 60, 'Order 60');
ok := CFIFO_Dequeue(q, @r); Assert(r = 70, 'Order 70');
ok := CFIFO_Dequeue(q, @r); Assert(r = 80, 'Order 80');
Assert(CFIFO_IsEmpty(q), 'Empty after drain');
{ === Edge: peek/dequeue on empty === }
p := CFIFO_Peek(q);
Assert(p = nil, 'Peek on empty returns nil');
ok := CFIFO_Dequeue(q, @r);
Assert(not ok, 'Dequeue on empty returns false');
CFIFO_Free(q);
PrintSummary;
end;
end. end.
+100
View File
@@ -92,8 +92,14 @@ uses
**} **}
procedure CFIFOLS_FreeAll(List : PCFIFOList); procedure CFIFOLS_FreeAll(List : PCFIFOList);
{** Runs unit tests for the contiguous FIFO list. **}
procedure UnitTest;
implementation implementation
uses
syslog, strings;
{ ---------------------------------------------------------------------------- } { ---------------------------------------------------------------------------- }
{ Internal helpers } { Internal helpers }
{ ---------------------------------------------------------------------------- } { ---------------------------------------------------------------------------- }
@@ -220,4 +226,98 @@ begin
kfree(void(List)); kfree(void(List));
end; end;
procedure UnitTest;
var
ls : PCFIFOList;
q1 : PCFIFOQueue;
q2 : PCFIFOQueue;
q3 : PCFIFOQueue;
got : PCFIFOQueue;
ok : boolean;
passed, failed : uint32;
procedure Assert(condition : boolean; testName : pchar);
var
msg : pchar;
begin
if condition then begin
inc(passed);
end else begin
inc(failed);
msg := stringConcat('FAIL: ', testName);
syslog.logln('CFIFOLS', msg);
kfree(void(msg));
end;
end;
procedure PrintSummary;
var
pStr, fStr, msg, tmp : pchar;
begin
pStr := intToString(passed);
fStr := intToString(failed);
msg := stringConcat(pStr, ' passed, ');
tmp := stringConcat(msg, fStr);
kfree(void(msg));
msg := stringConcat(tmp, ' failed.');
kfree(void(tmp));
syslog.logln('CFIFOLS', msg);
kfree(void(msg));
kfree(void(pStr));
kfree(void(fStr));
end;
begin
passed := 0;
failed := 0;
syslog.logln('CFIFOLS', 'Unit tests starting...');
{ === New / Empty / Count === }
ls := CFIFOLS_New(2);
Assert(ls <> nil, 'New returns non-nil');
Assert(CFIFOLS_IsEmpty(ls), 'Initially empty');
Assert(CFIFOLS_Count(ls) = 0, 'Initial count is 0');
q1 := CFIFO_New(sizeof(uint32), 4);
q2 := CFIFO_New(sizeof(uint32), 4);
q3 := CFIFO_New(sizeof(uint32), 4);
{ === Add / Get === }
CFIFOLS_Add(ls, q1);
CFIFOLS_Add(ls, q2);
CFIFOLS_Add(ls, q3);
Assert(CFIFOLS_Count(ls) = 3, 'Count after 3 adds');
Assert(CFIFOLS_Get(ls, 0) = q1, 'Get(0) returns q1');
Assert(CFIFOLS_Get(ls, 1) = q2, 'Get(1) returns q2');
Assert(CFIFOLS_Get(ls, 2) = q3, 'Get(2) returns q3');
{ === Out-of-bounds Get === }
got := CFIFOLS_Get(ls, 99);
Assert(got = nil, 'Get out-of-bounds returns nil');
{ === Remove middle === }
ok := CFIFOLS_Remove(ls, 1);
Assert(ok, 'Remove(1) succeeds');
Assert(CFIFOLS_Count(ls) = 2, 'Count after remove');
Assert(CFIFOLS_Get(ls, 0) = q1, 'After remove, Get(0) still q1');
Assert(CFIFOLS_Get(ls, 1) = q3, 'After remove, Get(1) is now q3');
{ === Remove out-of-bounds === }
ok := CFIFOLS_Remove(ls, 99);
Assert(not ok, 'Remove out-of-bounds returns false');
CFIFOLS_Free(ls);
CFIFO_Free(q1);
CFIFO_Free(q2);
CFIFO_Free(q3);
{ === FreeAll path === }
ls := CFIFOLS_New(2);
CFIFOLS_Add(ls, CFIFO_New(sizeof(uint32), 4));
CFIFOLS_Add(ls, CFIFO_New(sizeof(uint32), 4));
CFIFOLS_FreeAll(ls);
PrintSummary;
end;
end. end.
+104
View File
@@ -88,8 +88,14 @@ uses
**} **}
procedure circ_Free(Queue : PCircularQueue); procedure circ_Free(Queue : PCircularQueue);
{** Runs unit tests for the circular queue. **}
procedure UnitTest;
implementation implementation
uses
syslog, strings;
function circ_New(Capacity : uint32; ElementSize : uint32) : PCircularQueue; function circ_New(Capacity : uint32; ElementSize : uint32) : PCircularQueue;
begin begin
circ_New := PCircularQueue(kalloc(sizeof(TCircularQueue))); circ_New := PCircularQueue(kalloc(sizeof(TCircularQueue)));
@@ -162,4 +168,102 @@ begin
kfree(void(Queue)); kfree(void(Queue));
end; end;
procedure UnitTest;
var
q : PCircularQueue;
v, r : uint32;
ok : boolean;
p : void;
passed, failed : uint32;
procedure Assert(condition : boolean; testName : pchar);
var
msg : pchar;
begin
if condition then begin
inc(passed);
end else begin
inc(failed);
msg := stringConcat('FAIL: ', testName);
syslog.logln('CIRC', msg);
kfree(void(msg));
end;
end;
procedure PrintSummary;
var
pStr, fStr, msg, tmp : pchar;
begin
pStr := intToString(passed);
fStr := intToString(failed);
msg := stringConcat(pStr, ' passed, ');
tmp := stringConcat(msg, fStr);
kfree(void(msg));
msg := stringConcat(tmp, ' failed.');
kfree(void(tmp));
syslog.logln('CIRC', msg);
kfree(void(msg));
kfree(void(pStr));
kfree(void(fStr));
end;
begin
passed := 0;
failed := 0;
syslog.logln('CIRC', 'Unit tests starting...');
{ === New / Empty / Full / Size === }
q := circ_New(4, sizeof(uint32));
Assert(q <> nil, 'New returns non-nil');
Assert(circ_IsEmpty(q), 'Initially empty');
Assert(not circ_IsFull(q), 'Initially not full');
Assert(circ_Size(q) = 0, 'Initial size is 0');
{ === Fill to capacity === }
v := 100; ok := circ_Enqueue(q, @v); Assert(ok, 'Enqueue 1 ok');
v := 200; ok := circ_Enqueue(q, @v); Assert(ok, 'Enqueue 2 ok');
v := 300; ok := circ_Enqueue(q, @v); Assert(ok, 'Enqueue 3 ok');
v := 400; ok := circ_Enqueue(q, @v); Assert(ok, 'Enqueue 4 ok');
Assert(circ_IsFull(q), 'Full after 4 enqueues');
Assert(circ_Size(q) = 4, 'Size is 4 when full');
{ === Enqueue when full === }
v := 999;
ok := circ_Enqueue(q, @v);
Assert(not ok, 'Enqueue on full returns false');
{ === Peek === }
p := circ_Peek(q);
Assert(p <> nil, 'Peek non-nil');
Assert(uint32(p^) = 100, 'Peek returns first enqueued');
{ === Dequeue all — FIFO order === }
ok := circ_Dequeue(q, @r); Assert(r = 100, 'Dequeue 1 value');
ok := circ_Dequeue(q, @r); Assert(r = 200, 'Dequeue 2 value');
ok := circ_Dequeue(q, @r); Assert(r = 300, 'Dequeue 3 value');
ok := circ_Dequeue(q, @r); Assert(r = 400, 'Dequeue 4 value');
Assert(circ_IsEmpty(q), 'Empty after all dequeued');
{ === Edge: dequeue/peek on empty === }
ok := circ_Dequeue(q, @r);
Assert(not ok, 'Dequeue on empty returns false');
p := circ_Peek(q);
Assert(p = nil, 'Peek on empty returns nil');
{ === Wrap-around === }
v := 1; circ_Enqueue(q, @v);
v := 2; circ_Enqueue(q, @v);
circ_Dequeue(q, @r);
v := 3; circ_Enqueue(q, @v);
v := 4; circ_Enqueue(q, @v);
circ_Dequeue(q, @r); Assert(r = 2, 'Wraparound order 2');
circ_Dequeue(q, @r); Assert(r = 3, 'Wraparound order 3');
circ_Dequeue(q, @r); Assert(r = 4, 'Wraparound order 4');
Assert(circ_IsEmpty(q), 'Empty after wraparound');
circ_Free(q);
PrintSummary;
end;
end. end.
+94
View File
@@ -79,8 +79,14 @@ uses
**} **}
procedure FIFO_Free(Queue : PFIFOQueue); procedure FIFO_Free(Queue : PFIFOQueue);
{** Runs unit tests for the FIFO queue. **}
procedure UnitTest;
implementation implementation
uses
syslog, strings;
function FIFO_New(ElementSize : uint32) : PFIFOQueue; function FIFO_New(ElementSize : uint32) : PFIFOQueue;
begin begin
FIFO_New := PFIFOQueue(kalloc(sizeof(TFIFOQueue))); FIFO_New := PFIFOQueue(kalloc(sizeof(TFIFOQueue)));
@@ -162,4 +168,92 @@ begin
kfree(void(Queue)); kfree(void(Queue));
end; end;
procedure UnitTest;
var
q : PFIFOQueue;
v, r : uint32;
ok : boolean;
p : void;
passed, failed : uint32;
procedure Assert(condition : boolean; testName : pchar);
var
msg : pchar;
begin
if condition then begin
inc(passed);
end else begin
inc(failed);
msg := stringConcat('FAIL: ', testName);
syslog.logln('FIFO', msg);
kfree(void(msg));
end;
end;
procedure PrintSummary;
var
pStr, fStr, msg, tmp : pchar;
begin
pStr := intToString(passed);
fStr := intToString(failed);
msg := stringConcat(pStr, ' passed, ');
tmp := stringConcat(msg, fStr);
kfree(void(msg));
msg := stringConcat(tmp, ' failed.');
kfree(void(tmp));
syslog.logln('FIFO', msg);
kfree(void(msg));
kfree(void(pStr));
kfree(void(fStr));
end;
begin
passed := 0;
failed := 0;
syslog.logln('FIFO', 'Unit tests starting...');
{ === New / Empty / Size === }
q := FIFO_New(sizeof(uint32));
Assert(q <> nil, 'New returns non-nil');
Assert(FIFO_IsEmpty(q), 'Initially empty');
Assert(FIFO_Size(q) = 0, 'Initial size is 0');
{ === Enqueue / Size === }
v := 10; FIFO_Enqueue(q, @v);
v := 20; FIFO_Enqueue(q, @v);
v := 30; FIFO_Enqueue(q, @v);
Assert(FIFO_Size(q) = 3, 'Size after 3 enqueues');
Assert(not FIFO_IsEmpty(q), 'Not empty after enqueue');
{ === Peek === }
p := FIFO_Peek(q);
Assert(p <> nil, 'Peek non-nil');
Assert(uint32(p^) = 10, 'Peek returns first enqueued');
{ === Dequeue order === }
ok := FIFO_Dequeue(q, @r);
Assert(ok, 'Dequeue 1 succeeds');
Assert(r = 10, 'Dequeue 1 value');
ok := FIFO_Dequeue(q, @r);
Assert(ok, 'Dequeue 2 succeeds');
Assert(r = 20, 'Dequeue 2 value');
ok := FIFO_Dequeue(q, @r);
Assert(ok, 'Dequeue 3 succeeds');
Assert(r = 30, 'Dequeue 3 value');
Assert(FIFO_IsEmpty(q), 'Empty after all dequeued');
{ === Edge: dequeue/peek on empty === }
ok := FIFO_Dequeue(q, @r);
Assert(not ok, 'Dequeue on empty returns false');
p := FIFO_Peek(q);
Assert(p = nil, 'Peek on empty returns nil');
FIFO_Free(q);
PrintSummary;
end;
end. end.
+93
View File
@@ -79,8 +79,14 @@ uses
**} **}
procedure lifo_Free(Stack : PLIFOStack); procedure lifo_Free(Stack : PLIFOStack);
{** Runs unit tests for the LIFO stack. **}
procedure UnitTest;
implementation implementation
uses
syslog, strings;
function lifo_New(ElementSize : uint32) : PLIFOStack; function lifo_New(ElementSize : uint32) : PLIFOStack;
begin begin
lifo_New := PLIFOStack(kalloc(sizeof(TLIFOStack))); lifo_New := PLIFOStack(kalloc(sizeof(TLIFOStack)));
@@ -152,4 +158,91 @@ begin
kfree(void(Stack)); kfree(void(Stack));
end; end;
procedure UnitTest;
var
s : PLIFOStack;
v, r : uint32;
ok : boolean;
p : void;
passed, failed : uint32;
procedure Assert(condition : boolean; testName : pchar);
var
msg : pchar;
begin
if condition then begin
inc(passed);
end else begin
inc(failed);
msg := stringConcat('FAIL: ', testName);
syslog.logln('LIFO', msg);
kfree(void(msg));
end;
end;
procedure PrintSummary;
var
pStr, fStr, msg, tmp : pchar;
begin
pStr := intToString(passed);
fStr := intToString(failed);
msg := stringConcat(pStr, ' passed, ');
tmp := stringConcat(msg, fStr);
kfree(void(msg));
msg := stringConcat(tmp, ' failed.');
kfree(void(tmp));
syslog.logln('LIFO', msg);
kfree(void(msg));
kfree(void(pStr));
kfree(void(fStr));
end;
begin
passed := 0;
failed := 0;
syslog.logln('LIFO', 'Unit tests starting...');
{ === New / Empty / Size === }
s := lifo_New(sizeof(uint32));
Assert(s <> nil, 'New returns non-nil');
Assert(lifo_IsEmpty(s), 'Initially empty');
Assert(lifo_Size(s) = 0, 'Initial size is 0');
{ === Push / Size === }
v := 10; lifo_Push(s, @v);
v := 20; lifo_Push(s, @v);
v := 30; lifo_Push(s, @v);
Assert(lifo_Size(s) = 3, 'Size after 3 pushes');
{ === Peek (should return last pushed) === }
p := lifo_Peek(s);
Assert(p <> nil, 'Peek non-nil');
Assert(uint32(p^) = 30, 'Peek returns last pushed');
{ === Pop order (reverse) === }
ok := lifo_Pop(s, @r);
Assert(ok, 'Pop 1 succeeds');
Assert(r = 30, 'Pop 1 value');
ok := lifo_Pop(s, @r);
Assert(ok, 'Pop 2 succeeds');
Assert(r = 20, 'Pop 2 value');
ok := lifo_Pop(s, @r);
Assert(ok, 'Pop 3 succeeds');
Assert(r = 10, 'Pop 3 value');
Assert(lifo_IsEmpty(s), 'Empty after all popped');
{ === Edge: pop/peek on empty === }
ok := lifo_Pop(s, @r);
Assert(not ok, 'Pop on empty returns false');
p := lifo_Peek(s);
Assert(p = nil, 'Peek on empty returns nil');
lifo_Free(s);
PrintSummary;
end;
end. end.
+88 -1
View File
@@ -80,8 +80,14 @@ uses
**} **}
procedure maxh_Free(Heap : PBinaryHeap); procedure maxh_Free(Heap : PBinaryHeap);
{** Runs unit tests for the max-heap. **}
procedure UnitTest;
implementation implementation
uses
syslog, strings, lmemorymanager;
function maxh_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap; function maxh_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap;
begin begin
maxh_New := BHeap_New(ElementSize, InitialCapacity, false); maxh_New := BHeap_New(ElementSize, InitialCapacity, false);
@@ -117,4 +123,85 @@ begin
BHeap_Free(Heap); BHeap_Free(Heap);
end; end;
end. procedure UnitTest;
var
h : PBinaryHeap;
v, r : uint32;
ok : boolean;
p : void;
passed, failed : uint32;
procedure Assert(condition : boolean; testName : pchar);
var
msg : pchar;
begin
if condition then begin
inc(passed);
end else begin
inc(failed);
msg := stringConcat('FAIL: ', testName);
syslog.logln('MAXH', msg);
kfree(void(msg));
end;
end;
procedure PrintSummary;
var
pStr, fStr, msg, tmp : pchar;
begin
pStr := intToString(passed);
fStr := intToString(failed);
msg := stringConcat(pStr, ' passed, ');
tmp := stringConcat(msg, fStr);
kfree(void(msg));
msg := stringConcat(tmp, ' failed.');
kfree(void(tmp));
syslog.logln('MAXH', msg);
kfree(void(msg));
kfree(void(pStr));
kfree(void(fStr));
end;
begin
passed := 0;
failed := 0;
syslog.logln('MAXH', 'Unit tests starting...');
{ === New / Empty === }
h := maxh_New(sizeof(uint32), 4);
Assert(h <> nil, 'New returns non-nil');
Assert(maxh_IsEmpty(h), 'Initially empty');
{ === Insert out of order === }
v := 30; maxh_Insert(h, 30, @v);
v := 10; maxh_Insert(h, 10, @v);
v := 50; maxh_Insert(h, 50, @v);
v := 20; maxh_Insert(h, 20, @v);
v := 40; maxh_Insert(h, 40, @v);
Assert(maxh_Size(h) = 5, 'Size after 5 inserts');
{ === PeekMax === }
p := maxh_PeekMax(h);
Assert(p <> nil, 'PeekMax non-nil');
Assert(uint32(p^) = 50, 'PeekMax returns 50');
{ === ExtractMax in descending order === }
ok := maxh_ExtractMax(h, @r); Assert(ok, 'Extract 1 ok'); Assert(r = 50, 'Extract 50');
ok := maxh_ExtractMax(h, @r); Assert(ok, 'Extract 2 ok'); Assert(r = 40, 'Extract 40');
ok := maxh_ExtractMax(h, @r); Assert(ok, 'Extract 3 ok'); Assert(r = 30, 'Extract 30');
ok := maxh_ExtractMax(h, @r); Assert(ok, 'Extract 4 ok'); Assert(r = 20, 'Extract 20');
ok := maxh_ExtractMax(h, @r); Assert(ok, 'Extract 5 ok'); Assert(r = 10, 'Extract 10');
Assert(maxh_IsEmpty(h), 'Empty after all extracted');
{ === Edge: extract/peek on empty === }
ok := maxh_ExtractMax(h, @r);
Assert(not ok, 'Extract on empty returns false');
p := maxh_PeekMax(h);
Assert(p = nil, 'PeekMax on empty returns nil');
maxh_Free(h);
PrintSummary;
end;
end.
+108 -1
View File
@@ -80,8 +80,14 @@ uses
**} **}
procedure minh_Free(Heap : PBinaryHeap); procedure minh_Free(Heap : PBinaryHeap);
{** Runs unit tests for the min-heap. **}
procedure UnitTest;
implementation implementation
uses
syslog, strings, lmemorymanager;
function minh_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap; function minh_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap;
begin begin
minh_New := BHeap_New(ElementSize, InitialCapacity, true); minh_New := BHeap_New(ElementSize, InitialCapacity, true);
@@ -117,4 +123,105 @@ begin
BHeap_Free(Heap); BHeap_Free(Heap);
end; end;
end. procedure UnitTest;
var
h : PBinaryHeap;
v, r : uint32;
ok : boolean;
p : void;
i : uint32;
good : boolean;
passed, failed : uint32;
procedure Assert(condition : boolean; testName : pchar);
var
msg : pchar;
begin
if condition then begin
inc(passed);
end else begin
inc(failed);
msg := stringConcat('FAIL: ', testName);
syslog.logln('MINH', msg);
kfree(void(msg));
end;
end;
procedure PrintSummary;
var
pStr, fStr, msg, tmp : pchar;
begin
pStr := intToString(passed);
fStr := intToString(failed);
msg := stringConcat(pStr, ' passed, ');
tmp := stringConcat(msg, fStr);
kfree(void(msg));
msg := stringConcat(tmp, ' failed.');
kfree(void(tmp));
syslog.logln('MINH', msg);
kfree(void(msg));
kfree(void(pStr));
kfree(void(fStr));
end;
begin
passed := 0;
failed := 0;
syslog.logln('MINH', 'Unit tests starting...');
{ === New / Empty / Size === }
h := minh_New(sizeof(uint32), 4);
Assert(h <> nil, 'New returns non-nil');
Assert(minh_IsEmpty(h), 'Initially empty');
Assert(minh_Size(h) = 0, 'Initial size is 0');
{ === Insert out of order === }
v := 30; minh_Insert(h, 30, @v);
v := 10; minh_Insert(h, 10, @v);
v := 50; minh_Insert(h, 50, @v);
v := 20; minh_Insert(h, 20, @v);
v := 40; minh_Insert(h, 40, @v);
Assert(minh_Size(h) = 5, 'Size after 5 inserts');
{ === PeekMin === }
p := minh_PeekMin(h);
Assert(p <> nil, 'PeekMin non-nil');
Assert(uint32(p^) = 10, 'PeekMin returns 10');
{ === ExtractMin in ascending order === }
ok := minh_ExtractMin(h, @r); Assert(ok, 'Extract 1 ok'); Assert(r = 10, 'Extract 10');
ok := minh_ExtractMin(h, @r); Assert(ok, 'Extract 2 ok'); Assert(r = 20, 'Extract 20');
ok := minh_ExtractMin(h, @r); Assert(ok, 'Extract 3 ok'); Assert(r = 30, 'Extract 30');
ok := minh_ExtractMin(h, @r); Assert(ok, 'Extract 4 ok'); Assert(r = 40, 'Extract 40');
ok := minh_ExtractMin(h, @r); Assert(ok, 'Extract 5 ok'); Assert(r = 50, 'Extract 50');
Assert(minh_IsEmpty(h), 'Empty after all extracted');
{ === Edge: extract/peek on empty === }
ok := minh_ExtractMin(h, @r);
Assert(not ok, 'Extract on empty returns false');
p := minh_PeekMin(h);
Assert(p = nil, 'PeekMin on empty returns nil');
minh_Free(h);
{ === Stress: 50 elements reverse insert === }
h := minh_New(sizeof(uint32), 4);
for i := 50 downto 1 do
begin
v := i;
minh_Insert(h, i, @v);
end;
Assert(minh_Size(h) = 50, 'Stress: 50 inserted');
good := true;
for i := 1 to 50 do
begin
ok := minh_ExtractMin(h, @r);
if (not ok) or (r <> i) then good := false;
end;
Assert(good, 'Stress: 50 extracted in ascending order');
minh_Free(h);
PrintSummary;
end;
end.
+88 -1
View File
@@ -81,8 +81,14 @@ uses
**} **}
procedure prio_Free(Heap : PBinaryHeap); procedure prio_Free(Heap : PBinaryHeap);
{** Runs unit tests for the priority queue. **}
procedure UnitTest;
implementation implementation
uses
syslog, strings, lmemorymanager;
function prio_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap; function prio_New(ElementSize : uint32; InitialCapacity : uint32) : PBinaryHeap;
begin begin
prio_New := BHeap_New(ElementSize, InitialCapacity, true); prio_New := BHeap_New(ElementSize, InitialCapacity, true);
@@ -118,4 +124,85 @@ begin
BHeap_Free(Heap); BHeap_Free(Heap);
end; end;
end. procedure UnitTest;
var
h : PBinaryHeap;
v, r : uint32;
ok : boolean;
p : void;
passed, failed : uint32;
procedure Assert(condition : boolean; testName : pchar);
var
msg : pchar;
begin
if condition then begin
inc(passed);
end else begin
inc(failed);
msg := stringConcat('FAIL: ', testName);
syslog.logln('PRIO', msg);
kfree(void(msg));
end;
end;
procedure PrintSummary;
var
pStr, fStr, msg, tmp : pchar;
begin
pStr := intToString(passed);
fStr := intToString(failed);
msg := stringConcat(pStr, ' passed, ');
tmp := stringConcat(msg, fStr);
kfree(void(msg));
msg := stringConcat(tmp, ' failed.');
kfree(void(tmp));
syslog.logln('PRIO', msg);
kfree(void(msg));
kfree(void(pStr));
kfree(void(fStr));
end;
begin
passed := 0;
failed := 0;
syslog.logln('PRIO', 'Unit tests starting...');
{ === New / Empty === }
h := prio_New(sizeof(uint32), 4);
Assert(h <> nil, 'New returns non-nil');
Assert(prio_IsEmpty(h), 'Initially empty');
{ === Enqueue with varying priorities === }
v := 300; prio_Enqueue(h, 3, @v);
v := 100; prio_Enqueue(h, 1, @v);
v := 500; prio_Enqueue(h, 5, @v);
v := 200; prio_Enqueue(h, 2, @v);
v := 400; prio_Enqueue(h, 4, @v);
Assert(prio_Size(h) = 5, 'Size after 5 enqueues');
{ === Peek (highest priority = lowest value) === }
p := prio_Peek(h);
Assert(p <> nil, 'Peek non-nil');
Assert(uint32(p^) = 100, 'Peek returns data with priority 1');
{ === Dequeue by priority 1,2,3,4,5 === }
ok := prio_Dequeue(h, @r); Assert(ok, 'Dequeue 1 ok'); Assert(r = 100, 'Dequeue pri=1');
ok := prio_Dequeue(h, @r); Assert(ok, 'Dequeue 2 ok'); Assert(r = 200, 'Dequeue pri=2');
ok := prio_Dequeue(h, @r); Assert(ok, 'Dequeue 3 ok'); Assert(r = 300, 'Dequeue pri=3');
ok := prio_Dequeue(h, @r); Assert(ok, 'Dequeue 4 ok'); Assert(r = 400, 'Dequeue pri=4');
ok := prio_Dequeue(h, @r); Assert(ok, 'Dequeue 5 ok'); Assert(r = 500, 'Dequeue pri=5');
Assert(prio_IsEmpty(h), 'Empty after all dequeued');
{ === Edge: dequeue/peek on empty === }
ok := prio_Dequeue(h, @r);
Assert(not ok, 'Dequeue on empty returns false');
p := prio_Peek(h);
Assert(p = nil, 'Peek on empty returns nil');
prio_Free(h);
PrintSummary;
end;
end.
File diff suppressed because it is too large Load Diff
+10 -1
View File
@@ -67,7 +67,8 @@ uses
hashmap, vfs, hashmap, vfs,
video, vesa, doublebuffer, color, lvgl, desktop, uidebug, video, vesa, doublebuffer, color, lvgl, desktop, uidebug,
vterminal, vterminal,
graphicsrefresh, usbhotplug; graphicsrefresh, usbhotplug,
fifo, cfifo, cfifols, lifo, circ, minh, maxh, prio;
procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall; procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall;
@@ -271,6 +272,14 @@ begin
usbhub.UnitTest; usbhub.UnitTest;
usb_keyboard.UnitTest; usb_keyboard.UnitTest;
usb_mouse.UnitTest; usb_mouse.UnitTest;
fifo.UnitTest;
cfifo.UnitTest;
cfifols.UnitTest;
lifo.UnitTest;
circ.UnitTest;
minh.UnitTest;
maxh.UnitTest;
prio.UnitTest;
{ Register timer-driven tasks } { Register timer-driven tasks }
graphicsrefresh.init; graphicsrefresh.init;