mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-26 14:50:32 +02:00
* fix for Delphi incompatible DelimitedText, Mantis #19610, big patch from Reinier Olislagers.
git-svn-id: trunk@22549 -
This commit is contained in:
parent
78d31eb3cd
commit
a48aba60fb
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -12709,6 +12709,7 @@ tests/webtbs/tw19511.pp svneol=native#text/pascal
|
|||||||
tests/webtbs/tw19548.pp svneol=native#text/pascal
|
tests/webtbs/tw19548.pp svneol=native#text/pascal
|
||||||
tests/webtbs/tw19555.pp svneol=native#text/pascal
|
tests/webtbs/tw19555.pp svneol=native#text/pascal
|
||||||
tests/webtbs/tw19581.pp svneol=native#text/plain
|
tests/webtbs/tw19581.pp svneol=native#text/plain
|
||||||
|
tests/webtbs/tw19610.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw19622.pp -text svneol=native#text/plain
|
tests/webtbs/tw19622.pp -text svneol=native#text/plain
|
||||||
tests/webtbs/tw1964.pp svneol=native#text/plain
|
tests/webtbs/tw1964.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw19651.pp svneol=native#text/plain
|
tests/webtbs/tw19651.pp svneol=native#text/plain
|
||||||
|
@ -140,30 +140,33 @@ Function TStrings.GetDelimitedText: string;
|
|||||||
Var
|
Var
|
||||||
I : integer;
|
I : integer;
|
||||||
p : pchar;
|
p : pchar;
|
||||||
c : set of char;
|
BreakChars : set of char;
|
||||||
S : String;
|
S : String;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
CheckSpecialChars;
|
CheckSpecialChars;
|
||||||
result:='';
|
result:='';
|
||||||
if StrictDelimiter then
|
if StrictDelimiter then
|
||||||
c:=[#0,Delimiter]
|
BreakChars:=[#0,QuoteChar,Delimiter]
|
||||||
else
|
else
|
||||||
c:=[#0..' ',QuoteChar,Delimiter];
|
BreakChars:=[#0..' ',QuoteChar,Delimiter];
|
||||||
|
|
||||||
|
// Check for break characters and quote if required.
|
||||||
For i:=0 to count-1 do
|
For i:=0 to count-1 do
|
||||||
begin
|
begin
|
||||||
S:=Strings[i];
|
S:=Strings[i];
|
||||||
p:=pchar(S);
|
p:=pchar(S);
|
||||||
while not(p^ in c) do
|
//Quote strings that include BreakChars:
|
||||||
|
while not(p^ in BreakChars) do
|
||||||
inc(p);
|
inc(p);
|
||||||
// strings in list may contain #0
|
if (p<>pchar(S)+length(S)) then
|
||||||
if (p<>pchar(S)+length(S)) and not StrictDelimiter then
|
|
||||||
Result:=Result+QuoteString(S,QuoteChar)
|
Result:=Result+QuoteString(S,QuoteChar)
|
||||||
else
|
else
|
||||||
Result:=Result+S;
|
Result:=Result+S;
|
||||||
if I<Count-1 then
|
if I<Count-1 then
|
||||||
Result:=Result+Delimiter;
|
Result:=Result+Delimiter;
|
||||||
end;
|
end;
|
||||||
|
// Quote empty string:
|
||||||
If (Length(Result)=0) and (Count=1) then
|
If (Length(Result)=0) and (Count=1) then
|
||||||
Result:=QuoteChar+QuoteChar;
|
Result:=QuoteChar+QuoteChar;
|
||||||
end;
|
end;
|
||||||
@ -268,22 +271,48 @@ begin
|
|||||||
j:=1;
|
j:=1;
|
||||||
aNotFirst:=false;
|
aNotFirst:=false;
|
||||||
|
|
||||||
|
{ Paraphrased from Delphi XE2 help:
|
||||||
|
Strings must be separated by Delimiter characters or spaces.
|
||||||
|
They may be enclosed in QuoteChars.
|
||||||
|
QuoteChars in the string must be repeated to distinguish them from the QuoteChars enclosing the string.
|
||||||
|
}
|
||||||
try
|
try
|
||||||
Clear;
|
Clear;
|
||||||
If StrictDelimiter then
|
If StrictDelimiter then
|
||||||
begin
|
begin
|
||||||
// Easier, faster loop.
|
while i<=length(AValue) do begin
|
||||||
While I<=Length(AValue) do
|
// skip delimiter
|
||||||
begin
|
if aNotFirst and (i<=length(AValue)) and (AValue[i]=FDelimiter) then inc(i);
|
||||||
If (AValue[I] in [FDelimiter,#0]) then
|
|
||||||
begin
|
// read next string
|
||||||
Add(Copy(AValue,J,I-J));
|
if i<=length(AValue) then begin
|
||||||
J:=I+1;
|
if AValue[i]=FQuoteChar then begin
|
||||||
|
// next string is quoted
|
||||||
|
j:=i+1;
|
||||||
|
while (j<=length(AValue)) and
|
||||||
|
( (AValue[j]<>FQuoteChar) or
|
||||||
|
( (j+1<=length(AValue)) and (AValue[j+1]=FQuoteChar) ) ) do begin
|
||||||
|
if (j<=length(AValue)) and (AValue[j]=FQuoteChar) then inc(j,2)
|
||||||
|
else inc(j);
|
||||||
end;
|
end;
|
||||||
Inc(i);
|
// j is position of closing quote
|
||||||
|
Add( StringReplace (Copy(AValue,i+1,j-i-1),
|
||||||
|
FQuoteChar+FQuoteChar,FQuoteChar, [rfReplaceAll]));
|
||||||
|
i:=j+1;
|
||||||
|
end else begin
|
||||||
|
// next string is not quoted; read until delimiter
|
||||||
|
j:=i;
|
||||||
|
while (j<=length(AValue)) and
|
||||||
|
(AValue[j]<>FDelimiter) do inc(j);
|
||||||
|
Add( Copy(AValue,i,j-i));
|
||||||
|
i:=j;
|
||||||
|
end;
|
||||||
|
end else begin
|
||||||
|
if aNotFirst then Add('');
|
||||||
|
end;
|
||||||
|
|
||||||
|
aNotFirst:=true;
|
||||||
end;
|
end;
|
||||||
If (Length(AValue)>0) then
|
|
||||||
Add(Copy(AValue,J,I-J));
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
@ -310,7 +339,7 @@ begin
|
|||||||
FQuoteChar+FQuoteChar,FQuoteChar, [rfReplaceAll]));
|
FQuoteChar+FQuoteChar,FQuoteChar, [rfReplaceAll]));
|
||||||
i:=j+1;
|
i:=j+1;
|
||||||
end else begin
|
end else begin
|
||||||
// next string is not quoted
|
// next string is not quoted; read until control character/space/delimiter
|
||||||
j:=i;
|
j:=i;
|
||||||
while (j<=length(AValue)) and
|
while (j<=length(AValue)) and
|
||||||
(Ord(AValue[j])>Ord(' ')) and
|
(Ord(AValue[j])>Ord(' ')) and
|
||||||
|
713
tests/webtbs/tw19610.pp
Normal file
713
tests/webtbs/tw19610.pp
Normal file
@ -0,0 +1,713 @@
|
|||||||
|
{ Source provided for Free Pascal bug report 19610 }
|
||||||
|
{ Submitted by Reinier Olislagers on 20120920 }
|
||||||
|
{
|
||||||
|
Note: the tests here are somewhat more extensive than the original bug report.
|
||||||
|
They are aimed at confirming interoperability between Delphi and FPC sdf formats
|
||||||
|
The basis for the tests is therefore Delphi's handling.
|
||||||
|
|
||||||
|
The only exception are the Put tests, which also accept results that are always
|
||||||
|
quoted. As Get_StrictDelimTrueSafeQuote and Get_StrictDelimFalseSafeQuote prove,
|
||||||
|
always quoting output leads to correct/the same input.
|
||||||
|
The advantage of this is that having strictdelimiter on or off does not matter
|
||||||
|
and the output format is more unambiguous (i.e. more compatible with RFC4180
|
||||||
|
for CSV).
|
||||||
|
|
||||||
|
On Delphi, rename to .dpr.
|
||||||
|
|
||||||
|
Tests successfully completed on:
|
||||||
|
Turbo Delphi 2006 (Reinier Olislagers)
|
||||||
|
Delphi 2007 (OBones)
|
||||||
|
Delphi XE (Marco van de Voort, OBones)
|
||||||
|
Delphi XE2 Win32 (OBones)
|
||||||
|
Delphi XE2 Win64 (OBones)
|
||||||
|
}
|
||||||
|
{
|
||||||
|
This file is part of the Free Pascal packages.
|
||||||
|
Copyright (c) 1999-2012 by the Free Pascal development team
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**********************************************************************}
|
||||||
|
{$apptype console}
|
||||||
|
{$ifdef fpc}
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
{$endif fpc}
|
||||||
|
program tw19610;
|
||||||
|
|
||||||
|
uses Classes, SysUtils;
|
||||||
|
|
||||||
|
{$ifndef fpc}
|
||||||
|
//Delphi
|
||||||
|
const
|
||||||
|
LineEnding=#13+#10;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
|
function Get_StrictDelimFalse:boolean;
|
||||||
|
// Test if input works with Delphi-compatible sdf output
|
||||||
|
// Strictdelimiter:=false (default) when processing the delimitedtext
|
||||||
|
//
|
||||||
|
// Mainly check if reading quotes is according to Delphi sdf specs and works.
|
||||||
|
// Based on del4.zip in bug 19610
|
||||||
|
const
|
||||||
|
// Matches del4.zip in bug 19610:
|
||||||
|
DelimText='normal_string;"quoted_string";"quoted;delimiter";"quoted and space";"""quoted_and_starting_quote";"""quoted, starting quote, and space";"quoted_with_tab'+#9+'character";"quoted_multi'+LineEnding+
|
||||||
|
'line"; UnquotedSpacesInfront;UnquotedSpacesAtTheEnd ; "Spaces before quoted string"';
|
||||||
|
TestName='tw19610.Get_StrictDelimFalse';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
Expected: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
//Expected values:
|
||||||
|
Expected:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
Expected.Add('normal_string');
|
||||||
|
Expected.Add('quoted_string');
|
||||||
|
Expected.Add('quoted;delimiter');
|
||||||
|
Expected.Add('quoted and space');
|
||||||
|
Expected.Add('"quoted_and_starting_quote');
|
||||||
|
Expected.Add('"quoted, starting quote, and space');
|
||||||
|
Expected.Add('quoted_with_tab'+#9+'character');
|
||||||
|
Expected.Add('quoted_multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
Expected.Add('UnquotedSpacesInfront');
|
||||||
|
Expected.Add('UnquotedSpacesAtTheEnd');
|
||||||
|
Expected.Add('Spaces before quoted string');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
|
||||||
|
TestSL.StrictDelimiter:=false;
|
||||||
|
TestSL.DelimitedText:=DelimText;
|
||||||
|
//Test:
|
||||||
|
if Expected.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(Expected.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (Expected.Count>i) and (TestSL[i]<>Expected[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Expected.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Get_StrictDelimTrue:boolean;
|
||||||
|
// Test if input works with Delphi-compatible sdf output
|
||||||
|
// Strictdelimiter:=true when processing the delimitedtext
|
||||||
|
//
|
||||||
|
// Mainly check if reading quotes is according to Delphi sdf specs and works.
|
||||||
|
// Based on del4.zip in bug 19610
|
||||||
|
const
|
||||||
|
// Matches del4.zip in bug 19610:
|
||||||
|
DelimText='normal_string;"quoted_string";"quoted;delimiter";"quoted and space";"""quoted_and_starting_quote";"""quoted, starting quote, and space";"quoted_with_tab'+#9+'character";"quoted_multi'+LineEnding+
|
||||||
|
'line"; UnquotedSpacesInfront;UnquotedSpacesAtTheEnd ; "Spaces before quoted string"';
|
||||||
|
TestName='tw19610.Get_StrictDelimTrue';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
Expected: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
//Expected values:
|
||||||
|
Expected:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
Expected.Add('normal_string');
|
||||||
|
Expected.Add('quoted_string');
|
||||||
|
Expected.Add('quoted;delimiter');
|
||||||
|
Expected.Add('quoted and space');
|
||||||
|
Expected.Add('"quoted_and_starting_quote');
|
||||||
|
Expected.Add('"quoted, starting quote, and space');
|
||||||
|
Expected.Add('quoted_with_tab'+#9+'character');
|
||||||
|
Expected.Add('quoted_multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
Expected.Add(' UnquotedSpacesInfront');
|
||||||
|
Expected.Add('UnquotedSpacesAtTheEnd ');
|
||||||
|
Expected.Add(' "Spaces before quoted string"');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
|
||||||
|
TestSL.StrictDelimiter:=true;
|
||||||
|
TestSL.DelimitedText:=DelimText;
|
||||||
|
//Test:
|
||||||
|
if Expected.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(Expected.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (Expected.Count>i) and (TestSL[i]<>Expected[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Expected.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Get_StrictDelimFalseCornerCases:boolean;
|
||||||
|
// Test if input works with Delphi-compatible sdf output
|
||||||
|
// Strictdelimiter:=false (default) when processing the delimitedtext
|
||||||
|
//
|
||||||
|
// Has some corner cases that Delphi produces but are not evident from their
|
||||||
|
// documentation
|
||||||
|
// Based on del4.zip in bug 19610
|
||||||
|
const
|
||||||
|
// Matches del4.zip in bug 19610:
|
||||||
|
DelimText='"Spaces after quoted string" ;';
|
||||||
|
TestName='tw19610.Get_StrictDelimFalseCornerCases';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
Expected: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
//Expected values:
|
||||||
|
Expected:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
Expected.Add('Spaces after quoted string');
|
||||||
|
Expected.Add('');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
|
||||||
|
TestSL.StrictDelimiter:=false;
|
||||||
|
TestSL.DelimitedText:=DelimText;
|
||||||
|
//Test:
|
||||||
|
if Expected.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(Expected.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (Expected.Count>i) and (TestSL[i]<>Expected[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Expected.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Get_StrictDelimTrueCornerCases:boolean;
|
||||||
|
// Test if input works with Delphi-compatible sdf output
|
||||||
|
// Strictdelimiter:=true when processing the delimitedtext
|
||||||
|
//
|
||||||
|
// Has some corner cases that Delphi produces but are not evident from their
|
||||||
|
// documentation
|
||||||
|
// Based on del4.zip in bug 19610
|
||||||
|
const
|
||||||
|
// Matches del4.zip in bug 19610:
|
||||||
|
DelimText='"Spaces after quoted string" ;';
|
||||||
|
TestName='tw19610.Get_StrictDelimTrueCornerCases';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
Expected: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
//Expected values:
|
||||||
|
Expected:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
// With delimiter true, we get 2 extra empty lines, also some spaces
|
||||||
|
Expected.Add('Spaces after quoted string');
|
||||||
|
Expected.Add(' ');
|
||||||
|
Expected.Add('');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
|
||||||
|
TestSL.StrictDelimiter:=true;
|
||||||
|
TestSL.DelimitedText:=DelimText;
|
||||||
|
//Test:
|
||||||
|
if Expected.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(Expected.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (Expected.Count>i) and (TestSL[i]<>Expected[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Expected.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Get_StrictDelimTrueSafeQuote:boolean;
|
||||||
|
// Test if input works with sdf output that has always been quoted
|
||||||
|
// Delphi accepts this input even though it does not write it by default
|
||||||
|
// This is a more unambiguous format than unquoted
|
||||||
|
// Strictdelimiter:=true when processing the delimitedtext
|
||||||
|
//
|
||||||
|
const
|
||||||
|
DelimText='"normal_string";"""quoted_string""";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"string_with_tab'+#9+'character";"multi'+LineEnding+
|
||||||
|
'line";" SpacesInfront";"SpacesAtTheEnd ";" ""Spaces before quoted string"""';
|
||||||
|
TestName='tw19610.Get_StrictDelimTrueSafeQuote';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
Expected: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
//Expected values:
|
||||||
|
Expected:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
Expected.Add('normal_string');
|
||||||
|
Expected.Add('"quoted_string"');
|
||||||
|
Expected.Add('"quoted;delimiter"');
|
||||||
|
Expected.Add('"quoted and space"');
|
||||||
|
Expected.Add('"starting_quote');
|
||||||
|
Expected.Add('string_with_tab'+#9+'character');
|
||||||
|
Expected.Add('multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
Expected.Add(' SpacesInfront');
|
||||||
|
Expected.Add('SpacesAtTheEnd ');
|
||||||
|
Expected.Add(' "Spaces before quoted string"');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
|
||||||
|
TestSL.StrictDelimiter:=true;
|
||||||
|
TestSL.DelimitedText:=DelimText;
|
||||||
|
//Test:
|
||||||
|
if Expected.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(Expected.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (Expected.Count>i) and (TestSL[i]<>Expected[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Expected.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Get_StrictDelimFalseSafeQuote:boolean;
|
||||||
|
// Test if input works with sdf output that has always been quoted
|
||||||
|
// Delphi accepts this input even though it does not write it by default
|
||||||
|
// This is a more unambiguous format than unquoted
|
||||||
|
// Strictdelimiter:=false when processing the delimitedtext
|
||||||
|
//
|
||||||
|
const
|
||||||
|
DelimText='"normal_string";"""quoted_string""";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"string_with_tab'+#9+'character";"multi'+LineEnding+
|
||||||
|
'line";" SpacesInfront";"SpacesAtTheEnd ";" ""Spaces before quoted string"""';
|
||||||
|
TestName='tw19610.Get_StrictDelimTrueSafeQuote';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
Expected: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
//Expected values:
|
||||||
|
Expected:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
Expected.Add('normal_string');
|
||||||
|
Expected.Add('"quoted_string"');
|
||||||
|
Expected.Add('"quoted;delimiter"');
|
||||||
|
Expected.Add('"quoted and space"');
|
||||||
|
Expected.Add('"starting_quote');
|
||||||
|
Expected.Add('string_with_tab'+#9+'character');
|
||||||
|
Expected.Add('multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
Expected.Add(' SpacesInfront');
|
||||||
|
Expected.Add('SpacesAtTheEnd ');
|
||||||
|
Expected.Add(' "Spaces before quoted string"');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';'; //Match example in bug 19610, del4.zip
|
||||||
|
TestSL.StrictDelimiter:=false;
|
||||||
|
TestSL.DelimitedText:=DelimText;
|
||||||
|
//Test:
|
||||||
|
if Expected.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(Expected.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (Expected.Count>i) and (TestSL[i]<>Expected[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Expected.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Get_Commatext:boolean;
|
||||||
|
// Test if input works with Delphi-compatible commatext
|
||||||
|
const
|
||||||
|
CommaText='normal_string,"quoted_string","quoted,delimiter","quoted and space","""quoted_and_starting_quote","""quoted, starting quote, and space","quoted_with_tab'+#9+'character","quoted_multi'+LineEnding+
|
||||||
|
'line"," UnquotedSpacesInfront","UnquotedSpacesAtTheEnd "," ""Spaces before quoted string"""';
|
||||||
|
TestName='tw19610.Get_Commatext';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
Expected: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
//Expected values:
|
||||||
|
Expected:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
Expected.Add('normal_string');
|
||||||
|
Expected.Add('quoted_string');
|
||||||
|
Expected.Add('quoted,delimiter');
|
||||||
|
Expected.Add('quoted and space');
|
||||||
|
Expected.Add('"quoted_and_starting_quote');
|
||||||
|
Expected.Add('"quoted, starting quote, and space');
|
||||||
|
Expected.Add('quoted_with_tab'+#9+'character');
|
||||||
|
Expected.Add('quoted_multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
Expected.Add(' UnquotedSpacesInfront');
|
||||||
|
Expected.Add('UnquotedSpacesAtTheEnd ');
|
||||||
|
Expected.Add(' "Spaces before quoted string"');
|
||||||
|
|
||||||
|
TestSL.CommaText:=CommaText;
|
||||||
|
//Test:
|
||||||
|
if Expected.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(Expected.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (Expected.Count>i) and (TestSL[i]<>Expected[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
Expected.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function Put_StrictDelimFalse:boolean;
|
||||||
|
// Test if conversion stringlist=>delimitedtext gives the right data
|
||||||
|
// (right in this case: what Delphi outputs)
|
||||||
|
// Strictdelimiter:=false when processing the delimitedtext
|
||||||
|
const
|
||||||
|
Expected='normal_string;"""quoted_string""";"just;delimiter";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"single""quote";"""""quoted starting quote and space""";"with_tab'+#9+'character";"multi'+LineEnding+
|
||||||
|
'line";" UnquotedSpacesInfront";"UnquotedSpacesAtTheEnd ";" ""Spaces before quoted string"""';
|
||||||
|
//If we choose to output the "safely quoted" version, we need to test for it:
|
||||||
|
//Though this version is not the same output as Delphi, it leads to the
|
||||||
|
//same input if imported again (see Get_StrictDelimFalseSafeQuote for corresponding tests)
|
||||||
|
ExpectedSafeQuote='"normal_string";"""quoted_string""";"just;delimiter";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"single""quote";"""""quoted starting quote and space""";"with_tab'+#9+'character";"multi'+LineEnding+
|
||||||
|
'line";" UnquotedSpacesInfront";"UnquotedSpacesAtTheEnd ";" ""Spaces before quoted string"""';
|
||||||
|
TestName='tw19610.Put_StrictDelimFalse';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
TestSL.Add('normal_string');
|
||||||
|
TestSL.Add('"quoted_string"');
|
||||||
|
TestSL.Add('just;delimiter');
|
||||||
|
TestSL.Add('"quoted;delimiter"');
|
||||||
|
TestSL.Add('"quoted and space"');
|
||||||
|
TestSL.Add('"starting_quote');
|
||||||
|
TestSL.Add('single"quote');
|
||||||
|
TestSL.Add('""quoted starting quote and space"');
|
||||||
|
TestSL.Add('with_tab'+#9+'character');
|
||||||
|
TestSL.Add('multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
TestSL.Add(' UnquotedSpacesInfront');
|
||||||
|
TestSL.Add('UnquotedSpacesAtTheEnd ');
|
||||||
|
TestSL.Add(' "Spaces before quoted string"');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';';
|
||||||
|
TestSL.StrictDelimiter:=false;
|
||||||
|
if (TestSL.DelimitedText<>Expected) and (TestSL.DelimitedText<>ExpectedSafeQuote) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL.DelimitedText+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected+'*');
|
||||||
|
writeln('- or, with safe quote output:');
|
||||||
|
writeln('*'+ExpectedSafeQuote+'*');
|
||||||
|
result:=false
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function Put_StrictDelimTrue:boolean;
|
||||||
|
// Test if conversion stringlist=>delimitedtext gives the right data
|
||||||
|
// (right in this case: what Delphi outputs)
|
||||||
|
// Strictdelimiter:=true when processing the delimitedtext
|
||||||
|
const
|
||||||
|
Expected='normal_string;"""quoted_string""";"just;delimiter";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"single""quote";"""""quoted starting quote and space""";with_tab'+#9+'character;multi'+LineEnding+
|
||||||
|
'line; UnquotedSpacesInfront;UnquotedSpacesAtTheEnd ;" ""Spaces before quoted string"""';
|
||||||
|
//If we choose to output the "safely quoted" version, we need to test for it:
|
||||||
|
//Though this version is not the same output as Delphi, it leads to the
|
||||||
|
//same input if imported again (see Get_StrictDelimTrueSafeQuote for corresponding tests)
|
||||||
|
ExpectedSafeQuote='"normal_string";"""quoted_string""";"just;delimiter";"""quoted;delimiter""";"""quoted and space""";"""starting_quote";"single""quote";"""""quoted starting quote and space""";"with_tab'+#9+'character";"multi'+LineEnding+
|
||||||
|
'line";" UnquotedSpacesInfront";"UnquotedSpacesAtTheEnd ";" ""Spaces before quoted string"""';
|
||||||
|
TestName='tw19610.Put_StrictDelimTrue';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
TestSL.Add('normal_string');
|
||||||
|
TestSL.Add('"quoted_string"');
|
||||||
|
TestSL.Add('just;delimiter');
|
||||||
|
TestSL.Add('"quoted;delimiter"');
|
||||||
|
TestSL.Add('"quoted and space"');
|
||||||
|
TestSL.Add('"starting_quote');
|
||||||
|
TestSL.Add('single"quote');
|
||||||
|
TestSL.Add('""quoted starting quote and space"');
|
||||||
|
TestSL.Add('with_tab'+#9+'character');
|
||||||
|
TestSL.Add('multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
TestSL.Add(' UnquotedSpacesInfront');
|
||||||
|
TestSL.Add('UnquotedSpacesAtTheEnd ');
|
||||||
|
TestSL.Add(' "Spaces before quoted string"');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';';
|
||||||
|
TestSL.StrictDelimiter:=true;
|
||||||
|
if (TestSL.DelimitedText<>Expected) and (TestSL.DelimitedText<>ExpectedSafeQuote) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL.DelimitedText+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+Expected+'*');
|
||||||
|
writeln('- or, with safe quote output:');
|
||||||
|
writeln('*'+ExpectedSafeQuote+'*');
|
||||||
|
result:=false
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetPut_StrictDelimFalse:boolean;
|
||||||
|
// Test if conversion stringlist=>delimitedtext=>stringlist gives identical data
|
||||||
|
// Strictdelimiter:=false (default) when processing the delimitedtext
|
||||||
|
const
|
||||||
|
TestName='tw19610.GetPut_StrictDelimFalse';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
ResultSL: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
ResultSL:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
TestSL.Add('normal_string');
|
||||||
|
TestSL.Add('"quoted_string"');
|
||||||
|
TestSL.Add('"quoted;delimiter"');
|
||||||
|
TestSL.Add('"quoted and space"');
|
||||||
|
TestSL.Add('"starting_quote');
|
||||||
|
TestSL.Add('""quoted, starting quote, and space"');
|
||||||
|
TestSL.Add('with_tab'+#9+'character');
|
||||||
|
TestSL.Add('multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
TestSL.Add(' UnquotedSpacesInfront');
|
||||||
|
TestSL.Add('UnquotedSpacesAtTheEnd ');
|
||||||
|
TestSL.Add(' "Spaces before quoted string"');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';';
|
||||||
|
TestSL.StrictDelimiter:=false;
|
||||||
|
ResultSL.Delimiter:=';';
|
||||||
|
ResultSL.StrictDelimiter:=false;
|
||||||
|
ResultSL.DelimitedText:=TestSL.DelimitedText;
|
||||||
|
//Test:
|
||||||
|
if ResultSL.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(ResultSL.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (ResultSL.Count>i) and (TestSL[i]<>ResultSL[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+ResultSL[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
ResultSL.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function GetPut_StrictDelimTrue:boolean;
|
||||||
|
// Test if conversion stringlist=>delimitedtext=>stringlist gives identical data
|
||||||
|
// Strictdelimiter:=true when processing the delimitedtext
|
||||||
|
const
|
||||||
|
TestName='tw19610.GetPut_StrictDelimTrue';
|
||||||
|
var
|
||||||
|
TestSL: TStringList;
|
||||||
|
ResultSL: TStringList;
|
||||||
|
i: integer;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
ResultSL:=TStringList.Create;
|
||||||
|
TestSL:=TStringList.Create;
|
||||||
|
try
|
||||||
|
TestSL.Add('normal_string');
|
||||||
|
TestSL.Add('"quoted_string"');
|
||||||
|
TestSL.Add('"quoted;delimiter"');
|
||||||
|
TestSL.Add('"quoted and space"');
|
||||||
|
TestSL.Add('"starting_quote');
|
||||||
|
TestSL.Add('""quoted, starting quote, and space"');
|
||||||
|
TestSL.Add('with_tab'+#9+'character');
|
||||||
|
TestSL.Add('multi'+LineEnding+
|
||||||
|
'line');
|
||||||
|
TestSL.Add(' UnquotedSpacesInfront');
|
||||||
|
TestSL.Add('UnquotedSpacesAtTheEnd ');
|
||||||
|
TestSL.Add(' "Spaces before quoted string"');
|
||||||
|
|
||||||
|
TestSL.Delimiter:=';';
|
||||||
|
TestSL.StrictDelimiter:=false;
|
||||||
|
ResultSL.Delimiter:=';';
|
||||||
|
ResultSL.StrictDelimiter:=true;
|
||||||
|
ResultSL.DelimitedText:=TestSL.DelimitedText;
|
||||||
|
//Test:
|
||||||
|
if ResultSL.Count<>TestSL.Count then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: count mismatch: '+
|
||||||
|
inttostr(TestSL.Count)+' test strings; '+inttostr(ResultSL.Count)+' expected strings.');
|
||||||
|
end;
|
||||||
|
|
||||||
|
for i:=0 to TestSL.Count-1 do
|
||||||
|
begin
|
||||||
|
if (ResultSL.Count>i) and (TestSL[i]<>ResultSL[i]) then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln(TestName+': failed: result:');
|
||||||
|
writeln('*'+TestSL[i]+'*');
|
||||||
|
writeln('while expected was:');
|
||||||
|
writeln('*'+ResultSL[i]+'*');
|
||||||
|
result:=false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
ResultSL.Free;
|
||||||
|
TestSL.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
FailCount: integer;
|
||||||
|
begin
|
||||||
|
FailCount:=0;
|
||||||
|
// The Get_... tests load in delimitedtext and test the resulting stringlist:
|
||||||
|
if not(Get_StrictDelimFalse) then FailCount:=FailCount+1;
|
||||||
|
if not(Get_StrictDelimTrue) then FailCount:=FailCount+1;
|
||||||
|
if not(Get_StrictDelimFalseCornerCases) then FailCount:=FailCount+1;
|
||||||
|
if not(Get_StrictDelimTrueCornerCases) then FailCount:=FailCount+1;
|
||||||
|
if not(Get_StrictDelimTrueSafeQuote) then FailCount:=FailCount+1;
|
||||||
|
if not(Get_StrictDelimFalseSafeQuote) then FailCount:=FailCount+1;
|
||||||
|
|
||||||
|
if not(Get_CommaText) then FailCount:=FailCount+1;
|
||||||
|
|
||||||
|
// The Put_... tests load strings and test the resulting delimitedtext:
|
||||||
|
if not(Put_StrictDelimFalse) then FailCount:=FailCount+1;
|
||||||
|
if not(Put_StrictDelimTrue) then FailCount:=FailCount+1;
|
||||||
|
|
||||||
|
// Test writing to delimitedtext and reading from delimitedtext:
|
||||||
|
if not(GetPut_StrictDelimFalse) then FailCount:=FailCount+1;
|
||||||
|
if not(GetPut_StrictDelimTrue) then FailCount:=FailCount+1;
|
||||||
|
|
||||||
|
// Indicate success or failure to test framework:
|
||||||
|
if FailCount=0 then
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln('tw19610: sdf tests succeeded.');
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
writeln('');
|
||||||
|
writeln('tw19610: sdf test(s) failed. Number of failed test group(s): '+inttostr(FailCount));
|
||||||
|
end;
|
||||||
|
|
||||||
|
halt(FailCount);
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user