ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/testsuite/testApp/TestApplication.pas
Revision: 369
Committed: Wed Dec 8 13:12:10 2021 UTC (2 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 45332 byte(s)
Log Message:
TestApplication no longer dependent on TJnlEntry type being declared

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