2
0
Эх сурвалжийг харах

* More tests

git-svn-id: branches/cleanroom@9295 -
michael 18 жил өмнө
parent
commit
907b150b09

+ 5 - 0
.gitattributes

@@ -5528,8 +5528,13 @@ rtl/tests/fplists.pp svneol=native#text/plain
 rtl/tests/lists.pp svneol=native#text/plain
 rtl/tests/lltests.lpi svneol=native#text/plain
 rtl/tests/lltests.lpr svneol=native#text/plain
+rtl/tests/searchbuf.inc svneol=native#text/plain
 rtl/tests/tcfindnested.pp svneol=native#text/plain
+rtl/tests/tcstringlist.pp svneol=native#text/plain
+rtl/tests/tcstrutils.pp svneol=native#text/plain
 rtl/tests/testll.pp svneol=native#text/plain
+rtl/tests/tstrutils.lpi svneol=native#text/plain
+rtl/tests/tstrutils.lpr svneol=native#text/plain
 rtl/ucmaps/8859-1.txt svneol=native#text/plain
 rtl/ucmaps/8859-10.txt svneol=native#text/plain
 rtl/ucmaps/8859-13.txt svneol=native#text/plain

+ 117 - 0
rtl/tests/searchbuf.inc

@@ -0,0 +1,117 @@
+type
+  TEqualFunction = function (const a,b : char) : boolean;
+
+function EqualWithCase (const a,b : char) : boolean;
+begin
+  result := (a = b);
+end;
+
+function EqualWithoutCase (const a,b : char) : boolean;
+begin
+  result := (lowerCase(a) = lowerCase(b));
+end;
+
+function IsWholeWord (bufstart, bufend, wordstart, wordend : pchar) : boolean;
+begin
+            // Check start
+  result := ((wordstart = bufstart) or ((wordstart-1)^ in worddelimiters)) and
+            // Check end
+            ((wordend = bufend) or ((wordend+1)^ in worddelimiters));
+end;
+
+function SearchDown(buf,aStart,endchar:pchar; SearchString:string;
+    equal : TEqualFunction; WholeWords:boolean) : pchar;
+var Found : boolean;
+    s, c : pchar;
+begin
+  result := aStart;
+  Found := false;
+  while not Found and (result <= endchar) do
+    begin
+    // Search first letter
+    while (result <= endchar) and not Equal(result^,SearchString[1]) do
+      inc (result);
+    // Check if following is searchstring
+    c := result;
+    s := @(Searchstring[1]);
+    Found := true;
+    while (c <= endchar) and (s^ <> #0) and Found do
+      begin
+      Found := Equal(c^, s^);
+      inc (c);
+      inc (s);
+      end;
+    if s^ <> #0 then
+      Found := false;
+    // Check if it is a word
+    if Found and WholeWords then
+      Found := IsWholeWord(buf,endchar,result,c-1);
+    if not found then
+      inc (result);
+    end;
+  if not Found then
+    result := nil;
+end;
+
+Function SearchUp(buf,aStart,endchar:pchar; SearchString:string;
+    equal : TEqualFunction; WholeWords:boolean) : pchar;
+var Found : boolean;
+    s, c, l : pchar;
+begin
+  aStart := buf;
+  Found := false;
+  l := @(SearchString[length(SearchString)]);
+  while not Found and (result >= buf) do
+    begin
+    // Search last letter
+    while (result >= buf) and not Equal(result^,l^) do
+      dec (result);
+    // Check if before is searchstring
+    c := result;
+    s := l;
+    Found := true;
+    while (c >= buf) and (s >= @SearchString[1]) and Found do
+      begin
+      Found := Equal(c^, s^);
+      dec (c);
+      dec (s);
+      end;
+    if (s >= @(SearchString[1])) then
+      Found := false;
+    // Check if it is a word
+    if Found and WholeWords then
+      Found := IsWholeWord(buf,endchar,c+1,result);
+    if found then
+      result := c+1
+    else
+      dec (result);
+    end;
+  if not Found then
+    result := nil;
+end;
+
+//function SearchDown(buf,aStart,endchar:pchar; SearchString:string; equal : TEqualFunction; WholeWords:boolean) : pchar;
+function SearchBuf(Buf: PChar;BufLen: Integer;SelStart: Integer;SelLength: Integer;
+    SearchString: String;Options: TStringSearchOptions):PChar;
+var
+  equal : TEqualFunction;
+begin
+  {$ifdef noexception}
+  if SearchString = '' then
+    result := nil
+  else
+    begin
+  {$endif}
+    if soMatchCase in Options then
+      Equal := @EqualWithCase
+    else
+      Equal := @EqualWithoutCase;
+    if soDown in Options then
+      SearchDown(buf,buf+SelStart+SelLength,Buf+(BufLen-1), SearchString, Equal, (soWholeWord in Options))
+    else
+      SearchUp(buf,buf+SelStart+SelLength,Buf+(BufLen-1), SearchString, Equal, (soWholeWord in Options))
+    {$ifdef noexception}
+    end;
+    {$endif}
+end;
+

+ 334 - 0
rtl/tests/tcstringlist.pp

@@ -0,0 +1,334 @@
+unit tcstringlist;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry; 
+
+type
+
+  { TTestTStringList }
+
+  TTestTStringList= class(TTestCase)
+  private
+    procedure AddB;
+    procedure DeleteNegativeIndex;
+    procedure DeleteTooBigIndex;
+    procedure ExchangeNegativeIndex1;
+    procedure ExchangeTooBigIndex1;
+    procedure ExchangeNegativeIndex2;
+    procedure ExchangeTooBigIndex2;
+    procedure AccessNegativeIndex;
+    procedure AccessTooBigIndex;
+    Procedure Shuffle;
+  protected
+    List : TStringList;
+    Procedure FillList(ACount : Integer);
+    procedure SetUp; override; 
+    procedure TearDown; override; 
+  published
+    procedure TestCreate;
+    procedure TestAdd;
+    procedure TestAddIndex;
+    procedure TestAdd2;
+    procedure TestInsertFirst;
+    Procedure TestInsertMiddle;
+    procedure TestDelete;
+    Procedure TestClear;
+    Procedure TestIndexOf;
+    procedure TestExchange;
+    procedure TestAccesIndexOutOfBounds;
+    procedure TestDeleteIndexOutOfBounds;
+    procedure TestExchangeIndexOutOfBounds;
+    Procedure TestSort;
+    Procedure TestSorted;
+    Procedure TestSortedAdd;
+    Procedure TestSortedAddAll;
+    Procedure TestSortedDupError;
+    procedure TestSortedAddDuplicate;
+    Procedure TestSortedIndexOf;
+  end;
+
+implementation
+
+procedure TTestTStringList.TestCreate;
+begin
+  AssertEquals('Empty list has count 0',0,List.Count);
+  AssertEquals('Empty list has sorted false',False,List.Sorted);
+  If List.Duplicates<>dupIgnore then
+    Fail('Empty list has duplicates=dupIgnore');
+end;
+
+procedure TTestTStringList.TestAdd;
+
+begin
+  FillList(1);
+  AssertEquals('Add 1 element, count is 1',1,List.Count);
+  AssertEquals('Add 1 element, last element is "Item 1"','Item 1',List[0]);
+end;
+
+procedure TTestTStringList.TestAddIndex;
+
+begin
+  AssertEquals('Add first element at index 0',0,List.Add('First'));
+  AssertEquals('Add second element, at index 1',1,List.Add('second'));
+end;
+
+procedure TTestTStringList.TestAdd2;
+
+begin
+  FillList(2);
+  AssertEquals('Add 2 elements, count is 2',2,List.Count);
+  AssertEquals('Add 2 elements, first element is "Item 1"','Item 1',List[0]);
+  AssertEquals('Add 2 elements, second element is "Item 2"','Item 2',List[1]);
+end;
+
+procedure TTestTStringList.TestInsertFirst;
+begin
+  FillList(3);
+  List.Insert(0,'New');
+  AssertEquals('Insert 1 in 3, count is 4',4,List.Count);
+  AssertEquals('Insert 1 in 3, first is inserted','New',List[0]);
+  AssertEquals('Insert 1 in 3, second is old first','Item 1',List[1]);
+end;
+
+procedure TTestTStringList.TestInsertMiddle;
+begin
+  FillList(3);
+  List.Insert(1,'New');
+  AssertEquals('Insert 1 in 3, count is 4',4,List.Count);
+  AssertEquals('Insert 1 in 3, 1 is inserted','New',List[1]);
+  AssertEquals('Insert 1 in 3, 2 is old 2','Item 2',List[2]);
+  AssertEquals('Insert 1 in 3, 0 is untouched','Item 1',List[0]);
+end;
+
+procedure TTestTStringList.TestClear;
+begin
+  FillList(3);
+  List.Clear;
+  AssertEquals('Clear: count is 0',0,List.Count);
+end;
+
+procedure TTestTStringList.TestIndexOf;
+begin
+  FillList(11);
+  AssertEquals('Find third element',2,List.IndexOf('Item 3'));
+  AssertEquals('Find third element, wrong case',2,List.IndexOf('ITEM 3'));
+end;
+
+procedure TTestTStringList.TestDelete;
+
+begin
+  FillList(3);
+  List.Delete(1);
+  AssertEquals('Delete 1 from 3, count is 2',2,List.Count);
+  AssertEquals('Delete 1 from 3, first is "Item 1"','Item 1',List[0]);
+  AssertEquals('Delete 1 from 3, second is "Item 3"','Item 3',List[1]);
+end;
+
+procedure TTestTStringList.TestExchange;
+
+begin
+  FillList(3);
+  List.Exchange(0,2);
+  AssertEquals('Exchange 0 and 2, count is 3',3,List.Count);
+  AssertEquals('Exchange 0 and 2, first is "Item 3"','Item 3',List[0]);
+  AssertEquals('Exchange 0 and 2, second is "Item 2"','Item 2',List[1]);
+  AssertEquals('Exchange 0 and 2, third is "Item 1"','Item 1',List[2]);
+end;
+
+procedure TTestTStringList.DeleteNegativeIndex;
+begin
+  List.Delete(-1);
+end;
+
+procedure TTestTStringList.DeleteTooBigIndex;
+begin
+  List.Delete(3);
+end;
+
+procedure TTestTStringList.ExchangeNegativeIndex1;
+begin
+  List.Exchange(-1,2);
+end;
+
+procedure TTestTStringList.ExchangeTooBigIndex1;
+begin
+  List.Exchange(3,2);
+end;
+
+procedure TTestTStringList.ExchangeNegativeIndex2;
+begin
+  List.Exchange(2,-1);
+
+end;
+
+procedure TTestTStringList.ExchangeTooBigIndex2;
+begin
+  List.Exchange(2,3);
+end;
+
+procedure TTestTStringList.AccessNegativeIndex;
+
+begin
+  List[-1];
+end;
+
+procedure TTestTStringList.AccessTooBigIndex;
+
+begin
+  List[3];
+end;
+
+procedure TTestTStringList.Shuffle;
+
+Var
+  I,I1,I2 : Integer;
+
+begin
+  For I:=1 to List.Count* 2 do
+    begin
+    I1:=Random(List.Count);
+    I2:=Random(List.Count);
+    if I1<>I2 then
+      List.Exchange(I1,I2);
+    end;
+end;
+
+procedure TTestTStringList.TestAccesIndexOutOfBounds;
+begin
+  FillList(3);
+  AssertException('Access Negative Index',EStringListError,@AccessNegativeIndex);
+  AssertException('Access Index too big',EStringListError,@AccessTooBigIndex);
+end;
+
+procedure TTestTStringList.TestDeleteIndexOutOfBounds;
+begin
+  FillList(3);
+  AssertException('Delete Negative Index',EStringListError,@DeleteNegativeIndex);
+  AssertException('Delete Index too big',EStringListError,@DeleteTooBigIndex);
+end;
+
+procedure TTestTStringList.TestExchangeIndexOutOfBounds;
+begin
+  FillList(3);
+  AssertException('Exchange Negative first index',EStringListError,@ExchangeNegativeIndex1);
+  AssertException('Exchange Negative second index',EStringListError,@ExchangeNegativeIndex2);
+  AssertException('Exchange first Index too big',EStringListError,@ExchangeTooBigIndex1);
+  AssertException('Exchange second Index too big',EStringListError,@ExchangeTooBigIndex2);
+end;
+
+procedure TTestTStringList.TestSort;
+
+Var
+  I : Integer;
+
+begin
+  FillList(9);
+  Shuffle;
+  List.Sort;
+  For I:=0 to List.Count-1 do
+    If (List[i]<>'Item '+IntToStr(I+1)) then
+      Fail(Format('Item at position %d is out of place (%s)',[I,List[i]]));
+end;
+
+procedure TTestTStringList.TestSorted;
+
+Var
+  I : Integer;
+begin
+  FillList(9);
+  Shuffle;
+  List.Sorted:=True;
+  For I:=0 to List.Count-1 do
+    If (List[i]<>'Item '+IntToStr(I+1)) then
+      Fail(Format('Item at position %d is out of place (%s)',[I,List[i]]));
+end;
+
+procedure TTestTStringList.TestSortedAdd;
+begin
+  List.Sorted:=True;
+  List.Add('B');
+  AssertEquals('Add second element at first location in sorted list',0,List.Add('A'));
+  AssertEquals('Add third element at first location in sorted list',1,List.Add('AB'));
+  AssertEquals('Add fourth element at last location in sorted list',3,List.Add('C'));
+end;
+
+procedure TTestTStringList.TestSortedAddAll;
+
+Var
+  I : Integer;
+  
+begin
+  List.Sorted:=True;
+  FillList(9);
+  For I:=0 to List.Count-1 do
+    If (List[i]<>'Item '+IntToStr(I+1)) then
+      Fail(Format('Item at position %d is out of place (%s)',[I,List[i]]));
+end;
+
+procedure TTestTStringList.AddB;
+
+begin
+  List.Add('B');
+end;
+
+procedure TTestTStringList.TestSortedDupError;
+begin
+  List.Sorted:=True;
+  List.Duplicates:=dupError;
+  List.Add('B');
+  AssertEquals('Add second element at first location in sorted list',0,List.Add('A'));
+  AssertException(EStringListError,@AddB);
+end;
+
+procedure TTestTStringList.TestSortedAddDuplicate;
+
+begin
+  List.Sorted:=True;
+  List.Duplicates:=dupAccept;
+  List.Add('B');
+  AssertEquals('Add second element at first location in sorted list',0,List.Add('A'));
+  AssertEquals('Add third element at first location in sorted list',1,List.Add('B'));
+  AssertEquals('Add fourth element at last location in sorted list',3,List.Add('C'));
+end;
+
+procedure TTestTStringList.TestSortedIndexOf;
+
+// Tests find, as find is called in case of sorted index
+
+begin
+  List.Sorted:=True;
+  FillList(11);
+  // 1 10 11 2 3 - so index 4
+  AssertEquals('Find third element',4,List.IndexOf('Item 3'));
+  AssertEquals('Find third element, wrong case',4,List.IndexOf('ITEM 3'));
+end;
+
+
+procedure TTestTStringList.FillList(ACount: Integer);
+
+Var
+  I : integer;
+
+begin
+  For I:=1 to ACount do
+    List.Add('Item '+IntToStr(I));
+end;
+
+procedure TTestTStringList.SetUp; 
+begin
+  List:=TStringList.Create;
+end; 
+
+procedure TTestTStringList.TearDown; 
+begin
+  FreeAndNil(List);
+end;
+
+initialization
+  RegisterTest(TTestTStringList);
+end.
+

+ 157 - 0
rtl/tests/tcstrutils.pp

@@ -0,0 +1,157 @@
+unit tcstrutils;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+  Classes, SysUtils, fpcunit, testutils, testregistry, strutils;
+
+type
+
+  { TTestSearchBuf }
+
+  TTestSearchBuf= class(TTestCase)
+  Private
+    Procedure TestSearch(Sub:String; Start : Integer; O : TStringSearchOptions; Expected : Integer);
+  published
+    procedure TestSimple;
+    procedure TestSimpleNoRes;
+    procedure TestSimpleDown;
+    procedure TestSimpleDownNoRes;
+    procedure TestNotExistDown;
+    procedure TestNotExist;
+    procedure TestSimpleDownPos;
+    procedure TestSimplePos;
+    procedure TestSimpleCaseSensitive;
+    procedure TestSimpleCaseSensitiveDown;
+    procedure TestSimpleWholeWord;
+    procedure TestSimpleWholeWordDown;
+    procedure TestSimplePartialend;
+    procedure TestSimplePartialStart;
+    procedure TestEndMatchDown;
+    procedure TestEndMatch;
+  end;
+
+implementation
+
+Const
+   // Don't move this comment, it indicates the positions.
+   //           1         2         3         4
+   //  1234567890123456789012345678901234567890123456789
+  S = 'Some very long string with some words in it';
+  SLen = Length(S);
+  Starts : Array[1..3] of Integer = (0,10,41);
+  
+{$define usenew}
+{$ifdef usenew}
+{$i searchbuf.inc}
+{$endif}
+
+procedure TTestSearchBuf.TestSearch(Sub: String; Start: Integer;
+  O: TStringSearchOptions; Expected: Integer);
+
+Var
+  P,PR : PChar;
+  I : Integer;
+  
+begin
+  P:=PChar(S);
+  PR:=SearchBuf(P,Length(S),Start,0,Sub,O);
+  If (PR=Nil) then
+    begin
+    If (Expected<>-1) then
+      Fail(Format('Search for "%s" failed, expected result at %d',[Sub,Expected]));
+    end
+  else
+    begin
+    I:=(PR-P)+1;
+    If (I<>Expected) then
+      Fail(Format('Wrong result for search for "%s", expected result at %d, got %d',[Sub,Expected,I]));
+    end;
+end;
+
+procedure TTestSearchBuf.TestSimpleNoRes;
+begin
+  TestSearch('very',0,[],-1);
+end;
+
+procedure TTestSearchBuf.TestSimple;
+begin
+  TestSearch('very',SLen,[],6);
+end;
+
+procedure TTestSearchBuf.TestSimpleDownNoRes;
+begin
+  TestSearch('very',0,[soDown],6);
+end;
+
+procedure TTestSearchBuf.TestSimpleDown;
+begin
+  TestSearch('very',SLen,[soDown],-1);
+end;
+
+procedure TTestSearchBuf.TestSimplePartialend;
+begin
+  TestSearch('its',0,[soDown],-1);
+end;
+
+procedure TTestSearchBuf.TestSimplePartialStart;
+begin
+  TestSearch('Tso',SLen,[],-1);
+end;
+
+procedure TTestSearchBuf.TestEndMatchDown;
+begin
+  TestSearch('it',30,[soDown],42);
+end;
+
+procedure TTestSearchBuf.TestEndMatch;
+begin
+  TestSearch('it',SLen,[],42);
+end;
+
+procedure TTestSearchBuf.TestSimpleDownPos;
+begin
+  TestSearch('it',30,[soDown],42);
+end;
+
+procedure TTestSearchBuf.TestSimplePos;
+begin
+  TestSearch('it',30,[],24);
+end;
+
+procedure TTestSearchBuf.TestNotExist;
+begin
+  TestSearch('quid',SLen,[],-1);
+end;
+
+procedure TTestSearchBuf.TestNotExistDown;
+begin
+  TestSearch('quid',0,[soDown],-1);
+end;
+
+procedure TTestSearchBuf.TestSimpleCaseSensitive;
+begin
+  TestSearch('Very',SLen,[soMatchCase],-1);
+end;
+
+procedure TTestSearchBuf.TestSimpleCaseSensitiveDown;
+begin
+  TestSearch('Very',0,[soMatchCase,soDown],-1);
+end;
+
+procedure TTestSearchBuf.TestSimpleWholeWord;
+begin
+  TestSearch('in',SLen,[soWholeWord],39);
+end;
+
+procedure TTestSearchBuf.TestSimpleWholeWordDown;
+begin
+  TestSearch('in',0,[soWholeWord,soDown],39);
+end;
+
+initialization
+  RegisterTest(TTestSearchBuf);
+end.
+

+ 239 - 0
rtl/tests/tstrutils.lpi

@@ -0,0 +1,239 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <PathDelim Value="/"/>
+    <Version Value="6"/>
+    <General>
+      <MainUnit Value="0"/>
+      <TargetFileExt Value=""/>
+      <ActiveEditorIndexAtStart Value="1"/>
+    </General>
+    <VersionInfo>
+      <ProjectVersion Value=""/>
+      <Language Value=""/>
+      <CharSet Value=""/>
+    </VersionInfo>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IgnoreBinaries Value="False"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+        <CommandLineParams Value="--suite=TTestTStringList --format=plain"/>
+        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
+      </local>
+    </RunParams>
+    <RequiredPackages Count="2">
+      <Item1>
+        <PackageName Value="FPCUnitConsoleRunner"/>
+      </Item1>
+      <Item2>
+        <PackageName Value="FCL"/>
+      </Item2>
+    </RequiredPackages>
+    <Units Count="6">
+      <Unit0>
+        <Filename Value="tstrutils.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tstrutils"/>
+        <CursorPos X="1" Y="21"/>
+        <TopLine Value="1"/>
+        <EditorIndex Value="4"/>
+        <UsageCount Value="20"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="tcstrutils.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tcstrutils"/>
+        <CursorPos X="10" Y="52"/>
+        <TopLine Value="1"/>
+        <EditorIndex Value="0"/>
+        <UsageCount Value="20"/>
+        <Loaded Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="tcstringlist.pp"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="tcstringlist"/>
+        <CursorPos X="1" Y="2"/>
+        <TopLine Value="1"/>
+        <EditorIndex Value="2"/>
+        <UsageCount Value="20"/>
+        <Loaded Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="../../../../fpc/packages/fcl-fpcunit/src/fpcunit.pp"/>
+        <UnitName Value="fpcunit"/>
+        <CursorPos X="6" Y="554"/>
+        <TopLine Value="524"/>
+        <UsageCount Value="10"/>
+      </Unit3>
+      <Unit4>
+        <Filename Value="../../../../fpc/rtl/objpas/classes/classesh.inc"/>
+        <CursorPos X="3" Y="66"/>
+        <TopLine Value="40"/>
+        <EditorIndex Value="3"/>
+        <UsageCount Value="10"/>
+        <Loaded Value="True"/>
+      </Unit4>
+      <Unit5>
+        <Filename Value="searchbuf.inc"/>
+        <CursorPos X="15" Y="112"/>
+        <TopLine Value="65"/>
+        <EditorIndex Value="1"/>
+        <UsageCount Value="10"/>
+        <Loaded Value="True"/>
+      </Unit5>
+    </Units>
+    <JumpHistory Count="30" HistoryIndex="29">
+      <Position1>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="200" Column="15" TopLine="176"/>
+      </Position1>
+      <Position2>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="207" Column="40" TopLine="181"/>
+      </Position2>
+      <Position3>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="43" Column="1" TopLine="16"/>
+      </Position3>
+      <Position4>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="215" Column="5" TopLine="158"/>
+      </Position4>
+      <Position5>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="216" Column="8" TopLine="189"/>
+      </Position5>
+      <Position6>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="55" Column="1" TopLine="27"/>
+      </Position6>
+      <Position7>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="242" Column="1" TopLine="191"/>
+      </Position7>
+      <Position8>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="65" Column="54" TopLine="27"/>
+      </Position8>
+      <Position9>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="224" Column="1" TopLine="199"/>
+      </Position9>
+      <Position10>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="233" Column="5" TopLine="176"/>
+      </Position10>
+      <Position11>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="16" Column="3" TopLine="15"/>
+      </Position11>
+      <Position12>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="78" Column="25" TopLine="51"/>
+      </Position12>
+      <Position13>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="26" Column="38" TopLine="25"/>
+      </Position13>
+      <Position14>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="258" Column="82" TopLine="232"/>
+      </Position14>
+      <Position15>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="254" Column="13" TopLine="228"/>
+      </Position15>
+      <Position16>
+        <Filename Value="../../../../fpc/rtl/objpas/classes/classesh.inc"/>
+        <Caret Line="618" Column="36" TopLine="592"/>
+      </Position16>
+      <Position17>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="114" Column="5" TopLine="57"/>
+      </Position17>
+      <Position18>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="115" Column="69" TopLine="107"/>
+      </Position18>
+      <Position19>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="274" Column="5" TopLine="217"/>
+      </Position19>
+      <Position20>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="280" Column="1" TopLine="247"/>
+      </Position20>
+      <Position21>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="239" Column="5" TopLine="182"/>
+      </Position21>
+      <Position22>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="240" Column="20" TopLine="217"/>
+      </Position22>
+      <Position23>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="253" Column="15" TopLine="237"/>
+      </Position23>
+      <Position24>
+        <Filename Value="tcstringlist.pp"/>
+        <Caret Line="272" Column="1" TopLine="272"/>
+      </Position24>
+      <Position25>
+        <Filename Value="searchbuf.inc"/>
+        <Caret Line="1" Column="1" TopLine="1"/>
+      </Position25>
+      <Position26>
+        <Filename Value="searchbuf.inc"/>
+        <Caret Line="40" Column="21" TopLine="12"/>
+      </Position26>
+      <Position27>
+        <Filename Value="searchbuf.inc"/>
+        <Caret Line="56" Column="9" TopLine="31"/>
+      </Position27>
+      <Position28>
+        <Filename Value="searchbuf.inc"/>
+        <Caret Line="75" Column="21" TopLine="49"/>
+      </Position28>
+      <Position29>
+        <Filename Value="searchbuf.inc"/>
+        <Caret Line="65" Column="42" TopLine="39"/>
+      </Position29>
+      <Position30>
+        <Filename Value="searchbuf.inc"/>
+        <Caret Line="110" Column="94" TopLine="65"/>
+      </Position30>
+    </JumpHistory>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="5"/>
+    <CodeGeneration>
+      <Generate Value="Faster"/>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="True"/>
+      </Debugging>
+    </Linking>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="2">
+      <Item1>
+        <Name Value="ECodetoolError"/>
+      </Item1>
+      <Item2>
+        <Name Value="EFOpenError"/>
+      </Item2>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 26 - 0
rtl/tests/tstrutils.lpr

@@ -0,0 +1,26 @@
+program tstrutils;
+
+{$mode objfpc}{$H+}
+
+uses
+  Classes, consoletestrunner, tcstrutils, tcstringlist;
+
+type
+
+  { TLazTestRunner }
+
+  TMyTestRunner = class(TTestRunner)
+  protected
+  // override the protected methods of TTestRunner to customize its behavior
+  end;
+
+var
+  Application: TMyTestRunner;
+
+begin
+  Application := TMyTestRunner.Create(nil);
+  Application.Initialize;
+  Application.Title := 'FPCUnit Console test runner';
+  Application.Run;
+  Application.Free;
+end.