unit form_crwtestbench;

{$I _crw_sysdef}

{$mode Delphi}{$H+}

interface

uses
  _crw_sharemem, // NB: THIS UNIT MUST BE FIRST !!!
  {$IFDEF UNIX} cthreads, dl, {$ENDIF}
  {$IFDEF WINDOWS} windows, {$ENDIF}
  Classes, SysUtils, StrUtils, Math, Forms, Controls, Graphics, Dialogs,
  ExtCtrls, StdCtrls, ComCtrls, Buttons, Spin, Menus, FileUtil, process,
  lcltype,
  {$IFDEF UNIX} Unix, BaseUnix, Linux, termio, {$ENDIF}
  _crw_alloc, _crw_cmdargs, _crw_environ, _crw_zm, _crw_fifo, _crw_ascio,
  _crw_base32, _crw_base64, _crw_sort, _crw_fpu, _crw_lsqpoly, _crw_ef,
  _crw_plut, _crw_fft, _crw_fft24, _crw_delauna, _crw_guiutils, _crw_svd,
  _crw_spline, _crw_proc, _crw_rtc, _crw_dynar, _crw_simplex, _crw_hash,
  _crw_crypt, _crw_utf8, _crw_str, _crw_hl, _crw_bsencode, _crw_funmin,
  _crw_lsqmin, _crw_colors, _crw_fsm, _crw_fio, _crw_polling, _crw_meta,
  _crw_daqtags, _crw_rtdtc, _crw_couple, _crw_th123, _crw_riff, _crw_snd,
  _crw_mmt, _crw_ee, _crw_syscal, _crw_curves, _crw_daqevnt, _crw_calib,
  _crw_dim, _crw_dimq, _crw_dimc, _crw_dims, _crw_az, _crw_cgi, _crw_lmd,
  _crw_spcfld, _crw_guard, _crw_spk, _crw_pio, _crw_pkk4, _crw_i8255,
  pcrelib, perlregex, _crw_regexp, _crw_serio, _crw_wine, _crw_vbox,
  _crw_uart, _crw_eldraw, _crw_uac, _crw_sysid, _crw_lm, _crw_wmctrl,
  _crw_adodb_tlb, _crw_dbcon, _crw_opc, _crw_opcc, _crw_netif,
  _crw_smirtl, _crw_smiuirtl, _crw_pipe, _crw_tcp, _crw_pipeio,
  _crw_assoc, _crw_apputils, _crw_appforms, _crw_apptools,
  _crw_sharm, _crw_task, _crw_sesman, _crw_dima,
  Form_ListBoxSelection, Form_CheckListBoxSelection, Form_Calculator,
  Form_VoicePreset, Form_UartTerminal, Form_TextEditDialog,
  Form_StringGridEditDialog, Form_LoginDialog, Form_RecodeCodePageDialog,
  Form_RegExpCalculator,
  testsort, testfpu, testlsqpoly, testef, testsvd, testspline, testrtc,
  testdynar, teststr, testdaqtags, gettext;

type

  { TFormCrwTestBench }

  TFormCrwTestBench = class(TForm)
    BitBtnCrwSysIdTest1: TBitBtn;
    ButtonCrwNetIfTest1: TButton;
    ButtonCrwSesmanTest1: TButton;
    ButtonPipeServerOpen: TButton;
    ButtonPipeServerSend: TButton;
    ButtonDimaStart: TButton;
    ButtonDimaStop: TButton;
    ButtonPipeClientOpen: TButton;
    ButtonPipeClientSend: TButton;
    ButtonPrioTable: TButton;
    ButtonSetNice: TButton;
    ButtonCrwBsencodeTest1: TButton;
    ButtonCrwCalcTest1: TButton;
    ButtonCrwCalibTest1: TButton;
    ButtonCrwCheckListMenuTest: TButton;
    ButtonCrwColorsTest1: TButton;
    ButtonCrwCoupleTest1: TButton;
    ButtonCrwCurvesTest1: TButton;
    ButtonCrwDaqtagsTest1: TButton;
    ButtonCrwDimTest1: TButton;
    ButtonCrwEeSysEval: TButton;
    ButtonCrwEeTest1: TButton;
    ButtonCrwFioTest1: TButton;
    ButtonCrwFsmTest1: TButton;
    ButtonCrwGuardTest1: TButton;
    ButtonCrwHlTest1: TButton;
    ButtonCrwLoginDialogTest: TButton;
    ButtonCrwMetaTest1: TButton;
    ButtonCrwMmtStart: TButton;
    ButtonCrwPioTest1: TButton;
    ButtonCrwPollingKill: TButton;
    ButtonCrwPollingTest1: TButton;
    ButtonCrwPollingAdd: TButton;
    ButtonCrwProcTest1: TButton;
    ButtonCrwRecodeTest1: TButton;
    ButtonCrwRegExpCalcTest: TButton;
    ButtonCrwRegexpTest1: TButton;
    ButtonCrwRtdtcTest1: TButton;
    ButtonCrwSerioTest1: TButton;
    ButtonCrwSmiTest1: TButton;
    ButtonCrwSndTest1: TButton;
    ButtonCrwSpcfldTest1: TButton;
    ButtonCrwSpkTest1: TButton;
    ButtonCrwStringGridEditDialog: TButton;
    ButtonCrwStrTest1: TButton;
    ButtonCrwBase32Test1: TButton;
    ButtonCrwCryptTest1: TButton;
    ButtonCrwDynarTest1: TButton;
    ButtonCrwEfTest1: TButton;
    ButtonCrwFpuTest1: TButton;
    ButtonCrwHashTest1: TButton;
    ButtonCrwHashTest2: TButton;
    ButtonCrwLsqPolyTest1: TButton;
    ButtonCrwRtcTest1: TButton;
    ButtonCrwRtcTest2: TButton;
    ButtonCrwSortTest1: TButton;
    ButtonCrwAllocTest1: TButton;
    ButtonCrwAllocTest2: TButton;
    ButtonCrwAllocTest3: TButton;
    ButtonCrwAscioTest1: TButton;
    ButtonCrwAscioTest2: TButton;
    ButtonCrwBase64Test1: TButton;
    ButtonCrwCmdArgsTest1: TButton;
    ButtonCrwCmdArgsTest2: TButton;
    ButtonCrwEnvironTest1: TButton;
    ButtonCrwEnvironTest2: TButton;
    ButtonCrwEnvironTest3: TButton;
    ButtonCrwEnvironTest4: TButton;
    ButtonCrwEnvironTest5: TButton;
    ButtonCrwFifoTest1: TButton;
    ButtonCrwSplineTest1: TButton;
    ButtonCrwStrTest2: TButton;
    ButtonCrwStrTest3: TButton;
    ButtonCrwStrTest4: TButton;
    ButtonCrwSvdTest1: TButton;
    ButtonCrwTaskTest1: TButton;
    ButtonCrwTextEditDialogTest: TButton;
    ButtonCrwTh123Test1: TButton;
    ButtonCrwUartTerminalTest1: TButton;
    ButtonCrwUartTest1: TButton;
    ButtonCrwVoicePresetTest1: TButton;
    ButtonCrwWarningTest1: TButton;
    ButtonCrwWmctrlTest1: TButton;
    ButtonCrwZmTest1: TButton;
    ButtonGetNice: TButton;
    ButtonMenuBoxTest: TButton;
    ButtonShmGet: TButton;
    ButtonShmAdd: TButton;
    ButtonShmInfo: TButton;
    ButtonShmSub: TButton;
    ButtonShmPut: TButton;
    ButtonShmList: TButton;
    ButtonShmOpen: TButton;
    ButtonTcpClientOpen: TButton;
    ButtonTcpClientSend: TButton;
    ButtonTcpServerOpen: TButton;
    ButtonTcpServerSend: TButton;
    CheckBoxCrwAscioPolling: TCheckBox;
    CheckBoxCrwBase64UseStd: TCheckBox;
    ComboBoxCrwAllocBugType: TComboBox;
    ComboBoxCrwCmdArgsGetOpt: TComboBox;
    ComboBoxCrwCmdArgsListOptVal: TComboBox;
    ComboBoxCrwEnvironExpEnvText: TComboBox;
    ComboBoxCrwEnvironGetEnvName: TComboBox;
    ComboBoxCrwEnvironSetEnvText: TComboBox;
    ComboBoxDimaDns: TComboBox;
    ComboBoxDimaTask: TComboBox;
    ComboBoxForcePrio: TComboBox;
    ComboBoxRenicePid: TComboBox;
    ComboBoxReniceValue: TComboBox;
    EditCrwEeExpression: TEdit;
    EditPipeClientSend: TEdit;
    EditPipeServerSend: TEdit;
    EditPipeName: TEdit;
    EditShmData: TEdit;
    EditShmMonitor: TEdit;
    EditShmName: TEdit;
    EditTcpHost: TEdit;
    EditTcpServerSend: TEdit;
    EditTcpClientSend: TEdit;
    GroupBoxCrwAlloc: TGroupBox;
    GroupBoxCrwAscio: TGroupBox;
    GroupBoxCrwBase64Test1: TGroupBox;
    GroupBoxCrwCmdArgs: TGroupBox;
    GroupBoxCrwCrypt: TGroupBox;
    GroupBoxCrwDima: TGroupBox;
    GroupBoxCrwEe: TGroupBox;
    GroupBoxCrwEnviron: TGroupBox;
    GroupBoxCrwFifo: TGroupBox;
    GroupBoxCrwFioTest1: TGroupBox;
    GroupBoxCrwFsm: TGroupBox;
    GroupBoxCrwHash: TGroupBox;
    GroupBoxCrwHl: TGroupBox;
    GroupBoxCrwMmt: TGroupBox;
    GroupBoxCrwPipe: TGroupBox;
    GroupBoxCrwPolling: TGroupBox;
    GroupBoxCrwProc: TGroupBox;
    GroupBoxCrwRtcTest1: TGroupBox;
    GroupBoxCrwSharmTest: TGroupBox;
    GroupBoxCrwSortTest1: TGroupBox;
    GroupBoxCrwStr: TGroupBox;
    GroupBoxCrwSvd: TGroupBox;
    GroupBoxCrwTask: TGroupBox;
    GroupBoxCrwTcp: TGroupBox;
    GroupBoxCrwTestBenchLog: TGroupBox;
    GroupBoxCrwZm: TGroupBox;
    GroupBoxCrwWmctrl: TGroupBox;
    GroupBoxRenice: TGroupBox;
    GroupBoxShmMonitor: TGroupBox;
    LabelCrwCmdArgsOptParList: TLabel;
    LabelCrwMmtStatus: TLabel;
    LabelCrwPollingStatus: TLabel;
    LabelDimaDns: TLabel;
    LabelDimaTask: TLabel;
    LabelForcePrio: TLabel;
    LabelParentStatus: TLabel;
    LabelPipeClientStatus: TLabel;
    LabelPipeServerStatus: TLabel;
    LabelRenicePid: TLabel;
    LabelReniceValue: TLabel;
    LabelShmData: TLabel;
    LabelShmName: TLabel;
    LabelShmOffset: TLabel;
    LabelShmSize: TLabel;
    LabelTcpClientStatus: TLabel;
    LabelTcpPort: TLabel;
    LabelTcpServerStatus: TLabel;
    LabelWmctrlStatus: TLabel;
    MemoCrwTestBenchLog: TMemo;
    PageControlCrwTestBenchTabs: TPageControl;
    PanelTestBenchLog: TPanel;
    PanelCrwTestBenchTabs: TPanel;
    PanelCrwTestBenchMain: TPanel;
    RadioGroupShmAsType: TRadioGroup;
    SpinEditCrwMmtPeriod: TSpinEdit;
    SpinEditShmOffset: TSpinEdit;
    SpinEditShmSize: TSpinEdit;
    SpinEditTcpPort: TSpinEdit;
    TabSheetCrwPipe: TTabSheet;
    TabSheetCrwTask: TTabSheet;
    TabSheetUnitCrwWmctrl: TTabSheet;
    TabSheetCrwPolling: TTabSheet;
    TabSheetCrwStr: TTabSheet;
    TabSheetCrwSvdTabs: TTabSheet;
    TabSheetUnitCrwFifo: TTabSheet;
    TabSheetCrwEnviron: TTabSheet;
    TabSheetUnitCrwAlloc: TTabSheet;
    TimerCrwAscioPoll: TTimer;
    TimerPolling1000: TTimer;
    TimerPolling50: TTimer;
    TimerShm: TTimer;
    procedure BitBtnCrwSysIdTest1Click(Sender: TObject);
    procedure ButtonCrwBsencodeTest1Click(Sender: TObject);
    procedure ButtonCrwCalcTest1Click(Sender: TObject);
    procedure ButtonCrwCalibTest1Click(Sender: TObject);
    procedure ButtonCrwCheckListMenuTestClick(Sender: TObject);
    procedure ButtonCrwColorsTest1Click(Sender: TObject);
    procedure ButtonCrwCoupleTest1Click(Sender: TObject);
    procedure ButtonCrwCryptTest1Click(Sender: TObject);
    procedure ButtonCrwCurvesTest1Click(Sender: TObject);
    procedure ButtonCrwDaqtagsTest1Click(Sender: TObject);
    procedure ButtonCrwDimTest1Click(Sender: TObject);
    procedure ButtonCrwEeSysEvalClick(Sender: TObject);
    procedure ButtonCrwEeTest1Click(Sender: TObject);
    procedure ButtonCrwFioTest1Click(Sender: TObject);
    procedure ButtonCrwFsmTest1Click(Sender: TObject);
    procedure ButtonCrwGuardTest1Click(Sender: TObject);
    procedure ButtonCrwHashTest2Click(Sender: TObject);
    procedure ButtonCrwHlTest1Click(Sender: TObject);
    procedure ButtonCrwLoginDialogTestClick(Sender: TObject);
    procedure ButtonCrwMetaTest1Click(Sender: TObject);
    procedure ButtonCrwMmtStartClick(Sender: TObject);
    procedure ButtonCrwNetIfTest1Click(Sender: TObject);
    procedure ButtonCrwPioTest1Click(Sender: TObject);
    procedure ButtonCrwSesmanTest1Click(Sender: TObject);
    procedure ButtonPipeClientSendClick(Sender: TObject);
    procedure ButtonPipeServerOpenClick(Sender: TObject);
    procedure ButtonPipeServerSendClick(Sender: TObject);
    procedure ButtonCrwPollingKillClick(Sender: TObject);
    procedure ButtonCrwPollingTest1Click(Sender: TObject);
    procedure ButtonCrwPollingAddClick(Sender: TObject);
    procedure ButtonCrwProcTest1Click(Sender: TObject);
    procedure ButtonCrwRecodeTest1Click(Sender: TObject);
    procedure ButtonCrwRegExpCalcTestClick(Sender: TObject);
    procedure ButtonCrwRegexpTest1Click(Sender: TObject);
    procedure ButtonCrwRtdtcTest1Click(Sender: TObject);
    procedure ButtonCrwSerioTest1Click(Sender: TObject);
    procedure ButtonCrwSmiTest1Click(Sender: TObject);
    procedure ButtonCrwSndTest1Click(Sender: TObject);
    procedure ButtonCrwSpcfldTest1Click(Sender: TObject);
    procedure ButtonCrwSpkTest1Click(Sender: TObject);
    procedure ButtonCrwStringGridEditDialogClick(Sender: TObject);
    procedure ButtonCrwStrTest1Click(Sender: TObject);
    procedure ButtonCrwStrTest2Click(Sender: TObject);
    procedure ButtonCrwStrTest3Click(Sender: TObject);
    procedure ButtonCrwStrTest4Click(Sender: TObject);
    procedure ButtonCrwTaskTest1Click(Sender: TObject);
    procedure ButtonCrwTextEditDialogTestClick(Sender: TObject);
    procedure ButtonCrwTh123Test1Click(Sender: TObject);
    procedure ButtonCrwUartTerminalTest1Click(Sender: TObject);
    procedure ButtonCrwUartTest1Click(Sender: TObject);
    procedure ButtonCrwVoicePresetTest1Click(Sender: TObject);
    procedure ButtonCrwWarningTest1Click(Sender: TObject);
    procedure ButtonCrwWmctrlTest1Click(Sender: TObject);
    procedure ButtonDimaStartClick(Sender: TObject);
    procedure ButtonDimaStopClick(Sender: TObject);
    procedure ButtonGetNiceClick(Sender: TObject);
    procedure ButtonMenuBoxTestClick(Sender: TObject);
    procedure ButtonPipeClientOpenClick(Sender: TObject);
    procedure ButtonPrioTableClick(Sender: TObject);
    procedure ButtonSetNiceClick(Sender: TObject);
    procedure ButtonShmAddClick(Sender: TObject);
    procedure ButtonShmGetClick(Sender: TObject);
    procedure ButtonShmInfoClick(Sender: TObject);
    procedure ButtonShmListClick(Sender: TObject);
    procedure ButtonShmOpenClick(Sender: TObject);
    procedure ButtonShmPutClick(Sender: TObject);
    procedure ButtonShmSubClick(Sender: TObject);
    procedure ButtonTcpClientOpenClick(Sender: TObject);
    procedure ButtonTcpClientSendClick(Sender: TObject);
    procedure ButtonTcpServerOpenClick(Sender: TObject);
    procedure ButtonTcpServerSendClick(Sender: TObject);
    procedure ComboBoxForcePrioChange(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure SpinEditCrwMmtPeriodChange(Sender: TObject);
    procedure TimerCrwAscioPollTimer(Sender: TObject);
    procedure ButtonCrwAllocTest2Click(Sender: TObject);
    procedure ButtonCrwAllocTest3Click(Sender: TObject);
    procedure ButtonCrwAscioTest1Click(Sender: TObject);
    procedure ButtonCrwAscioTest2Click(Sender: TObject);
    procedure ButtonCrwBase32Test1Click(Sender: TObject);
    procedure ButtonCrwBase64Test1Click(Sender: TObject);
    procedure ButtonCrwCmdArgsTest1Click(Sender: TObject);
    procedure ButtonCrwCmdArgsTest2Click(Sender: TObject);
    procedure ButtonCrwDynarTest1Click(Sender: TObject);
    procedure ButtonCrwEfTest1Click(Sender: TObject);
    procedure ButtonCrwEnvironTest1Click(Sender: TObject);
    procedure ButtonCrwEnvironTest2Click(Sender: TObject);
    procedure ButtonCrwEnvironTest3Click(Sender: TObject);
    procedure ButtonCrwEnvironTest4Click(Sender: TObject);
    procedure ButtonCrwEnvironTest5Click(Sender: TObject);
    procedure ButtonCrwFifoTest1Click(Sender: TObject);
    procedure ButtonCrwFpuTest1Click(Sender: TObject);
    procedure ButtonCrwHashTest1Click(Sender: TObject);
    procedure ButtonCrwLsqPolyTest1Click(Sender: TObject);
    procedure ButtonCrwRtcTest1Click(Sender: TObject);
    procedure ButtonCrwRtcTest2Click(Sender: TObject);
    procedure ButtonCrwSortTest1Click(Sender: TObject);
    procedure ButtonCrwSplineTest1Click(Sender: TObject);
    procedure ButtonCrwSvdTest1Click(Sender: TObject);
    procedure ButtonCrwZmTest1Click(Sender: TObject);
    procedure ButtonCrwAllocTest1Click(Sender: TObject);
    procedure TimerPolling1000Timer(Sender: TObject);
    procedure TimerPolling50Timer(Sender: TObject);
    procedure TimerShmTimer(Sender: TObject);
  private
    ZStamp : String;
    shm    : Integer;
    procedure KillSharMem;
    function DoShmOp(op:Char; Mode:Integer):LongString;
  public
    procedure AddLog(When:TDateTime; Msg:String);
  public
    xtid : Integer;
  end;

function StartSession(arg:LongString):Boolean;

var
  FormCrwTestBench: TFormCrwTestBench = nil;

implementation

{$R *.lfm}

procedure CrwTestBenchEcho(const Msg:LongString);
var N:Integer;
begin
 if IsMainThread then
 if (FormCrwTestBench<>nil) then
 with FormCrwTestBench do begin
  N:=Length(Msg);
  if EndsStr(EOL,Msg)
  then Dec(N,Length(EOL));
  AddLog(Now,Copy(Msg,1,N));
 end;
end;

function SimulateSendToMainConsole(const Msg:LongString):Integer;
begin
 Result:=Length(Msg);
 Echo(Msg);
end;

procedure KillAllPolling;
var i:Integer;
begin
 for i:=FullPollingList.Count-1 downto 0 do FullPollingList[i].Free;
end;

procedure TFormCrwTestBench.FormCreate(Sender: TObject);
begin
 FormCenterToScreen(Self,0,0);
 SetButtonCursorToHandPoint(Self);
 SetDefaultMonoFontName(Font);
 //OpenResourceLeakageLogFile(AddPathDelim(ExtractFilePath(ParamStr(0)))+'leak.log');
 //SystemEchoProcedure:=@CrwTestBenchEcho;
 //SystemSendToMainConsoleFunction:=@SimulateSendToMainConsole;
 //TPolling.SetDefRedirectStdIo('012');
 //OpenIniLogFile(AddPathDelim(HomeDir)+'readini.log');
 ComboBoxCrwEnvironGetEnvName.Items.Text:=SysGetEnvironmentText(true);
 AddLog(Now,Format('DefaultSystemCodePage = %d',[DefaultSystemCodePage]));
 SetTempDir(HomeDir('temp'));
 writeln('Global GetAppConfigDir = '+GetAppConfigDir(true));
 writeln('Global GetAppConfigFile = '+GetAppConfigFile(true,true));
 writeln('Local GetAppConfigDir = '+GetAppConfigDir(false));
 writeln('Local GetAppConfigFile = '+GetAppConfigFile(false,true));
 writeln('SysConfigDir = ',SysConfigDir);
end;

procedure KillPipes; forward;
procedure KillTcps; forward;

procedure TFormCrwTestBench.FormDestroy(Sender: TObject);
begin
 if (xtid<>0) then begin task_free(xtid); xtid:=0; end;
 KillAllPolling;
 KillSharMem;
 KillPipes;
 KillTcps;
 inherited;
end;

procedure TFormCrwTestBench.KillSharMem;
begin
 if (shm<>0) then begin
  shm_free(shm);
  shm:=0;
 end;
end;

const
 PromptAr=' => ';
 DTFormat='yyyy.mm.dd-hh:mm:ss';

procedure TFormCrwTestBench.AddLog(When:TDateTime; Msg:String);
var Stamp:String; Logger:TStrings; List:TStringList; i:Integer;
begin
 if (Msg<>'') and not IsLexeme(Msg,lex_utf8) then Msg:=utf8_fixbroken(Msg);
 if (ZStamp='') then begin
  ZStamp:=FormatDateTime(DTFormat,Now);
  ZStamp:=Pad('',Length(ZStamp),'=')+PromptAr;
 end;
 if (When<=0)
 then Stamp:=ZStamp
 else Stamp:=FormatDateTime(DTFormat,When)+PromptAr;
 if (When<0) then begin Stamp:=''; ZStamp:=''; end;
 Logger:=MemoCrwTestBenchLog.Lines;
 if (Pos(LineEnding,Msg)=0) then begin
  Logger.Add(Stamp+Msg);
 end else begin
  List:=TStringList.Create;
  try
   List.Text:=Msg;
   for i:=0 to List.Count-1 do begin
    Logger.Add(Stamp+List.Strings[i]);
    if (i=0) then Stamp:=ZStamp;
   end;
  finally
   List.Free;
  end;
 end;
 MemoCrwTestBenchLog.SelStart:=MaxInt;
end;

procedure TFormCrwTestBench.ButtonCrwAllocTest1Click(Sender: TObject);
var p1,p2,p3:PChar; m1,m2:TMasterObject; list:TList; i,n,ref:Integer;
const probe:PChar='This is test string.';
var psi:PtrInt; pui:PtrUInt; p:Pointer;
begin
 try
  AddLog(Now,'_crw_alloc '+ButtonCrwAllocTest1.Caption);
  AddLog(0,Format('GetAllocMemSize=%d',[GetAllocMemSize]));
  AddLog(0,Format('GetAllocMemCount=%d',[GetAllocMemCount]));
  AddLog(0,Format('GetCurrentProcessId=%d',[GetCurrentProcessId]));
  if CompareMem(@ShareMemStorage.NewMM,@ShareMemStorage.OldMM,SizeOf(ShareMemStorage.OldMM))
  then AddLog(0,'Memory Manager - Uses default.')
  else AddLog(0,'Memory Manager - User defined.');
  p1:=probe; p2:=IncPtr(p1,8); p3:=DecPtr(p2,3);
  AddLog(0,'IncPtr/DecPtr/Probe='+p1+', '+p2+', '+p3);
  if (SubtractPointersAsPtrInt(p2,p1)=8) and (SubtractPointersAsPtrUInt(p3,p1)=5)
  then AddLog(0,'Subtract Pointers - Ok');
  p:=Allocate(10); p1:=p;
  psi:=PointerToPtrInt(p1); pui:=PointerToPtrUInt(p1);
  p2:=PtrIntToPointer(psi); p3:=PtrUIntToPointer(pui);
  Deallocate(p);
  AddLog(0,Format('PointerToPtrInt:  %x, %x',[PtrUInt(p1),psi]));
  AddLog(0,Format('PointerToPtrUInt: %x, %x',[PtrUInt(p1),pui]));
  AddLog(0,Format('PtrIntToPointer:  %x, %x',[psi,PtrUInt(p2)]));
  AddLog(0,Format('PtrUIntToPointer: %x, %x',[pui,PtrUInt(p3)]));
  if (p2=p3) then AddLog(0,'Pointers - Ok');
  AddLog(0,'BornKillFile='+GetBornKillFile);
  AddLog(0,'WindowID='+GetApplicationMainFormWindowId);
  p1:=Allocate(30); StrCopy(p1,probe);
  AddLog(0,Format('AllocSize=%d, AllocateBalance=%d, Str=%s',[AllocSize(p1),GetAllocateBalance,p1]));
  Reallocate(Pointer(p1),60);
  AddLog(0,Format('AllocSize=%d, AllocateBalance=%d, Str=%s',[AllocSize(p1),GetAllocateBalance,p1]));
  Deallocate(Pointer(p1));
  AddLog(0,Format('AllocSize=%d, AllocateBalance=%d',[AllocSize(p1),GetAllocateBalance,p1]));
  m1:=TMasterObject.Create; m1.Master:=@m1;
  AddLog(0,Format('Object1=%x,%x Ref=%d',[SizeUInt(m1),SizeUInt(m1.Master),m1.Ref]));
  m1.Free;
  AddLog(0,Format('Object1=%x,%x Ref=%d',[SizeUInt(m1),SizeUInt(m1.Master),m1.Ref]));
  n:=100;
  list:=TList.Create;
  try
   for i:=0 to n-1 do list.Add(TMasterObject.Create);
   for i:=0 to n-1 do begin
    m1:=TMasterObject(list.Items[i]);
    ref:=m1.ref; m2:=TMasterObject(ObjectRegistry.Items[ref]);
    AddLog(0,Format('Master[%d].Ref=%d, %x,%x',[i,ref,SizeUInt(m1),SizeUInt(m2)]));
   end;
   for i:=n-1 downto 0 do TObject(list.Items[i]).Free;
  finally
   Kill(list);
  end;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwAllocTest1Click');
 end;
end;

procedure TFormCrwTestBench.TimerCrwAscioPollTimer(Sender: TObject);
var line:String;
begin
 if CheckBoxCrwAscioPolling.Checked then
 try
  while StdIn.Count>0 do begin
   line:=StdIn.Get;
   AddLog(Now,'StdIn: '+line);
   // StdIn.Process(line);
  end;
 except
  on E:Exception do BugReport(E,Self,'TimerCrwAscioPollTimer');
 end;
end;

procedure TFormCrwTestBench.TimerPolling50Timer(Sender: TObject);
begin
 try
  Tick55Actions.Execute;
  if (StdOutputFifo.Count>0) then AddLog(-1,StdOutputFifo.GetText);
  if (StdErrOutputFifo.Count>0) then AddLog(-1,StdErrOutputFifo.GetText);
  if (SystemCalculator.Fifo.Count>0) then AddLog(-1,SystemCalculator.Fifo.GetText);
 except
  on E:Exception do BugReport(E,Self,'TimerPolling50Timer');
 end;
end;

procedure PrintPollingCpuLoad(Polling:TPolling);
var Summ,Kern,User,Freq:Double;
begin
 if Polling.GetCpuLoad(Summ,Kern,User,Freq) then begin
  writeln(Format('%s CpuLoad: Summ %.4g, Kern %.4g, User %.4g, Freq %.4g',
          [Polling.Name,Summ,Kern,User,Freq]));
 end;
end;

function GetParentStatus:LongString;
begin
 Result:='Parent PID: '+IntToStr(GetParentProcessID)+' '+GetParentProcessExe;
 if BecameOrphan then Result:=Result+' Orphan';
 if BecameZombie then Result:=Result+' Zombie';
end;

procedure ShowActiveWindowStatus;
var win:HWND; pid:TPid; s,wc,wn,ws,wt:LongString;
begin
 if Assigned(FormCrwTestBench) then with FormCrwTestBench do begin
  win:=wmctrl.ActiveWindow; if not wmctrl.IsWindow(win) then Exit;
  pid:=wmctrl.WindowPid(win);
  wc:=wmctrl.WindowClass(win);
  wn:=wmctrl.WindowTitle(win);
  wt:=wmctrl.WindowTypeList(win);
  wt:=StringReplace(Trim(wt),EOL,',',[rfReplaceAll]);
  wt:=StringReplace(wt,'_NET_WM_WINDOW_TYPE_','',[rfReplaceAll]);
  ws:=wmctrl.WindowStateList(win);
  ws:=StringReplace(Trim(ws),EOL,',',[rfReplaceAll]);
  ws:=StringReplace(ws,'_NET_WM_STATE_','',[rfReplaceAll]);
  s:=Format('Active WND:%u PID:%u CLS:"%s" TIT:"%s" WT:%s ST:%s',[win,pid,wc,wn,wt,ws]);
  LabelWmctrlStatus.Caption:=s;
 end;
end;

procedure TFormCrwTestBench.TimerPolling1000Timer(Sender: TObject);
var i:Integer; s:LongString; polling:TPolling;
const LoopCount:Cardinal=0;
begin
 try
  SecondActions.Execute;
  ShowActiveWindowStatus;
  LabelParentStatus.Caption:=GetParentStatus;
  s:=Format('Polling: %d thread(s)',[FullPollingList.Count]);
  for i:=0 to FullPollingList.Count-1 do begin
   polling:=TPolling(FullPollingList[i]);
   s:=Format('%s, %d',[s,polling.LoopCount]);
   if PosI('DebugOut[',polling.Name)>0 then Continue;
   if PosI('System.',polling.Name)>0 then Continue;
   if (LoopCount mod 5)=0 then PrintPollingCpuLoad(polling);
  end;
  LabelCrwPollingStatus.Caption:=s;
  inc(LoopCount);
  s:=Format('MultiMediaTimer: %d ms, %d calls',[mmTimer.Period,mmTimer.Counter]);
  LabelCrwMmtStatus.Caption:=s;
 except
  on E:Exception do BugReport(E,Self,'TimerPolling1000Timer');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwAllocTest2Click(Sender: TObject);
var xti,xvi,ti,ri,vi,ci,ne:LongInt; xtc,xvc,tc,rc,vc,cc:Cardinal;
 xts,xvs,ts,rs,vs,cs:SizeInt; xtq,xvq,tq,rq,vq,cq:SizeUInt;
 procedure TestLongInt(s:String; t,v,r,e,nt,et:LongInt);
 begin
  if (nt<>et) then inc(ne);
  AddLog(0,Format('%-22s %-3d %-3d %-3d %-3d %-3d %-3d, %d error(s)',[s,t,v,r,e,nt,et,ne]));
 end;
 procedure TestCardinal(s:String; t,v,r,e,nt,et:Cardinal);
 begin
  if (nt<>et) then inc(ne);
  AddLog(0,Format('%-22s %-3d %-3d %-3d %-3d %-3d %-3d, %d error(s)',[s,t,v,r,e,nt,et,ne]));
 end;
 procedure TestSizeInt(s:String; t,v,r,e,nt,et:SizeInt);
 begin
  if (nt<>et) then inc(ne);
  AddLog(0,Format('%-22s %-3d %-3d %-3d %-3d %-3d %-3d, %d error(s)',[s,t,v,r,e,nt,et,ne]));
 end;
 procedure TestSizeUInt(s:String; t,v,r,e,nt,et:SizeUInt);
 begin
  if (nt<>et) then inc(ne);
  AddLog(0,Format('%-22s %-3d %-3d %-3d %-3d %-3d %-3d, %d error(s)',[s,t,v,r,e,nt,et,ne]));
 end;
begin
 try
  ne:=0;
  AddLog(Now,'_crw_alloc '+ButtonCrwAllocTest2.Caption);
  AddLog(0,Format('LongInt %d',[SizeOf(xti)]));
  xti:=100; xvi:=10; ci:=xti;
  ti:=xti; vi:=xvi; ri:=LockedInc(ti);                   TestLongInt('LockedInc',ti,vi,ri,xti+1,ti,xti+1);
  ti:=xti; vi:=xvi; ri:=LockedDec(ti);                   TestLongInt('LockedDec',ti,vi,ri,xti-1,ti,xti-1);
  ti:=xti; vi:=xvi; ri:=LockedAdd(ti,vi);                TestLongInt('LockedAdd',ti,vi,ri,xti+xvi,ti,xti+xvi);
  ti:=xti; vi:=xvi; ri:=LockedSub(ti,vi);                TestLongInt('LockedSub',ti,vi,ri,xti-xvi,ti,xti-xvi);
  ti:=xti; vi:=xvi; ri:=LockedExchangeInc(ti);           TestLongInt('LockedExchangeInc',ti,vi,ri,xti,ti,xti+1);
  ti:=xti; vi:=xvi; ri:=LockedExchangeDec(ti);           TestLongInt('LockedExchangeDec',ti,vi,ri,xti,ti,xti-1);
  ti:=xti; vi:=xvi; ri:=LockedExchangeAdd(ti,vi);        TestLongInt('LockedExchangeAdd',ti,vi,ri,xti,ti,xti+xvi);
  ti:=xti; vi:=xvi; ri:=LockedExchangeSub(ti,vi);        TestLongInt('LockedExchangeSub',ti,vi,ri,xti,ti,xti-xvi);
  ti:=xti; vi:=xvi; ri:=LockedExchange(ti,vi);           TestLongInt('LockedExchange',ti,vi,ri,xti,ti,xvi);
  ti:=xti; vi:=xvi; ri:=LockedCompareExchange(ti,vi,ci); TestLongInt('LockedCompareExchange',ti,vi,ri,xti,ti,xvi);
  AddLog(0,Format('Cardinal %d',[SizeOf(xtc)]));
  xtc:=100; xvc:=10; cc:=xtc;
  tc:=xtc; vc:=xvc; rc:=LockedInc(tc);                   TestCardinal('LockedInc',tc,vc,rc,xtc+1,tc,xtc+1);
  tc:=xtc; vc:=xvc; rc:=LockedDec(tc);                   TestCardinal('LockedDec',tc,vc,rc,xtc-1,tc,xtc-1);
  tc:=xtc; vc:=xvc; rc:=LockedAdd(tc,vc);                TestCardinal('LockedAdd',tc,vc,rc,xtc+xvc,tc,xtc+xvc);
  tc:=xtc; vc:=xvc; rc:=LockedSub(tc,vc);                TestCardinal('LockedSub',tc,vc,rc,xtc-xvc,tc,xtc-xvc);
  tc:=xtc; vc:=xvc; rc:=LockedExchangeInc(tc);           TestCardinal('LockedExchangeInc',tc,vc,rc,xtc,tc,xtc+1);
  tc:=xtc; vc:=xvc; rc:=LockedExchangeDec(tc);           TestCardinal('LockedExchangeDec',tc,vc,rc,xtc,tc,xtc-1);
  tc:=xtc; vc:=xvc; rc:=LockedExchangeAdd(tc,vc);        TestCardinal('LockedExchangeAdd',tc,vc,rc,xtc,tc,xtc+xvc);
  tc:=xtc; vc:=xvc; rc:=LockedExchangeSub(tc,vc);        TestCardinal('LockedExchangeSub',tc,vc,rc,xtc,tc,xtc-xvc);
  tc:=xtc; vc:=xvc; rc:=LockedExchange(tc,vc);           TestCardinal('LockedExchange',tc,vc,rc,xtc,tc,xvc);
  tc:=xtc; vc:=xvc; rc:=LockedCompareExchange(tc,vc,cc); TestCardinal('LockedCompareExchange',tc,vc,rc,xtc,tc,xvc);
  AddLog(0,Format('SizeInt %d',[SizeOf(xts)]));
  xts:=100; xvs:=10; cs:=xts;
  ts:=xts; vs:=xvs; rs:=LockedInc(ts);                   TestSizeInt('LockedInc',ts,vs,rs,xts+1,ts,xts+1);
  ts:=xts; vs:=xvs; rs:=LockedDec(ts);                   TestSizeInt('LockedDec',ts,vs,rs,xts-1,ts,xts-1);
  ts:=xts; vs:=xvs; rs:=LockedAdd(ts,vs);                TestSizeInt('LockedAdd',ts,vs,rs,xts+xvs,ts,xts+xvs);
  ts:=xts; vs:=xvs; rs:=LockedSub(ts,vs);                TestSizeInt('LockedSub',ts,vs,rs,xts-xvs,ts,xts-xvs);
  ts:=xts; vs:=xvs; rs:=LockedExchangeInc(ts);           TestSizeInt('LockedExchangeInc',ts,vs,rs,xts,ts,xts+1);
  ts:=xts; vs:=xvs; rs:=LockedExchangeDec(ts);           TestSizeInt('LockedExchangeDec',ts,vs,rs,xts,ts,xts-1);
  ts:=xts; vs:=xvs; rs:=LockedExchangeAdd(ts,vs);        TestSizeInt('LockedExchangeAdd',ts,vs,rs,xts,ts,xts+xvs);
  ts:=xts; vs:=xvs; rs:=LockedExchangeSub(ts,vs);        TestSizeInt('LockedExchangeSub',ts,vs,rs,xts,ts,xts-xvs);
  ts:=xts; vs:=xvs; rs:=LockedExchange(ts,vs);           TestSizeInt('LockedExchange',ts,vs,rs,xts,ts,xvs);
  ts:=xts; vs:=xvs; rs:=LockedCompareExchange(ts,vs,cs); TestSizeInt('LockedCompareExchange',ts,vs,rs,xts,ts,xvs);
  AddLog(0,Format('SizeUInt %d',[SizeOf(xtq)]));
  xtq:=100; xvq:=10; cq:=xtq;
  tq:=xtq; vq:=xvq; rq:=LockedInc(tq);                   TestSizeUInt('LockedInc',tq,vq,rq,xtq+1,tq,xtq+1);
  tq:=xtq; vq:=xvq; rq:=LockedDec(tq);                   TestSizeUInt('LockedDec',tq,vq,rq,xtq-1,tq,xtq-1);
  tq:=xtq; vq:=xvq; rq:=LockedAdd(tq,vq);                TestSizeUInt('LockedAdd',tq,vq,rq,xtq+xvq,tq,xtq+xvq);
  tq:=xtq; vq:=xvq; rq:=LockedSub(tq,vq);                TestSizeUInt('LockedSub',tq,vq,rq,xtq-xvq,tq,xtq-xvq);
  tq:=xtq; vq:=xvq; rq:=LockedExchangeInc(tq);           TestSizeUInt('LockedExchangeInc',tq,vq,rq,xtq,tq,xtq+1);
  tq:=xtq; vq:=xvq; rq:=LockedExchangeDec(tq);           TestSizeUInt('LockedExchangeDec',tq,vq,rq,xtq,tq,xtq-1);
  tq:=xtq; vq:=xvq; rq:=LockedExchangeAdd(tq,vq);        TestSizeUInt('LockedExchangeAdd',tq,vq,rq,xtq,tq,xtq+xvq);
  tq:=xtq; vq:=xvq; rq:=LockedExchangeSub(tq,vq);        TestSizeUInt('LockedExchangeSub',tq,vq,rq,xtq,tq,xtq-xvq);
  tq:=xtq; vq:=xvq; rq:=LockedExchange(tq,vq);           TestSizeUInt('LockedExchange',tq,vq,rq,xtq,tq,xvq);
  tq:=xtq; vq:=xvq; rq:=LockedCompareExchange(tq,vq,cq); TestSizeUInt('LockedCompareExchange',tq,vq,rq,xtq,tq,xvq);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwAllocTest2Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwAllocTest3Click(Sender: TObject);
var extype:String; i,z:Integer;
begin
 try
  AddLog(Now,'_crw_alloc '+ButtonCrwAllocTest3.Caption);
  i:=1; z:=0;
  extype:=ComboBoxCrwAllocBugType.Text;
  if SameText(extype,'EEchoException')
  then Raise EEchoException.Create('Test '+extype+' exception.');
  if SameText(extype,'ESoftException')
  then Raise ESoftException.Create('Test '+extype+' exception.');
  if SameText(extype,'ENiceException')
  then Raise ENiceException.Create('Test '+extype+' exception.');
  if SameText(extype,'EHideException')
  then Raise EHideException.Create('Test '+extype+' exception.');
  if SameText(extype,'EHarmException')
  then Raise EHarmException.Create('Test '+extype+' exception.');
  if SameText(extype,'EFailException')
  then Raise EFailException.Create('Test '+extype+' exception.');
  if SameText(extype,'Exception')
  then Raise Exception.Create('Test '+extype+' exception.');
  if SameText(extype,'EDivByZero') then i:=(i div z);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwAllocTest3Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwCmdArgsTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_cmdargs '+ButtonCrwCmdArgsTest1.Caption);
  CmdArgs.ListOptVal:=ComboBoxCrwCmdArgsListOptVal.Text;
  AddLog(0,'ReportCmdArgs:'+EOL+ReportCmdArgs);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEnvironTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwCmdArgsTest2Click(Sender: TObject);
var opt:String;
begin
 try
  AddLog(Now,'_crw_cmdargs '+ButtonCrwCmdArgsTest2.Caption);
  CmdArgs.ListOptVal:=ComboBoxCrwCmdArgsListOptVal.Text;
  opt:=ComboBoxCrwCmdArgsGetOpt.Text;
  if CmdArgs.HasOption(opt) then begin
   if CmdArgs.HasOptionValue(opt)
   then AddLog(0,'HasOption '+opt+'='+CmdArgs.GetOptionValue(opt))
   else AddLog(0,'HasOption '+opt);
  end else begin
   AddLog(0,'Option is not found: '+opt);
  end;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEnvironTest2Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwEnvironTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_environ '+ButtonCrwEnvironTest1.Caption);
  AddLog(0,'SysGetEnvironmentText:'+EOL+SysGetEnvironmentText);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEnvironTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwEnvironTest2Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_environ '+ButtonCrwEnvironTest2.Caption);
  AddLog(0,'EnvironmentVariableList:'+EOL+EnvironmentVariableList.Text);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEnvironTest2Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwEnvironTest3Click(Sender: TObject);
var id:String;
begin
 try
  id:=Trim(ComboBoxCrwEnvironGetEnvName.Text);
  AddLog(Now,'_crw_environ '+ButtonCrwEnvironTest3.Caption);
  AddLog(0,'GetEnv: '+id+'='+GetEnv(id));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEnvironTest3Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwEnvironTest4Click(Sender: TObject);
var p:Integer; sn,sv:String;
begin
 try
  AddLog(Now,'_crw_environ '+ButtonCrwEnvironTest4.Caption);
  sv:=Trim(ComboBoxCrwEnvironSetEnvText.Text);
  p:=Pos('=',sv); sn:=Copy(sv,1,p-1); Delete(sv,1,p);
  if (sn='') then Raise ESoftException.Create('Expression (Name=Value) expected.');
  if SetEnv(sn,sv)
  then AddLog(0,'SetEnv: '+sn+'='+sv)
  else AddLog(0,'SetEnv: ERROR');
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEnvironTest4Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwEnvironTest5Click(Sender: TObject);
var expr:String;
begin
 try
  AddLog(Now,'_crw_environ '+ButtonCrwEnvironTest5.Caption);
  expr:=Trim(ComboBoxCrwEnvironExpEnvText.Text);
  expr:=ExpEnv(expr);
  AddLog(0,'ExpEnv: '+expr);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEnvironTest5Click');
 end;
end;

////////////////////////////////////////////////////////////////////////////////

procedure print(s:String);
begin
 Echo(s);
end;

function ClassicTestZero(x:double; Custom:Pointer):double;
begin
 ClassicTestZero:=x*(x*x-2)-5;
end;

function TestQuanc8(x:DOUBLE; Custom:Pointer):DOUBLE;
begin
 if x<>0.0 then Result:=sin(x)/x else Result:=1.0;
end;

procedure Test_ZM;
VAR NOFUN,MEM:INTEGER; A,B,RESULT,RELERR,ABSERR,ERREST,FLAG:DOUBLE;
begin
 print('********** test of _zeromin unit ***************');
 MEM:=GetAllocMemSize;
 print(Format('Test macheps = %g',[MachEps]));
 print('Test FindZero: expected 2.0945514815');
 print(Format('Result: %g',[FindZero(ClassicTestZero,2,3,MachEps,nil)]));
 print('Test FindMin: expected 0.81650');
 print(Format('Result: %g',[FindMin(ClassicTestZero,0,1,sqrt(MachEps),nil)]));
 print('Test QUANC8:expected RESULT=1.6054129768,FLAG=0');
 A:=0.0;
 B:=2.0;
 RELERR:=1.0E-10;
 ABSERR:=0.0;
 FLAG:=0; NOFUN:=0; ERREST:=0;
 RESULT:=QUANC8(TestQuanc8,A,B,ABSERR,RELERR,ERREST,NOFUN,FLAG,nil);
 print(Format('RESULT=%g',[RESULT]));
 print(Format('ERREST=%g',[ERREST]));
 IF(FLAG<>0.0) THEN print(Format('FLAG=%g',[FLAG]));
 MEM:=GetAllocMemSize-MEM;
 if (MEM<>0)
 then print('Memory leak '+IntToStr(MEM))
 else print('Memory leak not found.');
 print('********** end of test *************************');
end;

procedure TFormCrwTestBench.ButtonCrwZmTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_environ '+ButtonCrwZmTest1.Caption);
  Test_ZM;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwZmTest1Click');
 end;
end;

{$IFDEF UNIX}
// libc's clock_gettime function uses vDSO (avoid syscall) while FPC by default
// is compiled without FPC_USE_LIBC defined and do a syscall each time
//   GetTickCount64 fpc    2 494 563 op/sec
//   GetTickCount64 libc 119 919 893 op/sec
// note: for high-resolution QueryPerformanceMicroSeconds, calling the kernel
// is also slower
function clock_gettime(clk_id : clockid_t; tp: ptimespec) : cint; cdecl; external 'c' name 'clock_gettime';

function GetTickCount64(id:clockid_t=CLOCK_MONOTONIC_COARSE):QWord; inline;
var tp:timespec;
begin
 if (clock_gettime(id, @tp)=0) // exists since Linux Kernel 2.6
 then Result:=(Int64(tp.tv_sec)*1000)+(tp.tv_nsec div 1000000)
 else Result:=0;
end;
{$ENDIF ~UNIX}

////////////////////////////////////////////////////////////////////////////////

procedure test_fifo1;
type
 TDaqEvent=packed record
  What  : word;
  Chan  : word;
  Time  : double;
  Data  : array[0..1] of double;
 end;
const
 nmax         = 2000;
const
 fifo:TFifo=nil;
 n1:integer=0;
 n2:integer=0;
 n3:integer=0;
 n4:integer=0;
var
 s,d  : pchar;
 c    : char;
 t0   : QWord;
 n,m  : int64;
 i,j  : LongInt;
 ev   : TDaqEvent;
 mem  : LongInt;
 ss    : shortstring;
begin
 ss:='';
 n1:=0;
 n2:=0;
 n3:=0;
 n4:=0;
 mem:=GetAllocMemSize;
 s:=allocate(1024*1024);
 d:=allocate(1024*1024);
 fifo:=newfifo(1024+1);
 if not assigned(fifo) then writeln('nil');
 writeln(fifo.Size,' bytes fifo buffer');
 writeln(fifo.Count,' bytes stored in fifo');
 writeln(fifo.Space,' bytes available in fifo');
 writeln(fifo.Lost,' bytes lost');
 {
 put and get string
 }
 strcopy(s,'Testing fifo now...'+EOL);
 fifo.put(@s[0],strlen(s));
 while fifo.get(@c,1)>0 do write(c);
 {
 puts/gets
 }
 for i:=0 to 10000 do begin
  if not fifo.puts(' i = '+IntToStr(i)+' rnd = '+FloatToStr(random))
  then print('******************************************');
  if fifo.count>fifo.size/2 then begin
   while fifo.gets(ss) do print(ss);
  end;
 end;
 fifo.clear;
 {
 measure byte fifo performance
 }
 n:=0;
 t0:=gettickcount64;
 while gettickcount64-t0<nmax do begin
  inc(n);
  if fifo.put(@c,sizeof(c))=0 then print('put err');
  if fifo.get(@c,sizeof(c))=0 then print('get err');
 end;
 print('char io = '+FloatToStr(nmax*1000/n)+' mks under '+IntToStr(n)+' cycles '+IntToStr(fifo.Lost)+' lost');
 {
 measure int64 fifo performance
 }
 m:=0;
 n:=0;
 t0:=gettickcount64;
 while gettickcount64-t0<nmax do begin
  inc(n);
  if fifo.put(@n,sizeof(n))=0 then print('put err');
  if fifo.get(@m,sizeof(m))=0 then print('get err');
  if m<>n then print('put/get err');
 end;
 print('int64 io = '+FloatToStr(nmax*1000/n)+' mks under '+IntToStr(n)+' cycles '+IntToStr(fifo.Lost)+' lost');
 {
 measure TEvent fifo performance
 }
 n:=0;
 t0:=gettickcount64;
 while gettickcount64-t0<nmax do begin
  inc(n);
  if fifo.put(@ev,sizeof(ev))=0 then print('put err');
  if fifo.get(@ev,sizeof(ev))=0 then print('get err');
 end;
 print('event io = '+FloatToStr(nmax*1000/n)+' mks under '+IntToStr(n)+' cycles '+IntToStr(fifo.Lost)+' lost');
 {
 measure 512 bytes fifo performance
 }
 n:=0;
 t0:=gettickcount64;
 while gettickcount64-t0<nmax do begin
  inc(n);
  if fifo.put(@s[0],512)=0 then print('put err');
  if fifo.get(@s[0],512)=0 then print('get err');
 end;
 print('512 char io = '+FloatToStr(nmax*1000/n)+' mks under '+IntToStr(n)+' cycles '+IntToStr(fifo.Lost)+' lost');
 {
 measure 1024 bytes fifo performance
 }
 n:=0;
 t0:=gettickcount64;
 while gettickcount64-t0<nmax do begin
  inc(n);
  if fifo.put(@s[0],1024)=0 then print('put err');
  if fifo.get(@s[0],1024)=0 then print('get err');
 end;
 print('1024 char io = '+FloatToStr(nmax*1000/n)+' mks under '+IntToStr(n)+' cycles '+IntToStr(fifo.Lost)+' lost');
 {
 random data put / get
 }
 for i:=0 to sizeof(s)-1 do s[i]:=char(1+random(200));
 s[sizeof(s)-1]:=char(0);
 n:=0;
 j:=0;
 fifo.clear;
 while n<sizeof(s) do begin
  m:=1+random(64);
  if n+m>sizeof(s) then m:=sizeof(s)-n;
  if fifo.put(@s[n],m)=0 then print('put err');
  inc(j,fifo.get(@d[j],1+random(128)));
  inc(n,m);
 end;
 {
 information
 }
 print(IntToStr(fifo.Size)+' bytes fifo buffer');
 print(IntToStr(fifo.Count)+' bytes stored in fifo');
 print(IntToStr(fifo.Space)+' bytes available in fifo');
 print(IntToStr(fifo.Lost)+' bytes lost');
 print('n='+IntToStr(n)+' j='+IntToStr(j)+' Compare='+IntToStr(strcomp(s,d))+' (must be 0)');
 Sleep(1000);
 {
 check memory leak
 }
 Kill(fifo);
 deallocate(pointer(s));
 deallocate(pointer(d));
 mem:=GetAllocMemSize-mem;
 if mem<>0
 then print('Memory leak '+IntToStr(mem))
 else print('No memory leak found.');
end;

procedure TFormCrwTestBench.ButtonCrwFifoTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_fifo '+ButtonCrwFifoTest1.Caption);
  Test_fifo1;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwFifoTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwAscioTest1Click(Sender: TObject);
const LineNum:SizeInt=0; var msg:String;
begin
 try
  AddLog(Now,'_crw_ascio '+ButtonCrwAscioTest1.Caption);
  msg:=Format('Line %d',[LockedInc(LineNum)]);
  StdOut.Put:=FormatDateTime(StdDateTimeFormat,Now)+' => '+msg;
  AddLog(Now,Msg);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwAscioTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwAscioTest2Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_ascio '+ButtonCrwAscioTest2.Caption);
  test_crw_ascio;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwFifoTest2Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwBase32Test1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_base32 '+ButtonCrwBase32Test1.Caption);
  TestBase32Coder;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwBase32Test1Click');
 end;

end;

procedure TFormCrwTestBench.ButtonCrwBase64Test1Click(Sender: TObject);
var sf:Boolean;
begin
 try
  sf:=UseStdFpcBase64;
  UseStdFpcBase64:=CheckBoxCrwBase64UseStd.Checked;
  AddLog(Now,'_crw_base64 '+ButtonCrwBase64Test1.Caption);
  AddLog(Now,test_crw_base64_text);
  UseStdFpcBase64:=sf;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwBase64Test1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwSortTest1Click(Sender: TObject);
begin
  try
  AddLog(Now,'_crw_sort '+ButtonCrwSortTest1.Caption);
  AddLog(0,'(Output to console...)');
  test_sort;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwSortTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwFpuTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_fpu '+ButtonCrwFpuTest1.Caption);
  AddLog(0,'(Output to console...)');
  test_fpu;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwFpuTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwLsqPolyTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_lsqpoly '+ButtonCrwLsqPolyTest1.Caption);
  AddLog(0,'(Output to console...)');
  test_lsqpoly;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwLsqPolyTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwEfTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_ef '+ButtonCrwEfTest1.Caption);
  AddLog(0,'(Output to console...)');
  test_ef;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEfTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwSvdTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_svd '+ButtonCrwSvdTest1.Caption);
  AddLog(0,'(Output to console...)');
  test_svd;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwSvdTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwSplineTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_svd '+ButtonCrwSplineTest1.Caption);
  AddLog(0,'(Output to console...)');
  test_spline;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwSplineTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwRtcTest1Click(Sender: TObject);
var nt,ms,dt:Double;
begin
 try
  AddLog(Now,'_crw_rtc '+ButtonCrwRtcTest1.Caption);
  nt:=Now; ms:=MSecNow; dt:=ms-OleTimeToMs(nt);
  AddLog(0,Format('Now     %g = %g = %s',[nt,OleTimeToMs(nt),FormatDateTime(StdDateTimeFormat,nt)]));
  AddLog(0,Format('MsecNow %g = %g = %s',[ms,MsToOleTime(ms),FormatDateTime(StdDateTimeFormat,MsToOleTime(ms))]));
  AddLog(0,Format('Delta, ms = %g',[dt]));
  AddLog(0,Format('LMT-GMT bias = %g ms',[msecnow(rtc_lmt)-msecnow(rtc_gmt)]));
  AddLog(0,Format('CpuFreq (eastimate) = %.6g MHz',[EastimateCpuFrequencyMHz(1000)]));
  AddLog(0,Benchmark_RTC(1000*1000*1,false));
  AddLog(0,Benchmark_RTC(1000*1000*10,true));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwRtcTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwRtcTest2Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_rtc '+ButtonCrwRtcTest2.Caption);
  AddLog(0,'(Output to console...)');
  test_rtc;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwRtcTest2Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwDynarTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_dynar '+ButtonCrwDynarTest1.Caption);
  AddLog(0,'(Output to console...)');
  test_dynar;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwDynarTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwHashTest1Click(Sender: TObject);
 procedure TestRolRor;
 var w1,w2:Cardinal;
 begin
  w1:=$abcd;
  w2:=$bcda;
  if (rol16(w1,4)=w2)
  then AddLog(0,Format('ROL16 %4.4x => %4.4x OK',[w1,rol16(w1,4)]))
  else AddLog(0,Format('ROL16 %4.4x => %4.4x FAIL',[w1,rol16(w1,4)]));
  w2:=$dabc;
  if (ror16(w1,4)=w2)
  then AddLog(0,Format('ROR16 %4.4x => %4.4x OK',[w1,ror16(w1,4)]))
  else AddLog(0,Format('ROR16 %4.4x => %4.4x FAIL',[w1,ror16(w1,4)]));
  w1:=$89abcdef;
  w2:=$9abcdef8;
  if (rol32(w1,4)=w2)
  then AddLog(0,Format('ROL32 %4.4x => %4.4x OK',[w1,rol32(w1,4)]))
  else AddLog(0,Format('ROL32 %4.4x => %4.4x FAIL',[w1,rol32(w1,4)]));
  w2:=$f89abcde;
  if (ror32(w1,4)=w2)
  then AddLog(0,Format('ROR32 %4.4x => %4.4x OK',[w1,ror32(w1,4)]))
  else AddLog(0,Format('ROR32 %4.4x => %4.4x FAIL',[w1,ror32(w1,4)]));
 end;
begin
 try
  AddLog(Now,'_crw_hash '+ButtonCrwHashTest1.Caption);
  MakeHash32SanityTest(CrwTestBenchEcho);
  TestRolRor;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwHashTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwHashTest2Click(Sender: TObject);
var fname,msg:String; niter:Integer;
begin
 try
  AddLog(Now,'_crw_hash '+ButtonCrwHashTest2.Caption);
  fname:=CmdArgs.ExeFileDir+'/'+'dic_win32.txt'; niter:=1000;
  msg:=DoHashBench(fname,niter,CrwTestBenchEcho);
  MakeHash32SanityTest(CrwTestBenchEcho);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwHashTest2Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwCryptTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_crypt '+ButtonCrwHashTest2.Caption);
  AddLog(0,'(Output to console...)');
  test_crypt;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwCryptTest1Click');
 end;
end;

const
 Abc_RusWin = #$80#$81#$82#$83#$84#$85#$86#$87#$88#$89#$8A#$8B#$8C#$8D#$8E#$8F
            + #$90#$91#$92#$93#$94#$95#$96#$97#$98#$99#$9A#$9B#$9C#$9D#$9E#$9F
            + #$A0#$A1#$A2#$A3#$A4#$A5#$A6#$A7#$A8#$A9#$AA#$AB#$AC#$AD#$AE#$AF
            + #$B0#$B1#$B2#$B3#$B4#$B5#$B6#$B7#$B8#$B9#$BA#$BB#$BC#$BD#$BE#$BF
            + #$C0#$C1#$C2#$C3#$C4#$C5#$C6#$C7#$C8#$C9#$CA#$CB#$CC#$CD#$CE#$CF
            + #$D0#$D1#$D2#$D3#$D4#$D5#$D6#$D7#$D8#$D9#$DA#$DB#$DC#$DD#$DE#$DF
            + #$E0#$E1#$E2#$E3#$E4#$E5#$E6#$E7#$E8#$E9#$EA#$EB#$EC#$ED#$EE#$EF
            + #$F0#$F1#$F2#$F3#$F4#$F5#$F6#$F7#$F8#$F9#$FA#$FB#$FC#$FD#$FE#$FF;
 Abc_RusDos = #$B0#$B1#$B2#$B3#$B4#$B5#$B6#$B7#$B8#$B9#$BA#$BB#$BC#$BD#$BE#$BF
            + #$C0#$C1#$C2#$C3#$C4#$C5#$C6#$C7#$C8#$C9#$CA#$CB#$CC#$CD#$CE#$CF
            + #$D0#$D1#$D2#$D3#$D4#$D5#$D6#$D7#$F0#$D9#$DA#$DB#$DC#$DD#$DE#$DF
            + #$D8#$F8#$F2#$F3#$F4#$F5#$F6#$F7#$F1#$FC#$FA#$FB#$F9#$FD#$FE#$FF
            + #$80#$81#$82#$83#$84#$85#$86#$87#$88#$89#$8A#$8B#$8C#$8D#$8E#$8F
            + #$90#$91#$92#$93#$94#$95#$96#$97#$98#$99#$9A#$9B#$9C#$9D#$9E#$9F
            + #$A0#$A1#$A2#$A3#$A4#$A5#$A6#$A7#$A8#$A9#$AA#$AB#$AC#$AD#$AE#$AF
            + #$E0#$E1#$E2#$E3#$E4#$E5#$E6#$E7#$E8#$E9#$EA#$EB#$EC#$ED#$EE#$EF;
 Abc_RusKoi = #$80#$81#$82#$83#$84#$85#$86#$87#$88#$89#$3F#$8B#$8C#$8D#$8E#$8F
            + #$90#$91#$92#$93#$94#$95#$96#$97#$98#$99#$3F#$3F#$9C#$9D#$3F#$9F
            + #$3F#$A1#$A2#$3F#$A4#$A5#$A6#$A7#$B3#$3F#$AA#$AB#$AC#$AD#$AE#$AF
            + #$A8#$3F#$B2#$B1#$B4#$3F#$B6#$3F#$A3#$BC#$3F#$BB#$3F#$BD#$BE#$3F
            + #$E1#$E2#$F7#$E7#$E4#$E5#$F6#$FA#$E9#$EA#$EB#$EC#$ED#$EE#$EF#$F0
            + #$F2#$F3#$F4#$F5#$E6#$E8#$E3#$FE#$FB#$FD#$FF#$F9#$F8#$FC#$E0#$F1
            + #$C1#$C2#$D7#$C7#$C4#$C5#$D6#$DA#$C9#$CA#$CB#$CC#$CD#$CE#$CF#$D0
            + #$D2#$D3#$D4#$D5#$C6#$C8#$C3#$DE#$DB#$DD#$DF#$D9#$D8#$DC#$C0#$D1;

procedure TFormCrwTestBench.ButtonCrwStrTest1Click(Sender: TObject);
var s,t:LongString; p,n:Integer;
begin
 try
  AddLog(Now,'_crw_utf8 '+ButtonCrwStrTest1.Caption);
  t:='English Русский 0123456789';
  s:=t;
  AddLog(0,Format('StringCodePage(%s)=%d',[s,StringCodePage(s)]));
  AddLog(0,'Original UTF8 '+hex_encode(s));
  s:=ConvertCP(t,cp_UTF8,1251,CP_NONE);
  AddLog(0,'Convert  1251 '+hex_encode(s));
  s:=ConvertCP(s,1251,cp_UTF8,CP_ANSI);
  AddLog(0,'Convert  UTF8 '+hex_encode(s));
  AddLog(0,Format('StringCodePage(%s)=%d',[s,StringCodePage(s)]));
  AddLog(0,'Abc_RusWin'+EOL+ConvertCP(Abc_RusWin,1251,CP_UTF8,0));
  AddLog(0,'Abc_RusDos'+EOL+ConvertCP(Abc_RusDos,866,CP_UTF8,0));
  AddLog(0,'Abc_RusKoi'+EOL+ConvertCP(Abc_RusKoi,20866,CP_UTF8,0));
  n:=32; p:=Length(Abc_RusWin)-n+1;
  AddLog(0,'Abc_RusWin/Dos '+IntToStr(Ord(SameStr(ConvertCP(Copy(Abc_RusWin,p,n),1251,866,CP_NONE),Copy(Abc_RusDos,p,n)))));
  AddLog(0,'Abc_RusDos/Win '+IntToStr(Ord(SameStr(ConvertCP(Copy(Abc_RusDos,p,n),866,1251,CP_NONE),Copy(Abc_RusWin,p,n)))));
  AddLog(0,'Abc_RusWin/Koi '+IntToStr(Ord(SameStr(ConvertCP(Copy(Abc_RusWin,p,n),1251,20866,CP_NONE),Copy(Abc_RusKoi,p,n)))));
  AddLog(0,'Abc_RusKoi/Win '+IntToStr(Ord(SameStr(ConvertCP(Copy(Abc_RusKoi,p,n),20866,1251,CP_NONE),Copy(Abc_RusWin,p,n)))));
  AddLog(0,Test_crw_utf8);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwStrTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwStrTest2Click(Sender: TObject);
var i,nerr:Integer; c:Char; sa,sb:LongString;
begin
 try
  AddLog(Now,'_crw_str '+ButtonCrwStrTest2.Caption);
  nerr:=0;
  for c:=Low(c) to High(c) do begin
   if UpCase(c)<>System.UpCase(c) then inc(nerr);
   if LoCase(c)<>System.LowerCase(c) then inc(nerr);
   if not IsSameChar(Upcase(c),Locase(c)) then inc(nerr);
   if not IsSameText(Upcase(c),Locase(c)) then inc(nerr);
   if IsSameChar(Upcase(c),Locase(Pred(c))) then inc(nerr);
   if IsSameText(Upcase(c),Locase(Pred(c))) then inc(nerr);
  end;
  AddLog(0,Format('Up/LoCase errors: %d',[nerr]));
  sa:=Abc_Eng_Up+Abc_Eng_Lo+ConvertCP(Abc_RusWin,1251,CP_UTF8,0);
  sb:=LoCaseStr(sa); AddLog(0,Format('LoCaseStr%s  %s%s  %s',[EOL,sa,EOL,sb]));
  sb:=UpCaseStr(sa); AddLog(0,Format('UpCaseStr%s  %s%s  %s',[EOL,sa,EOL,sb]));
  //Format('Error of format %s',[1]);
  AddLog(0,'TailStr(123456789,4)   = '+TailStr('123456789',4));
  AddLog(0,'LeftStr(123456789,4)   = '+LeftStr('123456789',4));
  AddLog(0,'RightStr(123456789,4)  = '+RightStr('123456789',4));
  AddLog(0,'CharStr(15,*)          = '+CharStr(15,'*'));
  AddLog(0,'Pad(abc,15,*)          = '+Pad('abc',15,'*'));
  AddLog(0,'RightPad(abc,15,*)     = '+RightPad('abc',15,'*'));
  AddLog(0,'LeftPad(abc,15,*)      = '+LeftPad('abc',15,'*'));
  AddLog(0,'CenterStr(abc,15,*)    = '+CenterStr('abc',15,'*'));
  sb:=CenterStr('abc',15);
  AddLog(0,'String to trim         = '+sb+'.');
  AddLog(0,'TrimLeft               = '+TrimLeft(sb)+'.');
  AddLog(0,'TrimLead               = '+TrimLead(sb)+'.');
  AddLog(0,'TrimRight              = '+TrimRight(sb)+'.');
  AddLog(0,'TrimTrail              = '+TrimTrail(sb)+'.');
  AddLog(0,'Trim                   = '+Trim(sb)+'.');
  sb:=CenterStr('abc',15,'*');
  AddLog(0,'String to trim         = '+sb+'.');
  AddLog(0,'TrimLeft               = '+TrimLeftChars(sb,['*'])+'.');
  AddLog(0,'TrimLead               = '+TrimLeadChars(sb,['*'])+'.');
  AddLog(0,'TrimRight              = '+TrimRightChars(sb,['*'])+'.');
  AddLog(0,'TrimTrail              = '+TrimTrailChars(sb,['*'])+'.');
  AddLog(0,'Trim                   = '+TrimChars(sb,['*'],['*'])+'.');
  sa:='  one two three  ';
  AddLog(0,Format('Test words: "%s"',[sa]));
  for i:=0 to WordCount(sa,JustSpaces)+1 do begin
   AddLog(0,Format('Word[%d] = "%s", Skip: "%s"',[i,ExtractWord(i,sa,JustSpaces),SkipWords(i,sa,JustSpaces)]));
  end;
  AddLog(0,'FileName utils:');
  sa:='c:\path\file.ext';
  AddLog(0,Format('ExtractFileDrive   %-20s = %s',[sa,ExtractFileDrive(sa)]));
  sa:='/path/file.ext';
  AddLog(0,Format('ExtractFileDrive   %-20s = %s',[sa,ExtractFileDrive(sa)]));
  sa:='c:\path';
  AddLog(0,Format('AddBackSlash       %-20s = %s',[sa,AddBackSlash(sa)]));
  sa:='/opt/path';
  AddLog(0,Format('AddPathDelim       %-20s = %s',[sa,AddPathDelim(sa)]));
  sa:='c:\path\';
  AddLog(0,Format('DropBackSlash      %-20s = %s',[sa,DropBackSlash(sa)]));
  sa:='/opt/path/';
  AddLog(0,Format('DropPathDelim      %-20s = %s',[sa,DropPathDelim(sa)]));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwStrTest2Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwStrTest3Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_str '+ButtonCrwStrTest3.Caption);
  AddLog(0,test_crw_str_sanity);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwStrTest3Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwStrTest4Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_str '+ButtonCrwStrTest4.Caption);
  AddLog(0,'(Output to console...)');
  //test_ttext;
  test_str;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwStrTest4Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwHlTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_hl '+ButtonCrwHlTest1.Caption);
  AddLog(0,'(Output to console...)');
  TestHashListLeak(1000*100,Hash32_RS);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwHlTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwBsencodeTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_bsencode '+ButtonCrwBsencodeTest1.Caption);
  AddLog(0,backslash_encode_self_test_and_benchmark);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwBsencodeTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwColorsTest1Click(Sender: TObject);
var fname,html:LongString;
begin
 try
  AddLog(Now,'_crw_bsencode '+ButtonCrwColorsTest1.Caption);
  AddLog(0,Format('ColorToString %8.8X = %s',[clAqua,ColorToString(clAqua)]));
  AddLog(0,Format('StringToColor %8.8X = %s',[StringToColor('Aqua'),'Aqua']));
  fname:=AddPathDelim(ExtractFileDir(ParamStr(0)))+'colors.html';
  KnownColorsListCookies:=LoCaseStr(KnownColorsListCookies);
  html:=KnownColorsListAsText(3);
  DeleteFile(fname);
  if SafeFileWriteStr(fname,html)
  then AddLog(0,'Write File '+fname)
  else AddLog(0,'Error File '+fname);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwColorsTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwFsmTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_fsm '+ButtonCrwFsmTest1.Caption);
  AddLog(0,fsm_self_test);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwFsmTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwProcTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_proc '+ButtonCrwProcTest1.Caption);
  AddLog(0,Format('GetListOfProcesses: %s',[EOL+Trim(GetListOfProcesses(0,0,''))]));
  AddLog(0,Format('GetCurrentProcessAffinityMask = $%x',[GetProcessAffinityMask]));
  AddLog(0,Format('GetCurrentThreadAffinityMask = $%x',[GetThreadAffinityMask]));
  AddLog(0,Format('Current Process (list): %s',[GetListOfProcesses(GetCurrentProcessID,0,'')]));
  AddLog(0,Format('Current Process (curr): %d %s',[GetCurrentProcessID,GetProcessName]));
  AddLog(0,Format('Parent  Process (curr): %d %s',[GetParentProcessID,GetParentProcessName]));
  AddLog(0,Format('Parent  Process (snap): %d %s',[GetSnapshotParentProcessID,GetSnapshotParentProcessName]));
  AddLog(0,Format('Thread Curr %d, Main %d, %d',[GetCurrentThreadId,MainThreadId,Ord(IsMainThread)]));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwProcTest1Click');
 end;
end;

procedure fefa_Print(const FileName:LongString;const FileDetails:TSearchRec;
                     SubDirLevel:Integer; var Terminate:Boolean; CustomData:Pointer);
begin
 writeln(SubDirLevel:2,' ',FileName);
end;

procedure fetl_Print(const FileName:LongString; const Line:LongString;
                     Count:SizeInt; var Terminate:Boolean; CustomData:Pointer);
begin
 writeln(Count:2,' ',Line);
end;

procedure TFormCrwTestBench.ButtonCrwFioTest1Click(Sender: TObject);
var T:Text; fifo:TFifo; s,f:String; ts,tu:Int64; mf:TFilenameCaseMatch;
var vi,n:Integer; vr:Double; vs:ShortString; txt:TText;
begin
 try
  AddLog(Now,'_crw_fio '+ButtonCrwFioTest1.Caption);
  // Test NULL
  IoResult;
  AssignNull(T);
  AddLog(0,'Test NULL file IO: '+GetTextFileName(T));
  Rewrite(T);
  Writeln(T,GetListOfProcesses(0,0,''));
  SmartFileClose(T);
  AddLog(0,'Test NULL file IO: '+IntToStr(IoResult));
  fifo:=NewFifo(16,'Demo',2);
  // Test FIFO
  IoResult;
  AssignFifo(T,fifo);
  AddLog(0,'Test FIFO file IO: '+GetTextFileName(T));
  Rewrite(T);
  Writeln(T,GetListOfProcesses(0,0,''));
  Writeln(T,'Test fifo Ok.');
  Writeln(T,StdDateTimeStr(msecnow));
  SmartFileClose(T);
  AddLog(0,fifo.GetText);
  AddLog(0,'Test FIFO file IO: '+IntToStr(IoResult));
  Kill(fifo);
  // Test standard IO
  AddLog(0,'RedirectedStdIo = '+RedirectedStdIo
          +' '+IntToStr(GetTextFileBufSize(Input))
          +' '+IntToStr(GetTextFileBufSize(Output))
          +' '+IntToStr(GetTextFileBufSize(ErrOutput)));
  RedirectStdIo('012',true);
  AddLog(0,'RedirectedStdIo = '+RedirectedStdIo
          +' '+IntToStr(GetTextFileBufSize(Input))
          +' '+IntToStr(GetTextFileBufSize(Output))
          +' '+IntToStr(GetTextFileBufSize(ErrOutput)));
  writeln('Input '+GetTextFileName(Input));
  writeln('Output '+GetTextFileName(Output));
  writeln(ErrOutput,'ErrOutput '+GetTextFileName(ErrOutput));
  writeln('Test1 ',StdDateTimeStr(mSecNow));
  AddLog(-1,'Test1 Count '+IntToStr(StdOutputFifo.Count));
  RedirectStdIo('012',false);
  AddLog(0,'RedirectedStdIo = '+RedirectedStdIo
          +' '+IntToStr(GetTextFileBufSize(Input))
          +' '+IntToStr(GetTextFileBufSize(Output))
          +' '+IntToStr(GetTextFileBufSize(ErrOutput)));
  writeln('Test2 ',StdDateTimeStr(mSecNow));
  AddLog(-1,'Test2 Count '+IntToStr(StdOutputFifo.Count));
  RedirectStdIo('012',true);
  AddLog(0,'RedirectedStdIo = '+RedirectedStdIo
          +' '+IntToStr(GetTextFileBufSize(Input))
          +' '+IntToStr(GetTextFileBufSize(Output))
          +' '+IntToStr(GetTextFileBufSize(ErrOutput)));
  writeln('Test3 ',StdDateTimeStr(mSecNow));
  AddLog(-1,'Test3 Count '+IntToStr(StdOutputFifo.Count));
  writeln('File functions:');
  writeln('ProgName = '+ProgName);
  writeln('FileExist = '+IntToStr(Ord(FileExists(ProgName))));
  writeln('FileExist = '+IntToStr(Ord(FileExists(HomeDir+'/*.pas'))));
  writeln('DirExists = '+IntToStr(Ord(DirExists(HomeDir))));
  writeln('FileAttr = '+IntToStr(GetFileAttr(ProgName)));
  writeln('FileDate = '+StdDateTimeStr(GetFileDate(ProgName,true)));
  writeln('FileDate = '+StdDateTimeStr(FileTimeToMsec(GetFileDate(ProgName))));
  writeln('FileSize = '+IntToStr(GetFileSize(ProgName))+' bytes');
  writeln('HomeDir = '+HomeDir);
  writeln('TempDir = '+TempDir);
  SetTempDir(AddPathDelim(HomeDir)+'temp');
  writeln('TempDir = '+TempDir);
  writeln('UserHomeDir = '+UserHomeDir);
  writeln('StartupPath = '+StartupPath);
  writeln('StartAtDir = '+StartAtDir);
  writeln('SysIniFile = '+SysIniFile);
  writeln('LocalTempDir = '+LocalTempDir);
  writeln('GlobalTempDir = '+GlobalTempDir);
  if FileCopy(ProgName,ProgName+'.tmp',true)
  then writeln('FileCopy Ok') else writeln('FileCopy Failed');
  if FileErase(ProgName+'.tmp')
  then writeln('FileErase Ok') else writeln('FileErase Failed');
  if SetCurrDir(TempDir) then writeln('GetCurrDir = '+GetCurrDir);
  if SetCurrDir(HomeDir) then writeln('GetCurrDir = '+GetCurrDir);
  if MkDir(AddPathDelim(HomeDir)+'test') then writeln('MkDir Ok');
  if RmDir(AddPathDelim(HomeDir)+'test') then writeln('RmDir Ok');
  s:=Pad('',3);
  if ReadFileToBuffer(ProgName,PChar(s),Length(s),1)>0
  then writeln('ReadFile (1) = '+s,' ',IsSameStr(s,'ELF'));
  s:=ReadFileToBuffer(ProgName,3,1);
  writeln('ReadFile (2) = '+s,' ',IsSameStr(s,'ELF'));
  writeln('WriteBufferToFile ',WriteBufferToFile(AddPathDelim(TempDir)+'test.txt','Demo1'+EOL+'Demo2'+EOL));
  writeln(ReadFileToBuffer(AddPathDelim(TempDir)+'test.txt',MaxInt));
  ForEachTextLine(AddPathDelim(TempDir)+'test.txt',fetl_Print,nil,MaxInt);
  writeln('ForEachFile ',HomeDir,' * ');
  ForEachFile(HomeDir,'*',fefa_Print,2);
  //exit;
  StdOutputFifo.PutText('Thread Main  '+GetTextFileName(Output)
                       +' '+IntToStr(PointerToPtrInt(@Output))+EOL);
  //DebugOutOpenFile(1,AddPathDelim(TempDir)+'debug_1.log',1024*64,50,true,true);
  writeln('DebugOutGetFile '+DebugOutGetFile(1));
  DebugOut(1,StdDateTimeStr(mSecNow));
  writeln('UserName = ',UserName);
  writeln('ComputerName = ',ComputerName);
  writeln('HostName(0) = ',HostName(0));
  writeln('HostName(1) = ',HostName(1));
  writeln('GetEnv(HOME) = ',GetEnv('HOME'));
  writeln('SetEnv(X) = ',SetEnv('X','OK'));
  writeln('GetEnv(X) = ',GetEnv('X'));
  writeln('ExpEnv($HOME/projects) = ',ExpEnv('$HOME/projects'));
  writeln('ExpEnv(${HOME}projects) = ',ExpEnv('${HOME}projects'));
  // IniFiles
  ConfigCacheHoldingTime:=100;
  f:=AddPathDelim(HomeDir)+'TEST.cfg';
  s:='[demo]';
  writeln('ExtractTextSection(',f,',',s+')');
  writeln(ExtractTextSection(f,s,efConfigNC));
  f:=AddPathDelim(HomeDir)+'test.cfg';
  s:='[demo]';
  writeln('ExtractTextSection(',f,',',s+')');
  writeln(ExtractTextSection(f,s,efConfigNC));
  if ReadIniFileVariable(f,s,'Int%i',vi)
  then writeln('ReadIni int = ',vi);
  if ReadIniFileVariable(f,s,'Real%f',vr)
  then writeln('ReadIni real = ',vr);
  if ReadIniFileVariable(UpcaseStr(f),s,'String%s',vs,efConfigNC)
  then writeln('ReadIni string = ',vs);
  txt:=ConstructFullConfig(f); s:=txt.Text; Kill(txt);
  writeln('ConstructFullConfig(',f,')');
  writeln(s);
  writeln('ConfigCacheSnapshot(0):');
  writeln(ConfigCacheSnapshot(0));
  writeln('ConfigCacheSnapshot(1):');
  writeln(ConfigCacheSnapshot(1));
  writeln('ConfigCacheSnapshot(2):');
  writeln(ConfigCacheSnapshot(2));
  writeln('ConfigCacheSize = ',ConfigCacheSize);
  writeln('FreeConfigCache(0) = ',FreeConfigCache(0));
  writeln('ConfigCacheSize = ',ConfigCacheSize);
  // Process times
  GetProcessTimesAsFileTime(ts,tu);
  writeln(Format('Process times kern %g, user %g sec',[ts*1e-7,tu*1e-7]));
  GetThreadTimesAsFileTime(ts,tu);
  writeln(Format('Thread times kern %g, user %g sec',[ts*1e-7,tu*1e-7]));
  // File case
  s:=UpCaseStr(f);
  writeln('ExpandFileNameCase('+s+') = ',ExpandFileNameCase(s,mf));
  writeln('UnifyFileAlias('+s+') = ',UnifyFileAlias(s));
  //
  n:=0;
  s:=UpCaseStr(f);
  ts:=GetTickCount64;
  while GetTickCount64-ts<1000 do begin UnifyFileAlias(s); inc(n); end;
  ts:=GetTickCount64-ts;
  writeln(Format('UnifyFileAlias takes %.4g mks/call',[ts*1e3/n]));
  //
  n:=0;
  s:=AddPathDelim(HomeDir)+'Test.cfg';
  ts:=GetTickCount64;
  while GetTickCount64-ts<1000 do begin UnifyFileAlias(s); inc(n); end;
  ts:=GetTickCount64-ts;
  writeln(Format('UnifyFileAlias takes %.4g mks/call',[ts*1e3/n]));
  //
  n:=0;
  s:=f;
  ts:=GetTickCount64;
  while GetTickCount64-ts<1000 do begin UnifyFileAlias(s); inc(n); end;
  ts:=GetTickCount64-ts;
  writeln(Format('UnifyFileAlias takes %.4g mks/call',[ts*1e3/n]));
  // Createtempfile
  s:=CreateTempFile;
  f:=CreateTempFile;
  writeln('CreateTempFile(',s,') - ',FileExists(s));
  writeln('CreateTempFile(',f,') - ',FileExists(f));
  FileErase(s);
  FileErase(f);
  s:=CreateTempFile('abc.tmp');
  writeln('CreateTempFile(',s,') - ',FileExists(s));
  FileErase(s);
  // StringFromFile
  s:=FExpand(AddPathDelim(HomeDir)+'Test.cfg');
  writeln(StringFromFile(s,0));
  writeln(StringFromFile(s,MaxInt));
  // GetMacAddressListAsText
  writeln('GetMacAddresses:');
  writeln(GetMacAddresses);
  //
  n:=0;
  ts:=GetTickCount64;
  while GetTickCount64-ts<1000 do begin GetMacAddresses; inc(n); end;
  ts:=GetTickCount64-ts;
  writeln(Format('GetMacAddressListAsText takes %.4g mks/call',[ts*1e3/n]));
  // GetRealFilePathName
  s:=HomeDir+'/TEST.cfg';
  writeln('GetRealFilePathName('+s+') = '+GetRealFilePathName(s));
  //  ValidatePathList
  s:=GetEnv('PATH')+PathSep+UpCaseStr(HomeDir)+PathSep+'/xxx';
  writeln('ValidatePathList('+s+') = '+ValidatePathList(s));
  // SmartFileRef
  s:='../CrwTst/Test.cfg';
  writeln('SmartFileRef('+s+') = '+SmartFileRef(s,'.cfg',ProgName));
  s:='~/test.cfg';
  writeln('SmartFileRef('+s+') = '+SmartFileRef(s,'.cfg',ProgName));
  s:='~~/test.cfg';
  writeln('SmartFileRef('+s+') = '+SmartFileRef(s,'.cfg',ProgName));
  // SmartFileSearch
  s:='bash';
  writeln('SmartFileSearch('+s+') = '+SmartFileSearch(s));
  s:=AddSearchPath('PATH',HomeDir);
  writeln(s);
  s:=RemSearchPath('PATH','/usr/bin');
  writeln(s);
  writeln('GetCrwKitExe = ',GetCrwKitExe);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwFioTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwPollingTest1Click(Sender: TObject);
var i,c:Integer;
begin
 try
  AddLog(Now,'_crw_polling '+ButtonCrwPollingTest1.Caption);
  AddLog(0,Format('MainThreadId %d, CurrThreadId %d',[MainThreadId,GetThreadID]));
  ThreadSetPriority(MainThreadId,10);
  AddLog(0,Format('Main thread priority = %d',[ThreadGetPriority(MainThreadId)]));
  for i:=-20 to 20 do begin
   c:=GetPriorityClassByNice(i);
   writeln('nice ',i:3,' prio ',GetPriorityClassName(c));
  end;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwPollingTest1Click');
 end;
end;

procedure Stress(delay:Cardinal);
var tick:QWord;
begin
 if (delay>0) then begin
  tick:=GetTickCount64;
  while (GetTickCount64-tick<delay) do;
 end;
end;

procedure pa_TestPolling(aPolling:TPolling; var Terminate:Boolean);
//var Fifo:TFifo;
begin
 //Fifo:=GetTextFileFifo(Output);
 //if (Fifo=nil) or (Fifo<>StdOutputFifo) then RedirectStdIo('012',true);
 if aPolling.AwakeFlag then writeln(aPolling.Name,' Awake');
 Stress(50);
 writeln(aPolling.Name,' ',aPolling.LoopCount);
end;

procedure TFormCrwTestBench.ButtonCrwPollingAddClick(Sender: TObject);
var p:TPolling;
begin
 try
  AddLog(Now,'_crw_polling '+ButtonCrwPollingAdd.Caption);
  p:=NewPolling(pa_TestPolling,1000,tpNormal,true,Format('Poll[%d]',[FullPollingList.Count+1]));
  Sleep(50);
  p.Awake;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwPollingAddClick');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwPollingKillClick(Sender: TObject);
var polling:TPolling;
begin
 try
  AddLog(Now,'_crw_polling '+ButtonCrwPollingKill.Caption);
  if FullPollingList.Count>0 then begin
   polling:=TPolling(FullPollingList[FullPollingList.Count-1]);
   if PosI('DebugOut[',polling.Name)=0 then Polling.Free;
  end;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwPollingKillClick');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwMetaTest1Click(Sender: TObject);
var arg1,arg2,arg3:LongString;
begin
 try
  AddLog(Now,'_crw_meta '+ButtonCrwMetaTest1.Caption);
  arg1:='-h'; arg2:=''; arg3:='';
  writeln('TextMetaData ',' ',arg1,' ',arg2,' ',arg3,' = ',
          TextMetaDataUtility(arg1,arg2,arg3));
  arg1:='-c'; arg2:=AddPathDelim(HomeDir)+'meta.cfg'; arg3:='';
  writeln('TextMetaData ',' ',arg1,' ',arg2,' ',arg3,' = ',
          TextMetaDataUtility(arg1,arg2,arg3));
  arg1:='-a'; arg2:=AddPathDelim(HomeDir)+'meta.cfg'; arg3:='';
  writeln('TextMetaData ',' ',arg1,' ',arg2,' ',arg3,' = ',
          TextMetaDataUtility(arg1,arg2,arg3));
  writeln(GetFileVersionInfoAsText(ProgName));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwMetaTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwDaqtagsTest1Click(Sender: TObject);
var ms,n:Int64; Latch:TLatch; tag:Integer;
begin
 try
  AddLog(Now,'_crw_daqtags '+ButtonCrwDaqtagsTest1.Caption);
  AddLog(0,'(Output to console...)');
  Test_Daqtags;
  //
  tag:=InitTag('pi',2);
  writeln(rSetTag(tag,pi),' ',rGetTag(tag));
  //
  ms:=GetTickCount64; n:=0;
  while GetTickCount64-ms<1000 do begin
   inc(n);
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('Empty loop takes %.4g ns/call',[ms*1e6/n]));
  //
  ms:=GetTickCount64; n:=0;
  while GetTickCount64-ms<1000 do begin
   LockTags; inc(n); UnlockTags;
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('LockTags/UnlockTags takes %.4g ns/call',[ms*1e6/n]));
  //
  Latch:=TLatch.Create;
  ms:=GetTickCount64; n:=0;
  while GetTickCount64-ms<1000 do begin
   Latch.Lock; inc(n); Latch.Unlock;
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('TLatch.Lock/Unlock takes %.4g ns/call',[ms*1e6/n]));
  Kill(Latch);
  //
  ms:=GetTickCount64; n:=0;
  while GetTickCount64-ms<1000 do begin
   rSetTag(tag,n); inc(n); rGetTag(tag);
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('rSet/GetTag takes %.4g ns/call',[ms*1e6/n]));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwDaqtagsTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwRtdtcTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_rtdtc '+ButtonCrwRtdtcTest1.Caption);
  writeln('thermocouple_tst:');
  writeln(thermocouple_tst,' error(s) found');
  writeln('restemperdet_tst:');
  writeln(restemperdet_tst,' error(s) found');
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwRtdtcTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwCoupleTest1Click(Sender: TObject);
var IniFile,Section,Name:LongString; i:Integer; mv,tc:Double;
begin
 try
  AddLog(Now,'_crw_rtdtc '+ButtonCrwCoupleTest1.Caption);
  IniFile:=SysIniFile; Section:='[DataBase]'; Name:='ThermoCouples';
  InitCouples(IniFile,Section,Name,1);
  writeln(ThermoCoupleCount,' thermocpuple(s) found');
  for i:=0 to ThermoCoupleCount-1 do write(' ',ThermoCoupleName(i)); writeln;
  IniFile:=SysIniFile; Section:='[DataBase]'; Name:='RelationShips';
  InitRelationships(IniFile,Section,Name,1);
  writeln(RelationShipCount,' relationship(s) found');
  for i:=0 to RelationShipCount-1 do write(' ',RelationShipName(i)); writeln;
  i:=FindThermoCouple('HrCp'); // HrCp 800.000 66.469
  tc:=800; mv:=ThermoCouple(i,tc,false);
  writeln(Format('HrCp %.5g -> %.5g, expect %.5g, %.5g',[tc,mv,800.000,66.469]));
  mv:=66.469; tc:=ThermoCouple(i,mv,true);
  writeln(Format('HrCp %.5g <- %.5g, expect %.5g, %.5g',[tc,mv,800.000,66.469]));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwCoupleTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwTh123Test1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_th123 '+ButtonCrwTh123Test1.Caption);
  Test_Benchmark_TH123D;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwTh123Test1Click');
 end;
end;

procedure MyBlasterLogger(const Msg:LongString);
begin
 if (Msg<>'') then write(Msg);
end;

procedure TFormCrwTestBench.ButtonCrwSndTest1Click(Sender: TObject);
var s:String;
begin
 try
  AddLog(Now,'_crw_snd '+ButtonCrwSndTest1.Caption);
  //RunCommand('sleep 15',s); exit;
  if UsesBlaster or InitBlaster(0,HomeDir+'/../crwdaq/resource/sound')
  then writeln('Sound initialized');
  SetBlasterVolume(0.5,0.5);
  SetBlasterSpeed(1.5);
  Voice('ПРИВЕТ 12345');
  Voice('Чпок Чик wheel Click ');
  //sleep(500); StopBlaster;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwSndTest1Click');
 end;
end;

procedure mmAction(Sender:TmmTimer);
begin
 writeln(Sender.Counter);
end;

procedure TFormCrwTestBench.ButtonCrwMmtStartClick(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_snd '+ButtonCrwMmtStart.Caption);
  if (mmTimer.Period<=0)
  then mmTimer.Period:=SpinEditCrwMmtPeriod.Value
  else mmTimer.Period:=0;
  mmTimer.Add(mmAction);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwMmtStartClick');
 end;
end;

procedure TFormCrwTestBench.SpinEditCrwMmtPeriodChange(Sender: TObject);
begin
 if (mmTimer.Period>0) then mmTimer.Period:=SpinEditCrwMmtPeriod.Value;
end;

procedure BenchmarkTryExceptFinally(Delay:QWord);
var ms,n:QWord; m:Integer; Latch:TLatch;
 procedure TestIncDec0(var i:Integer);
 begin
  inc(i);
  dec(i);
 end;
 procedure TestIncDec1(var i:Integer);
 begin
  try
   inc(i);
  finally
   dec(i);
  end;
 end;
 procedure TestIncDec2(var i:Integer);
 begin
  try
   inc(i);
   dec(i);
  except
   on E:Exception do BugReport(E,nil,'TestIncDec2');
  end;
 end;
 procedure TestIncDec3(var i:Integer);
 begin
  try
   try
    inc(i);
   finally
    dec(i);
   end;
  except
   on E:Exception do BugReport(E,nil,'TestIncDec3');
  end;
 end;
 procedure TestIncDec4(var i:Integer);
 begin
  try
   Latch.Lock;
   try
    inc(i);
    dec(i);
   finally
    Latch.UnLock;
   end;
  except
   on E:Exception do BugReport(E,nil,'TestIncDec3');
  end;
 end;
begin
 writeln('Try/finally/except benchmark:');
 Latch:=NewLatch;
 try
  //
  n:=0; m:=0; ms:=GetTickCount64;
  while (GetTickCount64-ms<Delay) do begin
   TestIncDec0(m); TestIncDec0(m); TestIncDec0(m); TestIncDec0(m);  TestIncDec0(m);
   TestIncDec0(m); TestIncDec0(m); TestIncDec0(m); TestIncDec0(m);  TestIncDec0(m);
   inc(n,10);
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('Simple call: %g ns/call',[ms*1e6/n]));
  //
  n:=0; m:=0; ms:=GetTickCount64;
  while (GetTickCount64-ms<Delay) do begin
   TestIncDec1(m); TestIncDec1(m); TestIncDec1(m); TestIncDec1(m);  TestIncDec1(m);
   TestIncDec1(m); TestIncDec1(m); TestIncDec1(m); TestIncDec1(m);  TestIncDec1(m);
   inc(n,10);
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('Try/Finally call: %g ns/call',[ms*1e6/n]));
  //
  n:=0; m:=0; ms:=GetTickCount64;
  while (GetTickCount64-ms<Delay) do begin
   TestIncDec2(m); TestIncDec2(m); TestIncDec2(m); TestIncDec2(m);  TestIncDec2(m);
   TestIncDec2(m); TestIncDec2(m); TestIncDec2(m); TestIncDec2(m);  TestIncDec2(m);
   inc(n,10);
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('Try/Except call: %g ns/call',[ms*1e6/n]));
  //
  n:=0; m:=0; ms:=GetTickCount64;
  while (GetTickCount64-ms<Delay) do begin
   TestIncDec3(m); TestIncDec3(m); TestIncDec3(m); TestIncDec3(m);  TestIncDec3(m);
   TestIncDec3(m); TestIncDec3(m); TestIncDec3(m); TestIncDec3(m);  TestIncDec3(m);
   inc(n,10);
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('Try/Finally/Except call: %g ns/call',[ms*1e6/n]));
  //
  n:=0; m:=0; ms:=GetTickCount64;
  while (GetTickCount64-ms<Delay) do begin
   TestIncDec4(m); TestIncDec4(m); TestIncDec4(m); TestIncDec4(m);  TestIncDec4(m);
   TestIncDec4(m); TestIncDec4(m); TestIncDec4(m); TestIncDec4(m);  TestIncDec4(m);
   inc(n,10);
  end;
  ms:=GetTickCount64-ms;
  writeln(Format('Try/Finally/Except/Lock/Unlock call: %g ns/call',[ms*1e6/n]));
 finally
  Latch.Free;
 end;
end;

procedure TFormCrwTestBench.ButtonCrwEeTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_ee '+ButtonCrwEeTest1.Caption);
  writeln(ExpressionEvaluatorBenchmark(1000000));
  BenchmarkTryExceptFinally(1000);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEeTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwEeSysEvalClick(Sender: TObject);
var ans:Double; com:LongString;
begin
 try
  AddLog(Now,'SysEval '+EditCrwEeExpression.Text);
  if (SystemCalculator.Evaluate(EditCrwEeExpression.Text,ans,com)=ee_Ok)
  then writeln(Format('%g  %.16g',[ans,ans]))
  else writeln(com);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwEeSysEvalClick');
 end;
end;

procedure PrintCurve(crv:TCurve);
begin
 writeln(crv.Name,' = Curve ',crv.Count,' ',crv.Step,' ',ColorToString(crv.Color),' ',crv.Style and 15,' ',crv.Style shr 4);
 if crv.Comment.Count>0 then writeln(crv.Comment.text);
end;

procedure TFormCrwTestBench.ButtonCrwCurvesTest1Click(Sender: TObject);
var crvlist:TCurveList; txt:TText; i:Integer; crv:TCurve;
begin
 try
  AddLog(Now,'_crw_curves '+ButtonCrwCurvesTest1.Caption);
  crvlist:=ReadCurveList(NewCurveList,HomeDir+'/Curves.cfg','[datastorage]');
  txt:=crvlist.GetList(NewText);
  write(txt.Text);
  for i:=0 to crvlist.Count-1 do PrintCurve(crvlist[i]);
  Kill(txt);
  Kill(crvlist);
  crv:=NewCurve(0,'Test');
  for i:=1 to 10 do crv.AddPoint(i,i*i);
  crv.InsertPoint(0,0,0);
  for i:=0 to crv.Count-1 do writeln(Format('%g %g',[crv.XY[i].x,crv.XY[i].y]));
  Kill(crv);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwCurvesTest1Click');
 end;
end;

procedure Init_Thermocouple_SubSystem;
var p:TText; i:Integer;
begin
 //UpdateStatusLine(RusEng('Инициализирую термопары...','Initialize thermocouples...'));
 DebugOut(stdfDebug,'');
 DebugOut(stdfDebug,'Init thermocouples.');
 DebugOut(stdfDebug,'*******************');
 if ThermoCoupleCount=0 then InitCouples(SysIniFile,'[DataBase]','ThermoCouples',stdfDebug);
 if ThermoCoupleCount>0 then begin
  DebugOut(stdfDebug,'Ok.');
  Echo(RusEng('Таблицы термопар : Прочитаны.','Thermocouple tables : Ok.'));
  CalibTransformList.InitThermocouples;
 end else begin
  DebugOut(stdfDebug,'Fails.');
  Echo(RusEng('Таблица термопар : Сбой.','Thermocouple table : Fails.'));
 end;
 //UpdateStatusLine(RusEng('Инициализирую калибровки...','Initialize relationships...'));
 DebugOut(stdfDebug,'');
 DebugOut(stdfDebug,'Init relationships.');
 DebugOut(stdfDebug,'*******************');
 if RelationshipCount=0 then InitRelationShips(SysIniFile,'[DataBase]','Relationships',stdfDebug);
 if RelationshipCount>0 then begin
  DebugOut(stdfDebug,'Ok.');
  Echo(RusEng('Таблицы калибровок : Прочитаны.','Calibration tables : Ok.'));
  CalibTransformList.InitRelations;
 end else begin
  DebugOut(stdfDebug,'Fails.');
  Echo(RusEng('Таблицы калибровок : Сбой.','Calibration tables : Fails.'));
 end;
 p:=NewText;
 p.Text:=CalibTransformList.Text;
 DebugOut(stdfDebug,RusEng(EOL+'Список доступных типов калибровок:'+EOL+
                                '**********************************',
                           EOL+'List of available calibration tables:'+EOL+
                                '*************************************'));

 for i:=0 to p.Count-1 do DebugOut(stdfDebug,p[i]);
 Kill(p);
 FreeConfigCache(0);
end;

function CheckDimDll(fname:LongString):Boolean;
var lib:HModule;
begin
 Result:=false;
 lib:=SafeLoadLibrary(fname);
 if (lib<>0) then
 try
  if GetProcAddress(lib,'dim_init')=nil then Exit;
  Result:=true;
 finally
  FreeLibrary(lib);
 end;
end;

procedure TFormCrwTestBench.ButtonCrwCalibTest1Click(Sender: TObject);
var fcal:LongString; cal:TPolynomCalibration; i:Integer;
begin
 try
  if ThermoCoupleCount=0 then Init_Thermocouple_SubSystem;
  AddLog(Now,'_crw_calib '+ButtonCrwCalibTest1.Caption);
  fcal:=HomeDir+'/../crwdaq/resource/daqsite/stdlib/calibr/_HRAL.cal';
  fcal:=HomeDir+'/_HRAL.cal';
  cal:=NewCalibrationSmartLoadFromFile(fcal);
  writeln(CalibTransformList.Count,' calibration(s)');
  for i:=0 to CalibTransformList.Count-1 do writeln(CalibTransformList[i].Descr);
  writeln(fcal,' ',cal.SaveToFile(HomeDir+'/hral.cal'));
  writeln(StringFromFile(HomeDir+'/hral.cal',0));
  writeln(Format('%.16g %.16g',[cal.GetY(-6.458,0),cal.GetY(54.875,0)]));
  Kill(cal);
  writeln('dim ',CheckDimDll('libdim.so'));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwCalibTest1Click');
 end;
end;

var
 dns_version  : Integer = 0;                // To receive DNS version
 no_link      : Integer = -1;               // To mark "server die" event.

 //
 // Callback on receive DNS version
 //
procedure on_got_dns_version(var tag:TDimLong; buff:Pointer; var size:Integer); cdecl;
begin
 try
  if (size=SizeOf(no_link)) and (Integer(buff^) = no_link) then begin
   writeln('DNS server is dead. Please restart DNS.EXE.');
   dns_version:=no_link;
   Exit;
  end;
  if size=SizeOf(dns_version) then begin
   writeln(Format('Got DNS version: %d, tag:%d',[Integer(buff^),tag]));
   dns_version:=Integer(buff^);
   Exit;
  end;
  writeln(Format('Invalid data size: %d, tag:%d',[size,tag]));
  dns_version:=no_link;
 except
  on E:Exception do BugReport(E,nil,'on_got_dns_version');
 end;
end;

procedure TestDim;
var dns_node:array[byte] of char; ms:QWord;
begin
 try
  dim_init; dis_disable_padding; dic_disable_padding; dns_node:='';
  //if dim_get_dns_node(dns_node)=0 then raise Exception.Create('Fail get DNS.');
  if StrLen(dns_node)=0 then dim_set_dns_node('localhost');
  if dim_get_dns_node(dns_node)=0 then raise Exception.Create('Fail get DNS.');
  if StrLen(dns_node)=0 then raise Exception.Create('Fail set DNS.');
  writeln('DIM_DNS_NODE='+dns_node);
  //
  // 2. Subscribe DNS server version to call it only once.
  //
  dns_version:=0;
  dic_info_service('DIS_DNS/VERSION_NUMBER',        // DNS server version service name
                   ONCE_ONLY,                       // Call it only once
                   10,                              // Timeout, seconds
                   nil, 0, on_got_dns_version,      // Callback to receive DNS version
                   1,                               // Tag to identify this service
                   @no_link, SizeOf(no_link));      // Data to send in case of timeout
  ms:=GetTickCount64;
  while (GetTickCount64-ms<1000) and (dns_version=0) do Sleep(10);
  if dns_version>0 then writeln('DIS_DNS version ',dns_version,' is running on ',dns_node);
  if dns_version<=0 then writeln('DIS_DNS is not detected.');
 except
  on E:Exception do BugReport(E,nil,'TestDim');
 end;
end;


procedure TFormCrwTestBench.ButtonCrwDimTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_dim '+ButtonCrwDimTest1.Caption);
  TestDimQueue;
  writeln('LoadDimLibrary ',LoadDimLibrary,' ',LoadDimLibrary('libdim.so'));
  if ValidDimLibrary then TestDim;
  writeln(StringBuffer(5,'*'));
  StdOutPrintLn('StdOutPrintLn');
  writeln('StdIn ',FileTypeToString(GetFileType(GetStdHandle(STD_INPUT_HANDLE))));
  writeln('StdOut ',FileTypeToString(GetFileType(GetStdHandle(STD_OUTPUT_HANDLE))));
  writeln('StdErr ',FileTypeToString(GetFileType(GetStdHandle(STD_ERROR_HANDLE))));
  writeln(Format('CPU ID: %s',[ReadProcCpuInfo(1,'model name')]));
  if cpu_mhz(2)=0 then EastimateCpuFrequencyMHz(1000);
  writeln(Format('CPU %.4g %.4g %.4g MHz',[cpu_mhz(0),cpu_mhz(1),cpu_mhz(2)]));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwDimTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwSmiTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_smi '+ButtonCrwSmiTest1.Caption);
  writeln('LoadSmiRtlLibrary ',LoadSmiRtlLibrary,' ',SmiRtlLibrary.Report);
  writeln('LoadSmiRtlLibrary ',LoadSmiRtlLibrary('libsmi.so'),' ',SmiRtlLibrary.Report);
  writeln('LoadSmiRtlLibrary ',LoadSmiRtlLibrary('/opt/smi/libsmi.so'),' ',SmiRtlLibrary.Report);
  writeln('ValidSmiRtlLibrary = ',ValidSmiRtlLibrary,' ',SmiRtlLibrary.Report);
  writeln('ValidDimLibrary = ',ValidDimLibrary,' ',DimLibrary.Report);
  writeln('LoadSmiuiRtlLibrary ',LoadSmiuiRtlLibrary,' ',SmiuiRtlLibrary.Report);
  writeln('LoadSmiuiRtlLibrary ',LoadSmiuiRtlLibrary('libsmi.so'),' ',SmiuiRtlLibrary.Report);
  writeln('LoadSmiuiRtlLibrary ',LoadSmiuiRtlLibrary('/opt/smi/libsmiui.so'),' ',SmiuiRtlLibrary.Report);
  writeln('ValidSmiuiRtlLibrary = ',ValidSmiuiRtlLibrary,' ',SmiuiRtlLibrary.Report);
  writeln('ValidDimLibrary = ',ValidDimLibrary,' ',DimLibrary.Report);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwSmiTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwSpcfldTest1Click(Sender: TObject);
var i,k:Integer; id,dir:LongString;
begin
 try
  AddLog(Now,'_crw_spcfld '+ButtonCrwSpcfldTest1.Caption);
  writeln('CSIDL_ListAllAsText:',EOL,CSIDL_ListAllAsText);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwSpcfldTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwGuardTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_guard '+ButtonCrwGuardTest1.Caption);
  if (DebugOutGetFile(stdfDebug)='') then begin
   DebugOutOpenFile(stdfDebug,AddPathDelim(TempDir)+'debugout.log',1024*64,50,true,true);
   writeln('DebugOutGetFile '+DebugOutGetFile(stdfDebug));
  end;
  Guard.Startup;
  writeln('Password ',Guard.WritePassword(ga_Root,'root'),' ',Guard.ReadPassword(ga_Root));
  writeln('Guard.IniFile = ',Guard.IniFile);
  writeln('Guard.TrustList:',EOL,Guard.TrustList);
  writeln(Guard.Check(ga_Root),' ',Guard.Check(ga_User));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwGuardTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwSpkTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_spk '+ButtonCrwSpkTest1.Caption);
  writeln('SpeechApiInstalled = ',SpeechApiInstalled);
  Speaker.Engine:=0;
  writeln('Engines: ',StringReplace(Trim(Speaker.Engines.Text),EOL,',',[rfReplaceAll]));
  Speaker.Wait:=true;
  Speaker.Speak:='Привет, Мир.';
  Speaker.Pitch:=50; Speaker.Rate:=-50; Speaker.Volume:=-50;
  Speaker.Speak:='Привет, Мир.';
  Speaker.Engine:=1;
  //Speaker.Pitch:=0; Speaker.Rate:=0; Speaker.Volume:=0;
  Speaker.Speak:='Привет, Мир.';
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwSpkTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwPioTest1Click(Sender: TObject);
begin
 try
  AddLog(Now,'_crw_pio '+ButtonCrwPioTest1.Caption);
  writeln('Permit $61 ',IOPM_Permit($61,1,true));
  writeln('Permit $42 ',IOPM_Permit($42,2,true));
  writeln('IOPM_CheckIO ',IOPM_CheckIO);
  Sound(1000,1000); PlayGreetingSound;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwPioTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwRegexpTest1Click(Sender: TObject);
var prex:TPerlRegEx; rex:Integer;
begin
 try
  AddLog(Now,'_crw_regexp '+ButtonCrwRegexpTest1.Caption);
  writeln('LoadPCRE ',LoadPCRE,' ',IsPCRELoaded);
  prex:=TPerlRegEx.Create;
  prex.RegEx:='[0-9]';
  prex.Subject:='querty 123 456';
  writeln(prex.Match,' ',prex.SubExpressionCount);
  prex.Free;
  rex:=regexp_init(0,'/[0-9]+/igm');
  writeln(regexp_exec(rex,'querty 123 456'));
  writeln(regexp_matchnum(rex,0),' ',regexp_matchpos(rex,1,0),' ',regexp_matchlen(rex,1,0),' ',regexp_matchstr(rex,1,0));
  writeln(regexp_matchnum(rex,0),' ',regexp_matchpos(rex,2,0),' ',regexp_matchlen(rex,2,0),' ',regexp_matchstr(rex,2,0));
  regexp_free(rex);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwRegexpTest1Click');
 end;
end;

var serPort:TSerialHandle=0; serCount:Integer=0;

procedure serPolling;
begin
 Inc(serCount);
 SerWriteStr(serPort,StdDateTimeStr(mSecNow)+': '+IntToStr(serCount)+EOL);
 write(SerReadStr(serPort,255));
 if (serCount=10) then begin
  SecondActions.Remove(serPolling);
  SerClose(serPort);
  serCount:=0;
 end;
end;

procedure SerTestParams;
var p,pt:TSerParityType; s:LongString; iw,br:Integer;
begin
 for p:=Low(p) to High(p) do begin
  s:=SerParityTypeToString(p,false); pt:=p;
  writeln(Ord(p),' ',s,' ',Ord(SerStringToParityType(s)),' ',SerTryStringToParityType(s,pt));
  s:=SerParityTypeToString(p,true); pt:=p;
  writeln(Ord(p),' ',s,' ',Ord(SerStringToParityType(s)));
  s:=Copy(SerParityTypeToString(p,false),1,1);
  writeln(Ord(p),' ',s,' ',Ord(SerStringToParityType(s)));
 end;
 for iw:=1 to WordCount(SerListValidBaudRate,SerDelims) do begin
  s:=ExtractWord(iw,SerListValidBaudRate,SerDelims);
  writeln(s,' ',SerTryStringToBaudRate(s,br),' ',br,' ',SerBaudRateToString(br),' ',SerStringToBaudRate(s));
 end;
end;

procedure TFormCrwTestBench.ButtonCrwSerioTest1Click(Sender: TObject);
var s:TSerialState; l:LongWord;
begin
 try
  AddLog(Now,'_crw_serio '+ButtonCrwSerioTest1.Caption);
  writeln(ReadProcTtyDriversSerial);
  writeln(SerPortSearchList);
  writeln('GetSerialPortNames ',GetSerialPortNames(spnm_DelimText,','));
  writeln('SerPortMap.ListNames ',SerPortMap.ListBaseNames(','));
  writeln('SerPortMap.ListPaths ',SerPortMap.ListPathNames(','));
  writeln(TrimRight(SerPortMap.Table));
  writeln(SerPortMap.PortNum('COM1'));
  writeln(SerPortMap.PortNum('ttyUSB1'));
  writeln(SerPortMap.PortNum('/dev/ttyUSB1'));
  SerClose(serPort);
  serPort:=SerOpen(SerPortMap.PathName[1],O_SERNOBLK);
  writeln('Open ',SerPortMap.PathName[1],' ',SerGetParamsAsString(serPort));
  //writeln(serSetParams(serPort,115200,8,NoneParity,ONESTOPBIT,[]));
  writeln(serSetParams(serPort,'baudrate 115200 databits 8 parity None stopbits 1'));
  writeln('Set ',SerPortMap.PathName[1],' ',SerGetParamsAsString(serPort));
  //s:=SerSaveState(serPort); writeln('Speed ',cfgetispeed(s.tios));
  SecondActions.Add(serPolling);
  SerTestParams;
  //if SerGetLineState(serPort,l) then writeln('line ',hexl(l));
  writeln('detect_wine_host = ',detect_wine_host);
  writeln('detect_vbox_host = ',detect_vbox_host,' ',detect_vbox_string);
  writeln(EnumComPorts(','));
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwSerioTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwUartTest1Click(Sender: TObject);
var ask,ans:ShortString; ms:QWord; i,pn:Integer; p:TText; s,lng,fbk:String;
begin
 try
  AddLog(Now,'_crw_uart '+ButtonCrwUartTest1.Caption);
  writeln('EnumComPorts = '+EnumComPorts(','));
  pn:=1;
  uart[pn].Open(115200);
  for i:=1 to 10 do begin
   ask:='$01M'+ASCII_CR;
   ms:=GetTickCount64;
   ans:=uart[pn].ModalAnswerRequest(ask,250);
   ms:=GetTickCount64-ms;
   writeln('Ask ',ask,' Ans ',ans,' delay ',ms,' ms');
  end;
  p:=uart[pn].GetProperties(NewText);
  writeln(p.Text); Kill(p);
  uart[pn].Close;
  writeln('GetCommandLine = '+GetCommandLine);
  GetLanguageIDs(lng,fbk); writeln('LangIDs = ',lng,' Fallback = ',fbk);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwUartTest1Click');
 end;
end;

procedure TFormCrwTestBench.BitBtnCrwSysIdTest1Click(Sender: TObject);
var i:Integer; sw:LongString;
begin
 try
  AddLog(Now,'_crw_sysid '+BitBtnCrwSysIdTest1.Caption);
  Init_CpuFrequencyMHz;
  EchoBriefSystemInfo;
  writeln('GetSystemVersionString  = '+GetSystemVersionString);
  writeln('CPU ~MHz                = '+GetCpuVersionInfo(0,'~MHz'));
  writeln('CPU ProcessorNameString = '+GetCpuVersionInfo(0,'ProcessorNameString'));
  writeln('CPU VendorIdentifier    = '+GetCpuVersionInfo(0,'VendorIdentifier'));
  writeln('CPU Identifier          = '+GetCpuVersionInfo(0,'Identifier'));
  writeln('GetCpuFreqMHzNominal    = ',GetCpuFreqMHzNominal(0));
  for i:=1 to WordCount(MemInfoNameList,ScanSpaces) do begin
   sw:=ExtractWord(i,MemInfoNameList,ScanSpaces);
   writeln(sw:20,' = ',ReadProcMemInfo(sw));
  end;
  {$IFDEF UNIX}
  for i:=1 to WordCount(ReadSysDevicesVirtualDmiId('?'),ScanSpaces) do begin
   sw:=ExtractWord(i,ReadSysDevicesVirtualDmiId('?'),ScanSpaces);
   writeln(sw:20,' = ',ReadSysDevicesVirtualDmiId(sw));
  end;
  {$ENDIF ~UNIX}
  writeln('GetProcessStartTimeAsFileTime ',GetProcessStartTimeAsFileTime);
  writeln('GetProcessStartTimeAsFileTime ',StdDateTimeStr(FileTimeToMs(GetProcessStartTimeAsFileTime)));
  writeln('GetDieselPascalExe = ',GetDieselPascalExe,' ',HasDieselPascalExe);
  writeln('Modules:',EOL,GetListOfModulesAsText);
  writeln('which cmd.exe = ',file_which('cmd.exe'));
  writeln('which bash = ',file_which('bash'));
 except
  on E:Exception do BugReport(E,Self,'BitBtnCrwSysIdTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwWmctrlTest1Click(Sender: TObject);
var i:Integer; win:HWND;
begin
 try
  AddLog(Now,'_crw_wmctrl '+BitBtnCrwSysIdTest1.Caption);
  for i:=0 to 6 do writeln(GetListOfWindows(0,'','',i));
  for i:=0 to 6 do writeln(GetListOfWindows(GetCurrentProcessId,'','',i));
  for i:=0 to 6 do writeln(GetListOfWindows(0,'conky.conky','',i));
  for i:=0 to 6 do writeln(GetListOfWindows(0,'','conky (y510p)',i));
  writeln('wmctrl_get_active_window = ',wmctrl.ActiveWindow);
  writeln('numdesktops = ',wmctrl.DesktopCount);
  writeln('active desk = ',wmctrl.ActiveDesktop);
  //writeln(wmctrl_switch_desktop(nil,0));
  win:=FindWindowByPidClassTitle(0,'','KCalc');
  writeln('state = ',wmctrl.WindowStateList(win),' ',wmctrl.WindowStateFlags(win));
  writeln('activate ',win,' ',wmctrl.ActivateWindow(win));
  writeln('winbounds = ',RectToStr(wmctrl.WindowBounds(win)),' size '+PointToStr(RectSize(wmctrl.WindowBounds(win))));
  writeln('MoveResize = ',wmctrl.MoveResizeWindow(win,'0,200,300'));
  Sleep(100);
  writeln('winbounds = ',RectToStr(wmctrl.WindowBounds(win)),' size '+PointToStr(RectSize(wmctrl.WindowBounds(win))));
  writeln('MoveResize = ',wmctrl.MoveResizeWindow(win,'0,*,*,770,480'));
  Sleep(100);
  writeln('winbounds = ',RectToStr(wmctrl.WindowBounds(win)),' size '+PointToStr(RectSize(wmctrl.WindowBounds(win))));
  writeln('state = ',wmctrl.WindowStateList(win),' ',wmctrl.WindowStateFlags(win));
  writeln('types = ',wmctrl.WindowTypeList(win),' ',wmctrl.WindowTypeFlags(win));
  Sleep(1000);
  writeln('maxi ',wmctrl.WSFToStr(wmctrl.SetWindowStateFlags(win,WSC_ADD,WSF_MAXIMIZED)));
  Sleep(1000);
  writeln('maxi ',wmctrl.WSFToStr(wmctrl.SetWindowStateFlags(win,WSC_REMOVE,WSF_MAXIMIZED)));
  Sleep(1000);
  writeln('maxi ',wmctrl.WSFToStr(wmctrl.SetWindowStateFlags(win,WSC_ADD,WSF_HIDDEN)));
  win:=wmctrl.FindWindow(0,'','Таблица символов');
  writeln('close ',win,' ',wmctrl.CloseWindow(win));
  writeln('kill ',win,' ',wmctrl.KillWindow(win,0,100));
  writeln('wmctrl_get_supported_list ',wmctrl.SupportedList);
  writeln('window manager = ',wmctrl.WindowManagerName);
  writeln('xlibinfo = ',wmctrl.XLibInfo);
  writeln('display = ',wmctrl.DisplayInfo);
  wmctrl.CloseDisplay;
  writeln('balance = ',wmctrl.DisplayBalance);
 except
  on E:Exception do BugReport(E,Self,'BitBtnCrwSysIdTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonMenuBoxTestClick(Sender: TObject);
var s:LongString; i:Integer;
begin
 try
  Language:=lng_Russian;
  s:='';
  s:=s+'@set Panel.Font   Name:PT_Mono\Size:12\Color:Blue\Style:[Regular]'+EOL;
  s:=s+'@set ListBox.Font Name:PT_Mono\Size:16\Color:Black\Style:[Bold]'+EOL;
  //s:=s+'@set Form.Left    40  relative Screen'+EOL;
  //s:=s+'@set Form.Top     40  relative Desktop'+EOL;
  //s:=s+'@set Form.Left    40  relative '+GetMainFormTitle+EOL;
  //s:=s+'@set Form.Top     40  relative '+GetMainFormTitle+EOL;
  s:=s+'@set Form.Left    20  relative '+GetMainFormTitle+' ButtonMenuBoxTest'+EOL;
  s:=s+'@set Form.Top     25  relative '+GetMainFormTitle+' ButtonMenuBoxTest'+EOL;
  s:=s+'@set Form.Width   300'+EOL;
  s:=s+'@set Form.Height  200'+EOL;
  //s:=s+'@set Form.Width   80  relative Screen'+EOL;
  //s:=s+'@set Form.Height  50  relative Desktop'+EOL;
  i:=ListBoxMenu('ListBoxMenu Caption','The Title','Line1'+EOL+'Line2',0,s);
  writeln('ListBoxMenu = ',i);
 except
  on E:Exception do BugReport(E,Self,'ButtonMenuBoxTestClick');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwCalcTest1Click(Sender: TObject);
var i:Integer;
begin
 try
  Language:=lng_Russian;
  i:=ExecuteCalculator;
  writeln('Calculator = ',i);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwCalcTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwWarningTest1Click(Sender: TObject);
var i:Integer; s:LongString;
begin
 try
  Language:=lng_Russian;
  s:='';
  s:=s+'@set Form.Font   Name:PT_Mono\Size:12\Color:Blue\Style:[Regular]'+EOL;
  s:=s+'@set Form.Left    140 relative Screen'+EOL;
  s:=s+'@set Form.Top     40  relative Desktop'+EOL;
  i:=Warning('Test message.',s);
  writeln('warning = ',i);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwWarningTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwVoicePresetTest1Click(Sender: TObject);
begin
 try
  Language:=lng_Russian;
  AddLog(Now,'Form_VoicePreset '+ButtonCrwVoicePresetTest1.Caption);
  if UsesBlaster or InitBlaster(0,HomeDir+'/../crwdaq/resource/sound')
  then writeln('Sound initialized');
  SetBlasterVolume(0.7,0.7);
  SetBlasterSpeed(1.0);
  Voice('ПРИВЕТ 12345');
  Voice('Чпок Чик wheel Click ');
  writeln('FormVoicePresetExecute = ',FormVoicePresetExecute);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwVoicePresetTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwUartTerminalTest1Click(Sender: TObject);
begin
 try
  Language:=lng_Russian;
  AddLog(Now,'Form_UartTerminal '+ButtonCrwUartTerminalTest1.Caption);
  ExecuteUartTerminal;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwUartTerminalTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwCheckListMenuTestClick(Sender: TObject);
var s:LongString; i:Integer;
begin
 try
  Language:=lng_Russian;
  s:='';
  s:=s+'@set Panel.Font   Name:PT_Mono\Size:12\Color:Blue\Style:[Regular]'+EOL;
  s:=s+'@set ListBox.Font Name:PT_Mono\Size:16\Color:Black\Style:[Bold]'+EOL;
  //s:=s+'@set Form.Left    40  relative Screen'+EOL;
  //s:=s+'@set Form.Top     40  relative Desktop'+EOL;
  s:=s+'@set Form.Left    20  relative '+GetMainFormTitle+' ButtonCrwCheckListMenuTest'+EOL;
  s:=s+'@set Form.Top     25  relative '+GetMainFormTitle+' ButtonCrwCheckListMenuTest'+EOL;
  s:=s+'@set Form.Width   300'+EOL;
  s:=s+'@set Form.Height  200'+EOL;
  i:=CheckListBoxMenu('CheckListBoxMenu Caption','The Title','Line1'+EOL+'Line2'+EOL+'Line3',0,s);
  writeln('CheckListBoxMenu = ',i);
  writeln('CheckListBoxMultiSelection = ',CheckListBoxMultiSelection('CheckListBoxMultiSelection','The Title','Line1'+EOL+'Line2'+EOL+'Line3',false,false,0,0,s));
 except
  on E:Exception do BugReport(E,Self,'ButtonMenuBoxTestClick');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwTextEditDialogTestClick(Sender: TObject);
var s,e:LongString; i:Integer;
begin
 try
  Language:=lng_Russian; i:=0;
  s:='';
  s:=s+'@set Panel.Font   Name:PT_Mono\Size:12\Color:Blue\Style:[Regular]'+EOL;
  s:=s+'@set Editor.Font Name:PT_Mono\Size:16\Color:Black\Style:[Bold]'+EOL;
  //s:=s+'@set Form.Left    40  relative Screen'+EOL;
  //s:=s+'@set Form.Top     40  relative Desktop'+EOL;
  //s:=s+'@set Form.Left    40  relative '+GetMainFormTitle+EOL;
  //s:=s+'@set Form.Top     40  relative '+GetMainFormTitle+EOL;
  s:=s+'@set Form.Left    20  relative '+GetMainFormTitle+' ButtonCrwTextEditDialogTest'+EOL;
  s:=s+'@set Form.Top     25  relative '+GetMainFormTitle+' ButtonCrwTextEditDialogTest'+EOL;
  s:=s+'@set Form.Width   300'+EOL;
  s:=s+'@set Form.Height  200'+EOL;
  //s:=s+'@set Form.Width   80  relative Screen'+EOL;
  //s:=s+'@set Form.Height  50  relative Desktop'+EOL;
  e:=TextEditDialog('TextEditDialog Caption','The Title','Line1'+EOL+'Line2'+EOL+'Line3',s,@i);
  writeln('TextEditDialog = ',i,EOL,e);
 except
  on E:Exception do BugReport(E,Self,'ButtonMenuBoxTestClick');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwStringGridEditDialogClick(Sender: TObject);
var s,e:LongString; i:Integer;
begin
 try
  Language:=lng_Russian; i:=0;
  s:='';
  s:=s+'@set Panel.Font   Name:PT_Mono\Size:12\Color:Blue\Style:[Regular]'+EOL;
  s:=s+'@set StringGrid.Font Name:PT_Mono\Size:16\Color:Black\Style:[Bold]'+EOL;
  s:=s+'@set Form.Left    20  relative '+GetMainFormTitle+' ButtonCrwStringGridEditDialog'+EOL;
  s:=s+'@set Form.Top     25  relative '+GetMainFormTitle+' ButtonCrwStringGridEditDialog'+EOL;
  e:='Property to Edit:|DemoText';
  i:=ExecuteFormStringGridEditDialog('StringGridEdit Caption',e,'|',0,1,false,s);
  writeln('StringGridEdit = ',i,EOL,e);
 except
  on E:Exception do BugReport(E,Self,'ButtonMenuBoxTestClick');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwLoginDialogTestClick(Sender: TObject);
var usr,dom,psw:LongString; i:Integer;
begin
 try
  Language:=lng_Russian;
  usr:=UserName; dom:=HostName; psw:='';
  i:=FormLoginDialogExecute('LoginDialog Caption',usr,dom,psw,-1);
  writeln('StringGridEdit = ',i,EOL,usr,' ',dom,' ',psw);
 except
  on E:Exception do BugReport(E,Self,'ButtonMenuBoxTestClick');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwRecodeTest1Click(Sender: TObject);
var i:Integer;
begin
 try
  Language:=lng_Russian;
  i:=FormRecodeCodePageDialogExecute;
  writeln('RecodeCodePageDialog = ',i);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwRecodeTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwRegExpCalcTestClick(Sender: TObject);
var i:Integer;
begin
 try
  Language:=lng_Russian;
  i:=ExecuteRegExpCalculator;
  writeln('RegExpCalculator = ',i);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwRegExpCalcTestClick');
 end;
end;

function TFormCrwTestBench.DoShmOp(op:Char; Mode:Integer):LongString;
var typ,offs:Integer; ans,data:LongString;
begin
 Result:='';
 try
  if not Assigned(shm_ref(shm)) then Exit;
  typ:=RadioGroupShmAsType.ItemIndex+1;
  offs:=SpinEditShmOffset.Value;
  data:=EditShmData.Text;
  ans:='';
  case typ of
   1: ans:=Format('%d',[shm_iop(shm,offs,op,StrToIntDef(data,0))]);
   2: ans:=Format('%g',[shm_rop(shm,offs,op,StrToFloatDef(data,0))]);
   3: ans:=Format('%s',[shm_sop(shm,offs,op,data)]);
   else Exit;
  end;
  Result:=ans;
  if HasFlags(Mode,1)  then begin
   if Pos(op,'rR')>0 then writeln('Read[',shm_ref(shm).Name,',',offs,']: '+ans);
   if Pos(op,'++')>0 then writeln('Plus[',shm_ref(shm).Name,',',offs,']: '+ans);
   if Pos(op,'--')>0 then writeln('Minus[',shm_ref(shm).Name,',',offs,']: '+ans);
   if Pos(op,'wW')>0 then writeln('Write[',shm_ref(shm).Name,',',offs,']: '+Data,EOL,'Reply ',ans);
  end;
  if HasFlags(Mode,1)  then begin
   writeln('shm_ioresult: ',shm_ioresult,' shm_total_errors: ',shm_ctrl(shm,'shm_total_errors'));
  end;
 except
  on E:Exception do BugReport(E,Self,'DoShmOp');
 end;
end;

procedure TFormCrwTestBench.TimerShmTimer(Sender: TObject);
begin
 EditShmMonitor.Text:=DoShmOp('R',0);
end;

procedure TFormCrwTestBench.ButtonShmListClick(Sender: TObject);
var cmd,ans,fln:LongString;
begin
 writeln('PathName = ',shm_ctrl(shm,'PathName'));
 if IsUnix then
 try
  cmd:='ls /dev/shm';
  if RunCommand(cmd,ans) then writeln(Trim(cmd+EOL+ans));
  fln:='/dev/shm/'+Trim(EditShmName.Text);
  cmd:='cat '+fln;
  if FileExists(fln) then
  if RunCommand(cmd,ans) then writeln(Trim(cmd+EOL+ans));
 except
  on E:Exception do BugReport(E,Self,'ButtonShmListClick');
 end;
end;

procedure TFormCrwTestBench.ButtonShmOpenClick(Sender: TObject);
begin
 try
  Language:=lng_Russian;
  if (shm=0) then begin
   shm:=shm_init(Trim(EditShmName.Text),SpinEditShmSize.Value,0);
   if (shm<>0) then begin
    ButtonShmOpen.Caption:='Kill shm';
    writeln('Shared memory opened '+shm_ref(shm).Name,' ',shm_ref(shm).Size);
    if IsUnix then ButtonShmListClick(ButtonShmList);
   end else writeln('Could not open SharedMemory');
   writeln('Shm Size:',shm_ref(shm).Size,
           ' Capacity:',shm_ref(shm).Capacity,
           ' Page:',shm_ref(shm).SysPageSize);
  end else begin
   ButtonShmOpen.Caption:='Open shm';
   writeln('Close shared memory '+shm_ref(shm).Name,' ',shm_ref(shm).Size);
   writeln('shm_total_errors ',shm_ctrl(shm,'shm_total_errors=0'));
   KillSharMem;
  end;
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwRegExpCalcTestClick');
 end;
end;

procedure TFormCrwTestBench.ButtonShmGetClick(Sender: TObject);
begin
 DoShmOp('R',1);
end;

procedure TFormCrwTestBench.ButtonShmInfoClick(Sender: TObject);
begin
 if (shm<>0) then begin
  writeln(StringReplace(Trim(shm_ctrl(shm,'*')),EOL,',',[rfReplaceAll]));
  writeln(shm_ctrl(shm,'?'));
 end;
end;

procedure TFormCrwTestBench.ButtonShmPutClick(Sender: TObject);
begin
 DoShmOp('W',1);
end;

procedure TFormCrwTestBench.ButtonShmSubClick(Sender: TObject);
begin
 DoShmOp('-',1);
end;

procedure TFormCrwTestBench.ButtonShmAddClick(Sender: TObject);
begin
 DoShmOp('+',1);
end;

const xtidLoop:SizeInt=0;
procedure HandleXTid;
var ans:LongString;
begin
 if Assigned(FormCrwTestBench) then
 with FormCrwTestBench do
 if (xtid<>0) then
 try
  inc(xtidLoop);
  task_send(xtid,StdDateTimePrompt(mSecNow)+' '+IntToStr(xtidLoop)+EOL+'  ');
  ans:=task_recv(xtid,MaxInt);
  if (ans<>'') then Echo(ans);
 except
  on e:Exception do BugReport(E,nil,'HandleXTid');
 end;
end;

procedure TFormCrwTestBench.ButtonCrwTaskTest1Click(Sender: TObject);
var tid:Integer; cmd,ans:LongString; ms,me,mr:Int64;
begin
 try
  AddLog(Now,'_crw_task '+ButtonCrwTaskTest1.Caption);
  writeln('PidAffinity = ',PidAffinity(0));
  writeln('PidAffinity = ',PidAffinity(0,1));
  writeln('PidAffinity = ',PidAffinity(0,-1));
  cmd:='cat';
  cmd:='cat /opt/crwlib/_crw_crypt.pas';
  cmd:='find /usr/share/pixmaps/';
  cmd:='find /usr/share';
  cmd:='seq 500000';
  cmd:='seq 50';
  //cmd:='ls -al /';
  if IsWindows then cmd:='cmd /k dir c:\';
  tid:=task_init(cmd);
  task_ctrl(tid,'Display=1');
  //task_ctrl(tid,'StdInPipeSize=4096');
  task_ctrl(tid,'StdOutPipeSize=4096');
  task_ctrl(tid,'StdOutPipeLimit='+IntToStr(1024*1024*32));
  task_ctrl(tid,'StdOutPriority=tpHigher');
  task_ctrl(tid,'StdInpPriority=tpLower');
  if IsWindows then task_ctrl(tid,'CodePage=866');
  ms:=GetTickCount64;
  if task_run(tid) then begin
   //task_send(tid,'Hello,World!'+EOL);
   task_wait(tid,1000);
   me:=GetTickCount64-ms;
   //Sleep(1000);
   //writeln(task_ctrl(tid,'rxsync=100'));
   //writeln(SortTextLines(task_ctrl(tid,'?')));
   ans:=task_recv(tid,MaxInt);
   mr:=GetTickCount64-ms;
   writeln(ans);
   if IsWindows then task_send(tid,'exit'+EOL);
  end;
  writeln(SortTextLines(task_ctrl(tid,'?')));
  writeln('execution time ',me,', ',mr,' ms');
  task_free(tid);
  writeln('DM List = ',wmctrl.ListDesktopManagers(','));
  writeln('DM Sess = ',wmctrl.DesktopManager);
  writeln('Term List = ',wmctrl.ListTerminals(','));
  writeln('Term Curr = ',wmctrl.Terminal);
  writeln('term ',GetRealFilePathName(file_which('x-terminal-emulator')));
  if (xtid<>0) then begin task_free(xtid); xtid:=0; end;
  cmd:='unix cat'; // cmd:=file_which('unix')+' cat';
  xtid:=task_init(cmd);
  task_ctrl(xtid,'StdInPipeSize=4096');
  task_ctrl(xtid,'StdOutPipeSize=4096');
  task_ctrl(xtid,'StdErrPipeSize=4096');
  task_ctrl(xtid,'StdOutPipeLimit='+IntToStr(1024*1024*32));
  task_ctrl(xtid,'ProcessPriority=Higher');
  task_ctrl(xtid,'StdOutPriority=tpHighest');
  task_ctrl(xtid,'StdErrPriority=tpHigher');
  task_ctrl(xtid,'StdInpPriority=tpLower');
  task_run(xtid); task_ctrl(xtid,'?');
  SecondActions.Add(HandleXTid);
 except
  on E:Exception do BugReport(E,Self,'ButtonCrwTaskTest1Click');
 end;
end;

procedure TFormCrwTestBench.ButtonGetNiceClick(Sender: TObject);
var pid,nice:Integer;
begin
 pid:=StrToIntDef(Trim(ComboBoxRenicePid.Text),-1);
 nice:=GetProcessNice(pid);
 if (pid=0) then pid:=GetCurrentProcessId;
 writeln(GetListOfProcesses(pid,0,''));
 writeln('PID ',pid,' has NICE value ',nice);
end;

procedure TFormCrwTestBench.ButtonSetNiceClick(Sender: TObject);
var pid,nice:Integer;
begin
 pid:=StrToIntDef(Trim(ComboBoxRenicePid.Text),-1);
 nice:=StrToIntDef(Trim(ComboBoxReniceValue.Text),0);
 if (pid=0) then pid:=GetCurrentProcessId;
 writeln('renice -n ',nice,' -p ',pid,' - ',SetProcessNice(nice,pid));
 ButtonGetNiceClick(Sender);
end;

procedure TFormCrwTestBench.ButtonPrioTableClick(Sender: TObject);
var i:Integer; p:TPolling;
begin
 writeln('NiceToPP:');
 for i:=MIN_NICE to MAX_NICE do writeln(i:2,' ',ProcessPriorityToString(NiceToProcessPriority(i)));
 writeln('LevelToPP:');
 for i:=1 to 31 do writeln(i:2,' ',ProcessPriorityToString(LevelToProcessPriority(i)));
 writeln('WinPriorityToLevel:');
 writeln(PriorityTableAsText(WindowsPriorityToLevel));
 writeln('SchedOtherPriorityToRLimit:');
 writeln(PriorityTableAsText(SchedOtherPriorityToRLimit));
 writeln('SchedOtherPriorityToNice:');
 writeln(PriorityTableAsText(SchedOtherPriorityToNice));
 //writeln(read_proc_pid_file(0,'status'));
 //writeln(read_proc_pid_file(0,'status','pid,tgid'));
 p:=NewPolling(nil); //p.Enable(true);
 //SetProcessNice(10,p.Tid);
 p.Priority:=tpIdle;
 writeln(p.ThreadID,', ',p.ThreadHandle,', ',p.Tid,' ',ThreadPriorityToString(p.Priority));
 p.Priority:=tpLowest;
 writeln(p.ThreadID,', ',p.ThreadHandle,', ',p.Tid,' ',ThreadPriorityToString(p.Priority));
 p.Priority:=tpLower;
 writeln(p.ThreadID,', ',p.ThreadHandle,', ',p.Tid,' ',ThreadPriorityToString(p.Priority));
 p.Priority:=tpNormal;
 writeln(p.ThreadID,', ',p.ThreadHandle,', ',p.Tid,' ',ThreadPriorityToString(p.Priority));
 p.Priority:=tpHigher;
 writeln(p.ThreadID,', ',p.ThreadHandle,', ',p.Tid,' ',ThreadPriorityToString(p.Priority));
 p.Priority:=tpHighest;
 writeln(p.ThreadID,', ',p.ThreadHandle,', ',p.Tid,' ',ThreadPriorityToString(p.Priority));
 p.Priority:=tpTimeCritical;
 writeln(p.ThreadID,', ',p.ThreadHandle,', ',p.Tid,' ',ThreadPriorityToString(p.Priority));
 Kill(p);
end;

procedure TFormCrwTestBench.ComboBoxForcePrioChange(Sender: TObject);
var sprio:LongString; pp:TProcessPriority;
begin
 sprio:=Trim(ComboBoxForcePrio.Text);
 if IsEmptyStr(sprio) then begin
  SetCurrentProcessPriority(ppNormal);
  SecondActions.Remove(CheckPriorityClass);
  Exit;
 end;
 pp:=StringToProcessPriority(sprio);
 ForceProcessPriority(pp,5000);
 SecondActions.Add(CheckPriorityClass);
end;

procedure DimaPoll;
var Service:TDimService; msg:LongString; i,j:Integer;
begin
 if Assigned(FormCrwTestBench) then with FormCrwTestBench do begin
  if (DimAgent.Pid<>0)
  then msg:='DimAgent: PID '+IntToStr(DimAgent.Pid)+' '+DimAgent.RunningStr
  else msg:='DimAgent: '+DimAgent.RunningStr;
  if (DimAgent.Pid<>0) then msg:=msg+' Code: '+task_ctrl(DimAgent.tid,'ExitCode');
  if (DimAgent.Pid<>0) then msg:=msg+' Cmd: '+task_ctrl(DimAgent.tid,'CmdLine');
  if (DimAgent.Pid<>0) then msg:=msg+' In: '+task_ctrl(DimAgent.tid,'RxTotal');
  GroupBoxCrwDima.Caption:=msg;
  // DimAgent Polling Loop
  DimAgentDemoTesterPoll;
 end;
end;

procedure TestFormParse(s:LongString);
var i:Integer; o:LongString; ac:TDimAccess;
begin
 writeln('FormParse',s);
 ac:=TDimAccess.Create(nil,s);
 writeln(ac.Table);
 ac.Free;
end;

procedure TFormCrwTestBench.ButtonDimaStartClick(Sender: TObject);
var serv:TDimService; i:Integer; dns,task:LongString;
begin
 try
  ComboBoxDimaDns.Text:=TrimDef(ComboBoxDimaDns.Text,'localhost');
  ComboBoxDimaTask.Text:=TrimDef(ComboBoxDimaTask.Text,'DIMTEST');
  dns:=Trim(ComboBoxDimaDns.Text); task:=Trim(ComboBoxDimaTask.Text);
  DimAgentDemoTesterStart(dns,task);
  Tick55Actions.Add(DimaPoll);
  Voice('click');
 except
  on E:Exception do BugReport(E,Self,'ButtonDimaStartClick');
 end;
end;

procedure TFormCrwTestBench.ButtonDimaStopClick(Sender: TObject);
begin
 try
  DimAgentDemoTesterStop;
  TestFormParse('I');
  TestFormParse('C;D;F;I;L;S;X');
  TestFormParse('C;D;F;I;L;S;X;');
  TestFormParse('C:10;D:2;F:1;I:3;L:4;S:3;X');
  TestFormParse('C:10;D:2;F:1;I:3;L:4;S:3;X;');
 except
  on E:Exception do BugReport(E,Self,'ButtonDimaStopClick');
 end;
end;

var
 spipe:TPipe=nil;
 cpipe:TPipe=nil;

procedure KillPipes;
begin
 Kill(spipe);
 Kill(cpipe);
end;

procedure PipePolling;
begin
 if Assigned(FormCrwTestBench) then with FormCrwTestBench do begin
  if Assigned(spipe) then begin
   if spipe.Connected
   then LabelPipeServerStatus.Caption:='Connected'
   else LabelPipeServerStatus.Caption:='Disconnected';
   if spipe.RxFifo.Count>0 then writeln('ServerPipeRecv: ',spipe.RxFifo.GetText);
   //if (spipe.LogsCount>0) then write(spipe.LogsTextMove);
  end else begin
   LabelPipeServerStatus.Caption:='NULL';
  end;
  if Assigned(cpipe) then begin
   if cpipe.Connected
   then LabelPipeClientStatus.Caption:='Connected'
   else LabelPipeClientStatus.Caption:='Disconnected';
   if cpipe.RxFifo.Count>0 then writeln('ClientPipeRecv: ',cpipe.RxFifo.GetText);
   //if (cpipe.LogsCount>0) then write(cpipe.LogsTextMove);
  end else begin
   LabelPipeClientStatus.Caption:='NULL';
  end;
 end;
end;

procedure PipeReporter(Pipe:TPipe; When:Double; const What:LongString; Code:Integer);
var msg:LongString;
begin
 msg:=FormatDateTime(StdTimeOnlyFormatMs,MsToOleTime(When))+' => '
     +pipe.Polling.Name+': '+What+', '+SysErrorMessage(Code);
 writeln(msg);
end;

procedure TFormCrwTestBench.ButtonPipeServerOpenClick(Sender: TObject);
begin
 if Assigned(spipe) then begin
  ButtonPipeServerOpen.Caption:='Server Open';
  writeln('Server Pipe:');
  writeln(spipe.Ctrl('?'));
  Kill(spipe);
 end else begin
  spipe:=NewPipe('',Trim(EditPipeName.Text),PipeReporter);
  if Assigned(spipe) then begin
   ButtonPipeServerOpen.Caption:='Server Close';
   Tick55Actions.Add(PipePolling);
  end;
  writeln('Server Pipe:');
  write(spipe.GetProperties);
 end;
end;

procedure TFormCrwTestBench.ButtonPipeClientOpenClick(Sender: TObject);
begin
 if Assigned(cpipe) then begin
  ButtonPipeClientOpen.Caption:='Client Open';
  writeln('Client Pipe:');
  writeln(cpipe.Ctrl('?'));
  Kill(cpipe);
 end else begin
  cpipe:=NewPipe('.',Trim(EditPipeName.Text),PipeReporter);
  if Assigned(cpipe) then begin
   ButtonPipeClientOpen.Caption:='Client Close';
   Tick55Actions.Add(PipePolling);
  end;
  writeln('Client Pipe:');
  write(cpipe.GetProperties);
 end;
end;

procedure TFormCrwTestBench.ButtonPipeServerSendClick(Sender: TObject);
var s:LongString;
begin
 if Assigned(spipe) then begin
  s:=EditPipeServerSend.Text;
  if (s<>'') then
  if spipe.TxFifo.PutText(s) then writeln('ServerPipeSend: ',s);
 end;
end;

procedure TFormCrwTestBench.ButtonPipeClientSendClick(Sender: TObject);
var s:LongString;
begin
 if Assigned(cpipe) then begin
  s:=EditPipeClientSend.Text;
  if (s<>'') then
  if cpipe.TxFifo.PutText(s) then writeln('ClientPipeSend: ',s);
 end;
end;

procedure TFormCrwTestBench.ButtonCrwNetIfTest1Click(Sender: TObject);
var ip:LongString;
begin
 writeln('GetListOfNetworkInterfaces:');
 writeln(Trim(GetListOfNetworkInterfaces));
 writeln('GetListOfNetworkInterfaces:');
 writeln(Trim(GetListOfNetworkInterfaces(nim_nice)));
 ip:='127.0.0.1';
 writeln(ip,' ',IPv4BelongsToLocalHost(ip));
 ip:='192.168.0.11';
 writeln(ip,' ',IPv4BelongsToLocalHost(ip));
 ip:='192.168.0.10';
 writeln(ip,' ',IPv4BelongsToLocalHost(ip));
end;

var
 stcp:TTcpServer=nil;
 ctcp:TTcpClient=nil;

procedure KillTcps;
begin
 Kill(stcp);
 Kill(ctcp);
end;

procedure TcpPolling;
var i:Integer;
begin
 if Assigned(FormCrwTestBench) then with FormCrwTestBench do begin
  if Assigned(stcp) then begin
   LabelTcpServerStatus.Caption:='Connected '+IntToStr(stcp.Connected);
   for i:=0 to stcp.Count-1 do
   if stcp[i].RxFifo.Count>0 then writeln('ServerTcpRecv: ',stcp[i].RxFifo.GetText);
  end else begin
   LabelTcpServerStatus.Caption:='NULL';
  end;
  if Assigned(ctcp) then begin
   LabelTcpClientStatus.Caption:='Connected '+IntToStr(ctcp.Connected);
   if ctcp.RxFifo.Count>0 then writeln('ClientTcpRecv: ',ctcp.RxFifo.GetText);
  end else begin
   LabelTcpClientStatus.Caption:='NULL';
  end;
 end;
end;

procedure TcpReporter(Tcp:TSocketPipe; When:Double; What:PChar; Code:Integer);
var msg:LongString;
begin
 msg:=FormatDateTime(StdTimeOnlyFormatMs,MsToOleTime(When))+' => '
     +Tcp.Polling.Name+': '+What+', '+SysErrorMessage(Code);
 writeln(msg);
end;

procedure TFormCrwTestBench.ButtonTcpServerOpenClick(Sender: TObject);
begin
 if Assigned(stcp) then begin
  ButtonTcpServerOpen.Caption:='Server Open';
  writeln('Server TCP: Stop');
  writeln(stcp.Ctrl('?'));
  Kill(stcp);
 end else begin
  stcp:=NewTcpServer(SpinEditTcpPort.Value,2,TcpReporter);
  if Assigned(stcp) then begin
   ButtonTcpServerOpen.Caption:='Server Close';
   Tick55Actions.Add(TcpPolling);
  end;
  writeln('Server TCP: Start');
  write(stcp.GetProperties);
 end;
end;

procedure TFormCrwTestBench.ButtonTcpClientOpenClick(Sender: TObject);
begin
 if Assigned(ctcp) then begin
  ButtonTcpClientOpen.Caption:='Client Open';
  writeln('Client TCP: Stop');
  writeln(ctcp.Ctrl('?'));
  Kill(ctcp);
 end else begin
  ctcp:=NewTcpClient(SpinEditTcpPort.Value,Trim(EditTcpHost.Text),TcpReporter);
  if Assigned(ctcp) then begin
   ButtonTcpClientOpen.Caption:='Client Close';
   Tick55Actions.Add(TcpPolling);
  end;
  writeln('Client TCP: Start');
  write(ctcp.GetProperties);
 end;
end;

procedure TFormCrwTestBench.ButtonTcpServerSendClick(Sender: TObject);
var s:LongString; i:Integer;
begin
 if Assigned(stcp) then begin
  s:=EditTcpServerSend.Text;
  if (s<>'') then
  for i:=0 to stcp.Count-1 do
  if stcp[i].Connected>0 then
  if stcp[i].TxFifo.PutText(s) then writeln('ServerTcpSend: ',s);
 end;
end;

procedure TFormCrwTestBench.ButtonTcpClientSendClick(Sender: TObject);
var s:LongString;
begin
 if Assigned(ctcp) then begin
  s:=EditTcpClientSend.Text;
  if (s<>'') then
  if ctcp.Connected>0 then
  if ctcp.TxFifo.PutText(s) then writeln('ClientTcpSend: ',s);
 end;
end;

procedure TFormCrwTestBench.ButtonCrwSesmanTest1Click(Sender: TObject);
begin
 writeln('SessionManager:');
 if IsEmptyStr(SessionManager.SessionID)
 then writeln('InitByOptions = ',SessionManager.Start('$ 1'));
 writeln('SessionNb = ',SessionManager.SessionNb);
 writeln('SessionID = ',SessionManager.SessionID);
 writeln('DataDir = ',SessionManager.LocalDataDir,' ',DirectoryExists(SessionManager.LocalDataDir));
 writeln('ConfigDir = ',SessionManager.LocalConfigDir,' ',DirectoryExists(SessionManager.LocalConfigDir));
 writeln('SysTmpDir = ',SessionManager.SystemTmpDir,' ',DirectoryExists(SessionManager.SystemTmpDir));
 writeln('VarTmpDir = ',SessionManager.VarTmpDir,' ',DirectoryExists(SessionManager.VarTmpDir));
 writeln('HasServer = ',SessionManager.HasIpcServer);
 writeln('HasClient = ',SessionManager.HasIpcClient);
 writeln('IpcPipeId = ',SessionManager.IpcPipeId);
 writeln('DetectRunningPid(3) ',SessionManager.DetectRunningPid(3));
 writeln('DetectRunningPid(0) ',SessionManager.DetectRunningPid(0));
 SessionManager.SimpleIpcSendCommand('','','',0,0,'@Test command');
end;

procedure PollSession;
var msg:LongString;
begin
 if SessionManager.HasIpcServer then
 try
  while SessionManager.ReadIpcMessage(msg) do begin
   if (msg<>'') then writeln('SessionManager: '+msg);
  end;
 except
  on E:Exception do BugReport(E,nil,'PollSession');
 end;
end;

 {
 Start session:
 if StartSession('1')   then ... - run single instance - session 1.
 if StartSession('$ 1') then ... - use option --session N or run session 1.
 if StartSession('? 9') then ... - run first found free session in range [1..9].
 }
function StartSession(arg:LongString):Boolean;
begin
 Result:=SessionManager.Start(arg);
 if Result then begin
  SessionManager.RedirectStdIo;
  SessionManager.OpenLeakageLog;
  SessionManager.OpenReadIniLog;
  SessionManager.OpenDebugLog;
  SessionManager.OpenErrorLog;
  SessionManager.SetGuardIniPath;
  SessionManager.SetSystemEcho(CrwTestBenchEcho);
  SessionManager.SetBlasterLogger(MyBlasterLogger);
  SessionManager.SetSystemSendToMainConsole(SimulateSendToMainConsole);
  DefaultCanShowModalLimit:=3;
 end;
 if SessionManager.HasIpcServer then Tick55Actions.Add(PollSession);
end;

end.

