Skip to content

Instantly share code, notes, and snippets.

@jpluimers
Created December 26, 2014 12:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpluimers/90c033e28efebbe7d62e to your computer and use it in GitHub Desktop.
Save jpluimers/90c033e28efebbe7d62e to your computer and use it in GitHub Desktop.
Example of StartsWith and EndsWith versus the RTL functions SysUtils.StartsStr/EndsStr and HTTPUtil.StartsWith (which should have used StartsStr). See https://bitbucket.org/jeroenp/besharp.net/commits/1cc63544d699d893127cca3a015a748ae844a278
unit StringUtils;
interface
function EndsWith(const Value: string; const SubString: string): Boolean;
function StartsWith(const Value: string; const SubString: string): Boolean;
implementation
uses
StrUtils;
function EndsWith(const Value: string; const SubString: string): Boolean;
begin
// EndsStr is not symmetric to StartsStr and fails to handle empty SubString.
if SubString = '' then
Result := True
else
Result := EndsStr(SubString, Value);
end;
function StartsWith(const Value: string; const SubString: string): Boolean;
begin
Result := StartsStr(SubString, Value);
end;
end.
unit StringUtilsTests;
interface
uses
TestFramework;
type
// Delphi is very confusing in naming, when (not) using abbreviations and parameter order.
// So add an EndsWith that complements HTTPUtil.StartsWith (which could have used StartsStr in the first place:
// the RTL developers are Embarcadero don't even know what is inside the RTL!)
// Furthermore, in the RTL, StartsStr and EndsStr are not symmetric.
TStringFunctionTests = class(TTestCase)
published
procedure EndsStrTests;
procedure EndsWithTests;
procedure StartsStrTests;
procedure StartsWithTests;
procedure StartsWithHTTPUtilTests;
private
function CreateMessage(const FunctionName, Value, SubString: string): string;
const
LLeft = 'foo';
LRight = 'bar';
LValue = LLeft + LRight;
end;
implementation
uses
SysUtils,
StrUtils,
StringUtils,
HTTPUtil;
function TStringFunctionTests.CreateMessage(const FunctionName, Value, SubString: string): string;
begin
Result := Format('%s("%s", "%s")', [FunctionName, Value, SubString]);
end;
procedure TStringFunctionTests.EndsStrTests;
begin
CheckTrue(EndsStr(LRight, LValue), CreateMessage('EndsStr', LRight, LValue));
CheckFalse(EndsStr(LLeft, LValue), CreateMessage('not EndsStr', LLeft, LValue));
// Unlike StartsStr, EndsStr does not match on an empty string.
// This can never be fixed as EndsStr has been 'in the wild'.
// CheckTrue(EndsStr('', LValue), CreateMessage('EndsStr', '', LValue));
end;
procedure TStringFunctionTests.EndsWithTests;
begin
CheckTrue(EndsWith(LValue, LRight), CreateMessage('EndsWith', LValue, LRight));
CheckFalse(EndsWith(LValue, LLeft), CreateMessage('not EndsWith', LValue, LLeft));
CheckTrue(EndsWith(LValue, ''), CreateMessage('EndsWith', LValue, ''));
end;
procedure TStringFunctionTests.StartsStrTests;
begin
CheckFalse(StartsStr(LRight, LValue), CreateMessage('not StartsStr', LRight, LValue));
CheckTrue(StartsStr(LLeft, LValue), CreateMessage('StartsStr', LLeft, LValue));
CheckTrue(StartsStr('', LValue), CreateMessage('StartsStr', '', LValue));
end;
procedure TStringFunctionTests.StartsWithTests;
begin
CheckFalse(StartsWith(LValue, LRight), CreateMessage('not StartsWith', LValue, LRight));
CheckTrue(StartsWith(LValue, LLeft), CreateMessage('StartsWith', LValue, LLeft));
CheckTrue(StartsWith(LValue, ''), CreateMessage('StartsWith', LValue, ''));
end;
procedure TStringFunctionTests.StartsWithHTTPUtilTests;
begin
CheckFalse(HTTPUtil.StartsWith(LValue, LRight), CreateMessage('not HTTPUtil.StartsWith', LValue, LRight));
CheckTrue(HTTPUtil.StartsWith(LValue, LLeft), CreateMessage('HTTPUtil.StartsWith', LValue, LLeft));
CheckTrue(HTTPUtil.StartsWith(LValue, ''), CreateMessage('HTTPUtil.StartsWith', LValue, ''));
end;
initialization
RegisterTest(TStringFunctionTests.Suite);
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment