ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/testsuite/testApp/TestApplication.pas
Revision: 421
Committed: Sat Oct 21 14:22:28 2023 UTC (12 months, 3 weeks ago) by tony
Content type: text/x-pascal
File size: 45592 byte(s)
Log Message:
Release 2.6.3 Merged

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 begin
608 if getCharSetID = 1 then
609 begin
610 PrintHexString(getAsString);
611 writeln(Outfile);
612 end
613 else
614 writeln(Outfile,'Value = ',getAsString);
615 end;
616 writeln(OutFile);
617 end;
618 end;
619
620 {$if declared(TJnlEntry) }
621 procedure TTestBase.PrintJournalFile(aFileName: AnsiString);
622 begin
623 writeln(OutFile,'Journal Entries');
624 TJournalProcessor.Execute(aFileName,FirebirdAPI,HandleOnJnlEntry);
625 end;
626
627 procedure TTestBase.PrintJournalTable(Attachment: IAttachment);
628 var Results: IResultSet;
629 begin
630 writeln(OutFile,'Journal Table');
631 Results := Attachment.OpenCursorAtStart('Select * From IBX$JOURNALS');
632 while not Results.IsEof do
633 begin
634 ReportResult(Results);
635 Results.Fetchnext;
636 end;
637 end;
638 {$ifend}
639
640 function TTestBase.ReportResults(Statement: IStatement; ShowCursorName: boolean): IResultSet;
641 begin
642 Result := Statement.OpenCursor;
643 try
644 if ShowCursorName then
645 writeln(Outfile,'Results for Cursor: ',Result.GetCursorName);
646 while Result.FetchNext do
647 ReportResult(Result);
648 finally
649 Result.Close;
650 end;
651 writeln(OutFile);
652 end;
653
654 procedure TTestBase.ReportResult(aValue: IResults);
655 var i: integer;
656 begin
657 for i := 0 to aValue.getCount - 1 do
658 WriteSQLData(aValue[i]);
659 end;
660
661 function TTestBase.StringToHex(octetString: string; MaxLineLength: integer
662 ): string;
663
664 function ToHex(aValue: byte): string;
665 const
666 HexChars: array [0..15] of char = '0123456789ABCDEF';
667 begin
668 Result := HexChars[aValue shr 4] +
669 HexChars[(aValue and $0F)];
670 end;
671
672 var i, j: integer;
673 begin
674 i := 1;
675 Result := '';
676 if MaxLineLength = 0 then
677 while i <= Length(octetString) do
678 begin
679 Result := Result + ToHex(byte(octetString[i]));
680 Inc(i);
681 end
682 else
683 while i <= Length(octetString) do
684 begin
685 for j := 1 to MaxLineLength do
686 begin
687 if i > Length(octetString) then
688 Exit
689 else
690 Result := Result + ToHex(byte(octetString[i]));
691 inc(i);
692 end;
693 Result := Result + LineEnding;
694 end;
695 end;
696
697 procedure TTestBase.WriteAttachmentInfo(Attachment: IAttachment);
698 begin
699 writeln(outfile,'DB Connect String = ',Attachment.GetConnectString);
700 writeln(outfile,'DB Charset ID = ',Attachment.GetDefaultCharSetID);
701 writeln(outfile,'DB SQL Dialect = ',Attachment.GetSQLDialect);
702 writeln(outfile,'DB Remote Protocol = ', Attachment.GetRemoteProtocol);
703 writeln(outfile,'DB ODS Major Version = ',Attachment.GetODSMajorVersion);
704 writeln(outfile,'DB ODS Minor Version = ',Attachment.GetODSMinorVersion);
705 writeln(outfile,'User Authentication Method = ',Attachment.GetAuthenticationMethod);
706 writeln(outfile,'Firebird Library Path = ',Attachment.getFirebirdAPI.GetFBLibrary.GetLibraryFilePath);
707 writeln(outfile,'DB Client Implementation Version = ',Attachment.getFirebirdAPI.GetImplementationVersion);
708 end;
709
710 procedure TTestBase.WriteArray(ar: IArray);
711 var Bounds: TArrayBounds;
712 i,j: integer;
713 begin
714 write(OutFile,'Array: ');
715 Bounds := ar.GetBounds;
716 case ar.GetDimensions of
717 1:
718 begin
719 for i := Bounds[0].LowerBound to Bounds[0].UpperBound do
720 write(OutFile,'(',i,': ',ar.GetAsVariant([i]),') ');
721 end;
722
723 2:
724 begin
725 for i := Bounds[0].LowerBound to Bounds[0].UpperBound do
726 for j := Bounds[1].LowerBound to Bounds[1].UpperBound do
727 write(OutFile,'(',i,',',j,': ',ar.GetAsVariant([i,j]),') ');
728 end;
729 end;
730 writeln(OutFile);
731 writeln(OutFile);
732 end;
733
734 procedure TTestBase.WriteAffectedRows(Statement: IStatement);
735 var SelectCount, InsertCount, UpdateCount, DeleteCount: integer;
736 begin
737 Statement.GetRowsAffected(SelectCount, InsertCount, UpdateCount, DeleteCount);
738 writeln(OutFile,'Select Count = ', SelectCount,' InsertCount = ',InsertCount,' UpdateCount = ', UpdateCount, ' DeleteCount = ',DeleteCount);
739 end;
740
741 procedure TTestBase.WriteDBInfo(DBInfo: IDBInformation);
742 var i, j: integer;
743 bytes: TByteArray;
744 ConType: integer;
745 DBFileName: AnsiString;
746 DBSiteName: AnsiString;
747 Version: byte;
748 VersionString: AnsiString;
749 Users: TStringList;
750 begin
751 for i := 0 to DBInfo.GetCount - 1 do
752 with DBInfo[i] do
753 case getItemType of
754 isc_info_db_read_only:
755 if getAsInteger <> 0 then
756 writeln(OutFile,'Database is Read Only')
757 else
758 writeln(OutFile,'Database is Read/Write');
759 isc_info_allocation:
760 writeln(OutFile,'Pages =',getAsInteger);
761 isc_info_base_level:
762 begin
763 bytes := getAsBytes;
764 write(OutFile,'Base Level = ');
765 WriteBytes(Bytes);
766 end;
767 isc_info_db_id:
768 begin
769 DecodeIDCluster(ConType,DBFileName,DBSiteName);
770 writeln(OutFile,'Database ID = ', ConType,' FB = ', DBFileName, ' SN = ',DBSiteName);
771 end;
772 isc_info_implementation:
773 begin
774 bytes := getAsBytes;
775 write(OutFile,'Implementation = ');
776 WriteBytes(Bytes);
777 end;
778 isc_info_no_reserve:
779 writeln(OutFile,'Reserved = ',getAsInteger);
780 isc_info_ods_minor_version:
781 writeln(OutFile,'ODS minor = ',getAsInteger);
782 isc_info_ods_version:
783 writeln(OutFile,'ODS major = ',getAsInteger);
784 isc_info_page_size:
785 writeln(OutFile,'Page Size = ',getAsInteger);
786 isc_info_version:
787 begin
788 DecodeVersionString(Version,VersionString);
789 writeln(OutFile,'Version = ',Version,': ',VersionString);
790 end;
791 isc_info_current_memory:
792 writeln(OutFile,'Server Memory = ',getAsInteger);
793 isc_info_forced_writes:
794 writeln(OutFile,'Forced Writes = ',getAsInteger);
795 isc_info_max_memory:
796 writeln(OutFile,'Max Memory = ',getAsInteger);
797 isc_info_num_buffers:
798 writeln(OutFile,'Num Buffers = ',getAsInteger);
799 isc_info_sweep_interval:
800 writeln(OutFile,'Sweep Interval = ',getAsInteger);
801 isc_info_user_names:
802 begin
803 Users := TStringList.Create;
804 try
805 write(OutFile,'Logged in Users: ');
806 DecodeUserNames(Users);
807 for j := 0 to Users.Count - 1 do
808 write(OutFile,Users[j],',');
809
810 finally
811 Users.Free;
812 end;
813 writeln(OutFile);
814 end;
815 isc_info_fetches:
816 writeln(OutFile,'Fetches = ',getAsInteger);
817 isc_info_marks:
818 writeln(OutFile,'Writes = ',getAsInteger);
819 isc_info_reads:
820 writeln(OutFile,'Reads = ',getAsInteger);
821 isc_info_writes:
822 writeln(OutFile,'Page Writes = ',getAsInteger);
823 isc_info_backout_count:
824 WriteOperationCounts('Record Version Removals',getOperationCounts);
825 isc_info_delete_count:
826 WriteOperationCounts('Deletes',getOperationCounts);
827 isc_info_expunge_count:
828 WriteOperationCounts('Expunge Count',getOperationCounts);
829 isc_info_insert_count:
830 WriteOperationCounts('Insert Count',getOperationCounts);
831 isc_info_purge_count:
832 WriteOperationCounts('Purge Count Countites',getOperationCounts);
833 isc_info_read_idx_count:
834 WriteOperationCounts('Indexed Reads Count',getOperationCounts);
835 isc_info_read_seq_count:
836 WriteOperationCounts('Sequential Table Scans',getOperationCounts);
837 isc_info_update_count:
838 WriteOperationCounts('Update Count',getOperationCounts);
839 isc_info_db_SQL_Dialect:
840 writeln(OutFile,'SQL Dialect = ',getAsInteger);
841 isc_info_creation_date:
842 writeln(OutFile,'Database Created: ',DateTimeToStr(getAsDateTime));
843 isc_info_active_tran_count:
844 writeln(OutFile,'Active Transaction Count = ',getAsInteger);
845 fb_info_page_contents:
846 begin
847 writeln('Database Page');
848 PrintHexString(getAsString);
849 writeln(OutFile);
850 end;
851 fb_info_pages_used:
852 writeln(OutFile,'Pages Used = ',getAsInteger);
853 fb_info_pages_free:
854 writeln(OutFile,'Pages Free = ',getAsInteger);
855
856 isc_info_truncated:
857 writeln(OutFile,'Results Truncated');
858 else
859 writeln(OutFile,'Unknown Response ',getItemType);
860 end;
861 end;
862
863 procedure TTestBase.WriteTRInfo(TrInfo: ITrInformation);
864 var IsolationType, RecVersion: byte;
865 i: integer;
866 access: integer;
867 begin
868 for i := 0 to TrInfo.GetCount - 1 do
869 with TrInfo[i] do
870 case getItemType of
871 isc_info_tra_id:
872 writeln(OutFile,'Transaction ID = ',getAsInteger);
873 isc_info_tra_oldest_interesting:
874 writeln(OutFile,'Oldest Interesting = ',getAsInteger);
875 isc_info_tra_oldest_active:
876 writeln(OutFile,'Oldest Action = ',getAsInteger);
877 isc_info_tra_oldest_snapshot:
878 writeln(OutFile,'Oldest Snapshot = ',getAsInteger);
879 fb_info_tra_snapshot_number:
880 writeln(OutFile,'Oldest Snapshot Number = ',getAsInteger);
881 isc_info_tra_lock_timeout:
882 writeln(OutFile,'Lock Timeout = ',getAsInteger);
883 isc_info_tra_isolation:
884 begin
885 DecodeTraIsolation(IsolationType, RecVersion);
886 write(OutFile,'Isolation Type = ');
887 case IsolationType of
888 isc_info_tra_consistency:
889 write(OutFile,'isc_info_tra_consistency');
890 isc_info_tra_concurrency:
891 write(OutFile,'isc_info_tra_concurrency');
892 isc_info_tra_read_committed:
893 begin
894 write(OutFile,'isc_info_tra_read_committed, Options =');
895 case RecVersion of
896 isc_info_tra_no_rec_version:
897 write(OutFile,'isc_info_tra_no_rec_version');
898 isc_info_tra_rec_version:
899 write(OutFile,'isc_info_tra_rec_version');
900 isc_info_tra_read_consistency:
901 write(OutFile,'isc_info_tra_read_consistency');
902 end;
903 end;
904 end;
905 writeln(OutFile);
906 end;
907 isc_info_tra_access:
908 begin
909 write(OutFile,'Transaction Access = ');
910 access := getAsInteger;
911 case access of
912 isc_info_tra_readonly:
913 writeln(OutFile,'isc_info_tra_readonly');
914 isc_info_tra_readwrite:
915 writeln(OutFile,'isc_info_tra_readwrite');
916 end;
917 end;
918 fb_info_tra_dbpath:
919 writeln(OutFile,'Transaction Database Path = ',getAsString);
920 end;
921
922 end;
923
924 procedure TTestBase.WriteBytes(Bytes: TByteArray);
925 var i: integer;
926 begin
927 for i := 0 to length(Bytes) - 1 do
928 write(OutFile,Bytes[i],',');
929 writeln(OutFile);
930 end;
931
932 procedure TTestBase.WriteOperationCounts(Category: AnsiString;
933 ops: TDBOperationCounts);
934 var i: integer;
935 begin
936 writeln(OutFile,Category,' Operation Counts');
937 for i := 0 to Length(ops) - 1 do
938 begin
939 writeln(OutFile,'Table ID = ',ops[i].TableID);
940 writeln(OutFile,'Count = ',ops[i].Count);
941 end;
942 writeln(OutFile);
943 end;
944
945 procedure TTestBase.WritePerfStats(stats: TPerfCounters);
946 var LargeCompFormat: string;
947 ThreeSigPlacesFormat: string;
948 begin
949 {$IF declared(DefaultFormatSettings)}
950 with DefaultFormatSettings do
951 {$ELSE}
952 {$IF declared(FormatSettings)}
953 with FormatSettings do
954 {$IFEND}
955 {$IFEND}
956 begin
957 LargeCompFormat := '#' + ThousandSeparator + '##0';
958 ThreeSigPlacesFormat := '#0' + DecimalSeparator + '000';
959 end;
960 writeln(OutFile,'Current memory = ', FormatFloat(LargeCompFormat,stats[psCurrentMemory]));
961 writeln(OutFile,'Delta memory = ', FormatFloat(LargeCompFormat,stats[psDeltaMemory]));
962 writeln(OutFile,'Max memory = ', FormatFloat(LargeCompFormat,stats[psMaxMemory]));
963 writeln(OutFile,'Elapsed time= ', FormatFloat(ThreeSigPlacesFormat,stats[psRealTime]/1000),' sec');
964 writeln(OutFile,'Cpu = ', FormatFloat(ThreeSigPlacesFormat,stats[psUserTime]/1000),' sec');
965 writeln(OutFile,'Buffers = ', FormatFloat('#0',stats[psBuffers]));
966 writeln(OutFile,'Reads = ', FormatFloat('#0',stats[psReads]));
967 writeln(OutFile,'Writes = ', FormatFloat('#0',stats[psWrites]));
968 writeln(OutFile,'Fetches = ', FormatFloat('#0',stats[psFetches]));
969 end;
970
971 procedure TTestBase.WriteSQLData(aValue: ISQLData);
972 var s: AnsiString;
973 dt: TDateTime;
974 dstOffset: SmallInt;
975 aTimeZone: AnsiString;
976 begin
977 if aValue.IsNull then
978 writeln(OutFile,aValue.Name,' = NULL')
979 else
980 case aValue.SQLType of
981 SQL_ARRAY:
982 begin
983 write(OutFile, aValue.Name,' = ');
984 if not aValue.IsNull then
985 WriteArray(aValue.AsArray)
986 else
987 writeln(OutFile,'NULL');
988 end;
989 SQL_FLOAT,SQL_DOUBLE,
990 SQL_D_FLOAT:
991 writeln(OutFile, aValue.Name,' = ',FormatFloat(FFloatTpl,aValue.AsDouble));
992
993 SQL_INT64:
994 if aValue.Scale <> 0 then
995 writeln(OutFile, aValue.Name,' = ',FormatFloat(FFloatTpl,aValue.AsDouble))
996 else
997 writeln(OutFile,aValue.Name,' = ',aValue.AsString);
998
999 SQL_BLOB:
1000 if aValue.IsNull then
1001 writeln(OutFile,aValue.Name,' = (null blob)')
1002 else
1003 if aValue.SQLSubType = 1 then
1004 begin
1005 s := aValue.AsString;
1006 if FHexStrings then
1007 begin
1008 write(OutFile,aValue.Name,' = ');
1009 PrintHexString(s);
1010 writeln(OutFile,' (Charset Id = ',aValue.GetCharSetID, ' Codepage = ',StringCodePage(s),')');
1011 end
1012 else
1013 begin
1014 writeln(OutFile,aValue.Name,' (Charset Id = ',aValue.GetCharSetID, ' Codepage = ',StringCodePage(s),')');
1015 writeln(OutFile);
1016 writeln(OutFile,s);
1017 end
1018 end
1019 else
1020 begin
1021 writeln(OutFile,aValue.Name,' = (blob), Length = ',aValue.AsBlob.GetBlobSize);
1022 if FShowBinaryBlob then
1023 PrintHexString(aValue.AsString);
1024 end;
1025
1026 SQL_TEXT,SQL_VARYING:
1027 begin
1028 if aValue.GetCharSetID = 1 then
1029 s := aValue.AsString
1030 else
1031 s := TrimRight(aValue.AsString);
1032 if FHexStrings then
1033 begin
1034 write(OutFile,aValue.Name,' = ');
1035 PrintHexString(s);
1036 writeln(OutFile,' (Charset Id = ',aValue.GetCharSetID, ' Codepage = ',StringCodePage(s),')');
1037 end
1038 else
1039 if aValue.GetCharSetID > 0 then
1040 writeln(OutFile,aValue.Name,' = ',s,' (Charset Id = ',aValue.GetCharSetID, ' Codepage = ',StringCodePage(s),')')
1041 else
1042 writeln(OutFile,aValue.Name,' = ',s);
1043 end;
1044
1045 SQL_TIMESTAMP:
1046 writeln(OutFile,aValue.Name,' = ',FBFormatDateTime('yyyy/mm/dd hh:nn:ss.zzzz',aValue.AsDateTime));
1047 SQL_TYPE_DATE:
1048 writeln(OutFile,aValue.Name,' = ',FBFormatDateTime('yyyy/mm/dd',aValue.AsDate));
1049 SQL_TYPE_TIME:
1050 writeln(OutFile,aValue.Name,' = ',FBFormatDateTime('hh:nn:ss.zzzz',aValue.AsTime));
1051 SQL_TIMESTAMP_TZ,
1052 SQL_TIMESTAMP_TZ_EX:
1053 begin
1054 aValue.GetAsDateTime(dt,dstOffset,aTimeZone);
1055 writeln(OutFile,aValue.Name,' =');
1056 writeln(OutFile,' AsString = ',aValue.GetAsString);
1057 writeln(OutFile,' Formatted = ',FBFormatDateTime('yyyy/mm/dd hh:nn:ss.zzzz',dt),' ',aTimeZone);
1058 writeln(OutFile,' TimeZoneID = ',aValue.GetStatement.GetAttachment.GetTimeZoneServices.TimeZoneName2TimeZoneID(aTimeZone));
1059 writeln(OutFile,' Time Zone Name = ',aTimeZone);
1060 writeln(OutFile,' UTC Time = ',DateTimeToStr( aValue.GetAsUTCDateTime));
1061 writeln(OutFile,' DST Offset = ',dstOffset);
1062 end;
1063 SQL_TIME_TZ,
1064 SQL_TIME_TZ_EX:
1065 begin
1066 aValue.GetAsDateTime(dt,dstOffset,aTimeZone);
1067 writeln(OutFile,aValue.Name,' =');
1068 writeln(OutFile,' AsString = ',aValue.GetAsString);
1069 writeln(OutFile,' Formatted = ',FBFormatDateTime('hh:nn:ss.zzzz',dt),' ',aTimeZone);
1070 writeln(OutFile,' TimeZoneID = ',aValue.GetStatement.GetAttachment.GetTimeZoneServices.TimeZoneName2TimeZoneID(aTimeZone));
1071 writeln(OutFile,' Time Zone Name = ',aTimeZone);
1072 writeln(OutFile,' UTC Time = ',TimeToStr( aValue.GetAsUTCDateTime));
1073 writeln(OutFile,' DST Offset = ',dstOffset);
1074 end;
1075
1076 else
1077 writeln(OutFile,aValue.Name,' = ',aValue.AsString);
1078 end;
1079 end;
1080
1081 procedure TTestBase.CheckActivity(Attachment: IAttachment);
1082 begin
1083 writeln(OutFile,'Database Activity = ',Attachment.HasActivity)
1084 end;
1085
1086 procedure TTestBase.CheckActivity(Transaction: ITransaction);
1087 begin
1088 writeln(OutFile,'Transaction Activity = ',Transaction.HasActivity)
1089 end;
1090
1091 procedure TTestBase.InitTest;
1092 begin
1093 //Do nothing yet
1094 end;
1095
1096 function TTestBase.SkipTest: boolean;
1097 begin
1098 Result := false;
1099 end;
1100
1101 procedure TTestBase.ProcessResults;
1102 begin
1103 //Do nothing
1104 end;
1105
1106 procedure TTestBase.SetFloatTemplate(tpl: Ansistring);
1107 begin
1108 FFloatTpl := tpl;
1109 end;
1110
1111 { TTestApplication }
1112
1113 class procedure TTestApplication.CreateTestList;
1114 begin
1115 if FTests = nil then
1116 begin
1117 FTests := TStringList.Create;
1118 FTests.Sorted := true;
1119 FTests.Duplicates := dupError;
1120 end;
1121 end;
1122
1123 class procedure TTestApplication.DestroyTestList;
1124 var i: integer;
1125 TestID: Ansistring;
1126 begin
1127 if assigned(FTests) then
1128 begin
1129 for i := 0 to FTests.Count - 1 do
1130 if FTests.Objects[i] <> nil then
1131 try
1132 TestID := TTestBase(FTests.Objects[i]).TestID;
1133 FTests.Objects[i].Free;
1134 except on E: Exception do
1135 writeln('Error Freeing Test ',TestID,' Error message = ',E.Message);
1136 end;
1137 FreeAndNil(FTests);
1138 end;
1139 end;
1140
1141 procedure TTestApplication.CleanUp;
1142 var DPB: IDPB;
1143 Attachment: IAttachment;
1144 begin
1145 DPB := FirebirdAPI.AllocateDPB;
1146 DPB.Add(isc_dpb_user_name).setAsString(GetUserName);
1147 DPB.Add(isc_dpb_password).setAsString(GetPassword);
1148 Attachment := FirebirdAPI.OpenDatabase(GetNewDatabaseName,DPB,false);
1149 if Attachment <> nil then
1150 Attachment.DropDatabase;
1151 Attachment := FirebirdAPI.OpenDatabase(GetSecondNewDatabaseName,DPB,false);
1152 if Attachment <> nil then
1153 Attachment.DropDatabase;
1154 end;
1155
1156 function TTestApplication.GetFirebirdAPI: IFirebirdAPI;
1157 begin
1158 if FFirebirdAPI = nil then
1159 begin
1160 FFirebirdAPI := IB.FirebirdAPI;
1161 FFirebirdAPI.GetStatus.SetIBDataBaseErrorMessages([ShowIBMessage]);;
1162 end;
1163 Result := FFirebirdAPI;
1164 end;
1165
1166 function TTestApplication.GetIndexByTestID(aTestID: AnsiString): integer;
1167 begin
1168 try
1169 Result := FTests.IndexOf(aTestID);
1170 except
1171 raise Exception.CreateFmt('Invalid Test ID - %s',[aTestID]);
1172 end;
1173 if Result = -1 then
1174 raise Exception. CreateFmt('Invalid Test ID - %s',[aTestID]);
1175 end;
1176
1177 constructor TTestApplication.Create(AOwner: TComponent);
1178 var i: integer;
1179 begin
1180 inherited Create(AOwner);
1181 TestApp := self;
1182 CreateTestList;
1183 FNewDatabaseName := GetTempDir + 'fbtestsuite.fdb';
1184 FSecondNewDatabaseName := GetTempDir + 'fbtestsuite2.fdb';
1185 FUserName := 'SYSDBA';
1186 FPassword := 'masterkey';
1187 FEmployeeDatabaseName := 'employee';
1188 FBackupFileName := GetTempDir + 'testbackup.gbk';
1189 FServer := 'localhost';
1190 for i := 0 to FTests.Count - 1 do
1191 begin
1192 TTestBase(FTests.Objects[i]).SetOwner(self);
1193 // TTestBase(FTests.Objects[i]).CreateObjects(self);
1194 end;
1195 end;
1196
1197 destructor TTestApplication.Destroy;
1198 begin
1199 DestroyTestList;
1200 TestApp := nil;
1201 inherited Destroy;
1202 end;
1203
1204 function TTestApplication.GetUserName: AnsiString;
1205 begin
1206 Result := FUserName;
1207 end;
1208
1209 function TTestApplication.GetPassword: AnsiString;
1210 begin
1211 Result := FPassword;
1212 end;
1213
1214 function TTestApplication.GetEmployeeDatabaseName: AnsiString;
1215 begin
1216 if FirebirdAPI.GetClientMajor < 3 then
1217 Result := MakeConnectString(FServer, FEmployeeDatabaseName, TCP,FPortNo)
1218 else
1219 Result := MakeConnectString(FServer, FEmployeeDatabaseName, inet,FPortNo);
1220 end;
1221
1222 function TTestApplication.GetNewDatabaseName: AnsiString;
1223 begin
1224 if FirebirdAPI.GetClientMajor < 3 then
1225 Result := MakeConnectString(FServer, FNewDatabaseName, TCP,FPortNo)
1226 else
1227 Result := MakeConnectString(FServer, FNewDatabaseName, inet,FPortNo);
1228 end;
1229
1230 function TTestApplication.GetTempDatabaseName: AnsiString;
1231 begin
1232 Result := GetTempDir + 'fbtest.fbd';
1233 end;
1234
1235 function TTestApplication.GetSecondNewDatabaseName: AnsiString;
1236 begin
1237 if FirebirdAPI.GetClientMajor < 3 then
1238 Result := MakeConnectString(FServer, FSecondNewDatabaseName, TCP,FPortNo)
1239 else
1240 Result := MakeConnectString(FServer, FSecondNewDatabaseName, inet,FPortNo);
1241 end;
1242
1243 function TTestApplication.GetBackupFileName: AnsiString;
1244 begin
1245 Result := FBackupFileName;
1246 end;
1247
1248 procedure TTestApplication.RunAll;
1249 var i: integer;
1250 begin
1251 CleanUp;
1252 for i := 0 to FTests.Count - 1 do
1253 begin
1254 DoTest(i);
1255 if not Quiet then
1256 writeln(Outfile,'------------------------------------------------------');
1257 Sleep(500);
1258 end;
1259 end;
1260
1261 procedure TTestApplication.RunTest(TestID: AnsiString);
1262 begin
1263 CleanUp;
1264 DoTest(GetIndexByTestID(TestID));
1265 end;
1266
1267 procedure TTestApplication.SetClientLibraryPath(aLibName: string);
1268 var i: integer;
1269 begin
1270 FFirebirdAPI := LoadFBLibrary(aLibName).GetFirebirdAPI;
1271 FClientLibraryPath := aLibName;
1272 for i := 0 to FTests.Count - 1 do
1273 TTestBase(FTests.Objects[i]).ClientLibraryPathChanged;
1274
1275 end;
1276
1277 procedure TTestApplication.SetUserName(aValue: AnsiString);
1278 begin
1279 FUserName := aValue;
1280 end;
1281
1282 procedure TTestApplication.SetPassword(aValue: AnsiString);
1283 begin
1284 FPassword := aValue;
1285 end;
1286
1287 procedure TTestApplication.SetEmployeeDatabaseName(aValue: AnsiString);
1288 begin
1289 FEmployeeDatabaseName := aValue;
1290 end;
1291
1292 procedure TTestApplication.SetNewDatabaseName(aValue: AnsiString);
1293 begin
1294 FNewDatabaseName := aValue;
1295 end;
1296
1297 procedure TTestApplication.SetSecondNewDatabaseName(aValue: AnsiString);
1298 begin
1299 FSecondNewDatabaseName := aValue;
1300 end;
1301
1302 procedure TTestApplication.SetBackupFileName(aValue: AnsiString);
1303 begin
1304 FBackupFileName := aValue;
1305 end;
1306
1307 procedure TTestApplication.SetServerName(AValue: AnsiString);
1308 begin
1309 if FServer = AValue then Exit;
1310 FServer := AValue;
1311 end;
1312
1313 procedure TTestApplication.SetPortNum(aValue: AnsiString);
1314 begin
1315 FPortNo := aValue;
1316 end;
1317
1318 procedure TTestApplication.SetTestOption(aValue: AnsiString);
1319 begin
1320 FTestOption := AValue;
1321 end;
1322
1323 {$IFDEF FPC}
1324 function TTestApplication.GetShortOptions: AnsiString;
1325 begin
1326 Result := 'htupensbolrSPXOq';
1327 end;
1328
1329 function TTestApplication.GetLongOptions: AnsiString;
1330 begin
1331 Result := 'help test user passwd employeedb newdbname secondnewdbname backupfile '+
1332 'outfile fbclientlibrary server stats port prompt TestOption quiet';
1333 end;
1334
1335 procedure TTestApplication.GetParams(var DoPrompt: boolean; var TestID: string);
1336 var ErrorMsg: String;
1337 begin
1338 // quick check parameters
1339 ErrorMsg := CheckOptions(GetShortOptions,GetLongOptions);
1340 if ErrorMsg <> '' then begin
1341 ShowException(Exception.Create(ErrorMsg));
1342 Terminate;
1343 Exit;
1344 end;
1345
1346 // parse parameters
1347 if HasOption('h', 'help') then begin
1348 WriteHelp;
1349 Terminate;
1350 Exit;
1351 end;
1352
1353 if HasOption('t') then
1354 TestID := GetOptionValue('t');
1355 if Length(TestID) = 1 then
1356 TestID := '0' + TestID;
1357
1358 DoPrompt := HasOption('X','prompt');
1359
1360 if HasOption('u','user') then
1361 SetUserName(GetOptionValue('u'));
1362
1363 if HasOption('p','passwd') then
1364 SetPassword(GetOptionValue('p'));
1365
1366 if HasOption('e','employeedb') then
1367 SetEmployeeDatabaseName(GetOptionValue('e'));
1368
1369 if HasOption('n','newdbname') then
1370 SetNewDatabaseName(GetOptionValue('n'));
1371
1372 if HasOption('s','secondnewdbname') then
1373 SetSecondNewDatabaseName(GetOptionValue('s'));
1374
1375 if HasOption('b','backupfile') then
1376 SetBackupFileName(GetOptionValue('b'));
1377
1378 if HasOption('l','fbclientlibrary') then
1379 SetClientLibraryPath(GetOptionValue('l'));
1380
1381 if HasOption('r','server') then
1382 SetServerName(GetOptionValue('r'));
1383
1384 if HasOption('o','outfile') then
1385 begin
1386 system.Assign(outFile,GetOptionValue('o'));
1387 ReWrite(outFile);
1388 end;
1389
1390 if HasOption('P','port') then
1391 SetPortNum(GetOptionValue('P'));
1392
1393 ShowStatistics := HasOption('S','stats');
1394
1395 if HasOption('O','TestOption') then
1396 SetTestOption(GetOptionValue('O'));
1397
1398 FQuiet := HasOption('q','quiet')
1399 end;
1400 {$ENDIF}
1401
1402 {$IFDEF DCC}
1403 procedure TTestApplication.GetParams(var DoPrompt: boolean; var TestID: string);
1404
1405 function GetCmdLineValue(const Switch: string; var aValue: string): boolean;
1406 var i: integer;
1407 begin
1408 aValue := '';
1409 Result := FindCmdLineSwitch(Switch,false);
1410 if Result then
1411 begin
1412 for i := 0 to ParamCount do
1413 if (ParamStr(i) = '-' + Switch) and (i <= ParamCount) then
1414 begin
1415 aValue := ParamStr(i+1);
1416 exit;
1417 end;
1418 Result := false;
1419 end;
1420 end;
1421
1422 var aValue: string;
1423
1424 begin
1425 // parse parameters
1426 if FindCmdLineSwitch('h') or FindCmdLineSwitch('help') then
1427 begin
1428 WriteHelp;
1429 Exit;
1430 end;
1431
1432 if GetCmdLineValue('t',aValue) then
1433 TestID := aValue;
1434
1435 DoPrompt := GetCmdLineValue('X',aValue);
1436
1437 if GetCmdLineValue('u',aValue) or GetCmdLineValue('user',aValue) then
1438 SetUserName(aValue);
1439
1440 if GetCmdLineValue('p',aValue) or GetCmdLineValue('passwd',aValue) then
1441 SetPassword(aValue);
1442
1443 if GetCmdLineValue('e',aValue) or GetCmdLineValue('employeedb',aValue) then
1444 SetEmployeeDatabaseName(aValue);
1445
1446 if GetCmdLineValue('n',aValue) or GetCmdLineValue('newdbname',aValue) then
1447 SetNewDatabaseName(aValue);
1448
1449 if GetCmdLineValue('s',aValue) or GetCmdLineValue('secondnewdbname',aValue) then
1450 SetSecondNewDatabaseName(aValue);
1451
1452 if GetCmdLineValue('b',aValue) or GetCmdLineValue('backupfile',aValue) then
1453 SetBackupFileName(aValue);
1454
1455 if GetCmdLineValue('r',aValue) or GetCmdLineValue('server',aValue) then
1456 SetServerName(aValue);
1457
1458 if GetCmdLineValue('P',aValue) or GetCmdLineValue('port',aValue) then
1459 SetPortNum(aValue);
1460
1461 if GetCmdLineValue('l',aValue) or GetCmdLineValue('fbclientlibrary',aValue) then
1462 SetClientLibraryPath(aValue);
1463
1464 if GetCmdLineValue('o',aValue) or GetCmdLineValue('outfile',aValue) then
1465 begin
1466 system.Assign(outFile,aValue);
1467 ReWrite(outFile);
1468 end;
1469
1470 ShowStatistics := FindCmdLineSwitch('S',false) or FindCmdLineSwitch('stats');
1471
1472 if GetCmdLineValue('O',aValue) or GetCmdLineValue('TestOption',aValue) then
1473 SetTestOption(aValue);
1474
1475 FQuiet := FindCmdLineSwitch('q',false) or FindCmdLineSwitch('quiet');
1476 end;
1477 {$ENDIF}
1478
1479 procedure TTestApplication.DoRun;
1480 var
1481 DoPrompt: boolean;
1482 TestID: string;
1483 MasterProvider: IFBIMasterProvider;
1484 begin
1485 {$IFDEF FPC}
1486 OutFile := stdout;
1487 {$ELSE}
1488 AssignFile(OutFile,'');
1489 ReWrite(outFile);
1490 {$ENDIF}
1491
1492 GetParams(DoPrompt,TestID);
1493 if length(TestID) = 1 then
1494 TestID := '0' + TestID;
1495 {$ifdef DCC}
1496 {$IF declared(SetConsoleOutputCP)}
1497 SetConsoleOutputCP(cp_utf8);
1498 {$IFEND}
1499 {$IF declared(SetTextCodePage)}
1500 {Ensure consistent UTF-8 output}
1501 SetTextCodePage(OutFile,cp_utf8);
1502 {$IFEND}
1503 {$endif}
1504
1505 {Ensure consistent date reporting across platforms}
1506 SetFormatSettings;
1507
1508 if not Quiet then
1509 begin
1510 writeln(OutFile,Title);
1511 writeln(OutFile,Copyright);
1512 writeln(OutFile);
1513 writeln(OutFile,'Starting Tests');
1514 writeln(OutFile,'Client API Version = ',FirebirdAPI.GetImplementationVersion);
1515 writeln(OutFile,'Firebird Environment Variable = ',sysutils.GetEnvironmentVariable('FIREBIRD'));
1516 if FirebirdAPI.HasMasterIntf and (FirebirdAPI.QueryInterface(IFBIMasterProvider,MasterProvider) = S_OK) then
1517 with MasterProvider.GetIMasterIntf.getConfigManager do
1518 begin
1519 writeln(OutFile,'Firebird Bin Directory = ', getDirectory(DIR_BIN));
1520 writeln(OutFile,'Firebird Conf Directory = ', getDirectory(DIR_CONF));
1521 end;
1522 writeln(OutFile,'Firebird Client Library Path = ',FirebirdAPI.GetFBLibrary.GetLibraryFilePath);
1523 end;
1524
1525 try
1526 if TestID = '' then
1527 RunAll
1528 else
1529 RunTest(TestID);
1530 CleanUp;
1531 except on E: Exception do
1532 begin
1533 writeln('Exception: ',E.Message);
1534 writeln(OutFile,'Exception: ',E.Message);
1535 end;
1536 end;
1537
1538 writeln(OutFile,'Test Suite Ends');
1539 Flush(OutFile);
1540 {$IFDEF WINDOWS}
1541 if DoPrompt then
1542 begin
1543 write('Press Entry to continue');
1544 readln; {when running from IDE and console window closes before you can view results}
1545 end;
1546 {$ENDIF}
1547
1548 // stop program loop
1549 Terminate;
1550 end;
1551
1552 procedure TTestApplication.DoTest(index: integer);
1553 begin
1554 if FTests.Objects[index] = nil then Exit;
1555 try
1556 with TTestBase(FTests.Objects[index]) do
1557 if SkipTest then
1558 writeln(OutFile,' Skipping ' + TestID)
1559 else
1560 begin
1561 if not Quiet then
1562 writeln(OutFile,'Running ' + TestTitle);
1563 if not ChildProcess then
1564 writeln(ErrOutput,'Running ' + TestTitle);
1565 try
1566 CreateObjects(self);
1567 InitTest;
1568 RunTest('UTF8',3);
1569 ProcessResults;
1570 except
1571 on E:ESkipException do
1572 writeln(OutFile,'Skipping Test: ' + E.Message);
1573 on E:Exception do
1574 begin
1575 writeln(OutFile,'Test Completed with Error: ' + E.Message);
1576 Exit;
1577 end;
1578 end;
1579 if not Quiet then
1580 begin
1581 writeln(OutFile);
1582 writeln(OutFile);
1583 end;
1584 end;
1585 finally
1586 FTests.Objects[index].Free;
1587 FTests.Objects[index] := nil;
1588 DestroyComponents;
1589 end;
1590 end;
1591
1592 procedure TTestApplication.SetFormatSettings;
1593 begin
1594 {$ifdef FPC}
1595 SetMultiByteConversionCodePage(cp_utf8);
1596 {$endif}
1597 {$IF declared(DefaultFormatSettings)}
1598 with DefaultFormatSettings do
1599 {$ELSE}
1600 {$IF declared(FormatSettings)}
1601 with FormatSettings do
1602 {$IFEND}{$IFEND}
1603 begin
1604 ShortDateFormat := 'dd/m/yyyy';
1605 LongTimeFormat := 'HH:MM:SS';
1606 DateSeparator := '/';
1607 end;
1608 end;
1609
1610 procedure TTestApplication.WriteHelp;
1611 begin
1612 { add your help code here }
1613 writeln(OutFile,'Usage: ', ExeName, ' -h');
1614 end;
1615
1616 {$IFNDEF FPC}
1617 function TCustomApplication.Exename: string;
1618 begin
1619 Result := ParamStr(0);
1620 end;
1621
1622 procedure TCustomApplication.Run;
1623 begin
1624 try
1625 DoRun;
1626 except on E: Exception do
1627 writeln(OutFile,E.Message);
1628 end;
1629 end;
1630
1631 procedure TCustomApplication.Terminate;
1632 begin
1633
1634 end;
1635 {$ENDIF}
1636
1637 end.
1638

Properties

Name Value
svn:eol-style native