ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/testsuite/testApp/TestApplication.pas
Revision: 410
Committed: Thu Jun 22 13:52:39 2023 UTC (17 months ago) by tony
Content type: text/x-pascal
File size: 45347 byte(s)
Log Message:
Release 2.6.0 beta

File Contents

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

Properties

Name Value
svn:eol-style native