ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/branches/journaling/fbintf/testsuite/testApp/TestApplication.pas
Revision: 351
Committed: Wed Oct 20 15:04:35 2021 UTC (2 years, 5 months ago) by tony
Content type: text/x-pascal
Original Path: ibx/trunk/fbintf/testsuite/testApp/TestApplication.pas
File size: 40431 byte(s)
Log Message:
Add Missing testsuite files

File Contents

# User Rev Content
1 tony 334 (*
2     * MWA Software Test suite. This unit provides common
3     * code for all Firebird Database tests.
4     *
5     * The contents of this file are subject to the Initial Developer's
6     * Public License Version 1.0 (the "License"); you may not use this
7     * file except in compliance with the License. You may obtain a copy
8     * of the License here:
9     *
10     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
11     *
12     * Software distributed under the License is distributed on an "AS
13     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14     * implied. See the License for the specific language governing rights
15     * and limitations under the License.
16     *
17     * The Initial Developer of the Original Code is Tony Whyman.
18     *
19     * The Original Code is (C) 2016-2020 Tony Whyman, MWA Software
20     * (http://www.mwasoftware.co.uk).
21     *
22     * All Rights Reserved.
23     *
24     * Contributor(s): ______________________________________.
25     *
26     *)
27     unit TestApplication;
28     {$IFDEF MSWINDOWS}
29     {$DEFINE WINDOWS}
30     {$ENDIF}
31    
32     {$IFDEF FPC}
33     {$mode delphi}
34     {$codepage utf8}
35     {$ENDIF}
36    
37     {$IF not defined (DCC) and not defined (FPC)}
38     {$DEFINE DCC}
39     {$IFEND}
40    
41     interface
42    
43     uses
44     Classes, SysUtils, {$IFDEF FPC}CustApp,{$ENDIF} Firebird, IB, IBUtils, FmtBCD, FBClientLib;
45    
46     {$IF not defined(LineEnding)}
47     const
48     {$IFDEF WINDOWS}
49     LineEnding = #$0D#$0A;
50     {$ELSE}
51     LineEnding = #$0A;
52     {$ENDIF}
53     {$IFEND}
54    
55     const
56     Copyright = 'Copyright MWA Software 2016-2021';
57    
58     type
59     {$IFDEF DCC}
60     TCustomApplication = class(TComponent)
61     private
62     FTitle: string;
63     protected
64     procedure DoRun; virtual; abstract;
65     public
66     function Exename: string;
67     procedure Run;
68     procedure Terminate;
69     property Title: string read FTitle write FTitle;
70     end;
71     {$ENDIF}
72    
73     TTestApplication = class;
74    
75     { TTestBase }
76    
77     TTestBase = class
78     private
79     FOwner: TTestApplication;
80 tony 351 FFloatTpl: AnsiString;
81     FCursorSeq: integer;
82 tony 334 function GetFirebirdAPI: IFirebirdAPI;
83     procedure SetOwner(AOwner: TTestApplication);
84     protected
85     FHexStrings: boolean;
86 tony 351 FShowBinaryBlob: boolean;
87 tony 334 procedure DumpBCD(bcd: tBCD);
88     procedure ClientLibraryPathChanged; virtual;
89     procedure CreateObjects(Application: TTestApplication); virtual;
90     function ExtractDBName(ConnectString: AnsiString): AnsiString;
91     function GetTestID: AnsiString; virtual; abstract;
92     function GetTestTitle: AnsiString; virtual; abstract;
93     procedure PrintHexString(s: AnsiString);
94     procedure PrintDPB(DPB: IDPB);
95     procedure PrintTPB(TPB: ITPB);
96     procedure PrintSPB(SPB: ISPB);
97     procedure PrintMetaData(meta: IMetaData);
98     procedure ParamInfo(SQLParams: ISQLParams);
99 tony 351 function ReportResults(Statement: IStatement; ShowCursorName: boolean=false): IResultSet;
100 tony 334 procedure ReportResult(aValue: IResults);
101     function StringToHex(octetString: string; MaxLineLength: integer=0): string;
102     procedure WriteArray(ar: IArray);
103     procedure WriteAffectedRows(Statement: IStatement);
104     procedure WriteDBInfo(DBInfo: IDBInformation);
105     procedure WriteBytes(Bytes: TByteArray);
106     procedure WriteOperationCounts(Category: AnsiString; ops: TDBOperationCounts);
107     procedure WritePerfStats(stats: TPerfCounters);
108     procedure WriteSQLData(aValue: ISQLData);
109     procedure CheckActivity(Attachment: IAttachment); overload;
110     procedure CheckActivity(Transaction: ITransaction); overload;
111     procedure InitTest; virtual;
112     function SkipTest: boolean; virtual;
113     procedure ProcessResults; virtual;
114 tony 351 procedure SetFloatTemplate(tpl: Ansistring);
115 tony 334 public
116     constructor Create(aOwner: TTestApplication); virtual;
117     function ChildProcess: boolean; virtual;
118     function TestTitle: AnsiString; virtual;
119     property FirebirdAPI: IFirebirdAPI read GetFirebirdAPI;
120     procedure RunTest(CharSet: AnsiString; SQLDialect: integer); virtual; abstract;
121     property Owner: TTestApplication read FOwner;
122     property TestID: AnsiString read GetTestID;
123     end;
124    
125     TTest = class of TTestBase;
126    
127     { TTestApplication }
128    
129     TTestApplication = class(TCustomApplication)
130     private
131     class var FTests: TStringList;
132     private
133     class procedure CreateTestList;
134     class procedure DestroyTestList;
135     private
136     FClientLibraryPath: string;
137     FServer: AnsiString;
138     FEmployeeDatabaseName: AnsiString;
139     FNewDatabaseName: AnsiString;
140     FSecondNewDatabaseName: AnsiString;
141     FTestOption: AnsiString;
142     FUserName: AnsiString;
143     FPassword: AnsiString;
144     FBackupFileName: AnsiString;
145     FShowStatistics: boolean;
146     FFirebirdAPI: IFirebirdAPI;
147     FPortNo: AnsiString;
148     FCreateObjectsDone: boolean;
149     FQuiet: boolean;
150     procedure CleanUp;
151     function GetFirebirdAPI: IFirebirdAPI;
152     function GetIndexByTestID(aTestID: AnsiString): integer;
153     procedure SetClientLibraryPath(aLibName: string);
154     procedure SetUserName(aValue: AnsiString);
155     procedure SetPassword(aValue: AnsiString);
156     procedure SetEmployeeDatabaseName(aValue: AnsiString);
157     procedure SetNewDatabaseName(aValue: AnsiString);
158     procedure SetSecondNewDatabaseName(aValue: AnsiString);
159     procedure SetBackupFileName(aValue: AnsiString);
160     procedure SetServerName(AValue: AnsiString);
161     procedure SetPortNum(aValue: AnsiString);
162     procedure SetTestOption(aValue: AnsiString);
163     protected
164     {$IFDEF FPC}
165     function GetShortOptions: AnsiString; virtual;
166     function GetLongOptions: AnsiString; virtual;
167     {$ENDIF}
168     procedure GetParams(var DoPrompt: boolean; var TestID: string); virtual;
169     procedure DoRun; override;
170     procedure DoTest(index: integer);
171     procedure SetFormatSettings; virtual;
172     procedure WriteHelp; virtual;
173     public
174     constructor Create(AOwner: TComponent); override;
175     destructor Destroy; override;
176     function GetUserName: AnsiString;
177     function GetPassword: AnsiString;
178     function GetEmployeeDatabaseName: AnsiString;
179     function GetNewDatabaseName: AnsiString;
180 tony 351 function GetTempDatabaseName: AnsiString;
181 tony 334 function GetSecondNewDatabaseName: AnsiString;
182     function GetBackupFileName: AnsiString;
183     procedure RunAll;
184     procedure RunTest(TestID: AnsiString);
185     property ShowStatistics: boolean read FShowStatistics write FShowStatistics;
186     property FirebirdAPI: IFirebirdAPI read GetFirebirdAPI;
187     property Server: AnsiString read FServer;
188     property PortNo: AnsiString read FPortNo;
189     property ClientLibraryPath: string read FClientLibraryPath;
190     property TestOption: AnsiString read FTestOption write SetTestOption;
191     property Quiet: boolean read FQuiet;
192     end;
193    
194 tony 351 { TMsgHash }
195    
196     TMsgHash = class
197     private
198     FFinalised: boolean;
199     protected
200     procedure CheckNotFinalised;
201     public
202     procedure AddText(aText: AnsiString); virtual; abstract;
203     procedure Finalise; virtual;
204     function SameHash(otherHash: TMsgHash): boolean;
205     function Digest: AnsiString; virtual; abstract;
206     class function CreateMsgHash: TMsgHash;
207     property Finalised: boolean read FFinalised;
208     end;
209    
210 tony 334 ESkipException = class(Exception);
211    
212     var
213     TestApp: TTestApplication = nil;
214    
215     var OutFile: text;
216    
217     procedure RegisterTest(aTest: TTest);
218    
219     implementation
220    
221 tony 351 {$IFNDEF MSWINDOWS}
222     uses MD5;
223     {$ENDIF}
224    
225 tony 334 {$IFDEF MSWINDOWS}
226 tony 351 uses {$IFDEF FPC}MD5,{$ENDIF} windows;
227 tony 334
228     function GetTempDir: AnsiString;
229     var
230     tempFolder: array[0..MAX_PATH] of Char;
231     begin
232     GetTempPath(MAX_PATH, @tempFolder);
233     result := StrPas(tempFolder);
234     end;
235     {$ENDIF}
236    
237     procedure RegisterTest(aTest: TTest);
238     var test: TTestBase;
239     begin
240     TTestApplication.CreateTestList;
241     test := aTest.Create(TestApp);
242     TTestApplication.FTests.AddObject(test.GetTestID,test);
243     // if TestApp <> nil then
244     // test.CreateObjects(TestApp);
245     end;
246    
247 tony 351 {$IFDEF FPC}
248     type
249    
250     { TMD5MsgHash }
251    
252     TMD5MsgHash = class(TMsgHash)
253     private
254     FMD5Context: TMDContext;
255     FDigest: TMDDigest;
256     public
257     constructor Create;
258     procedure AddText(aText: AnsiString); override;
259     procedure Finalise; override;
260     function Digest: AnsiString; override;
261     end;
262    
263     {$DEFINE MSG_HASH_AVAILABLE}
264    
265     { TMD5MsgHash }
266    
267     constructor TMD5MsgHash.Create;
268     begin
269     inherited Create;
270     MDInit(FMD5Context,MD_VERSION_5);
271     end;
272    
273     procedure TMD5MsgHash.AddText(aText: AnsiString);
274     begin
275     CheckNotFinalised;
276     MDUpdate(FMD5Context,PAnsiChar(aText)^,Length(aText));
277     end;
278    
279     procedure TMD5MsgHash.Finalise;
280     begin
281     CheckNotFinalised;
282     MDFinal(FMD5Context,FDigest);
283     inherited Finalise;
284     end;
285    
286     function TMD5MsgHash.Digest: AnsiString;
287     begin
288     if not FFinalised then
289     Finalise;
290     Result := MD5Print(FDigest);
291     end;
292    
293     class function TMsgHash.CreateMsgHash: TMsgHash;
294     begin
295     Result := TMD5MsgHash.Create;
296     end;
297     {$ENDIF}
298    
299     {$IFNDEF MSG_HASH_AVAILABLE}
300     type
301    
302     { TSimpleMsgHash }
303    
304     TSimpleMsgHash = class(TMsgHash)
305     private
306     FDigest: Int64;
307     Finalised: boolean;
308     public
309     procedure AddText(aText: AnsiString); override;
310     function Digest: AnsiString; override;
311     end;
312    
313     { TSimpleMsgHash }
314    
315     procedure TSimpleMsgHash.AddText(aText: AnsiString);
316     const
317     modulus = high(Int64) div 100;
318     var i: integer;
319     begin
320     CheckNotFinalised;
321     for i := 1 to length(aText) do
322     FDigest := (FDigest * 7 + ord(aText[i])) mod modulus;
323     end;
324    
325     function TSimpleMsgHash.Digest: AnsiString;
326     begin
327     if not Finalised then
328     Finalise;
329     Result := IntToStr(FDigest);
330     end;
331    
332     class function TMsgHash.CreateMsgHash: TMsgHash;
333     begin
334     Result := TSimpleMsgHash.Create;
335     end;
336    
337     {$ENDIF}
338    
339     procedure TMsgHash.CheckNotFinalised;
340     begin
341     if FFinalised then
342     raise Exception.Create('Digest has been finalised');
343     end;
344    
345     procedure TMsgHash.Finalise;
346     begin
347     FFinalised := true;
348     end;
349    
350     function TMsgHash.SameHash(otherHash: TMsgHash): boolean;
351     begin
352     Result := Digest = OtherHash.Digest;
353     end;
354    
355 tony 334 { TTestBase }
356    
357     constructor TTestBase.Create(aOwner: TTestApplication);
358     begin
359     inherited Create;
360     FOwner := aOwner;
361 tony 351 FFloatTpl := '#,###.00';
362 tony 334 end;
363    
364     function TTestBase.ChildProcess: boolean;
365     begin
366     Result := false;
367     end;
368    
369     function TTestBase.TestTitle: AnsiString;
370     begin
371     Result := 'Test ' + GetTestID + ': ' + GetTestTitle;
372     end;
373    
374     function TTestBase.GetFirebirdAPI: IFirebirdAPI;
375     begin
376     Result := FOwner.FirebirdAPI;
377     end;
378    
379     procedure TTestBase.SetOwner(AOwner: TTestApplication);
380     begin
381     FOwner := AOwner;
382     end;
383    
384     procedure TTestBase.DumpBCD(bcd: tBCD);
385     var i,l: integer;
386     begin
387     with bcd do
388     begin
389     writeln(OutFile,' Precision = ',bcd.Precision);
390     writeln(OutFile,' Sign = ',(SignSpecialPlaces and $80) shr 7);
391     writeln(OutFile,' Special = ', (SignSpecialPlaces and $40) shl 6);
392     writeln(OutFile,' Places = ', SignSpecialPlaces and $7F);
393     write(OutFile,' Digits = ');
394     l := Precision div 2;
395     if not odd(Precision) then l := l - 1;
396     for i := 0 to l do
397     write(OutFile,Format('%.2x',[Fraction[i]]),' ');
398     writeln(OutFile);
399     end;
400     end;
401    
402     procedure TTestBase.ClientLibraryPathChanged;
403     begin
404     //Do nothing yet
405     end;
406    
407     procedure TTestBase.CreateObjects(Application: TTestApplication);
408     begin
409     //Do nothing yet
410     end;
411    
412     function TTestBase.ExtractDBName(ConnectString: AnsiString): AnsiString;
413     var ServerName: AnsiString;
414     Protocol: TProtocolAll;
415     PortNo: AnsiString;
416     i: integer;
417     begin
418     if not ParseConnectString(ConnectString, ServerName, Result, Protocol,PortNo) then
419     begin
420     {assume either inet format (remote) or localhost}
421     Result := ConnectString;
422     if Pos('inet',Result) = 1 then
423     begin
424     system.Delete(Result,1,7);
425     i := Pos('/',Result);
426     if i > 0 then
427     system.delete(Result,1,i);
428     end
429     else
430     if Pos('localhost:',Result) = 1 then
431     system.Delete(Result,1,10)
432     end;
433     end;
434    
435     procedure TTestBase.PrintHexString(s: AnsiString);
436     var i: integer;
437     begin
438     for i := 1 to length(s) do
439     write(OutFile,Format('%x ',[byte(s[i])]));
440     end;
441    
442     procedure TTestBase.PrintDPB(DPB: IDPB);
443     var i: integer;
444     begin
445     writeln(OutFile,'DPB: Item Count = ', DPB.getCount);
446     for i := 0 to DPB.getCount - 1 do
447     begin
448     write(OutFile,' ',DPB[i].getParamTypeName);
449     if DPB[i].AsString <> '' then
450     writeln(Outfile,' = ', DPB[i].AsString)
451     else
452     writeln(OutFile);
453     end;
454     writeln(OutFile);
455     end;
456    
457     procedure TTestBase.PrintTPB(TPB: ITPB);
458     var i: integer;
459     begin
460     writeln(OutFile,'TPB: Item Count = ', TPB.getCount);
461     for i := 0 to TPB.getCount - 1 do
462     begin
463     write(OutFile,' ',TPB[i].getParamTypeName);
464     if TPB[i].AsString <> '' then
465     writeln(Outfile,' = ', TPB[i].AsString)
466     else
467     writeln(OutFile);
468     end;
469     writeln(OutFile);
470     end;
471    
472     procedure TTestBase.PrintSPB(SPB: ISPB);
473     var i: integer;
474     begin
475     writeln(OutFile,'SPB: Item Count = ', SPB.getCount);
476     for i := 0 to SPB.getCount - 1 do
477     begin
478     write(OutFile,' ',SPB[i].getParamTypeName);
479     if SPB[i].AsString <> '' then
480     writeln(Outfile,' = ', SPB[i].AsString)
481     else
482     writeln(OutFile);
483     end;
484     writeln(OutFile);
485     end;
486    
487     procedure TTestBase.PrintMetaData(meta: IMetaData);
488     var i, j: integer;
489     ar: IArrayMetaData;
490     bm: IBlobMetaData;
491     Bounds: TArrayBounds;
492     begin
493     writeln(OutFile,'Metadata');
494     for i := 0 to meta.GetCount - 1 do
495     with meta[i] do
496     begin
497     writeln(OutFile,'SQLType =',GetSQLTypeName);
498     writeln(OutFile,'sub type = ',getSubType);
499     writeln(OutFile,'Table = ',getRelationName);
500     writeln(OutFile,'Owner = ',getOwnerName);
501     writeln(OutFile,'Column Name = ',getSQLName);
502     writeln(OutFile,'Alias Name = ',getAliasName);
503     writeln(OutFile,'Field Name = ',getName);
504     writeln(OutFile,'Scale = ',getScale);
505     writeln(OutFile,'Charset id = ',getCharSetID);
506     if getIsNullable then writeln(OutFile,'Nullable') else writeln(OutFile,'Not Null');
507     writeln(OutFile,'Size = ',GetSize);
508     case getSQLType of
509     SQL_ARRAY:
510     begin
511     writeln(OutFile,'Array Meta Data:');
512     ar := GetArrayMetaData;
513     writeln(OutFile,'SQLType =',ar.GetSQLTypeName);
514     writeln(OutFile,'Scale = ',ar.getScale);
515     writeln(OutFile,'Charset id = ',ar.getCharSetID);
516     writeln(OutFile,'Size = ',ar.GetSize);
517     writeln(OutFile,'Table = ',ar.GetTableName);
518     writeln(OutFile,'Column = ',ar.GetColumnName);
519     writeln(OutFile,'Dimensions = ',ar.GetDimensions);
520     write(OutFile,'Bounds: ');
521     Bounds := ar.GetBounds;
522     for j := 0 to Length(Bounds) - 1 do
523     write(OutFile,'(',Bounds[j].LowerBound,':',Bounds[j].UpperBound,') ');
524     writeln(OutFile);
525     end;
526     SQL_BLOB:
527     begin
528     writeln(OutFile);
529     writeln(OutFile,'Blob Meta Data');
530     bm := GetBlobMetaData;
531     writeln(OutFile,'SQL SubType =',bm.GetSubType);
532     writeln(OutFile,'Table = ',bm.GetRelationName);
533     writeln(OutFile,'Column = ',bm.GetColumnName);
534     writeln(OutFile,'CharSetID = ',bm.GetCharSetID);
535     writeln(OutFile,'Segment Size = ',bm.GetSegmentSize);
536     writeln(OutFile);
537     end;
538     end;
539     writeln(OutFile);
540     end;
541     end;
542    
543     procedure TTestBase.ParamInfo(SQLParams: ISQLParams);
544     var i: integer;
545     begin
546     writeln(OutFile,'SQL Params');
547     for i := 0 to SQLParams.Count - 1 do
548     with SQLParams[i] do
549     begin
550     writeln(OutFile,'SQLType =',GetSQLTypeName);
551     writeln(OutFile,'sub type = ',getSubType);
552     writeln(OutFile,'Field Name = ',getName);
553     writeln(OutFile,'Scale = ',getScale);
554     writeln(OutFile,'Charset id = ',getCharSetID);
555     if getIsNullable then writeln(OutFile,'Nullable') else writeln(OutFile,'Not Null');
556     writeln(OutFile,'Size = ',GetSize);
557 tony 351 if not IsNull then
558     writeln(Outfile,'Value = ',getAsString);
559 tony 334 writeln(OutFile);
560     end;
561     end;
562    
563 tony 351 function TTestBase.ReportResults(Statement: IStatement; ShowCursorName: boolean): IResultSet;
564 tony 334 begin
565     Result := Statement.OpenCursor;
566     try
567 tony 351 if ShowCursorName then
568     writeln(Outfile,'Results for Cursor: ',Result.GetCursorName);
569 tony 334 while Result.FetchNext do
570     ReportResult(Result);
571     finally
572     Result.Close;
573     end;
574     writeln(OutFile);
575     end;
576    
577     procedure TTestBase.ReportResult(aValue: IResults);
578     var i: integer;
579     begin
580     for i := 0 to aValue.getCount - 1 do
581     WriteSQLData(aValue[i]);
582     end;
583    
584     function TTestBase.StringToHex(octetString: string; MaxLineLength: integer
585     ): string;
586    
587     function ToHex(aValue: byte): string;
588     const
589     HexChars: array [0..15] of char = '0123456789ABCDEF';
590     begin
591     Result := HexChars[aValue shr 4] +
592     HexChars[(aValue and $0F)];
593     end;
594    
595     var i, j: integer;
596     begin
597     i := 1;
598     Result := '';
599     if MaxLineLength = 0 then
600     while i <= Length(octetString) do
601     begin
602     Result := Result + ToHex(byte(octetString[i]));
603     Inc(i);
604     end
605     else
606     while i <= Length(octetString) do
607     begin
608     for j := 1 to MaxLineLength do
609     begin
610     if i > Length(octetString) then
611     Exit
612     else
613     Result := Result + ToHex(byte(octetString[i]));
614     inc(i);
615     end;
616     Result := Result + LineEnding;
617     end;
618     end;
619    
620     procedure TTestBase.WriteArray(ar: IArray);
621     var Bounds: TArrayBounds;
622     i,j: integer;
623     begin
624     write(OutFile,'Array: ');
625     Bounds := ar.GetBounds;
626     case ar.GetDimensions of
627     1:
628     begin
629     for i := Bounds[0].LowerBound to Bounds[0].UpperBound do
630     write(OutFile,'(',i,': ',ar.GetAsVariant([i]),') ');
631     end;
632    
633     2:
634     begin
635     for i := Bounds[0].LowerBound to Bounds[0].UpperBound do
636     for j := Bounds[1].LowerBound to Bounds[1].UpperBound do
637     write(OutFile,'(',i,',',j,': ',ar.GetAsVariant([i,j]),') ');
638     end;
639     end;
640     writeln(OutFile);
641     writeln(OutFile);
642     end;
643    
644     procedure TTestBase.WriteAffectedRows(Statement: IStatement);
645     var SelectCount, InsertCount, UpdateCount, DeleteCount: integer;
646     begin
647     Statement.GetRowsAffected(SelectCount, InsertCount, UpdateCount, DeleteCount);
648     writeln(OutFile,'Select Count = ', SelectCount,' InsertCount = ',InsertCount,' UpdateCount = ', UpdateCount, ' DeleteCount = ',DeleteCount);
649     end;
650    
651     procedure TTestBase.WriteDBInfo(DBInfo: IDBInformation);
652     var i, j: integer;
653     bytes: TByteArray;
654     ConType: integer;
655     DBFileName: AnsiString;
656     DBSiteName: AnsiString;
657     Version: byte;
658     VersionString: AnsiString;
659     Users: TStringList;
660     begin
661     for i := 0 to DBInfo.GetCount - 1 do
662     with DBInfo[i] do
663     case getItemType of
664     isc_info_db_read_only:
665     if getAsInteger <> 0 then
666     writeln(OutFile,'Database is Read Only')
667     else
668     writeln(OutFile,'Database is Read/Write');
669     isc_info_allocation:
670     writeln(OutFile,'Pages =',getAsInteger);
671     isc_info_base_level:
672     begin
673     bytes := getAsBytes;
674     write(OutFile,'Base Level = ');
675     WriteBytes(Bytes);
676     end;
677     isc_info_db_id:
678     begin
679     DecodeIDCluster(ConType,DBFileName,DBSiteName);
680     writeln(OutFile,'Database ID = ', ConType,' FB = ', DBFileName, ' SN = ',DBSiteName);
681     end;
682     isc_info_implementation:
683     begin
684     bytes := getAsBytes;
685     write(OutFile,'Implementation = ');
686     WriteBytes(Bytes);
687     end;
688     isc_info_no_reserve:
689     writeln(OutFile,'Reserved = ',getAsInteger);
690     isc_info_ods_minor_version:
691     writeln(OutFile,'ODS minor = ',getAsInteger);
692     isc_info_ods_version:
693     writeln(OutFile,'ODS major = ',getAsInteger);
694     isc_info_page_size:
695     writeln(OutFile,'Page Size = ',getAsInteger);
696     isc_info_version:
697     begin
698     DecodeVersionString(Version,VersionString);
699     writeln(OutFile,'Version = ',Version,': ',VersionString);
700     end;
701     isc_info_current_memory:
702     writeln(OutFile,'Server Memory = ',getAsInteger);
703     isc_info_forced_writes:
704     writeln(OutFile,'Forced Writes = ',getAsInteger);
705     isc_info_max_memory:
706     writeln(OutFile,'Max Memory = ',getAsInteger);
707     isc_info_num_buffers:
708     writeln(OutFile,'Num Buffers = ',getAsInteger);
709     isc_info_sweep_interval:
710     writeln(OutFile,'Sweep Interval = ',getAsInteger);
711     isc_info_user_names:
712     begin
713     Users := TStringList.Create;
714     try
715     write(OutFile,'Logged in Users: ');
716     DecodeUserNames(Users);
717     for j := 0 to Users.Count - 1 do
718     write(OutFile,Users[j],',');
719    
720     finally
721     Users.Free;
722     end;
723     writeln(OutFile);
724     end;
725     isc_info_fetches:
726     writeln(OutFile,'Fetches = ',getAsInteger);
727     isc_info_marks:
728     writeln(OutFile,'Writes = ',getAsInteger);
729     isc_info_reads:
730     writeln(OutFile,'Reads = ',getAsInteger);
731     isc_info_writes:
732     writeln(OutFile,'Page Writes = ',getAsInteger);
733     isc_info_backout_count:
734     WriteOperationCounts('Record Version Removals',getOperationCounts);
735     isc_info_delete_count:
736     WriteOperationCounts('Deletes',getOperationCounts);
737     isc_info_expunge_count:
738     WriteOperationCounts('Expunge Count',getOperationCounts);
739     isc_info_insert_count:
740     WriteOperationCounts('Insert Count',getOperationCounts);
741     isc_info_purge_count:
742     WriteOperationCounts('Purge Count Countites',getOperationCounts);
743     isc_info_read_idx_count:
744     WriteOperationCounts('Indexed Reads Count',getOperationCounts);
745     isc_info_read_seq_count:
746     WriteOperationCounts('Sequential Table Scans',getOperationCounts);
747     isc_info_update_count:
748     WriteOperationCounts('Update Count',getOperationCounts);
749     isc_info_db_SQL_Dialect:
750     writeln(OutFile,'SQL Dialect = ',getAsInteger);
751     isc_info_creation_date:
752     writeln(OutFile,'Database Created: ',DateTimeToStr(getAsDateTime));
753     isc_info_active_tran_count:
754     writeln(OutFile,'Active Transaction Count = ',getAsInteger);
755     fb_info_page_contents:
756     begin
757     writeln('Database Page');
758     PrintHexString(getAsString);
759     writeln;
760     end;
761     fb_info_pages_used:
762     writeln(OutFile,'Pages Used = ',getAsInteger);
763     fb_info_pages_free:
764     writeln(OutFile,'Pages Free = ',getAsInteger);
765    
766     isc_info_truncated:
767     writeln(OutFile,'Results Truncated');
768     else
769     writeln(OutFile,'Unknown Response ',getItemType);
770     end;
771     end;
772    
773     procedure TTestBase.WriteBytes(Bytes: TByteArray);
774     var i: integer;
775     begin
776     for i := 0 to length(Bytes) - 1 do
777     write(OutFile,Bytes[i],',');
778     writeln(OutFile);
779     end;
780    
781     procedure TTestBase.WriteOperationCounts(Category: AnsiString;
782     ops: TDBOperationCounts);
783     var i: integer;
784     begin
785     writeln(OutFile,Category,' Operation Counts');
786     for i := 0 to Length(ops) - 1 do
787     begin
788     writeln(OutFile,'Table ID = ',ops[i].TableID);
789     writeln(OutFile,'Count = ',ops[i].Count);
790     end;
791     writeln(OutFile);
792     end;
793    
794     procedure TTestBase.WritePerfStats(stats: TPerfCounters);
795     var LargeCompFormat: string;
796     ThreeSigPlacesFormat: string;
797     begin
798     {$IF declared(DefaultFormatSettings)}
799     with DefaultFormatSettings do
800     {$ELSE}
801     {$IF declared(FormatSettings)}
802     with FormatSettings do
803     {$IFEND}
804     {$IFEND}
805     begin
806     LargeCompFormat := '#' + ThousandSeparator + '##0';
807     ThreeSigPlacesFormat := '#0' + DecimalSeparator + '000';
808     end;
809     writeln(OutFile,'Current memory = ', FormatFloat(LargeCompFormat,stats[psCurrentMemory]));
810     writeln(OutFile,'Delta memory = ', FormatFloat(LargeCompFormat,stats[psDeltaMemory]));
811     writeln(OutFile,'Max memory = ', FormatFloat(LargeCompFormat,stats[psMaxMemory]));
812     writeln(OutFile,'Elapsed time= ', FormatFloat(ThreeSigPlacesFormat,stats[psRealTime]/1000),' sec');
813     writeln(OutFile,'Cpu = ', FormatFloat(ThreeSigPlacesFormat,stats[psUserTime]/1000),' sec');
814     writeln(OutFile,'Buffers = ', FormatFloat('#0',stats[psBuffers]));
815     writeln(OutFile,'Reads = ', FormatFloat('#0',stats[psReads]));
816     writeln(OutFile,'Writes = ', FormatFloat('#0',stats[psWrites]));
817     writeln(OutFile,'Fetches = ', FormatFloat('#0',stats[psFetches]));
818     end;
819    
820     procedure TTestBase.WriteSQLData(aValue: ISQLData);
821     var s: AnsiString;
822     dt: TDateTime;
823     dstOffset: SmallInt;
824     aTimeZone: AnsiString;
825     begin
826     if aValue.IsNull then
827     writeln(OutFile,aValue.Name,' = NULL')
828     else
829     case aValue.SQLType of
830     SQL_ARRAY:
831     begin
832     write(OutFile, aValue.Name,' = ');
833     if not aValue.IsNull then
834     WriteArray(aValue.AsArray)
835     else
836     writeln(OutFile,'NULL');
837     end;
838     SQL_FLOAT,SQL_DOUBLE,
839     SQL_D_FLOAT:
840 tony 351 writeln(OutFile, aValue.Name,' = ',FormatFloat(FFloatTpl,aValue.AsDouble));
841 tony 334
842     SQL_INT64:
843     if aValue.Scale <> 0 then
844 tony 351 writeln(OutFile, aValue.Name,' = ',FormatFloat(FFloatTpl,aValue.AsDouble))
845 tony 334 else
846     writeln(OutFile,aValue.Name,' = ',aValue.AsString);
847    
848     SQL_BLOB:
849     if aValue.IsNull then
850     writeln(OutFile,aValue.Name,' = (null blob)')
851     else
852     if aValue.SQLSubType = 1 then
853     begin
854     s := aValue.AsString;
855     if FHexStrings then
856     begin
857     write(OutFile,aValue.Name,' = ');
858     PrintHexString(s);
859     writeln(OutFile,' (Charset Id = ',aValue.GetCharSetID, ' Codepage = ',StringCodePage(s),')');
860     end
861     else
862     begin
863     writeln(OutFile,aValue.Name,' (Charset Id = ',aValue.GetCharSetID, ' Codepage = ',StringCodePage(s),')');
864     writeln(OutFile);
865     writeln(OutFile,s);
866     end
867     end
868     else
869 tony 351 begin
870 tony 334 writeln(OutFile,aValue.Name,' = (blob), Length = ',aValue.AsBlob.GetBlobSize);
871 tony 351 if FShowBinaryBlob then
872     PrintHexString(aValue.AsString);
873     end;
874 tony 334
875     SQL_TEXT,SQL_VARYING:
876     begin
877     if aValue.GetCharSetID = 1 then
878     s := aValue.AsString
879     else
880     s := TrimRight(aValue.AsString);
881     if FHexStrings then
882     begin
883     write(OutFile,aValue.Name,' = ');
884     PrintHexString(s);
885     writeln(OutFile,' (Charset Id = ',aValue.GetCharSetID, ' Codepage = ',StringCodePage(s),')');
886     end
887     else
888     if aValue.GetCharSetID > 0 then
889     writeln(OutFile,aValue.Name,' = ',s,' (Charset Id = ',aValue.GetCharSetID, ' Codepage = ',StringCodePage(s),')')
890     else
891     writeln(OutFile,aValue.Name,' = ',s);
892     end;
893    
894     SQL_TIMESTAMP:
895     writeln(OutFile,aValue.Name,' = ',FBFormatDateTime('yyyy/mm/dd hh:nn:ss.zzzz',aValue.AsDateTime));
896     SQL_TYPE_DATE:
897     writeln(OutFile,aValue.Name,' = ',FBFormatDateTime('yyyy/mm/dd',aValue.AsDate));
898     SQL_TYPE_TIME:
899     writeln(OutFile,aValue.Name,' = ',FBFormatDateTime('hh:nn:ss.zzzz',aValue.AsTime));
900     SQL_TIMESTAMP_TZ,
901     SQL_TIMESTAMP_TZ_EX:
902     begin
903     aValue.GetAsDateTime(dt,dstOffset,aTimeZone);
904     writeln(OutFile,aValue.Name,' =');
905     writeln(OutFile,' AsString = ',aValue.GetAsString);
906     writeln(OutFile,' Formatted = ',FBFormatDateTime('yyyy/mm/dd hh:nn:ss.zzzz',dt),' ',aTimeZone);
907     writeln(OutFile,' TimeZoneID = ',aValue.GetStatement.GetAttachment.GetTimeZoneServices.TimeZoneName2TimeZoneID(aTimeZone));
908     writeln(OutFile,' Time Zone Name = ',aTimeZone);
909     writeln(OutFile,' UTC Time = ',DateTimeToStr( aValue.GetAsUTCDateTime));
910     writeln(OutFile,' DST Offset = ',dstOffset);
911     end;
912     SQL_TIME_TZ,
913     SQL_TIME_TZ_EX:
914     begin
915     aValue.GetAsDateTime(dt,dstOffset,aTimeZone);
916     writeln(OutFile,aValue.Name,' =');
917     writeln(OutFile,' AsString = ',aValue.GetAsString);
918     writeln(OutFile,' Formatted = ',FBFormatDateTime('hh:nn:ss.zzzz',dt),' ',aTimeZone);
919     writeln(OutFile,' TimeZoneID = ',aValue.GetStatement.GetAttachment.GetTimeZoneServices.TimeZoneName2TimeZoneID(aTimeZone));
920     writeln(OutFile,' Time Zone Name = ',aTimeZone);
921     writeln(OutFile,' UTC Time = ',TimeToStr( aValue.GetAsUTCDateTime));
922     writeln(OutFile,' DST Offset = ',dstOffset);
923     end;
924    
925     else
926     writeln(OutFile,aValue.Name,' = ',aValue.AsString);
927     end;
928     end;
929    
930     procedure TTestBase.CheckActivity(Attachment: IAttachment);
931     begin
932     writeln(OutFile,'Database Activity = ',Attachment.HasActivity)
933     end;
934    
935     procedure TTestBase.CheckActivity(Transaction: ITransaction);
936     begin
937     writeln(OutFile,'Transaction Activity = ',Transaction.HasActivity)
938     end;
939    
940     procedure TTestBase.InitTest;
941     begin
942     //Do nothing yet
943     end;
944    
945     function TTestBase.SkipTest: boolean;
946     begin
947     Result := false;
948     end;
949    
950     procedure TTestBase.ProcessResults;
951     begin
952     //Do nothing
953     end;
954    
955 tony 351 procedure TTestBase.SetFloatTemplate(tpl: Ansistring);
956     begin
957     FFloatTpl := tpl;
958     end;
959    
960 tony 334 { TTestApplication }
961    
962     class procedure TTestApplication.CreateTestList;
963     begin
964     if FTests = nil then
965     begin
966     FTests := TStringList.Create;
967     FTests.Sorted := true;
968     FTests.Duplicates := dupError;
969     end;
970     end;
971    
972     class procedure TTestApplication.DestroyTestList;
973     var i: integer;
974     TestID: Ansistring;
975     begin
976     if assigned(FTests) then
977     begin
978     for i := 0 to FTests.Count - 1 do
979     if FTests.Objects[i] <> nil then
980     try
981     TestID := TTestBase(FTests.Objects[i]).TestID;
982     FTests.Objects[i].Free;
983     except on E: Exception do
984     writeln('Error Freeing Test ',TestID,' Error message = ',E.Message);
985     end;
986     FreeAndNil(FTests);
987     end;
988     end;
989    
990     procedure TTestApplication.CleanUp;
991     var DPB: IDPB;
992     Attachment: IAttachment;
993     begin
994     DPB := FirebirdAPI.AllocateDPB;
995     DPB.Add(isc_dpb_user_name).setAsString(GetUserName);
996     DPB.Add(isc_dpb_password).setAsString(GetPassword);
997     Attachment := FirebirdAPI.OpenDatabase(GetNewDatabaseName,DPB,false);
998     if Attachment <> nil then
999     Attachment.DropDatabase;
1000     Attachment := FirebirdAPI.OpenDatabase(GetSecondNewDatabaseName,DPB,false);
1001     if Attachment <> nil then
1002     Attachment.DropDatabase;
1003     end;
1004    
1005     function TTestApplication.GetFirebirdAPI: IFirebirdAPI;
1006     begin
1007     if FFirebirdAPI = nil then
1008 tony 351 begin
1009 tony 334 FFirebirdAPI := IB.FirebirdAPI;
1010 tony 351 FFirebirdAPI.GetStatus.SetIBDataBaseErrorMessages([ShowIBMessage]);;
1011     end;
1012 tony 334 Result := FFirebirdAPI;
1013     end;
1014    
1015     function TTestApplication.GetIndexByTestID(aTestID: AnsiString): integer;
1016     begin
1017     try
1018     Result := FTests.IndexOf(aTestID);
1019     except
1020     raise Exception.CreateFmt('Invalid Test ID - %s',[aTestID]);
1021     end;
1022     if Result = -1 then
1023     raise Exception. CreateFmt('Invalid Test ID - %s',[aTestID]);
1024     end;
1025    
1026     constructor TTestApplication.Create(AOwner: TComponent);
1027     var i: integer;
1028     begin
1029     inherited Create(AOwner);
1030     TestApp := self;
1031     CreateTestList;
1032     FNewDatabaseName := GetTempDir + 'fbtestsuite.fdb';
1033     FSecondNewDatabaseName := GetTempDir + 'fbtestsuite2.fdb';
1034     FUserName := 'SYSDBA';
1035     FPassword := 'masterkey';
1036     FEmployeeDatabaseName := 'employee';
1037     FBackupFileName := GetTempDir + 'testbackup.gbk';
1038     FServer := 'localhost';
1039     for i := 0 to FTests.Count - 1 do
1040     begin
1041     TTestBase(FTests.Objects[i]).SetOwner(self);
1042     // TTestBase(FTests.Objects[i]).CreateObjects(self);
1043     end;
1044     end;
1045    
1046     destructor TTestApplication.Destroy;
1047     begin
1048     DestroyTestList;
1049     TestApp := nil;
1050     inherited Destroy;
1051     end;
1052    
1053     function TTestApplication.GetUserName: AnsiString;
1054     begin
1055     Result := FUserName;
1056     end;
1057    
1058     function TTestApplication.GetPassword: AnsiString;
1059     begin
1060     Result := FPassword;
1061     end;
1062    
1063     function TTestApplication.GetEmployeeDatabaseName: AnsiString;
1064     begin
1065     if FirebirdAPI.GetClientMajor < 3 then
1066     Result := MakeConnectString(FServer, FEmployeeDatabaseName, TCP,FPortNo)
1067     else
1068     Result := MakeConnectString(FServer, FEmployeeDatabaseName, inet,FPortNo);
1069     end;
1070    
1071     function TTestApplication.GetNewDatabaseName: AnsiString;
1072     begin
1073     if FirebirdAPI.GetClientMajor < 3 then
1074     Result := MakeConnectString(FServer, FNewDatabaseName, TCP,FPortNo)
1075     else
1076     Result := MakeConnectString(FServer, FNewDatabaseName, inet,FPortNo);
1077     end;
1078    
1079 tony 351 function TTestApplication.GetTempDatabaseName: AnsiString;
1080     begin
1081     Result := GetTempDir + 'fbtest.fbd';
1082     end;
1083    
1084 tony 334 function TTestApplication.GetSecondNewDatabaseName: AnsiString;
1085     begin
1086     if FirebirdAPI.GetClientMajor < 3 then
1087     Result := MakeConnectString(FServer, FSecondNewDatabaseName, TCP,FPortNo)
1088     else
1089     Result := MakeConnectString(FServer, FSecondNewDatabaseName, inet,FPortNo);
1090     end;
1091    
1092     function TTestApplication.GetBackupFileName: AnsiString;
1093     begin
1094     Result := FBackupFileName;
1095     end;
1096    
1097     procedure TTestApplication.RunAll;
1098     var i: integer;
1099     begin
1100     CleanUp;
1101     for i := 0 to FTests.Count - 1 do
1102     begin
1103     DoTest(i);
1104     if not Quiet then
1105     writeln(Outfile,'------------------------------------------------------');
1106 tony 351 Sleep(500);
1107 tony 334 end;
1108     end;
1109    
1110     procedure TTestApplication.RunTest(TestID: AnsiString);
1111     begin
1112     CleanUp;
1113     DoTest(GetIndexByTestID(TestID));
1114     end;
1115    
1116     procedure TTestApplication.SetClientLibraryPath(aLibName: string);
1117     var i: integer;
1118     begin
1119     FFirebirdAPI := LoadFBLibrary(aLibName).GetFirebirdAPI;
1120     FClientLibraryPath := aLibName;
1121     for i := 0 to FTests.Count - 1 do
1122     TTestBase(FTests.Objects[i]).ClientLibraryPathChanged;
1123    
1124     end;
1125    
1126     procedure TTestApplication.SetUserName(aValue: AnsiString);
1127     begin
1128     FUserName := aValue;
1129     end;
1130    
1131     procedure TTestApplication.SetPassword(aValue: AnsiString);
1132     begin
1133     FPassword := aValue;
1134     end;
1135    
1136     procedure TTestApplication.SetEmployeeDatabaseName(aValue: AnsiString);
1137     begin
1138     FEmployeeDatabaseName := aValue;
1139     end;
1140    
1141     procedure TTestApplication.SetNewDatabaseName(aValue: AnsiString);
1142     begin
1143     FNewDatabaseName := aValue;
1144     end;
1145    
1146     procedure TTestApplication.SetSecondNewDatabaseName(aValue: AnsiString);
1147     begin
1148     FSecondNewDatabaseName := aValue;
1149     end;
1150    
1151     procedure TTestApplication.SetBackupFileName(aValue: AnsiString);
1152     begin
1153     FBackupFileName := aValue;
1154     end;
1155    
1156     procedure TTestApplication.SetServerName(AValue: AnsiString);
1157     begin
1158     if FServer = AValue then Exit;
1159     FServer := AValue;
1160     end;
1161    
1162     procedure TTestApplication.SetPortNum(aValue: AnsiString);
1163     begin
1164     FPortNo := aValue;
1165     end;
1166    
1167     procedure TTestApplication.SetTestOption(aValue: AnsiString);
1168     begin
1169     FTestOption := AValue;
1170     end;
1171    
1172     {$IFDEF FPC}
1173     function TTestApplication.GetShortOptions: AnsiString;
1174     begin
1175     Result := 'htupensbolrSPXOq';
1176     end;
1177    
1178     function TTestApplication.GetLongOptions: AnsiString;
1179     begin
1180     Result := 'help test user passwd employeedb newdbname secondnewdbname backupfile '+
1181     'outfile fbclientlibrary server stats port prompt TestOption quiet';
1182     end;
1183    
1184     procedure TTestApplication.GetParams(var DoPrompt: boolean; var TestID: string);
1185     var ErrorMsg: String;
1186     begin
1187     // quick check parameters
1188     ErrorMsg := CheckOptions(GetShortOptions,GetLongOptions);
1189     if ErrorMsg <> '' then begin
1190     ShowException(Exception.Create(ErrorMsg));
1191     Terminate;
1192     Exit;
1193     end;
1194    
1195     // parse parameters
1196     if HasOption('h', 'help') then begin
1197     WriteHelp;
1198     Terminate;
1199     Exit;
1200     end;
1201    
1202     if HasOption('t') then
1203     TestID := GetOptionValue('t');
1204     if Length(TestID) = 1 then
1205     TestID := '0' + TestID;
1206    
1207     DoPrompt := HasOption('X','prompt');
1208    
1209     if HasOption('u','user') then
1210     SetUserName(GetOptionValue('u'));
1211    
1212     if HasOption('p','passwd') then
1213     SetPassword(GetOptionValue('p'));
1214    
1215     if HasOption('e','employeedb') then
1216     SetEmployeeDatabaseName(GetOptionValue('e'));
1217    
1218     if HasOption('n','newdbname') then
1219     SetNewDatabaseName(GetOptionValue('n'));
1220    
1221     if HasOption('s','secondnewdbname') then
1222     SetSecondNewDatabaseName(GetOptionValue('s'));
1223    
1224     if HasOption('b','backupfile') then
1225     SetBackupFileName(GetOptionValue('b'));
1226    
1227     if HasOption('l','fbclientlibrary') then
1228     SetClientLibraryPath(GetOptionValue('l'));
1229    
1230     if HasOption('r','server') then
1231     SetServerName(GetOptionValue('r'));
1232    
1233     if HasOption('o','outfile') then
1234     begin
1235     system.Assign(outFile,GetOptionValue('o'));
1236     ReWrite(outFile);
1237     end;
1238    
1239     if HasOption('P','port') then
1240     SetPortNum(GetOptionValue('P'));
1241    
1242     ShowStatistics := HasOption('S','stats');
1243    
1244     if HasOption('O','TestOption') then
1245     SetTestOption(GetOptionValue('O'));
1246    
1247     FQuiet := HasOption('q','quiet')
1248     end;
1249     {$ENDIF}
1250    
1251     {$IFDEF DCC}
1252     procedure TTestApplication.GetParams(var DoPrompt: boolean; var TestID: string);
1253    
1254     function GetCmdLineValue(const Switch: string; var aValue: string): boolean;
1255     var i: integer;
1256     begin
1257     aValue := '';
1258     Result := FindCmdLineSwitch(Switch,false);
1259     if Result then
1260     begin
1261     for i := 0 to ParamCount do
1262     if (ParamStr(i) = '-' + Switch) and (i <= ParamCount) then
1263     begin
1264     aValue := ParamStr(i+1);
1265     exit;
1266     end;
1267     Result := false;
1268     end;
1269     end;
1270    
1271     var aValue: string;
1272    
1273     begin
1274     // parse parameters
1275     if FindCmdLineSwitch('h') or FindCmdLineSwitch('help') then
1276     begin
1277     WriteHelp;
1278     Exit;
1279     end;
1280    
1281     if GetCmdLineValue('t',aValue) then
1282     TestID := aValue;
1283    
1284     DoPrompt := GetCmdLineValue('X',aValue);
1285    
1286     if GetCmdLineValue('u',aValue) or GetCmdLineValue('user',aValue) then
1287     SetUserName(aValue);
1288    
1289     if GetCmdLineValue('p',aValue) or GetCmdLineValue('passwd',aValue) then
1290     SetPassword(aValue);
1291    
1292     if GetCmdLineValue('e',aValue) or GetCmdLineValue('employeedb',aValue) then
1293     SetEmployeeDatabaseName(aValue);
1294    
1295     if GetCmdLineValue('n',aValue) or GetCmdLineValue('newdbname',aValue) then
1296     SetNewDatabaseName(aValue);
1297    
1298     if GetCmdLineValue('s',aValue) or GetCmdLineValue('secondnewdbname',aValue) then
1299     SetSecondNewDatabaseName(aValue);
1300    
1301     if GetCmdLineValue('b',aValue) or GetCmdLineValue('backupfile',aValue) then
1302     SetBackupFileName(aValue);
1303    
1304     if GetCmdLineValue('r',aValue) or GetCmdLineValue('server',aValue) then
1305     SetServerName(aValue);
1306    
1307     if GetCmdLineValue('P',aValue) or GetCmdLineValue('port',aValue) then
1308     SetPortNum(aValue);
1309    
1310     if GetCmdLineValue('l',aValue) or GetCmdLineValue('fbclientlibrary',aValue) then
1311     SetClientLibraryPath(aValue);
1312    
1313     if GetCmdLineValue('o',aValue) or GetCmdLineValue('outfile',aValue) then
1314     begin
1315     system.Assign(outFile,aValue);
1316     ReWrite(outFile);
1317     end;
1318    
1319     ShowStatistics := FindCmdLineSwitch('S',false) or FindCmdLineSwitch('stats');
1320    
1321     if GetCmdLineValue('O',aValue) or GetCmdLineValue('TestOption',aValue) then
1322     SetTestOption(aValue);
1323    
1324     FQuiet := FindCmdLineSwitch('q',false) or FindCmdLineSwitch('quiet');
1325     end;
1326     {$ENDIF}
1327    
1328     procedure TTestApplication.DoRun;
1329     var
1330     DoPrompt: boolean;
1331     TestID: string;
1332     MasterProvider: IFBIMasterProvider;
1333     begin
1334     {$IFDEF FPC}
1335     OutFile := stdout;
1336     {$ELSE}
1337     AssignFile(OutFile,'');
1338     ReWrite(outFile);
1339     {$ENDIF}
1340    
1341     GetParams(DoPrompt,TestID);
1342     if length(TestID) = 1 then
1343     TestID := '0' + TestID;
1344     {$IF declared(SetTextCodePage)}
1345     {Ensure consistent UTF-8 output}
1346     SetTextCodePage(OutFile,cp_utf8);
1347     {$IFEND}
1348     {$IF declared(SetConsoleOutputCP)}
1349     SetConsoleOutputCP(cp_utf8);
1350     {$IFEND}
1351    
1352    
1353     {Ensure consistent date reporting across platforms}
1354     SetFormatSettings;
1355    
1356     if not Quiet then
1357     begin
1358     writeln(OutFile,Title);
1359     writeln(OutFile,Copyright);
1360     writeln(OutFile);
1361     writeln(OutFile,'Starting Tests');
1362     writeln(OutFile,'Client API Version = ',FirebirdAPI.GetImplementationVersion);
1363     writeln(OutFile,'Firebird Environment Variable = ',sysutils.GetEnvironmentVariable('FIREBIRD'));
1364     if FirebirdAPI.HasMasterIntf and (FirebirdAPI.QueryInterface(IFBIMasterProvider,MasterProvider) = S_OK) then
1365     with MasterProvider.GetIMasterIntf.getConfigManager do
1366     begin
1367     writeln(OutFile,'Firebird Bin Directory = ', getDirectory(DIR_BIN));
1368     writeln(OutFile,'Firebird Conf Directory = ', getDirectory(DIR_CONF));
1369     end;
1370     writeln(OutFile,'Firebird Client Library Path = ',FirebirdAPI.GetFBLibrary.GetLibraryFilePath);
1371     end;
1372    
1373     try
1374     if TestID = '' then
1375     RunAll
1376     else
1377     RunTest(TestID);
1378 tony 351 CleanUp;
1379 tony 334 except on E: Exception do
1380     begin
1381     writeln('Exception: ',E.Message);
1382     writeln(OutFile,'Exception: ',E.Message);
1383     end;
1384     end;
1385    
1386     writeln(OutFile,'Test Suite Ends');
1387     Flush(OutFile);
1388     {$IFDEF WINDOWS}
1389     if DoPrompt then
1390     begin
1391     write('Press Entry to continue');
1392     readln; {when running from IDE and console window closes before you can view results}
1393     end;
1394     {$ENDIF}
1395    
1396     // stop program loop
1397     Terminate;
1398     end;
1399    
1400     procedure TTestApplication.DoTest(index: integer);
1401     begin
1402     if FTests.Objects[index] = nil then Exit;
1403     try
1404     with TTestBase(FTests.Objects[index]) do
1405     if SkipTest then
1406     writeln(OutFile,' Skipping ' + TestID)
1407     else
1408     begin
1409     if not Quiet then
1410     writeln(OutFile,'Running ' + TestTitle);
1411     if not ChildProcess then
1412     writeln(ErrOutput,'Running ' + TestTitle);
1413     try
1414     CreateObjects(self);
1415     InitTest;
1416     RunTest('UTF8',3);
1417     ProcessResults;
1418     except
1419     on E:ESkipException do
1420     writeln(OutFile,'Skipping Test: ' + E.Message);
1421     on E:Exception do
1422     begin
1423     writeln(OutFile,'Test Completed with Error: ' + E.Message);
1424     Exit;
1425     end;
1426     end;
1427     if not Quiet then
1428     begin
1429     writeln(OutFile);
1430     writeln(OutFile);
1431     end;
1432     end;
1433     finally
1434     FTests.Objects[index].Free;
1435     FTests.Objects[index] := nil;
1436     DestroyComponents;
1437     end;
1438     end;
1439    
1440     procedure TTestApplication.SetFormatSettings;
1441     begin
1442     {$IF declared(DefaultFormatSettings)}
1443     with DefaultFormatSettings do
1444     {$ELSE}
1445     {$IF declared(FormatSettings)}
1446     with FormatSettings do
1447     {$IFEND}{$IFEND}
1448     begin
1449     ShortDateFormat := 'dd/m/yyyy';
1450     LongTimeFormat := 'HH:MM:SS';
1451     DateSeparator := '/';
1452     end;
1453     end;
1454    
1455     procedure TTestApplication.WriteHelp;
1456     begin
1457     { add your help code here }
1458     writeln(OutFile,'Usage: ', ExeName, ' -h');
1459     end;
1460    
1461     {$IFNDEF FPC}
1462     function TCustomApplication.Exename: string;
1463     begin
1464     Result := ParamStr(0);
1465     end;
1466    
1467     procedure TCustomApplication.Run;
1468     begin
1469     try
1470     DoRun;
1471     except on E: Exception do
1472     writeln(OutFile,E.Message);
1473     end;
1474     end;
1475    
1476     procedure TCustomApplication.Terminate;
1477     begin
1478    
1479     end;
1480     {$ENDIF}
1481    
1482     end.
1483