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

# Content
1 (*
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 FFloatTpl: AnsiString;
81 FCursorSeq: integer;
82 function GetFirebirdAPI: IFirebirdAPI;
83 procedure SetOwner(AOwner: TTestApplication);
84 {$if declared(TJnlEntry) }
85 procedure HandleOnJnlEntry(JnlEntry: TJnlEntry);
86 {$endif}
87 protected
88 FHexStrings: boolean;
89 FShowBinaryBlob: boolean;
90 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 {$if declared(TJnlEntry) }
103 procedure PrintJournalFile(aFileName: AnsiString);
104 procedure PrintJournalTable(Attachment: IAttachment);
105 {$ifend}
106 function ReportResults(Statement: IStatement; ShowCursorName: boolean=false): IResultSet;
107 procedure ReportResult(aValue: IResults);
108 function StringToHex(octetString: string; MaxLineLength: integer=0): string;
109 procedure WriteAttachmentInfo(Attachment: IAttachment);
110 procedure WriteArray(ar: IArray);
111 procedure WriteAffectedRows(Statement: IStatement);
112 procedure WriteDBInfo(DBInfo: IDBInformation);
113 procedure WriteTRInfo(TrInfo: ITrInformation);
114 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 procedure SetFloatTemplate(tpl: Ansistring);
124 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 function GetTempDatabaseName: AnsiString;
190 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 { 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 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 {$IFNDEF MSWINDOWS}
231 uses MD5;
232 {$ENDIF}
233
234 {$IFDEF MSWINDOWS}
235 uses {$IFDEF FPC}MD5,{$ENDIF} windows;
236
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 {$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 { TTestBase }
365
366 constructor TTestBase.Create(aOwner: TTestApplication);
367 begin
368 inherited Create;
369 FOwner := aOwner;
370 FFloatTpl := '#,###.00';
371 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 {$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 writeln(Outfile,'Attachment ID = ',AttachmentID);
405 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 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 if not IsNull then
607 writeln(Outfile,'Value = ',getAsString);
608 writeln(OutFile);
609 end;
610 end;
611
612 {$if declared(TJnlEntry) }
613 procedure TTestBase.PrintJournalFile(aFileName: AnsiString);
614 begin
615 writeln(OutFile,'Journal Entries');
616 TJournalProcessor.Execute(aFileName,FirebirdAPI,HandleOnJnlEntry);
617 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 function TTestBase.ReportResults(Statement: IStatement; ShowCursorName: boolean): IResultSet;
633 begin
634 Result := Statement.OpenCursor;
635 try
636 if ShowCursorName then
637 writeln(Outfile,'Results for Cursor: ',Result.GetCursorName);
638 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 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 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 writeln(OutFile);
842 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 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 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 writeln(OutFile, aValue.Name,' = ',FormatFloat(FFloatTpl,aValue.AsDouble));
984
985 SQL_INT64:
986 if aValue.Scale <> 0 then
987 writeln(OutFile, aValue.Name,' = ',FormatFloat(FFloatTpl,aValue.AsDouble))
988 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 begin
1013 writeln(OutFile,aValue.Name,' = (blob), Length = ',aValue.AsBlob.GetBlobSize);
1014 if FShowBinaryBlob then
1015 PrintHexString(aValue.AsString);
1016 end;
1017
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 procedure TTestBase.SetFloatTemplate(tpl: Ansistring);
1099 begin
1100 FFloatTpl := tpl;
1101 end;
1102
1103 { 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 begin
1152 FFirebirdAPI := IB.FirebirdAPI;
1153 FFirebirdAPI.GetStatus.SetIBDataBaseErrorMessages([ShowIBMessage]);;
1154 end;
1155 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 function TTestApplication.GetTempDatabaseName: AnsiString;
1223 begin
1224 Result := GetTempDir + 'fbtest.fbd';
1225 end;
1226
1227 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 Sleep(500);
1250 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 CleanUp;
1522 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