Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ unfinished form on my harddrive for more than a year. Finally it slipped out.
<tr><td><code>-u TestUnit TestUnit2</code></td><td>The units that shall be checked for code coverage</td></tr>
<tr><td><code>-uf filename</code></td><td>Cover units listed in the file pointed to by filename. One unit per line in the file</td></tr>
<tr><td><code>-v</code></td><td>Show verbose output</td></tr>
<tr><td><code>-dproj ProjectFile.dproj</code></td><td>Parse the project file for source dirs</td></tr>
<tr><td><code>-dproj ProjectFile.dproj</code></td><td>Parse 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.</td></tr>
<tr><td><code>-a Param Param2</code></td><td>Parameters to pass on to the application that shall be checked for code coverage. ^ is an escape character</td></tr>
<tr><td><code>-lt [filename]</code></td><td>Log events to a text log file. Default file name is: Delphi-Code-Coverage-Debug.log</td></tr>
<tr><td><code>-lapi</code></td><td>Log events to the Windows API OutputDebugString</td></tr>
Expand All @@ -94,6 +94,7 @@ unfinished form on my harddrive for more than a year. Finally it slipped out.
<tr><td><code>-uns dll_or_exe unitname [unitname_2]</code></td><td>Create a separate namespace (the namespace name will be the name of the module without extension) ONLY for the listed units within the module</td></tr>
<tr><td><code>-mns name dll_or_exe [dll_or_exe_2]</code></td><td>Create a separate namespace with the given name for the listed dll:s. All modules loaded in those module(s) will be namespaced.</td></tr>
<tr><td><code>-lcl LineCountLimit</code></td><td>Count number of times a line is executed up to the specified limit</td></tr>
<tr><td><code>-cp CodePage</code></td><td>Code page number of source files</td></tr>
<tr><td><code>-tec</code></td><td>Passthrough the exitcode of the application inspected</td></tr>
<tr><td><code>-twd</code></td><td>Use the application's path as working directory</td></tr>
</table>
Expand Down
43 changes: 43 additions & 0 deletions Source/CoverageConfiguration.pas
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ TCoverageConfiguration = class(TInterfacedObject, ICoverageConfiguration)
FModuleNameSpaces: TModuleNameSpaceList;
FUnitNameSpaces: TUnitNameSpaceList;
FLineCountLimit: Integer;
FCodePage: Integer;
FLogManager: ILogManager;

procedure ReadSourcePathFile(const ASourceFileName: string);
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.

2 changes: 2 additions & 0 deletions Source/Debugger.pas
Original file line number Diff line number Diff line change
Expand Up @@ -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 +
Expand Down
7 changes: 6 additions & 1 deletion Source/HTMLCoverageReport.pas
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ function THTMLCoverageReport.GenerateUnitReport(
OutputFile: TTextWriter;
SourceFileName: string;
OutputFileName: string;
Encoding: TEncoding;
begin
Result.HasFile:= False;
Result.LinkFileName:= ACoverageUnit.ReportFileName + '.html';
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions Source/I_CoverageConfiguration.pas
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
13 changes: 13 additions & 0 deletions Test/CoverageConfigurationTest.pas
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ TCoverageConfigurationTest = class(TTestCase)
procedure TestInvalidParameter;

procedure TestEnableApiLogging;
procedure TestSetCodepage;

procedure TestEnableFileLoggingDefaultFile;
procedure TestEnableFileLoggingSpecifiedFile;
Expand Down Expand Up @@ -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';
//==============================================================================
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1485,6 +1497,7 @@ procedure TCoverageConfigurationTest.TestDProj;
LDProj.Add('<PropertyGroup Condition="''$(Base)''!=''''">');
LDProj.Add('<DCC_ExeOutput>..\build\$(PLATFORM)</DCC_ExeOutput>');
LDProj.Add('<DCC_UnitSearchPath>..\src\;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>');
LDProj.Add('<DCC_CodePage>65001</DCC_CodePage>');
LDProj.Add('</PropertyGroup>');

LTotalUnitList := TStringList.Create;
Expand Down