Files
comet/test/test_outbound.pas
Ken Johnson 46912a9798
Some checks failed
Build and Release / build-and-release (push) Has been cancelled
Version 1.1-1, standardize naming and move tests
- Adopt standard versioning: 1.0, 1.1, 1.1-1 (major.minor-revision)
- Archive naming: comet-1.1-1-linux-x64.tar.gz (professional format)
- Move test sources from src/ to test/ directory
- Update Makefile, release script, and CI workflow to match
2026-04-07 09:00:39 -07:00

283 lines
7.6 KiB
ObjectPascal

{
test_outbound.pas - Test BSO, FrontDoor .MSG, and D'Bridge Q-file outbound
}
program test_outbound;
{$mode objfpc}{$H+}
uses
SysUtils, Classes, cometdef, cometpath, cometbso, cometlog;
var
TestDir: string;
OK, AllOK: Boolean;
TestCount, PassCount: Integer;
procedure Check(const Name: string; Condition: Boolean);
begin
Inc(TestCount);
if Condition then
begin
Inc(PassCount);
WriteLn(Name, ' OK');
end
else
WriteLn(Name, ' FAIL');
end;
{ ---- BSO Tests ---- }
procedure TestBSO;
var
Items: TCometOutboundItemArray;
Entries: TCometFloEntryArray;
FloPath: string;
begin
WriteLn('--- BSO ---');
{ Create outbound structure: node 1:213/723 = 00D502D3 }
ForceDirectories(TestDir + '/outbound');
{ Create a .FLO with test files }
FloPath := TestDir + '/outbound/00d502d3.flo';
with TStringList.Create do
try
Add(TestDir + '/testfile.txt');
Add('^' + TestDir + '/killfile.txt');
Add('#' + TestDir + '/truncfile.txt');
Add('~' + TestDir + '/sentfile.txt');
SaveToFile(FloPath);
finally
Free;
end;
{ Create the test files }
with TStringList.Create do
try
Add('test data');
SaveToFile(TestDir + '/testfile.txt');
SaveToFile(TestDir + '/killfile.txt');
SaveToFile(TestDir + '/truncfile.txt');
SaveToFile(TestDir + '/sentfile.txt');
finally
Free;
end;
{ Test BSOReadFlo }
Entries := BSOReadFlo(FloPath);
Check('BSO: read .FLO entries', Length(Entries) = 4);
Check('BSO: normal entry action', Entries[0].Action = csaNone);
Check('BSO: delete entry action', Entries[1].Action = csaDelete);
Check('BSO: truncate entry action', Entries[2].Action = csaTruncate);
Check('BSO: sent entry marked', Entries[3].Sent = True);
{ Test BSOScanOutbound }
Items := BSOScanOutbound(TestDir + '/outbound', 1);
Check('BSO: scan found 1 node', Length(Items) = 1);
if Length(Items) > 0 then
begin
Check('BSO: correct net', Items[0].Address.Net = $00D5);
Check('BSO: correct node', Items[0].Address.Node = $02D3);
Check('BSO: has files', Items[0].HasFiles);
end;
end;
{ ---- FrontDoor .MSG Tests ---- }
procedure WriteWord(var Buf; Offset: Integer; W: Word);
begin
PByte(@Buf)[Offset] := W and $FF;
PByte(@Buf)[Offset + 1] := (W shr 8) and $FF;
end;
procedure TestFrontDoor;
var
MsgDir: string;
F: file;
Hdr: array[0..189] of Byte;
Items: TCometOutboundItemArray;
Addr: TCometAddress;
Files: TStringList;
KillSent: Boolean;
SubjStr: string;
begin
WriteLn('--- FrontDoor ---');
MsgDir := TestDir + '/fdmsg';
ForceDirectories(MsgDir);
{ Create a test file to attach }
with TStringList.Create do
try
Add('FrontDoor test file content');
SaveToFile(TestDir + '/fdtest.txt');
finally
Free;
end;
{ Build a Type-2 .MSG with file-attach attribute (190 byte header)
Offsets: From=0(36), To=36(36), Subject=72(72), DateTime=144(20),
TimesRead=164(2), DestNode=166(2), OrigNode=168(2), Cost=170(2),
OrigNet=172(2), DestNet=174(2), DateWritten=176(4), DateArrived=180(4),
ReplyTo=184(2), Attr=186(2), NextReply=188(2) }
FillChar(Hdr, SizeOf(Hdr), 0);
StrPCopy(PChar(@Hdr[0]), 'Test Sender'); { From }
StrPCopy(PChar(@Hdr[36]), 'Test Receiver'); { To }
SubjStr := TestDir + '/fdtest.txt';
Move(SubjStr[1], Hdr[72], Length(SubjStr)); { Subject = file path }
WriteWord(Hdr, 166, 723); { DestNode }
WriteWord(Hdr, 168, 725); { OrigNode }
WriteWord(Hdr, 172, 213); { OrigNet }
WriteWord(Hdr, 174, 213); { DestNet }
WriteWord(Hdr, 186, $0090); { Attr = FileAttach+KillSent }
AssignFile(F, MsgDir + '/1.MSG');
Rewrite(F, 1);
BlockWrite(F, Hdr, SizeOf(Hdr));
CloseFile(F);
{ Test FDReadMsg }
OK := FDReadMsg(MsgDir + '/1.MSG', Addr, Files, KillSent);
Check('FD: read msg success', OK);
if OK then
begin
Check('FD: dest net', Addr.Net = 213);
Check('FD: dest node', Addr.Node = 723);
Check('FD: kill sent flag', KillSent);
Check('FD: file count', Files.Count = 1);
if Files.Count > 0 then
Check('FD: file path', Pos('fdtest.txt', Files[0]) > 0);
Files.Free;
end;
{ Test FDScanOutbound }
Items := FDScanOutbound(MsgDir);
Check('FD: scan found 1 node', Length(Items) = 1);
if Length(Items) > 0 then
begin
Check('FD: scan dest net', Items[0].Address.Net = 213);
Check('FD: scan dest node', Items[0].Address.Node = 723);
Check('FD: scan has files', Items[0].HasFiles);
end;
{ Test that non-file-attach messages are ignored }
FillChar(Hdr, SizeOf(Hdr), 0);
StrPCopy(PChar(@Hdr[0]), 'Test');
StrPCopy(PChar(@Hdr[36]), 'Test');
StrPCopy(PChar(@Hdr[72]), 'Hello');
WriteWord(Hdr, 186, $0001); { Attr = Private, NOT file attach }
WriteWord(Hdr, 174, 213); { DestNet }
WriteWord(Hdr, 166, 724); { DestNode }
AssignFile(F, MsgDir + '/2.MSG');
Rewrite(F, 1);
BlockWrite(F, Hdr, SizeOf(Hdr));
CloseFile(F);
OK := FDReadMsg(MsgDir + '/2.MSG', Addr, Files, KillSent);
Check('FD: non-attach msg skipped', not OK);
end;
{ ---- D'Bridge Q-file Tests ---- }
procedure TestDBridge;
var
QDir, QPath: string;
Items: TCometOutboundItemArray;
Entries: TCometFloEntryArray;
begin
WriteLn('--- D''Bridge ---');
QDir := TestDir + '/dbridge';
ForceDirectories(QDir);
{ Create test file }
with TStringList.Create do
try
Add('D''Bridge test file');
SaveToFile(TestDir + '/dbtest.txt');
finally
Free;
end;
{ Create a Q-file for node 1:213/723
Zone 1 = base36 "001", Net 213 = base36 "5X", Node 723 = base36 "K3"
Actually let me compute: 213 = 5*36+33 = "5X", 723 = 20*36+3 = "K3"
Zone 1 = "001", but Base36Encode pads to 3 chars }
{ Use DBridgeAddQueue to create it properly }
with TStringList.Create do
try
{ Manual Q-file: flavour T filepath filename [K] }
Add('N T ' + TestDir + '/dbtest.txt dbtest.txt');
Add('C T ' + TestDir + '/dbtest.txt dbtest.txt K');
{ Build the Q-file path the same way DBridgeAddQueue does }
QPath := QDir + '/Q-' + Base36Encode(1) + Base36Encode(213) + '.' +
Base36Encode(723);
SaveToFile(QPath);
finally
Free;
end;
WriteLn(' Q-file: ', ExtractFileName(QPath));
{ Test DBridgeReadQueue }
Entries := DBridgeReadQueue(QPath);
Check('DB: read queue entries', Length(Entries) = 2);
if Length(Entries) >= 2 then
begin
Check('DB: entry 1 normal', Entries[0].Action = csaNone);
Check('DB: entry 2 kill', Entries[1].Action = csaDelete);
Check('DB: entry 1 path', Pos('dbtest.txt', Entries[0].FilePath) > 0);
end;
{ Test DBridgeScanOutbound }
Items := DBridgeScanOutbound(QDir);
Check('DB: scan found 1 node', Length(Items) = 1);
if Length(Items) > 0 then
begin
Check('DB: scan zone', Items[0].Address.Zone = 1);
Check('DB: scan net', Items[0].Address.Net = 213);
Check('DB: scan node', Items[0].Address.Node = 723);
Check('DB: scan has files', Items[0].HasFiles);
end;
{ Test Base36 round-trip }
Check('B36: encode 1', Base36Encode(1) = '001');
Check('B36: encode 213', Base36Encode(213) = '05X');
Check('B36: decode 001', Base36Decode('001') = 1);
Check('B36: decode 05X', Base36Decode('05X') = 213);
Check('B36: round-trip 723', Base36Decode(Base36Encode(723)) = 723);
end;
{ ---- Main ---- }
begin
TestCount := 0;
PassCount := 0;
TestDir := GetTempDir + 'comet-outbound-test';
ForceDirectories(TestDir);
try
TestBSO;
TestFrontDoor;
TestDBridge;
finally
{ Cleanup }
// Leave test dir for inspection if needed
end;
WriteLn;
WriteLn(PassCount, '/', TestCount, ' tests passed.');
if PassCount = TestCount then
WriteLn('All outbound tests passed.')
else
begin
WriteLn('SOME TESTS FAILED');
Halt(1);
end;
end.