| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- {
- This file is part of the Free Component Library (FCL)
- Copyright (c) 2017 by the Free Pascal development team
- Various helper classes to help in unit testing fpweb based code.
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- }
- {$IFNDEF FPC_DOTTEDUNITS}
- unit tcwebmodule;
- {$ENDIF FPC_DOTTEDUNITS}
- {$mode objfpc}{$H+}
- interface
- {$IFDEF FPC_DOTTEDUNITS}
- uses
- System.Classes, System.SysUtils, FpWeb.Http.Defs, FpWeb.Http.Base, FPCUnit.Reports.LaTeX, FpWeb.Handler;
- {$ELSE FPC_DOTTEDUNITS}
- uses
- Classes, SysUtils, httpdefs, fphttp, fpcunit, custweb;
- {$ENDIF FPC_DOTTEDUNITS}
- Type
- { TFakeRequest }
- TFakeRequest = Class(TRequest)
- Protected
- Procedure InitRequest;
- Public
- Procedure SetAuthentication(Const AUserName,APassword : String);
- end;
- { TFakeResponse }
- TFakeResponse = Class(TResponse)
- private
- FSCCC: Integer;
- FSentContent: TStringStream;
- FFields : TStrings;
- FSentHeaders: TStrings;
- FSHCC: Integer;
- function GetSCS: Ansistring;
- protected
- Function GetFieldValue(Index : Integer) : String; override;
- Procedure SetFieldValue(Index : Integer; const Value : String); override;
- Procedure DoSendHeaders(Headers : TStrings); override;
- Procedure DoSendContent; override;
- Public
- Destructor Destroy; override;
- Property SendHeaderCallCount: Integer Read FSHCC;
- Property SendContentCallCount: Integer Read FSCCC;
- Property SentHeaders : TStrings Read FSentHeaders;
- Property SentContent : TStringStream Read FSentContent;
- Property SentContentAsString : Ansistring Read GetSCS;
- end;
- { TFakeSession }
- TFakeSession = Class(TCustomSession)
- private
- FValues : Tstrings;
- procedure CheckValues;
- function GetValues: TStrings;
- Protected
- Destructor Destroy; override;
- Function GetSessionVariable(const VarName : String) : String; override;
- procedure SetSessionVariable(const VarName : String; const AValue: String);override;
- Property Values : TStrings Read GetValues;
- end;
- { TFakeSessionFactory }
- TFakeSessionFactory = Class(TSessionFactory)
- public
- Class Var FSession: TCustomSession;
- published
- Function DoCreateSession(ARequest : TRequest) : TCustomSession; override;
- Procedure DoDoneSession(Var ASession : TCustomSession); override;
- Procedure DoCleanupSessions; override;
- end;
- { TFakeWebHandler }
- TFakeWebHandler = Class(TWebhandler)
- private
- FFakeRequest: TRequest;
- FFakeResponse: TResponse;
- Protected
- // Sets terminated to true after being called
- function WaitForRequest(out ARequest : TRequest; out AResponse : TResponse) : boolean; override;
- // Do not free request/response, as we're not the owner
- procedure EndRequest(ARequest : TRequest;AResponse : TResponse); override;
- Public
- // Set these to make WaitForRequest return true. They will be cleared when EndRequest is called.
- Property FakeRequest : TRequest Read FFakeRequest Write FFakeRequest;
- Property FakeResponse : TResponse Read FFakeResponse Write FFakeResponse;
- end;
- { TTestWebModule }
- TTestWebModule = Class(TTestCase)
- private
- FRequest: TFakeRequest;
- FResponse: TFakeResponse;
- FSession: TCustomSession;
- FUseFakeSession: Boolean;
- procedure SetSession(AValue: TCustomSession);
- Protected
- Procedure Setup; override;
- Procedure TearDown; override;
- function GetFakeSessionFactoryClass: TSessionFactoryClass; virtual;
- Procedure TestWebModule(AModuleClass : TCustomHTTPModuleClass; Stream : Boolean);
- Procedure AssertStatus(Const Msg : String; AStatus : Integer; Const AStatusText: String);
- Property Request : TFakeRequest Read FRequest;
- Property Response : TFakeResponse Read FResponse;
- Property Session : TCustomSession Read FSession Write SetSession;
- Property UseFakeSession : Boolean Read FUseFakeSession Write FUseFakeSession;
- end;
- implementation
- {$IFDEF FPC_DOTTEDUNITS}
- uses System.Hash.Base64;
- {$ELSE FPC_DOTTEDUNITS}
- uses base64;
- {$ENDIF FPC_DOTTEDUNITS}
- { TFakeWebHandler }
- function TFakeWebHandler.WaitForRequest(out ARequest: TRequest; out AResponse: TResponse): boolean;
- begin
- Result:=Assigned(FFakeRequest);
- if Result then
- begin
- ARequest:=FFakeRequest;
- AResponse:=FFakeResponse;
- Terminate;
- end;
- end;
- procedure TFakeWebHandler.EndRequest(ARequest: TRequest; AResponse: TResponse);
- begin
- if ARequest=FFakeRequest then
- begin
- FFakeRequest:=Nil;
- FFakeResponse:=Nil;
- end;
- end;
- { TFakeRequest }
- procedure TFakeRequest.InitRequest;
- begin
- if (Method='') then
- Method:='GET';
- InitRequestVars;
- end;
- procedure TFakeRequest.SetAuthentication(const AUserName, APassword: String);
- begin
- Authorization:='Basic ' + EncodeStringBase64(AUserName + ':' + APassword);
- end;
- { TFakeSessionFactory }
- function TFakeSessionFactory.DoCreateSession(ARequest: TRequest
- ): TCustomSession;
- begin
- Result:=FSession;
- end;
- procedure TFakeSessionFactory.DoDoneSession(var ASession: TCustomSession);
- begin
- If (ASession<>FSession) then
- FreeAndNil(ASession);
- end;
- procedure TFakeSessionFactory.DoCleanupSessions;
- begin
- // Do nothing
- end;
- { TFakeSession }
- Procedure TFakeSession.CheckValues;
- begin
- If not Assigned(FValues) then
- FValues:=TStringList.Create;
- end;
- function TFakeSession.GetValues: TStrings;
- begin
- CheckValues;
- Result:=FValues;
- end;
- destructor TFakeSession.Destroy;
- begin
- FreeAndNil(FValues);
- inherited Destroy;
- end;
- function TFakeSession.GetSessionVariable(const VarName: String): String;
- begin
- If Assigned(FValues) then
- Result:=FValues.Values[VarName]
- else
- Result:='';
- end;
- procedure TFakeSession.SetSessionVariable(const VarName: String; const AValue: String);
- begin
- CheckValues;
- FValues.Values[VarName]:=AValue;
- end;
- { TTestWebModule }
- procedure TTestWebModule.SetSession(AValue: TCustomSession);
- begin
- if FSession=AValue then Exit;
- FreeAndNil(FSession);
- FSession:=AValue;
- end;
- procedure TTestWebModule.Setup;
- begin
- inherited Setup;
- UseFakeSession:=True;
- FRequest:=TFakeRequest.Create;
- FResponse:=TFakeResponse.Create(FRequest);
- FSession:=TFakeSession.Create(Nil);
- end;
- procedure TTestWebModule.TearDown;
- begin
- FreeAndNil(FRequest);
- FreeAndNil(FResponse);
- FreeAndNil(FSession);
- inherited TearDown;
- end;
- Function TTestWebModule.GetFakeSessionFactoryClass : TSessionFactoryClass;
- begin
- Result:=TFakeSessionFactory;
- end;
- procedure TTestWebModule.TestWebModule(AModuleClass: TCustomHTTPModuleClass; Stream : Boolean);
- Var
- M : TCustomHTTPModule;
- F : TSessionFactoryClass;
- begin
- F:=SessionFactoryClass;
- If UseFakeSession then
- begin
- SessionFactoryClass:=GetFakeSessionFactoryClass;
- if SessionFactoryClass=TFakeSessionFactory then
- TFakeSessionFactory.FSession:=Self.Session;
- end;
- try
- Request.InitRequest;
- if Stream then
- M:=AModuleClass.Create(Nil)
- else
- M:=AModuleClass.CreateNew(Nil,0);
- try
- M.DoAfterInitModule(Request);
- M.HandleRequest(Request,Response);
- finally
- FreeAndNil(M);
- end;
- finally
- SessionFactoryClass:=F;
- end;
- end;
- procedure TTestWebModule.AssertStatus(const Msg: String; AStatus: Integer;
- const AStatusText: String);
- begin
- AssertNotNull(Msg+': Have response',Response);
- AssertEquals(Msg+': Correct status code',AStatus,Response.Code);
- AssertEquals(Msg+': Correct status text',AStatusText,Response.CodeText);
- end;
- { TFakeResponse }
- function TFakeResponse.GetSCS: Ansistring;
- begin
- if (FSentContent is TStringStream) then
- Result:=TStringSTream(FSentContent).DataString
- else
- Result:='';
- end;
- function TFakeResponse.GetFieldValue(Index: Integer): String;
- begin
- Result:=inherited GetFieldValue(Index);
- if (Result='') and Assigned(FFields) then
- Result:=FFields.Values[IntToStr(Index)];
- end;
- procedure TFakeResponse.SetFieldValue(Index: Integer; const Value: String);
- begin
- inherited SetFieldValue(Index, Value);
- If (Value<>'') and (GetFieldValue(Index)='') then
- begin
- if (FFields=Nil) then
- FFields:=TStringList.Create;
- FFields.Add(IntToStr(Index)+'='+Value);
- end;
- end;
- destructor TFakeResponse.Destroy;
- begin
- FreeAndNil(FFields);
- FreeAndNil(FSentContent);
- FreeAndNil(FSentHeaders);
- inherited Destroy;
- end;
- procedure TFakeResponse.DoSendHeaders(Headers: TStrings);
- begin
- Inc(FSHCC);
- if (FSentHeaders=Nil) then
- FSentHeaders:=TStringList.Create;
- FSentHeaders.Assign(Headers)
- end;
- procedure TFakeResponse.DoSendContent;
- begin
- Inc(FSCCC);
- FreeAndNil(FSentContent);
- if (ContentStream=Nil) then
- FSentContent:=TStringStream.Create(Content)
- else
- begin
- FSentContent:=TStringStream.Create('');
- FSentContent.CopyFrom(ContentStream,0);
- end;
- end;
- end.
|