From ebc2cf4cedd776a0162263e3ac13a60919b24b51 Mon Sep 17 00:00:00 2001 From: Fr0sT-Brutal Date: Tue, 3 Aug 2021 19:21:46 +0300 Subject: [PATCH 1/4] + New option - codepage of source files. Could be set via command line argument `-cp` or read from DPROJ --- Source/CoverageConfiguration.pas | 43 ++++++++++++++++++++++++++++++ Source/Debugger.pas | 2 ++ Source/HTMLCoverageReport.pas | 7 ++++- Source/I_CoverageConfiguration.pas | 2 ++ 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Source/CoverageConfiguration.pas b/Source/CoverageConfiguration.pas index 1e59fd6..91e3bf3 100644 --- a/Source/CoverageConfiguration.pas +++ b/Source/CoverageConfiguration.pas @@ -52,6 +52,7 @@ TCoverageConfiguration = class(TInterfacedObject, ICoverageConfiguration) FModuleNameSpaces: TModuleNameSpaceList; FUnitNameSpaces: TUnitNameSpaceList; FLineCountLimit: Integer; + FCodePage: Integer; FLogManager: ILogManager; procedure ReadSourcePathFile(const ASourceFileName: string); @@ -62,6 +63,7 @@ TCoverageConfiguration = class(TInterfacedObject, ICoverageConfiguration) function GetBasePropertyGroupNode(const Project: IXMLNode): IXMLNode; function GetExeOutputFromDProj(const Project: IXMLNode; const ProjectName: TFileName): string; function GetSourceDirsFromDProj(const Project: IXMLNode): string; + function GetCodePageFromDProj(const Project: IXMLNode): Integer; procedure ParseDProj(const DProjFilename: TFileName); function IsPathInExclusionList(const APath: TFileName): Boolean; procedure ExcludeSourcePaths; @@ -90,6 +92,7 @@ TCoverageConfiguration = class(TInterfacedObject, ICoverageConfiguration) procedure ParseModuleNameSpaceSwitch(var AParameter: Integer); procedure ParseUnitNameSpaceSwitch(var AParameter: Integer); procedure ParseLineCountSwitch(var AParameter: Integer); + procedure ParseCodePageSwitch(var AParameter: Integer); public constructor Create(const AParameterProvider: IParameterProvider); destructor Destroy; override; @@ -117,6 +120,7 @@ TCoverageConfiguration = class(TInterfacedObject, ICoverageConfiguration) function TestExeExitCode: Boolean; function UseTestExePathAsWorkingDir: Boolean; function LineCountLimit: Integer; + function CodePage: Integer; function ModuleNameSpace(const AModuleName: string): TModuleNameSpace; function UnitNameSpace(const AModuleName: string): TUnitNameSpace; @@ -213,6 +217,11 @@ function TCoverageConfiguration.LineCountLimit: integer; Result := FLineCountLimit; end; +function TCoverageConfiguration.CodePage: Integer; +begin + Result := FCodePage; +end; + function TCoverageConfiguration.IsComplete(var AReason: string): Boolean; begin if FSourcePathLst.Count = 0 then @@ -574,6 +583,8 @@ procedure TCoverageConfiguration.ParseSwitch(var AParameter: Integer); FStripFileExtension := False else if (SwitchItem = I_CoverageConfiguration.cPARAMETER_LINE_COUNT) then ParseLineCountSwitch(AParameter) + else if (SwitchItem = I_CoverageConfiguration.cPARAMETER_CODE_PAGE) then + ParseCodePageSwitch(AParameter) else if (SwitchItem = I_CoverageConfiguration.cPARAMETER_EMMA_OUTPUT) or (SwitchItem = I_CoverageConfiguration.cPARAMETER_EMMA21_OUTPUT) or (SwitchItem = I_CoverageConfiguration.cPARAMETER_EMMA_SEPARATE_META) @@ -931,6 +942,20 @@ function TCoverageConfiguration.GetSourceDirsFromDProj(const Project: IXMLNode): Result := StringReplace(Node.Text, '$(DCC_UnitSearchPath)', '', [rfReplaceAll, rfIgnoreCase]); end; +function TCoverageConfiguration.GetCodePageFromDProj(const Project: IXMLNode): Integer; +var + Node: IXMLNode; +begin + Result := 0; + Assert(Assigned(Project)); + + Node := GetBasePropertyGroupNode(Project); + if Node = nil then Exit; + Node := Node.ChildNodes.FindNode('DCC_CodePage'); + if Node = nil then Exit; + Result := StrToIntDef(Node.Text, 0); +end; + function TCoverageConfiguration.GetExeOutputFromDProj(const Project: IXMLNode; const ProjectName: TFileName): string; var CurrentConfig: string; @@ -1007,6 +1032,8 @@ procedure TCoverageConfiguration.ParseDProj(const DProjFilename: TFileName); end; end; + FCodePage := GetCodePageFromDProj(Project); + ItemGroup := Project.ChildNodes.FindNode('ItemGroup'); if ItemGroup <> nil then begin @@ -1139,5 +1166,21 @@ procedure TCoverageConfiguration.ParseLineCountSwitch(var AParameter: Integer); end; end; +procedure TCoverageConfiguration.ParseCodePageSwitch(var AParameter: Integer); +var + ParsedParameter: string; +begin + Inc(AParameter); + ParsedParameter := ParseParameter(AParameter); + if ParsedParameter.StartsWith('-') then // This is a switch, not a number + begin + Dec(AParameter); + end + else + begin + FCodePage := StrToIntDef(ParsedParameter, 0); + end; +end; + end. diff --git a/Source/Debugger.pas b/Source/Debugger.pas index 34357ec..6f578cb 100644 --- a/Source/Debugger.pas +++ b/Source/Debugger.pas @@ -265,6 +265,8 @@ procedure TDebugger.PrintUsage; ' dll_or_exe unitname [unitname2] -- Create a separate namespace (the namespace name will be the name of the module without extension) *ONLY* for the listed units within the module.'); ConsoleOutput(I_CoverageConfiguration.cPARAMETER_LINE_COUNT + ' [number] -- Count number of times a line is executed up to the specified limit (default 0 - disabled)'); + ConsoleOutput(I_CoverageConfiguration.cPARAMETER_CODE_PAGE + + ' [number] -- Code page of source files'); ConsoleOutput(I_CoverageConfiguration.cPARAMETER_TESTEXE_EXIT_CODE + ' -- Passthrough the exitcode of the application'); ConsoleOutput(I_CoverageConfiguration.cPARAMETER_USE_TESTEXE_WORKING_DIR + diff --git a/Source/HTMLCoverageReport.pas b/Source/HTMLCoverageReport.pas index dfece46..125a141 100644 --- a/Source/HTMLCoverageReport.pas +++ b/Source/HTMLCoverageReport.pas @@ -201,6 +201,7 @@ function THTMLCoverageReport.GenerateUnitReport( OutputFile: TTextWriter; SourceFileName: string; OutputFileName: string; + Encoding: TEncoding; begin Result.HasFile:= False; Result.LinkFileName:= ACoverageUnit.ReportFileName + '.html'; @@ -211,7 +212,11 @@ function THTMLCoverageReport.GenerateUnitReport( SourceFileName := FindSourceFile(ACoverageUnit, Result); try - InputFile := TStreamReader.Create(SourceFileName, TEncoding.ANSI, True); + if FCoverageConfiguration.CodePage <> 0 then + Encoding := TEncoding.GetEncoding(FCoverageConfiguration.CodePage) + else + Encoding := TEncoding.ANSI; + InputFile := TStreamReader.Create(SourceFileName, Encoding, True); except on E: EFileStreamError do begin diff --git a/Source/I_CoverageConfiguration.pas b/Source/I_CoverageConfiguration.pas index 67a6d5e..4695e65 100644 --- a/Source/I_CoverageConfiguration.pas +++ b/Source/I_CoverageConfiguration.pas @@ -44,6 +44,7 @@ interface function ModuleNameSpace(const AModuleName: string): TModuleNameSpace; function UnitNameSpace(const AModuleName: string): TUnitNameSpace; function LineCountLimit: Integer; + function CodePage: Integer; end; const @@ -77,6 +78,7 @@ interface cPARAMETER_TESTEXE_EXIT_CODE = '-tec'; cPARAMETER_USE_TESTEXE_WORKING_DIR = '-twd'; cPARAMETER_LINE_COUNT = '-lcl'; + cPARAMETER_CODE_PAGE = '-cp'; cIGNORE_UNIT_PREFIX = '!'; implementation From 7f5b440e1d301e8d022b3d435f1f7cdd74104ecd Mon Sep 17 00:00:00 2001 From: Fr0sT-Brutal Date: Tue, 10 Aug 2021 15:41:39 +0300 Subject: [PATCH 2/4] + Add tests --- Test/CoverageConfigurationTest.pas | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Test/CoverageConfigurationTest.pas b/Test/CoverageConfigurationTest.pas index e1e1160..e90454a 100644 --- a/Test/CoverageConfigurationTest.pas +++ b/Test/CoverageConfigurationTest.pas @@ -31,6 +31,7 @@ TCoverageConfigurationTest = class(TTestCase) procedure TestInvalidParameter; procedure TestEnableApiLogging; + procedure TestSetCodepage; procedure TestEnableFileLoggingDefaultFile; procedure TestEnableFileLoggingSpecifiedFile; @@ -115,6 +116,7 @@ implementation cUNIT_PARAMETER : array [0 .. 0] of string = (I_CoverageConfiguration.cPARAMETER_UNIT); cMAP_FILE_PARAMETER : array [0 .. 0] of string = (I_CoverageConfiguration.cPARAMETER_MAP_FILE); cEXECUTABLE_PARAMETER : array [0 .. 0] of string = (I_CoverageConfiguration.cPARAMETER_EXECUTABLE); + cCODE_PAGE : array [0 .. 1] of string = (I_CoverageConfiguration.cPARAMETER_CODE_PAGE, '1250'); cSOME_EXTENSION = '.someExt'; cEXCLUDE_FILES_PREFIX = 'exclude'; //============================================================================== @@ -231,6 +233,16 @@ procedure TCoverageConfigurationTest.TestEnableApiLogging; CheckTrue(LCoverageConfiguration.UseApiDebug, 'API Logging was not turned on.'); end; +//============================================================================== +procedure TCoverageConfigurationTest.TestSetCodepage; +var + LCoverageConfiguration: ICoverageConfiguration; +begin + LCoverageConfiguration := TCoverageConfiguration.Create(TMockCommandLineProvider.Create(cCODE_PAGE)); + LCoverageConfiguration.ParseCommandLine; + CheckEquals(StrToInt(cCODE_PAGE[1]), LCoverageConfiguration.CodePage, 'Code page was not set.'); +end; + //============================================================================== procedure TCoverageConfigurationTest.TestEnableFileLoggingDefaultFile; var @@ -1485,6 +1497,7 @@ procedure TCoverageConfigurationTest.TestDProj; LDProj.Add(''); LDProj.Add('..\build\$(PLATFORM)'); LDProj.Add('..\src\;$(DCC_UnitSearchPath)'); + LDProj.Add('65001'); LDProj.Add(''); LTotalUnitList := TStringList.Create; From 8fb9d39c6051501c9ed728de2d52848370a1fc4f Mon Sep 17 00:00:00 2001 From: Fr0sT-Brutal Date: Tue, 10 Aug 2021 17:48:34 +0300 Subject: [PATCH 3/4] Add -cp option to README.markdown --- README.markdown | 1 + 1 file changed, 1 insertion(+) diff --git a/README.markdown b/README.markdown index dac3b69..383279e 100644 --- a/README.markdown +++ b/README.markdown @@ -94,6 +94,7 @@ unfinished form on my harddrive for more than a year. Finally it slipped out. -uns dll_or_exe unitname [unitname_2]Create a separate namespace (the namespace name will be the name of the module without extension) ONLY for the listed units within the module -mns name dll_or_exe [dll_or_exe_2]Create a separate namespace with the given name for the listed dll:s. All modules loaded in those module(s) will be namespaced. -lcl LineCountLimitCount number of times a line is executed up to the specified limit + -cp CodePageCode page number of source files -tecPassthrough the exitcode of the application inspected -twdUse the application's path as working directory From 1a9c51528ffdcb9853cce49a210010a69b8f0e8e Mon Sep 17 00:00:00 2001 From: Fr0sT-Brutal Date: Thu, 19 Aug 2021 17:35:35 +0300 Subject: [PATCH 4/4] Update README.markdown Add note about -dproj combined with other options --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 383279e..def60b3 100644 --- a/README.markdown +++ b/README.markdown @@ -78,7 +78,7 @@ unfinished form on my harddrive for more than a year. Finally it slipped out. -u TestUnit TestUnit2The units that shall be checked for code coverage -uf filenameCover units listed in the file pointed to by filename. One unit per line in the file -vShow verbose output - -dproj ProjectFile.dprojParse the project file for source dirs + -dproj ProjectFile.dprojParse the project file for source dirs, executable name, code page and other options. Note that options that could only have single value, like code page, will be overwritten in the order of appearance if multiple related switches are encountered. -a Param Param2Parameters to pass on to the application that shall be checked for code coverage. ^ is an escape character -lt [filename]Log events to a text log file. Default file name is: Delphi-Code-Coverage-Debug.log -lapiLog events to the Windows API OutputDebugString